From 03a51b516b685829f88a9b58a10319c222a0ede1 Mon Sep 17 00:00:00 2001 From: jkobject Date: Mon, 9 Sep 2024 17:05:09 +0200 Subject: [PATCH] Deployed a0294a1 with MkDocs version: 1.6.0 --- index.html | 144 +++++++++++++++++++++++++++++++-------- index.md | 136 +++++++++++++++++++++++++++++------- search/search_index.json | 2 +- sitemap.xml | 22 +++--- sitemap.xml.gz | Bin 297 -> 295 bytes 5 files changed, 241 insertions(+), 63 deletions(-) diff --git a/index.html b/index.html index 24e7fb1..066656a 100644 --- a/index.html +++ b/index.html @@ -43,9 +43,17 @@ @@ -150,14 +160,15 @@

scPRINT: Large Cell Model for scRNAseq data

-

PyPI version -Documentation Status +

codecov +CI +PyPI version Downloads Downloads Downloads GitHub issues Code style: black -DOI

+DOI

logo

scPRINT is a large transformer model built for the inference of gene networks (connections between genes explaining the cell's expression profile) from scRNAseq data.

It uses novel encoding and decoding of the cell expression profile and new pre-training methodologies to learn a cell model.

@@ -168,29 +179,103 @@

scPRINT: Large Cell Model fo
  • label prediction: predict the cell type, disease, sequencer, sex, and ethnicity of your cells
  • gene network inference: generate a gene network from any cell or cell cluster in your scRNAseq dataset
  • -

    Read the paper! if you would like to know more about scPRINT.

    +

    Read the manuscript! if you would like to know more about scPRINT. Have a look at some of my X-plainers.

    figure1

    +

    Table of Contents

    +

    Install scPRINT

    -

    For the moment scPRINT has been tested on MacOS and Linux (Ubuntu 20.04) with Python 3.10.

    +

    For the moment scPRINT has been tested on MacOS and Linux (Ubuntu 20.04) with Python 3.10. Its instalation takes on average 10 minutes.

    If you want to be using flashattention2, know that it only supports triton 2.0 MLIR's version and torch==2.0.0 for now.

    -
    conda create -n "[whatever]" python==3.10
    +

    lamin.ai

    +

    To use scPRINT, I need you to use lamin.ai. This is needed to load biological informations like genes, cell types, organisms etc...

    +

    To do so, you will need to connect with google or github to lamin.ai, then be sure to connect before running anything (or before starting a notebook): lamin login <email> --key <API-key>. Follow the instructions on their website.

    +

    install

    +

    To start you will need to do:

    +
    conda create -n <env-name> python==3.10 #scprint might work with python >3.10, but it is not tested
     #one of
     pip install scprint # OR
    -pip install scprint[dev] # for the dev dependencies (building etc..) AND/OR [dev,flash]
    -pip install scprint[flash] && pip install -e "git+https:/
    -/github.com/triton-lang/triton.git@legacy-backend
    -#egg=triton&subdirectory=python" # to use flashattention2, you will need to install triton 2.0.0.dev20221202 specifically, working on removing this dependency # only if you have a compatible gpu (e.g. not available for apple GPUs for now, see https://github.com/triton-lang/triton?tab=readme-ov-file#compatibility)
    +pip install scprint[dev] # for the dev dependencies (building etc..) OR
    +pip install scprint[flash] # to use flashattention2 with triton: only if you have a compatible gpu (e.g. not available for apple GPUs for now, see https://github.com/triton-lang/triton?tab=readme-ov-file#compatibility)
    +#OR pip install scPRINT[dev,flash]
    +
    +lamin login <email> --key <API-key>
    +lamin init --storage <folder-name-where-lamin-data-will-be-stored> --schema bionty
     
    -

    We make use of some additional packages we developed alongside scPRint. -Please refer to their documentation for more information:

    +

    if you start with lamin and had to do a lamin init, you will also need to populate your ontologies. This is because scPRINT is using ontologies to define its cell types, diseases, sexes, ethnicities, etc.

    +

    you can do it manually or with our function:

    +
    from scdataloader.utils import populate_my_ontology
    +
    +populate_my_ontology() #to populate everything (recommended) (can take 2-10mns)
    +
    +populate_my_ontology( #the minimum for scprint to run some inferences (denoising, grn inference)
    +organisms: List[str] = ["NCBITaxon:10090", "NCBITaxon:9606"],
    +    sex: List[str] = ["PATO:0000384", "PATO:0000383"],
    +    celltypes = None,
    +    ethnicities = None,
    +    assays = None,
    +    tissues = None,
    +    diseases = None,
    +    dev_stages = None,
    +)
    +
    +

    We make use of some additional packages we developed alongside scPRint.

    +

    Please refer to their documentation for more information:

    • scDataLoader: a dataloader for training large cell models.
    • GRnnData: a package to work with gene networks from single cell data.
    • benGRN: a package to benchmark gene network inference methods from single cell data.
    -

    lamin.ai

    -

    ⚠️ if you want to use the scDataloader's multi-dataset mode or if you want to preprocess datasets and other functions of the model, you will need to use lamin.ai.

    -

    In that case, connect with google or github to lamin.ai, then be sure to connect before running anything (or before starting a notebook): lamin login <email> --key <API-key>. Follow the instructions on their website.

    +

    pytorch and GPUs

    +

    scPRINT can run on machines without GPUs, but it will be slow. It is highly recommended to use a GPU for inference.

    +

    Once you have a GPU, and installed the required drivers, you might need to install a specific version of pytorch that is compatible with your drivers (e.g. nvidia 550 drivers will lead to a nvidia toolkit 11.7 or 11.8 which might mean you need to re-install a different flavor of pytorch for things to work. e.g. using the command: +pip install torch==2.2.0 torchvision==0.17.0 torchaudio==2.2.0 --index-url https://download.pytorch.org/whl/cu118 on my case on linux + ).

    +

    I was able to test it with nvidia 11.7, 11.8, 12.2.

    +

    dev install

    +

    If you want to use the latest version of scPRINT and work on the code yourself use git clone and pip -e instead of pip install.

    +
    git clone https://github.com/jkobject/scPRINT
    +git clone https://github.com/jkobject/scDataLoader
    +git clone https://github.com/cantinilab/GRnnData
    +git clone https://github.com/jkobject/benGRN
    +pip install -e scPRINT[dev]
    +pip install -e scDataLoader[dev]
    +pip install -e GRnnData[dev]
    +pip install -e benGRN[dev]
    +

    Usage

    scPRINT's basic commands

    This is the most minimal example of how scPRINT works:

    @@ -213,7 +298,7 @@

    scPRINT's basic commands

    $ scprint fit/train/predict/test/denoise/embed/gninfer --config config/[medium|large|vlarge] ...
     

    find out more about the commands by running scprint --help or scprint [command] --help.

    -

    more examples of using the command line are available in the docs.

    +

    more examples of using the command line are available in the docs.

    Notes on GPU/CPU usage with triton

    If you do not have triton installed you will not be able to take advantage of GPU acceleration, but you can still use the model on the CPU.

    In that case, if loading from a checkpoint that was trained with flashattention, you will need to specify transformer="normal" in the load_from_checkpoint function like so:

    @@ -221,21 +306,23 @@

    Notes on GPU/CPU usage with triton

    +

    Simple tests:

    +

    An instalation of scPRINT and a simple test of the denoiser is performed during each commit to the main branch with a Github action and pytest workflow. It also provides an expected runtime for the installation and run of scPRINT.

    We now explore the different usages of scPRINT:

    FAQ

    I want to generate gene networks from scRNAseq data:

    -> Refer to the section . gene network inference in this notebook.

    -

    -> More examples in this notebook notebooks/assessments/bench_omni.ipynb.

    +

    -> More examples in this notebook ./notebooks/assessments/bench_omni.ipynb.

    I want to generate cell embeddings and cell label predictions from scRNAseq data:

    -> Refer to the embeddings and cell annotations section in this notebook.

    -

    I want to denoising my scRNAseq dataset:

    +

    I want to denoise my scRNAseq dataset:

    -> Refer to the Denoising of B-cell section in this notebook.

    -

    -> More example in our benchmark notebook notebooks/assessments/bench_denoising.ipynb.

    +

    -> More example in our benchmark notebook ./notebooks/assessments/bench_denoising.ipynb.

    I want to generate an atlas-level embedding

    -

    -> Refer to the notebook figures/nice_umap.ipynb.

    +

    -> Refer to the notebook nice_umap.ipynb.

    I need to generate gene tokens using pLLMs

    To run scPRINT, you can use the option to define the gene tokens using protein language model embeddings of genes. This is done by providing the path to a parquet file of the precomputed set of embeddings for each gene name to scPRINT via "precpt_gene_emb"

    -

    -> To generate this file please refer to the notebook notebooks/generate_gene_embeddings.ipynb.

    +

    -> To generate this file please refer to the notebook generate_gene_embeddings.

    I want to pre-train scPRINT from scratch on my own data

    -> Refer to the documentation page pretrain scprint

    how can I find if scPRINT was trained on my data?

    @@ -253,26 +340,27 @@

    where to find the gene embeddings? -

    You can also recreate the gene embedding file through this notebook. Just call the functions, and it should recreate the file itself.

    +

    You can also recreate the gene embedding file through this notebook. Just call the functions, and it should recreate the file itself.

    the file itself is also available on hugging face

    Documentation

    For more information on usage please see the documentation in https://www.jkobject.com/scPRINT/

    Model Weights

    Model weights are available on hugging face.

    Development

    -

    Read the CONTRIBUTING.md file.

    +

    Read the CONTRIBUTING.md file.

    Read the training runs document to know more about how pre-training was performed and the its behavior.

    +

    code coverage is not right as I am using the command line interface for now. >50% of the code is covered by my current unit test.

    Acknowledgement: python template laminDB lightning

    -

    Work in progress:

    +

    Work in progress (PR welcomed):

    1. remove the triton dependencies
    2. add version with additional labels (tissues, age) and organisms (mouse, zebrafish) and more datasets from cellxgene
    3. version with separate transformer blocks for the encoding part of the bottleneck learning and for the cell embeddings
    4. improve classifier to output uncertainties and topK predictions when unsure
    5. -
    6. +
    7. setup latest lamindb version

    Awesome Large Cell Model created by Jeremie Kalfon.

    @@ -323,5 +411,5 @@

    Work in progress:

    diff --git a/index.md b/index.md index 200a77b..3a54557 100644 --- a/index.md +++ b/index.md @@ -1,14 +1,15 @@ # scPRINT: Large Cell Model for scRNAseq data +[![codecov](https://codecov.io/gh/jkobject/scPRINT/branch/main/graph/badge.svg?token=GRnnData_token_here)](https://codecov.io/gh/jkobject/scPRINT) +[![CI](https://github.com/jkobject/scPRINT/actions/workflows/main.yml/badge.svg)](https://github.com/jkobject/scPRINT/actions/workflows/main.yml) [![PyPI version](https://badge.fury.io/py/scprint.svg)](https://badge.fury.io/py/scprint) -[![Documentation Status](https://readthedocs.org/projects/scprint/badge/?version=latest)](https://scprint.readthedocs.io/en/latest/?badge=latest) [![Downloads](https://pepy.tech/badge/scprint)](https://pepy.tech/project/scprint) [![Downloads](https://pepy.tech/badge/scprint/month)](https://pepy.tech/project/scprint) [![Downloads](https://pepy.tech/badge/scprint/week)](https://pepy.tech/project/scprint) [![GitHub issues](https://img.shields.io/github/issues/jkobject/scPRINT)](https://img.shields.io/github/issues/jkobject/scPRINT) [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) -[![DOI](https://zenodo.org/badge/391909874.svg)]() +[![DOI](https://zenodo.org/badge/391909874.svg)](https://doi.org/10.1101/2024.07.29.605556) ![logo](logo.png) @@ -23,39 +24,122 @@ scPRINT can be used to perform the following analyses: - __label prediction__: predict the cell type, disease, sequencer, sex, and ethnicity of your cells - __gene network inference__: generate a gene network from any cell or cell cluster in your scRNAseq dataset -[Read the paper!](https://www.biorxiv.org/content/10.1101/2024.07.29.605556v1) if you would like to know more about scPRINT. +[Read the manuscript!](https://www.biorxiv.org/content/10.1101/2024.07.29.605556v1) if you would like to know more about scPRINT. Have a look at some of my [X-plainers](https://twitter.com/jkobject). ![figure1](figure1.png) +## Table of Contents + +- [scPRINT: Large Cell Model for scRNAseq data](#scprint-large-cell-model-for-scrnaseq-data) + - [Table of Contents](#table-of-contents) + - [Install `scPRINT`](#install-scprint) + - [lamin.ai](#laminai) + - [install](#install) + - [pytorch and GPUs](#pytorch-and-gpus) + - [dev install](#dev-install) + - [Usage](#usage) + - [scPRINT's basic commands](#scprints-basic-commands) + - [Notes on GPU/CPU usage with triton](#notes-on-gpucpu-usage-with-triton) + - [Simple tests:](#simple-tests) + - [FAQ](#faq) + - [I want to generate gene networks from scRNAseq data:](#i-want-to-generate-gene-networks-from-scrnaseq-data) + - [I want to generate cell embeddings and cell label predictions from scRNAseq data:](#i-want-to-generate-cell-embeddings-and-cell-label-predictions-from-scrnaseq-data) + - [I want to denoise my scRNAseq dataset:](#i-want-to-denoise-my-scrnaseq-dataset) + - [I want to generate an atlas-level embedding](#i-want-to-generate-an-atlas-level-embedding) + - [I need to generate gene tokens using pLLMs](#i-need-to-generate-gene-tokens-using-pllms) + - [I want to pre-train scPRINT from scratch on my own data](#i-want-to-pre-train-scprint-from-scratch-on-my-own-data) + - [how can I find if scPRINT was trained on my data?](#how-can-i-find-if-scprint-was-trained-on-my-data) + - [can I use scPRINT on other organisms rather than human?](#can-i-use-scprint-on-other-organisms-rather-than-human) + - [how long does scPRINT takes? what kind of resources do I need? (or in alternative: can i run scPRINT locally?)](#how-long-does-scprint-takes-what-kind-of-resources-do-i-need-or-in-alternative-can-i-run-scprint-locally) + - [I have different scRNASeq batches. Should I integrate my data before running scPRINT?](#i-have-different-scrnaseq-batches-should-i-integrate-my-data-before-running-scprint) + - [where to find the gene embeddings?](#where-to-find-the-gene-embeddings) + - [Documentation](#documentation) + - [Model Weights](#model-weights) + - [Development](#development) + - [Work in progress (PR welcomed):](#work-in-progress-pr-welcomed) + ## Install `scPRINT` -For the moment scPRINT has been tested on MacOS and Linux (Ubuntu 20.04) with Python 3.10. +For the moment scPRINT has been tested on MacOS and Linux (Ubuntu 20.04) with Python 3.10. Its instalation takes on average 10 minutes. If you want to be using flashattention2, know that it only supports triton 2.0 MLIR's version and torch==2.0.0 for now. -```python -conda create -n "[whatever]" python==3.10 +### lamin.ai + +To use scPRINT, I need you to use lamin.ai. This is needed to load biological informations like genes, cell types, organisms etc... + +To do so, you will need to connect with google or github to [lamin.ai](https://lamin.ai/login), then be sure to connect before running anything (or before starting a notebook): `lamin login --key `. Follow the instructions on [their website](https://docs.lamin.ai/guide). + +### install + +To start you will need to do: + +```bash +conda create -n python==3.10 #scprint might work with python >3.10, but it is not tested #one of pip install scprint # OR -pip install scprint[dev] # for the dev dependencies (building etc..) AND/OR [dev,flash] -pip install scprint[flash] && pip install -e "git+https:/ -/github.com/triton-lang/triton.git@legacy-backend -#egg=triton&subdirectory=python" # to use flashattention2, you will need to install triton 2.0.0.dev20221202 specifically, working on removing this dependency # only if you have a compatible gpu (e.g. not available for apple GPUs for now, see https://github.com/triton-lang/triton?tab=readme-ov-file#compatibility) +pip install scprint[dev] # for the dev dependencies (building etc..) OR +pip install scprint[flash] # to use flashattention2 with triton: only if you have a compatible gpu (e.g. not available for apple GPUs for now, see https://github.com/triton-lang/triton?tab=readme-ov-file#compatibility) +#OR pip install scPRINT[dev,flash] + +lamin login --key +lamin init --storage --schema bionty +``` + +if you start with lamin and had to do a `lamin init`, you will also need to populate your ontologies. This is because scPRINT is using ontologies to define its cell types, diseases, sexes, ethnicities, etc. + +you can do it manually or with our function: + +```python +from scdataloader.utils import populate_my_ontology + +populate_my_ontology() #to populate everything (recommended) (can take 2-10mns) + +populate_my_ontology( #the minimum for scprint to run some inferences (denoising, grn inference) +organisms: List[str] = ["NCBITaxon:10090", "NCBITaxon:9606"], + sex: List[str] = ["PATO:0000384", "PATO:0000383"], + celltypes = None, + ethnicities = None, + assays = None, + tissues = None, + diseases = None, + dev_stages = None, +) ``` We make use of some additional packages we developed alongside scPRint. + Please refer to their documentation for more information: - [scDataLoader](https://github.com/jkobject/scDataLoader): a dataloader for training large cell models. - [GRnnData](https://github.com/cantinilab/GRnnData): a package to work with gene networks from single cell data. - [benGRN](https://github.com/jkobject/benGRN): a package to benchmark gene network inference methods from single cell data. -### lamin.ai +### pytorch and GPUs + +scPRINT can run on machines without GPUs, but it will be slow. It is highly recommended to use a GPU for inference. + +Once you have a GPU, and installed the required drivers, you might need to install a specific version of pytorch that is compatible with your drivers (e.g. nvidia 550 drivers will lead to a nvidia toolkit 11.7 or 11.8 which might mean you need to re-install a different flavor of pytorch for things to work. e.g. using the command: +`pip install torch==2.2.0 torchvision==0.17.0 torchaudio==2.2.0 --index-url https://download.pytorch.org/whl/cu118` on my case on linux + ). + +I was able to test it with nvidia 11.7, 11.8, 12.2. -⚠️ if you want to use the scDataloader's multi-dataset mode or if you want to preprocess datasets and other functions of the model, you will need to use lamin.ai. +### dev install -In that case, connect with google or github to [lamin.ai](https://lamin.ai/login), then be sure to connect before running anything (or before starting a notebook): `lamin login --key `. Follow the instructions on [their website](https://docs.lamin.ai/guide). +If you want to use the latest version of scPRINT and work on the code yourself use `git clone` and `pip -e` instead of `pip install`. + +```bash +git clone https://github.com/jkobject/scPRINT +git clone https://github.com/jkobject/scDataLoader +git clone https://github.com/cantinilab/GRnnData +git clone https://github.com/jkobject/benGRN +pip install -e scPRINT[dev] +pip install -e scDataLoader[dev] +pip install -e GRnnData[dev] +pip install -e benGRN[dev] +``` ## Usage @@ -88,7 +172,7 @@ $ scprint fit/train/predict/test/denoise/embed/gninfer --config config/[medium|l find out more about the commands by running `scprint --help` or `scprint [command] --help`. -more examples of using the command line are available in the [docs](./docs/usage.md). +more examples of using the command line are available in the [docs](usage.md). ### Notes on GPU/CPU usage with triton @@ -102,6 +186,10 @@ model = scPrint.load_from_checkpoint( transformer="normal") ``` +### Simple tests: + +An instalation of scPRINT and a simple test of the denoiser is performed during each commit to the main branch with a [Github action](https://github.com/jkobject/scPRINT/actions) and [pytest workflow](https://github.com/jkobject/scPRINT/blob/main/.github/workflows/main.yml). It also provides an expected runtime for the installation and run of scPRINT. + We now explore the different usages of scPRINT: ## FAQ @@ -110,27 +198,27 @@ We now explore the different usages of scPRINT: -> Refer to the section . gene network inference in [this notebook](./notebooks/cancer_usecase.ipynb#). --> More examples in this notebook [notebooks/assessments/bench_omni.ipynb](../notebooks/bench_omni.ipynb). +-> More examples in this notebook [./notebooks/assessments/bench_omni.ipynb](https://github.com/jkobject/scPRINT/blob/main/notebooks/bench_omni.ipynb). ### I want to generate cell embeddings and cell label predictions from scRNAseq data: -> Refer to the embeddings and cell annotations section in [this notebook](./notebooks/cancer_usecase.ipynb#). -### I want to denoising my scRNAseq dataset: +### I want to denoise my scRNAseq dataset: -> Refer to the Denoising of B-cell section in [this notebook](./notebooks/cancer_usecase.ipynb). --> More example in our benchmark notebook [notebooks/assessments/bench_denoising.ipynb](../notebooks/bench_denoising.ipynb). +-> More example in our benchmark notebook [./notebooks/assessments/bench_denoising.ipynb](https://github.com/jkobject/scPRINT/blob/main/notebooks/bench_denoising.ipynb). ### I want to generate an atlas-level embedding --> Refer to the notebook [figures/nice_umap.ipynb](../figures/nice_umap.ipynb). +-> Refer to the notebook [nice_umap.ipynb](https://github.com/jkobject/scPRINT/blob/main/figures/nice_umap.ipynb). ### I need to generate gene tokens using pLLMs To run scPRINT, you can use the option to define the gene tokens using protein language model embeddings of genes. This is done by providing the path to a parquet file of the precomputed set of embeddings for each gene name to scPRINT via "precpt_gene_emb" --> To generate this file please refer to the notebook [notebooks/generate_gene_embeddings.ipynb](../notebooks/generate_gene_embeddings.ipynb). +-> To generate this file please refer to the notebook [generate_gene_embeddings](https://github.com/jkobject/scPRINT/blob/main/notebooks/generate_gene_embeddings.ipynb). ### I want to pre-train scPRINT from scratch on my own data @@ -163,7 +251,7 @@ model = scPrint.load_from_checkpoint( ) ``` -You can also recreate the gene embedding file through [this notebook](notebooks/generate_gene_embeddings.ipynb). Just call the functions, and it should recreate the file itself. +You can also recreate the gene embedding file through [this notebook](https://github.com/jkobject/scPRINT/blob/main/notebooks/generate_gene_embeddings.ipynb). Just call the functions, and it should recreate the file itself. the file itself is also available on [hugging face](https://huggingface.co/jkobject/scPRINT/tree/main) @@ -177,21 +265,23 @@ Model weights are available on [hugging face](https://huggingface.co/jkobject/sc ## Development -Read the [CONTRIBUTING.md](CONTRIBUTING.md) file. +Read the [CONTRIBUTING.md](https://github.com/jkobject/scPRINT/blob/main/CONTRIBUTING.md) file. Read the [training runs](https://wandb.ai/ml4ig/scprint_scale/reports/scPRINT-trainings--Vmlldzo4ODIxMjgx?accessToken=80metwx7b08hhourotpskdyaxiflq700xzmzymr6scvkp69agybt79l341tv68hp) document to know more about how pre-training was performed and the its behavior. +code coverage is not right as I am using the command line interface for now. >50% of the code is covered by my current unit test. + Acknowledgement: [python template](https://github.com/rochacbruno/python-project-template) [laminDB](https://lamin.ai/) [lightning](https://lightning.ai/) -## Work in progress: +## Work in progress (PR welcomed): 1. remove the triton dependencies 2. add version with additional labels (tissues, age) and organisms (mouse, zebrafish) and more datasets from cellxgene 3. version with separate transformer blocks for the encoding part of the bottleneck learning and for the cell embeddings 4. improve classifier to output uncertainties and topK predictions when unsure -5. +5. setup latest lamindb version Awesome Large Cell Model created by Jeremie Kalfon. diff --git a/search/search_index.json b/search/search_index.json index 838c3f8..7a69633 100644 --- a/search/search_index.json +++ b/search/search_index.json @@ -1 +1 @@ -{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"scPRINT: Large Cell Model for scRNAseq data scPRINT is a large transformer model built for the inference of gene networks (connections between genes explaining the cell's expression profile) from scRNAseq data. It uses novel encoding and decoding of the cell expression profile and new pre-training methodologies to learn a cell model. scPRINT can be used to perform the following analyses: expression denoising : increase the resolution of your scRNAseq data cell embedding : generate a low-dimensional representation of your dataset label prediction : predict the cell type, disease, sequencer, sex, and ethnicity of your cells gene network inference : generate a gene network from any cell or cell cluster in your scRNAseq dataset Read the paper! if you would like to know more about scPRINT. Install scPRINT For the moment scPRINT has been tested on MacOS and Linux (Ubuntu 20.04) with Python 3.10. If you want to be using flashattention2, know that it only supports triton 2.0 MLIR's version and torch==2.0.0 for now. conda create -n \"[whatever]\" python==3.10 #one of pip install scprint # OR pip install scprint[dev] # for the dev dependencies (building etc..) AND/OR [dev,flash] pip install scprint[flash] && pip install -e \"git+https:/ /github.com/triton-lang/triton.git@legacy-backend #egg=triton&subdirectory=python\" # to use flashattention2, you will need to install triton 2.0.0.dev20221202 specifically, working on removing this dependency # only if you have a compatible gpu (e.g. not available for apple GPUs for now, see https://github.com/triton-lang/triton?tab=readme-ov-file#compatibility) We make use of some additional packages we developed alongside scPRint. Please refer to their documentation for more information: scDataLoader : a dataloader for training large cell models. GRnnData : a package to work with gene networks from single cell data. benGRN : a package to benchmark gene network inference methods from single cell data. lamin.ai \u26a0\ufe0f if you want to use the scDataloader's multi-dataset mode or if you want to preprocess datasets and other functions of the model, you will need to use lamin.ai. In that case, connect with google or github to lamin.ai , then be sure to connect before running anything (or before starting a notebook): lamin login --key . Follow the instructions on their website . Usage scPRINT's basic commands This is the most minimal example of how scPRINT works: from lightning.pytorch import Trainer from scprint import scPrint from scdataloader import DataModule datamodule = DataModule(...) model = scPrint(...) # to train / fit / test the model trainer = Trainer(...) trainer.fit(model, datamodule=datamodule) # to do predictions Denoiser, Embedder, GNInfer denoiser = Denoiser(...) adata = sc.read_h5ad(...) denoiser(model, adata=adata) ... or, from a bash command line $ scprint fit/train/predict/test/denoise/embed/gninfer --config config/[medium|large|vlarge] ... find out more about the commands by running scprint --help or scprint [command] --help . more examples of using the command line are available in the docs . Notes on GPU/CPU usage with triton If you do not have triton installed you will not be able to take advantage of GPU acceleration, but you can still use the model on the CPU. In that case, if loading from a checkpoint that was trained with flashattention, you will need to specify transformer=\"normal\" in the load_from_checkpoint function like so: model = scPrint.load_from_checkpoint( '../data/temp/last.ckpt', precpt_gene_emb=None, transformer=\"normal\") We now explore the different usages of scPRINT: FAQ I want to generate gene networks from scRNAseq data: -> Refer to the section . gene network inference in this notebook . -> More examples in this notebook notebooks/assessments/bench_omni.ipynb . I want to generate cell embeddings and cell label predictions from scRNAseq data: -> Refer to the embeddings and cell annotations section in this notebook . I want to denoising my scRNAseq dataset: -> Refer to the Denoising of B-cell section in this notebook . -> More example in our benchmark notebook notebooks/assessments/bench_denoising.ipynb . I want to generate an atlas-level embedding -> Refer to the notebook figures/nice_umap.ipynb . I need to generate gene tokens using pLLMs To run scPRINT, you can use the option to define the gene tokens using protein language model embeddings of genes. This is done by providing the path to a parquet file of the precomputed set of embeddings for each gene name to scPRINT via \"precpt_gene_emb\" -> To generate this file please refer to the notebook notebooks/generate_gene_embeddings.ipynb . I want to pre-train scPRINT from scratch on my own data -> Refer to the documentation page pretrain scprint how can I find if scPRINT was trained on my data? If your data is available in cellxgene, scPRINT was likely trained on it. However some cells, datasets were dropped due to low quality data and some were randomly removed to be part of the validation / test sets. can I use scPRINT on other organisms rather than human? scPRINT has been pretrained on both humans and mouse, and can be used on any organism with a similar gene set. If you want to use scPRINT on very different organisms, you will need to generate gene embeddings for that organism and re-train scPRINT how long does scPRINT takes? what kind of resources do I need? (or in alternative: can i run scPRINT locally?) please look at our supplementary tables in the manuscript I have different scRNASeq batches. Should I integrate my data before running scPRINT? scPRINT takes raw count as inputs, so please don't use integrated data. Just give the raw counts to scPRINT and it will take care of the rest. where to find the gene embeddings? If you think you need the gene embeddings file for loading the model from a checkpoint, you don't, as the embeddings are also stored in the model weights. You just need to load the weights like this: model = scPrint.load_from_checkpoint( '../../data/temp/last.ckpt', precpt_gene_emb=None, ) You can also recreate the gene embedding file through this notebook . Just call the functions, and it should recreate the file itself. the file itself is also available on hugging face Documentation For more information on usage please see the documentation in https://www.jkobject.com/scPRINT/ Model Weights Model weights are available on hugging face . Development Read the CONTRIBUTING.md file. Read the training runs document to know more about how pre-training was performed and the its behavior. Acknowledgement: python template laminDB lightning Work in progress: remove the triton dependencies add version with additional labels (tissues, age) and organisms (mouse, zebrafish) and more datasets from cellxgene version with separate transformer blocks for the encoding part of the bottleneck learning and for the cell embeddings improve classifier to output uncertainties and topK predictions when unsure Awesome Large Cell Model created by Jeremie Kalfon.","title":"Home"},{"location":"#scprint-large-cell-model-for-scrnaseq-data","text":"scPRINT is a large transformer model built for the inference of gene networks (connections between genes explaining the cell's expression profile) from scRNAseq data. It uses novel encoding and decoding of the cell expression profile and new pre-training methodologies to learn a cell model. scPRINT can be used to perform the following analyses: expression denoising : increase the resolution of your scRNAseq data cell embedding : generate a low-dimensional representation of your dataset label prediction : predict the cell type, disease, sequencer, sex, and ethnicity of your cells gene network inference : generate a gene network from any cell or cell cluster in your scRNAseq dataset Read the paper! if you would like to know more about scPRINT.","title":"scPRINT: Large Cell Model for scRNAseq data"},{"location":"#install-scprint","text":"For the moment scPRINT has been tested on MacOS and Linux (Ubuntu 20.04) with Python 3.10. If you want to be using flashattention2, know that it only supports triton 2.0 MLIR's version and torch==2.0.0 for now. conda create -n \"[whatever]\" python==3.10 #one of pip install scprint # OR pip install scprint[dev] # for the dev dependencies (building etc..) AND/OR [dev,flash] pip install scprint[flash] && pip install -e \"git+https:/ /github.com/triton-lang/triton.git@legacy-backend #egg=triton&subdirectory=python\" # to use flashattention2, you will need to install triton 2.0.0.dev20221202 specifically, working on removing this dependency # only if you have a compatible gpu (e.g. not available for apple GPUs for now, see https://github.com/triton-lang/triton?tab=readme-ov-file#compatibility) We make use of some additional packages we developed alongside scPRint. Please refer to their documentation for more information: scDataLoader : a dataloader for training large cell models. GRnnData : a package to work with gene networks from single cell data. benGRN : a package to benchmark gene network inference methods from single cell data.","title":"Install scPRINT"},{"location":"#laminai","text":"\u26a0\ufe0f if you want to use the scDataloader's multi-dataset mode or if you want to preprocess datasets and other functions of the model, you will need to use lamin.ai. In that case, connect with google or github to lamin.ai , then be sure to connect before running anything (or before starting a notebook): lamin login --key . Follow the instructions on their website .","title":"lamin.ai"},{"location":"#usage","text":"","title":"Usage"},{"location":"#scprints-basic-commands","text":"This is the most minimal example of how scPRINT works: from lightning.pytorch import Trainer from scprint import scPrint from scdataloader import DataModule datamodule = DataModule(...) model = scPrint(...) # to train / fit / test the model trainer = Trainer(...) trainer.fit(model, datamodule=datamodule) # to do predictions Denoiser, Embedder, GNInfer denoiser = Denoiser(...) adata = sc.read_h5ad(...) denoiser(model, adata=adata) ... or, from a bash command line $ scprint fit/train/predict/test/denoise/embed/gninfer --config config/[medium|large|vlarge] ... find out more about the commands by running scprint --help or scprint [command] --help . more examples of using the command line are available in the docs .","title":"scPRINT's basic commands"},{"location":"#notes-on-gpucpu-usage-with-triton","text":"If you do not have triton installed you will not be able to take advantage of GPU acceleration, but you can still use the model on the CPU. In that case, if loading from a checkpoint that was trained with flashattention, you will need to specify transformer=\"normal\" in the load_from_checkpoint function like so: model = scPrint.load_from_checkpoint( '../data/temp/last.ckpt', precpt_gene_emb=None, transformer=\"normal\") We now explore the different usages of scPRINT:","title":"Notes on GPU/CPU usage with triton"},{"location":"#faq","text":"","title":"FAQ"},{"location":"#i-want-to-generate-gene-networks-from-scrnaseq-data","text":"-> Refer to the section . gene network inference in this notebook . -> More examples in this notebook notebooks/assessments/bench_omni.ipynb .","title":"I want to generate gene networks from scRNAseq data:"},{"location":"#i-want-to-generate-cell-embeddings-and-cell-label-predictions-from-scrnaseq-data","text":"-> Refer to the embeddings and cell annotations section in this notebook .","title":"I want to generate cell embeddings and cell label predictions from scRNAseq data:"},{"location":"#i-want-to-denoising-my-scrnaseq-dataset","text":"-> Refer to the Denoising of B-cell section in this notebook . -> More example in our benchmark notebook notebooks/assessments/bench_denoising.ipynb .","title":"I want to denoising my scRNAseq dataset:"},{"location":"#i-want-to-generate-an-atlas-level-embedding","text":"-> Refer to the notebook figures/nice_umap.ipynb .","title":"I want to generate an atlas-level embedding"},{"location":"#i-need-to-generate-gene-tokens-using-pllms","text":"To run scPRINT, you can use the option to define the gene tokens using protein language model embeddings of genes. This is done by providing the path to a parquet file of the precomputed set of embeddings for each gene name to scPRINT via \"precpt_gene_emb\" -> To generate this file please refer to the notebook notebooks/generate_gene_embeddings.ipynb .","title":"I need to generate gene tokens using pLLMs"},{"location":"#i-want-to-pre-train-scprint-from-scratch-on-my-own-data","text":"-> Refer to the documentation page pretrain scprint","title":"I want to pre-train scPRINT from scratch on my own data"},{"location":"#how-can-i-find-if-scprint-was-trained-on-my-data","text":"If your data is available in cellxgene, scPRINT was likely trained on it. However some cells, datasets were dropped due to low quality data and some were randomly removed to be part of the validation / test sets.","title":"how can I find if scPRINT was trained on my data?"},{"location":"#can-i-use-scprint-on-other-organisms-rather-than-human","text":"scPRINT has been pretrained on both humans and mouse, and can be used on any organism with a similar gene set. If you want to use scPRINT on very different organisms, you will need to generate gene embeddings for that organism and re-train scPRINT","title":"can I use scPRINT on other organisms rather than human?"},{"location":"#how-long-does-scprint-takes-what-kind-of-resources-do-i-need-or-in-alternative-can-i-run-scprint-locally","text":"please look at our supplementary tables in the manuscript","title":"how long does scPRINT takes? what kind of resources do I need? (or in alternative: can i run scPRINT locally?)"},{"location":"#i-have-different-scrnaseq-batches-should-i-integrate-my-data-before-running-scprint","text":"scPRINT takes raw count as inputs, so please don't use integrated data. Just give the raw counts to scPRINT and it will take care of the rest.","title":"I have different scRNASeq batches. Should I integrate my data before running scPRINT?"},{"location":"#where-to-find-the-gene-embeddings","text":"If you think you need the gene embeddings file for loading the model from a checkpoint, you don't, as the embeddings are also stored in the model weights. You just need to load the weights like this: model = scPrint.load_from_checkpoint( '../../data/temp/last.ckpt', precpt_gene_emb=None, ) You can also recreate the gene embedding file through this notebook . Just call the functions, and it should recreate the file itself. the file itself is also available on hugging face","title":"where to find the gene embeddings?"},{"location":"#documentation","text":"For more information on usage please see the documentation in https://www.jkobject.com/scPRINT/","title":"Documentation"},{"location":"#model-weights","text":"Model weights are available on hugging face .","title":"Model Weights"},{"location":"#development","text":"Read the CONTRIBUTING.md file. Read the training runs document to know more about how pre-training was performed and the its behavior. Acknowledgement: python template laminDB lightning","title":"Development"},{"location":"#work-in-progress","text":"remove the triton dependencies add version with additional labels (tissues, age) and organisms (mouse, zebrafish) and more datasets from cellxgene version with separate transformer blocks for the encoding part of the bottleneck learning and for the cell embeddings improve classifier to output uncertainties and topK predictions when unsure Awesome Large Cell Model created by Jeremie Kalfon.","title":"Work in progress:"},{"location":"cli/","text":"Documentation for the cli modules scprint.__main__ Entry point for scprint. MySaveConfig Bases: SaveConfigCallback MySaveConfig is a subclass of SaveConfigCallback to parametrize the wandb logger further in cli mode scprint.cli MyCLI Bases: LightningCLI MyCLI is a subclass of LightningCLI to add some missing params and create bindings between params of the model and the data. Used to allow calling denoise / embed / gninfer from the command line. Also to add more parameters and link parameters between the scdataloader and the scPRINT model. scprint.trainer.trainer TrainingMode Bases: Callback TrainingMode a callback to set the training specific info to the model. This is because lightning is unfortunately setup this way. the model should be separated from training but at the same time it has training specific methods... so we have to do this. Parameters: do_denoise ( bool , default: True ) \u2013 Whether to apply denoising during training. Defaults to True. noise ( List [ float ] , default: [0.6] ) \u2013 List of noise levels to apply if denoising is enabled. Defaults to [0.6], meaning only one forward path with 60% of the counts being dropped will happen. do_cce ( bool , default: False ) \u2013 Whether to apply the Contrastive Cell Embedding from scGPT during training. Defaults to False. cce_sim ( float , default: 0.5 ) \u2013 Similarity threshold for CCE. Defaults to 0.5. cce_scale ( float , default: 0.002 ) \u2013 Scaling factor for CCE loss. Defaults to 0.002. do_ecs ( bool , default: False ) \u2013 Whether to apply the Elastic Cell Similarity loss from scGPT during training. Defaults to False. ecs_threshold ( float , default: 0.3 ) \u2013 Threshold for ECS. Defaults to 0.3. ecs_scale ( float , default: 0.05 ) \u2013 Scaling factor for ECS loss. Defaults to 0.05. do_mvc ( bool , default: False ) \u2013 Whether to do the cell embedding generation with the scGPT's MVC loss. Defaults to False. mvc_scale ( float , default: 1.0 ) \u2013 Scaling factor for MVC loss. Defaults to 1.0. do_adv_cls ( bool , default: False ) \u2013 Whether to apply adversarial classification during training. Defaults to False. do_generate ( bool , default: True ) \u2013 Whether to do the bottleneck learning task. Defaults to True. class_scale ( float , default: 1.5 ) \u2013 Scaling factor for classification loss. Defaults to 1.5. mask_ratio ( List [ float ] , default: [] ) \u2013 List of mask ratios to apply during training. Defaults to [], meaning no masking is applied during pretraining. warmup_duration ( int , default: 500 ) \u2013 Number of warmup steps for learning rate scheduling. Defaults to 500. fused_adam ( bool , default: False ) \u2013 Whether to use fused Adam optimizer. Defaults to True. adv_class_scale ( float , default: 0.1 ) \u2013 Scaling factor for adversarial classification loss. Defaults to 0.1. lr_reduce_patience ( int , default: 1 ) \u2013 Number of epochs with no improvement after which learning rate will be reduced. Defaults to 1. lr_reduce_factor ( float , default: 0.6 ) \u2013 Factor by which the learning rate will be reduced. Defaults to 0.6. lr_reduce_monitor ( str , default: 'val_loss' ) \u2013 Quantity to be monitored for learning rate reduction. Defaults to \"val_loss\". do_cls ( bool , default: True ) \u2013 Whether to perform classification during training. Defaults to True. do_adv_batch ( bool , default: False ) \u2013 Whether to apply adversarial batch training. Defaults to False. run_full_forward ( bool , default: False ) \u2013 Whether to run a second forward pass without masking or denoising for the bottleneck learning / MVC case. Defaults to False. lr ( float , default: 0.001 ) \u2013 Initial learning rate. Defaults to 0.001. optim ( str , default: 'adamW' ) \u2013 Optimizer to use during training. Defaults to \"adamW\". weight_decay ( float , default: 0.01 ) \u2013 Weight decay to apply during optimization. Defaults to 0.01. name ( str , default: '' ) \u2013 Name of the training mode. Defaults to an empty string. should be an ID for the model Source code in scprint/trainer/trainer.py 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 def __init__ ( self , do_denoise : bool = True , noise : List [ float ] = [ 0.6 ], do_cce : bool = False , cce_sim : float = 0.5 , # .6 cce_scale : float = 0.002 , # .01 do_ecs : bool = False , ecs_threshold : float = 0.3 , ecs_scale : float = 0.05 , # .1 do_mvc : bool = False , mvc_scale : float = 1.0 , do_adv_cls : bool = False , do_next_tp : bool = False , do_generate : bool = True , class_scale : float = 1.5 , mask_ratio : List [ float ] = [], # 0.3 warmup_duration : int = 500 , fused_adam : bool = False , adv_class_scale : float = 0.1 , lr_reduce_patience : int = 1 , lr_reduce_factor : float = 0.6 , lr_reduce_monitor : str = \"val_loss\" , do_cls : bool = True , do_adv_batch : bool = False , run_full_forward : bool = False , lr : float = 0.001 , optim : str = \"adamW\" , weight_decay : float = 0.01 , name = \"\" , ): \"\"\" TrainingMode a callback to set the training specific info to the model. This is because lightning is unfortunately setup this way. the model should be separated from training but at the same time it has training specific methods... so we have to do this. Args: do_denoise (bool): Whether to apply denoising during training. Defaults to True. noise (List[float]): List of noise levels to apply if denoising is enabled. Defaults to [0.6], meaning only one forward path with 60% of the counts being dropped will happen. do_cce (bool): Whether to apply the Contrastive Cell Embedding from scGPT during training. Defaults to False. cce_sim (float): Similarity threshold for CCE. Defaults to 0.5. cce_scale (float): Scaling factor for CCE loss. Defaults to 0.002. do_ecs (bool): Whether to apply the Elastic Cell Similarity loss from scGPT during training. Defaults to False. ecs_threshold (float): Threshold for ECS. Defaults to 0.3. ecs_scale (float): Scaling factor for ECS loss. Defaults to 0.05. do_mvc (bool): Whether to do the cell embedding generation with the scGPT's MVC loss. Defaults to False. mvc_scale (float): Scaling factor for MVC loss. Defaults to 1.0. do_adv_cls (bool): Whether to apply adversarial classification during training. Defaults to False. do_generate (bool): Whether to do the bottleneck learning task. Defaults to True. class_scale (float): Scaling factor for classification loss. Defaults to 1.5. mask_ratio (List[float]): List of mask ratios to apply during training. Defaults to [], meaning no masking is applied during pretraining. warmup_duration (int): Number of warmup steps for learning rate scheduling. Defaults to 500. fused_adam (bool): Whether to use fused Adam optimizer. Defaults to True. adv_class_scale (float): Scaling factor for adversarial classification loss. Defaults to 0.1. lr_reduce_patience (int): Number of epochs with no improvement after which learning rate will be reduced. Defaults to 1. lr_reduce_factor (float): Factor by which the learning rate will be reduced. Defaults to 0.6. lr_reduce_monitor (str): Quantity to be monitored for learning rate reduction. Defaults to \"val_loss\". do_cls (bool): Whether to perform classification during training. Defaults to True. do_adv_batch (bool): Whether to apply adversarial batch training. Defaults to False. run_full_forward (bool): Whether to run a second forward pass without masking or denoising for the bottleneck learning / MVC case. Defaults to False. lr (float): Initial learning rate. Defaults to 0.001. optim (str): Optimizer to use during training. Defaults to \"adamW\". weight_decay (float): Weight decay to apply during optimization. Defaults to 0.01. name (str): Name of the training mode. Defaults to an empty string. should be an ID for the model \"\"\" super () . __init__ () self . do_denoise = do_denoise self . noise = noise self . do_cce = do_cce self . cce_sim = cce_sim self . cce_scale = cce_scale self . do_ecs = do_ecs self . ecs_threshold = ecs_threshold self . ecs_scale = ecs_scale self . do_mvc = do_mvc self . do_adv_cls = do_adv_cls self . do_next_tp = do_next_tp self . do_generate = do_generate self . class_scale = class_scale self . mask_ratio = mask_ratio self . warmup_duration = warmup_duration self . fused_adam = fused_adam self . mvc_scale = mvc_scale self . do_cls = do_cls self . adv_class_scale = adv_class_scale self . lr_reduce_patience = lr_reduce_patience self . lr_reduce_factor = lr_reduce_factor self . lr_reduce_monitor = lr_reduce_monitor self . lr = lr self . optim = optim self . weight_decay = weight_decay self . do_cls = do_cls self . do_adv_batch = do_adv_batch self . run_full_forward = run_full_forward self . name = name","title":"cli"},{"location":"cli/#documentation-for-the-cli-modules","text":"","title":"Documentation for the cli modules"},{"location":"cli/#scprint.__main__","text":"Entry point for scprint.","title":"__main__"},{"location":"cli/#scprint.__main__.MySaveConfig","text":"Bases: SaveConfigCallback MySaveConfig is a subclass of SaveConfigCallback to parametrize the wandb logger further in cli mode","title":"MySaveConfig"},{"location":"cli/#scprint.cli","text":"","title":"cli"},{"location":"cli/#scprint.cli.MyCLI","text":"Bases: LightningCLI MyCLI is a subclass of LightningCLI to add some missing params and create bindings between params of the model and the data. Used to allow calling denoise / embed / gninfer from the command line. Also to add more parameters and link parameters between the scdataloader and the scPRINT model.","title":"MyCLI"},{"location":"cli/#scprint.trainer.trainer","text":"","title":"trainer"},{"location":"cli/#scprint.trainer.trainer.TrainingMode","text":"Bases: Callback TrainingMode a callback to set the training specific info to the model. This is because lightning is unfortunately setup this way. the model should be separated from training but at the same time it has training specific methods... so we have to do this. Parameters: do_denoise ( bool , default: True ) \u2013 Whether to apply denoising during training. Defaults to True. noise ( List [ float ] , default: [0.6] ) \u2013 List of noise levels to apply if denoising is enabled. Defaults to [0.6], meaning only one forward path with 60% of the counts being dropped will happen. do_cce ( bool , default: False ) \u2013 Whether to apply the Contrastive Cell Embedding from scGPT during training. Defaults to False. cce_sim ( float , default: 0.5 ) \u2013 Similarity threshold for CCE. Defaults to 0.5. cce_scale ( float , default: 0.002 ) \u2013 Scaling factor for CCE loss. Defaults to 0.002. do_ecs ( bool , default: False ) \u2013 Whether to apply the Elastic Cell Similarity loss from scGPT during training. Defaults to False. ecs_threshold ( float , default: 0.3 ) \u2013 Threshold for ECS. Defaults to 0.3. ecs_scale ( float , default: 0.05 ) \u2013 Scaling factor for ECS loss. Defaults to 0.05. do_mvc ( bool , default: False ) \u2013 Whether to do the cell embedding generation with the scGPT's MVC loss. Defaults to False. mvc_scale ( float , default: 1.0 ) \u2013 Scaling factor for MVC loss. Defaults to 1.0. do_adv_cls ( bool , default: False ) \u2013 Whether to apply adversarial classification during training. Defaults to False. do_generate ( bool , default: True ) \u2013 Whether to do the bottleneck learning task. Defaults to True. class_scale ( float , default: 1.5 ) \u2013 Scaling factor for classification loss. Defaults to 1.5. mask_ratio ( List [ float ] , default: [] ) \u2013 List of mask ratios to apply during training. Defaults to [], meaning no masking is applied during pretraining. warmup_duration ( int , default: 500 ) \u2013 Number of warmup steps for learning rate scheduling. Defaults to 500. fused_adam ( bool , default: False ) \u2013 Whether to use fused Adam optimizer. Defaults to True. adv_class_scale ( float , default: 0.1 ) \u2013 Scaling factor for adversarial classification loss. Defaults to 0.1. lr_reduce_patience ( int , default: 1 ) \u2013 Number of epochs with no improvement after which learning rate will be reduced. Defaults to 1. lr_reduce_factor ( float , default: 0.6 ) \u2013 Factor by which the learning rate will be reduced. Defaults to 0.6. lr_reduce_monitor ( str , default: 'val_loss' ) \u2013 Quantity to be monitored for learning rate reduction. Defaults to \"val_loss\". do_cls ( bool , default: True ) \u2013 Whether to perform classification during training. Defaults to True. do_adv_batch ( bool , default: False ) \u2013 Whether to apply adversarial batch training. Defaults to False. run_full_forward ( bool , default: False ) \u2013 Whether to run a second forward pass without masking or denoising for the bottleneck learning / MVC case. Defaults to False. lr ( float , default: 0.001 ) \u2013 Initial learning rate. Defaults to 0.001. optim ( str , default: 'adamW' ) \u2013 Optimizer to use during training. Defaults to \"adamW\". weight_decay ( float , default: 0.01 ) \u2013 Weight decay to apply during optimization. Defaults to 0.01. name ( str , default: '' ) \u2013 Name of the training mode. Defaults to an empty string. should be an ID for the model Source code in scprint/trainer/trainer.py 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 def __init__ ( self , do_denoise : bool = True , noise : List [ float ] = [ 0.6 ], do_cce : bool = False , cce_sim : float = 0.5 , # .6 cce_scale : float = 0.002 , # .01 do_ecs : bool = False , ecs_threshold : float = 0.3 , ecs_scale : float = 0.05 , # .1 do_mvc : bool = False , mvc_scale : float = 1.0 , do_adv_cls : bool = False , do_next_tp : bool = False , do_generate : bool = True , class_scale : float = 1.5 , mask_ratio : List [ float ] = [], # 0.3 warmup_duration : int = 500 , fused_adam : bool = False , adv_class_scale : float = 0.1 , lr_reduce_patience : int = 1 , lr_reduce_factor : float = 0.6 , lr_reduce_monitor : str = \"val_loss\" , do_cls : bool = True , do_adv_batch : bool = False , run_full_forward : bool = False , lr : float = 0.001 , optim : str = \"adamW\" , weight_decay : float = 0.01 , name = \"\" , ): \"\"\" TrainingMode a callback to set the training specific info to the model. This is because lightning is unfortunately setup this way. the model should be separated from training but at the same time it has training specific methods... so we have to do this. Args: do_denoise (bool): Whether to apply denoising during training. Defaults to True. noise (List[float]): List of noise levels to apply if denoising is enabled. Defaults to [0.6], meaning only one forward path with 60% of the counts being dropped will happen. do_cce (bool): Whether to apply the Contrastive Cell Embedding from scGPT during training. Defaults to False. cce_sim (float): Similarity threshold for CCE. Defaults to 0.5. cce_scale (float): Scaling factor for CCE loss. Defaults to 0.002. do_ecs (bool): Whether to apply the Elastic Cell Similarity loss from scGPT during training. Defaults to False. ecs_threshold (float): Threshold for ECS. Defaults to 0.3. ecs_scale (float): Scaling factor for ECS loss. Defaults to 0.05. do_mvc (bool): Whether to do the cell embedding generation with the scGPT's MVC loss. Defaults to False. mvc_scale (float): Scaling factor for MVC loss. Defaults to 1.0. do_adv_cls (bool): Whether to apply adversarial classification during training. Defaults to False. do_generate (bool): Whether to do the bottleneck learning task. Defaults to True. class_scale (float): Scaling factor for classification loss. Defaults to 1.5. mask_ratio (List[float]): List of mask ratios to apply during training. Defaults to [], meaning no masking is applied during pretraining. warmup_duration (int): Number of warmup steps for learning rate scheduling. Defaults to 500. fused_adam (bool): Whether to use fused Adam optimizer. Defaults to True. adv_class_scale (float): Scaling factor for adversarial classification loss. Defaults to 0.1. lr_reduce_patience (int): Number of epochs with no improvement after which learning rate will be reduced. Defaults to 1. lr_reduce_factor (float): Factor by which the learning rate will be reduced. Defaults to 0.6. lr_reduce_monitor (str): Quantity to be monitored for learning rate reduction. Defaults to \"val_loss\". do_cls (bool): Whether to perform classification during training. Defaults to True. do_adv_batch (bool): Whether to apply adversarial batch training. Defaults to False. run_full_forward (bool): Whether to run a second forward pass without masking or denoising for the bottleneck learning / MVC case. Defaults to False. lr (float): Initial learning rate. Defaults to 0.001. optim (str): Optimizer to use during training. Defaults to \"adamW\". weight_decay (float): Weight decay to apply during optimization. Defaults to 0.01. name (str): Name of the training mode. Defaults to an empty string. should be an ID for the model \"\"\" super () . __init__ () self . do_denoise = do_denoise self . noise = noise self . do_cce = do_cce self . cce_sim = cce_sim self . cce_scale = cce_scale self . do_ecs = do_ecs self . ecs_threshold = ecs_threshold self . ecs_scale = ecs_scale self . do_mvc = do_mvc self . do_adv_cls = do_adv_cls self . do_next_tp = do_next_tp self . do_generate = do_generate self . class_scale = class_scale self . mask_ratio = mask_ratio self . warmup_duration = warmup_duration self . fused_adam = fused_adam self . mvc_scale = mvc_scale self . do_cls = do_cls self . adv_class_scale = adv_class_scale self . lr_reduce_patience = lr_reduce_patience self . lr_reduce_factor = lr_reduce_factor self . lr_reduce_monitor = lr_reduce_monitor self . lr = lr self . optim = optim self . weight_decay = weight_decay self . do_cls = do_cls self . do_adv_batch = do_adv_batch self . run_full_forward = run_full_forward self . name = name","title":"TrainingMode"},{"location":"embedder/","text":"Documentation for the tokenizers module scprint.tokenizers.protein_embedder PROTBERT PROTBERT a ghost class to call protein LLMs to encode protein sequences. Parameters: config ( str , default: 'esm-extract' ) \u2013 The configuration for the model. Defaults to \"esm-extract\". pretrained_model ( str , default: 'esm2_t33_650M_UR50D' ) \u2013 The pretrained model to be used. Defaults to \"esm2_t33_650M_UR50D\". Source code in scprint/tokenizers/protein_embedder.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def __init__ ( self , config : str = \"esm-extract\" , pretrained_model : str = \"esm2_t33_650M_UR50D\" , ): \"\"\" PROTBERT a ghost class to call protein LLMs to encode protein sequences. Args: config (str, optional): The configuration for the model. Defaults to \"esm-extract\". pretrained_model (str, optional): The pretrained model to be used. Defaults to \"esm2_t33_650M_UR50D\". \"\"\" self . config = config self . pretrained_model = pretrained_model __call__ Call the PROTBERT model on the input file. Parameters: input_file ( str ) \u2013 The input file to be processed. output_folder ( str , default: '/tmp/esm_out/' ) \u2013 The folder where the output will be stored. Defaults to \"/tmp/esm_out/\". cache ( bool , default: True ) \u2013 If True, use cached data if available. Defaults to True. Returns: DataFrame \u2013 pd.DataFrame: The results of the model as a DataFrame. Source code in scprint/tokenizers/protein_embedder.py 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 def __call__ ( self , input_file : str , output_folder : str = \"/tmp/esm_out/\" , cache : bool = True ) -> pd . DataFrame : \"\"\" Call the PROTBERT model on the input file. Args: input_file (str): The input file to be processed. output_folder (str, optional): The folder where the output will be stored. Defaults to \"/tmp/esm_out/\". cache (bool, optional): If True, use cached data if available. Defaults to True. Returns: pd.DataFrame: The results of the model as a DataFrame. \"\"\" if not os . path . exists ( output_folder ) or not cache : os . makedirs ( output_folder , exist_ok = True ) print ( \"running protbert\" ) cmd = ( self . config + \" \" + self . pretrained_model + \" \" + input_file + \" \" + output_folder + \" --include mean\" ) try : run_command ( cmd , shell = True ) except Exception as e : raise RuntimeError ( \"An error occurred while running the esm-extract command: \" + str ( e ) ) return self . read_results ( output_folder ) read_results Read multiple .pt files in a folder and convert them into a DataFrame. Parameters: output_folder ( str ) \u2013 The folder where the .pt files are stored. Returns: \u2013 pd.DataFrame: The results of the model as a DataFrame. Source code in scprint/tokenizers/protein_embedder.py 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 def read_results ( self , output_folder ): \"\"\" Read multiple .pt files in a folder and convert them into a DataFrame. Args: output_folder (str): The folder where the .pt files are stored. Returns: pd.DataFrame: The results of the model as a DataFrame. \"\"\" files = os . listdir ( output_folder ) files = [ i for i in files if i . endswith ( \".pt\" )] results = [] for file in files : results . append ( load ( output_folder + file )[ \"mean_representations\" ][ 33 ] . numpy () . tolist () ) return pd . DataFrame ( data = results , index = [ file . split ( \".\" )[ 0 ] for file in files ]) scprint.tokenizers.embedder protein_embeddings_generator protein_embeddings_generator embed a set of genes using fasta file and LLMs Parameters: genedf ( DataFrame ) \u2013 A DataFrame containing gene information. organism ( str , default: 'homo_sapiens' ) \u2013 The organism to which the genes belong. Defaults to \"homo_sapiens\". cache ( bool , default: True ) \u2013 If True, the function will use cached data if available. Defaults to True. fasta_path ( str , default: '/tmp/data/fasta/' ) \u2013 The path to the directory where the fasta files are stored. Defaults to \"/tmp/data/fasta/\". embedding_size ( int , default: 512 ) \u2013 The size of the embeddings to be generated. Defaults to 512. Returns: \u2013 pd.DataFrame: Returns a DataFrame containing the protein embeddings, and the RNA embeddings. Source code in scprint/tokenizers/embedder.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 def protein_embeddings_generator ( genedf : pd . DataFrame , organism : str = \"homo_sapiens\" , # mus_musculus, cache : bool = True , fasta_path : str = \"/tmp/data/fasta/\" , embedding_size : int = 512 , ): \"\"\" protein_embeddings_generator embed a set of genes using fasta file and LLMs Args: genedf (pd.DataFrame): A DataFrame containing gene information. organism (str, optional): The organism to which the genes belong. Defaults to \"homo_sapiens\". cache (bool, optional): If True, the function will use cached data if available. Defaults to True. fasta_path (str, optional): The path to the directory where the fasta files are stored. Defaults to \"/tmp/data/fasta/\". embedding_size (int, optional): The size of the embeddings to be generated. Defaults to 512. Returns: pd.DataFrame: Returns a DataFrame containing the protein embeddings, and the RNA embeddings. \"\"\" # given a gene file and organism # load the organism fasta if not already done utils . load_fasta_species ( species = organism , output_path = fasta_path , cache = cache ) # subset the fasta fasta_file = next ( file for file in os . listdir ( fasta_path ) if file . endswith ( \".all.fa.gz\" ) ) protgenedf = genedf [ genedf [ \"biotype\" ] == \"protein_coding\" ] utils . utils . run_command ([ \"gunzip\" , fasta_path + fasta_file ]) utils . subset_fasta ( protgenedf . index . tolist (), subfasta_path = fasta_path + \"subset.fa\" , fasta_path = fasta_path + fasta_file [: - 3 ], drop_unknown_seq = True , ) # subset the gene file # embed prot_embedder = PROTBERT () prot_embeddings = prot_embedder ( fasta_path + \"subset.fa\" , output_folder = fasta_path + \"esm_out/\" , cache = cache ) # load the data and erase / zip the rest utils . utils . run_command ([ \"gzip\" , fasta_path + fasta_file [: - 3 ]]) # return the embedding and gene file # TODO: to redebug # do the same for RNA # rnagenedf = genedf[genedf[\"biotype\"] != \"protein_coding\"] # fasta_file = next( # file for file in os.listdir(fasta_path) if file.endswith(\".ncrna.fa.gz\") # ) # utils.utils.run_command([\"gunzip\", fasta_path + fasta_file]) # utils.subset_fasta( # rnagenedf[\"ensembl_gene_id\"].tolist(), # subfasta_path=fasta_path + \"subset.ncrna.fa\", # fasta_path=fasta_path + fasta_file[:-3], # drop_unknown_seq=True, # ) # rna_embedder = RNABERT() # rna_embeddings = rna_embedder(fasta_path + \"subset.ncrna.fa\") ## Check if the sizes of the cembeddings are not the same # utils.utils.run_command([\"gzip\", fasta_path + fasta_file[:-3]]) # m = AdaptiveAvgPool1d ( embedding_size ) prot_embeddings = pd . DataFrame ( data = m ( torch . tensor ( prot_embeddings . values )), index = prot_embeddings . index ) # rna_embeddings = pd.DataFrame( # data=m(torch.tensor(rna_embeddings.values)), index=rna_embeddings.index # ) # Concatenate the embeddings return prot_embeddings # pd.concat([prot_embeddings, rna_embeddings])","title":"embedders"},{"location":"embedder/#documentation-for-the-tokenizers-module","text":"","title":"Documentation for the tokenizers module"},{"location":"embedder/#scprint.tokenizers.protein_embedder","text":"","title":"protein_embedder"},{"location":"embedder/#scprint.tokenizers.protein_embedder.PROTBERT","text":"PROTBERT a ghost class to call protein LLMs to encode protein sequences. Parameters: config ( str , default: 'esm-extract' ) \u2013 The configuration for the model. Defaults to \"esm-extract\". pretrained_model ( str , default: 'esm2_t33_650M_UR50D' ) \u2013 The pretrained model to be used. Defaults to \"esm2_t33_650M_UR50D\". Source code in scprint/tokenizers/protein_embedder.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def __init__ ( self , config : str = \"esm-extract\" , pretrained_model : str = \"esm2_t33_650M_UR50D\" , ): \"\"\" PROTBERT a ghost class to call protein LLMs to encode protein sequences. Args: config (str, optional): The configuration for the model. Defaults to \"esm-extract\". pretrained_model (str, optional): The pretrained model to be used. Defaults to \"esm2_t33_650M_UR50D\". \"\"\" self . config = config self . pretrained_model = pretrained_model","title":"PROTBERT"},{"location":"embedder/#scprint.tokenizers.protein_embedder.PROTBERT.__call__","text":"Call the PROTBERT model on the input file. Parameters: input_file ( str ) \u2013 The input file to be processed. output_folder ( str , default: '/tmp/esm_out/' ) \u2013 The folder where the output will be stored. Defaults to \"/tmp/esm_out/\". cache ( bool , default: True ) \u2013 If True, use cached data if available. Defaults to True. Returns: DataFrame \u2013 pd.DataFrame: The results of the model as a DataFrame. Source code in scprint/tokenizers/protein_embedder.py 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 def __call__ ( self , input_file : str , output_folder : str = \"/tmp/esm_out/\" , cache : bool = True ) -> pd . DataFrame : \"\"\" Call the PROTBERT model on the input file. Args: input_file (str): The input file to be processed. output_folder (str, optional): The folder where the output will be stored. Defaults to \"/tmp/esm_out/\". cache (bool, optional): If True, use cached data if available. Defaults to True. Returns: pd.DataFrame: The results of the model as a DataFrame. \"\"\" if not os . path . exists ( output_folder ) or not cache : os . makedirs ( output_folder , exist_ok = True ) print ( \"running protbert\" ) cmd = ( self . config + \" \" + self . pretrained_model + \" \" + input_file + \" \" + output_folder + \" --include mean\" ) try : run_command ( cmd , shell = True ) except Exception as e : raise RuntimeError ( \"An error occurred while running the esm-extract command: \" + str ( e ) ) return self . read_results ( output_folder )","title":"__call__"},{"location":"embedder/#scprint.tokenizers.protein_embedder.PROTBERT.read_results","text":"Read multiple .pt files in a folder and convert them into a DataFrame. Parameters: output_folder ( str ) \u2013 The folder where the .pt files are stored. Returns: \u2013 pd.DataFrame: The results of the model as a DataFrame. Source code in scprint/tokenizers/protein_embedder.py 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 def read_results ( self , output_folder ): \"\"\" Read multiple .pt files in a folder and convert them into a DataFrame. Args: output_folder (str): The folder where the .pt files are stored. Returns: pd.DataFrame: The results of the model as a DataFrame. \"\"\" files = os . listdir ( output_folder ) files = [ i for i in files if i . endswith ( \".pt\" )] results = [] for file in files : results . append ( load ( output_folder + file )[ \"mean_representations\" ][ 33 ] . numpy () . tolist () ) return pd . DataFrame ( data = results , index = [ file . split ( \".\" )[ 0 ] for file in files ])","title":"read_results"},{"location":"embedder/#scprint.tokenizers.embedder","text":"","title":"embedder"},{"location":"embedder/#scprint.tokenizers.embedder.protein_embeddings_generator","text":"protein_embeddings_generator embed a set of genes using fasta file and LLMs Parameters: genedf ( DataFrame ) \u2013 A DataFrame containing gene information. organism ( str , default: 'homo_sapiens' ) \u2013 The organism to which the genes belong. Defaults to \"homo_sapiens\". cache ( bool , default: True ) \u2013 If True, the function will use cached data if available. Defaults to True. fasta_path ( str , default: '/tmp/data/fasta/' ) \u2013 The path to the directory where the fasta files are stored. Defaults to \"/tmp/data/fasta/\". embedding_size ( int , default: 512 ) \u2013 The size of the embeddings to be generated. Defaults to 512. Returns: \u2013 pd.DataFrame: Returns a DataFrame containing the protein embeddings, and the RNA embeddings. Source code in scprint/tokenizers/embedder.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 def protein_embeddings_generator ( genedf : pd . DataFrame , organism : str = \"homo_sapiens\" , # mus_musculus, cache : bool = True , fasta_path : str = \"/tmp/data/fasta/\" , embedding_size : int = 512 , ): \"\"\" protein_embeddings_generator embed a set of genes using fasta file and LLMs Args: genedf (pd.DataFrame): A DataFrame containing gene information. organism (str, optional): The organism to which the genes belong. Defaults to \"homo_sapiens\". cache (bool, optional): If True, the function will use cached data if available. Defaults to True. fasta_path (str, optional): The path to the directory where the fasta files are stored. Defaults to \"/tmp/data/fasta/\". embedding_size (int, optional): The size of the embeddings to be generated. Defaults to 512. Returns: pd.DataFrame: Returns a DataFrame containing the protein embeddings, and the RNA embeddings. \"\"\" # given a gene file and organism # load the organism fasta if not already done utils . load_fasta_species ( species = organism , output_path = fasta_path , cache = cache ) # subset the fasta fasta_file = next ( file for file in os . listdir ( fasta_path ) if file . endswith ( \".all.fa.gz\" ) ) protgenedf = genedf [ genedf [ \"biotype\" ] == \"protein_coding\" ] utils . utils . run_command ([ \"gunzip\" , fasta_path + fasta_file ]) utils . subset_fasta ( protgenedf . index . tolist (), subfasta_path = fasta_path + \"subset.fa\" , fasta_path = fasta_path + fasta_file [: - 3 ], drop_unknown_seq = True , ) # subset the gene file # embed prot_embedder = PROTBERT () prot_embeddings = prot_embedder ( fasta_path + \"subset.fa\" , output_folder = fasta_path + \"esm_out/\" , cache = cache ) # load the data and erase / zip the rest utils . utils . run_command ([ \"gzip\" , fasta_path + fasta_file [: - 3 ]]) # return the embedding and gene file # TODO: to redebug # do the same for RNA # rnagenedf = genedf[genedf[\"biotype\"] != \"protein_coding\"] # fasta_file = next( # file for file in os.listdir(fasta_path) if file.endswith(\".ncrna.fa.gz\") # ) # utils.utils.run_command([\"gunzip\", fasta_path + fasta_file]) # utils.subset_fasta( # rnagenedf[\"ensembl_gene_id\"].tolist(), # subfasta_path=fasta_path + \"subset.ncrna.fa\", # fasta_path=fasta_path + fasta_file[:-3], # drop_unknown_seq=True, # ) # rna_embedder = RNABERT() # rna_embeddings = rna_embedder(fasta_path + \"subset.ncrna.fa\") ## Check if the sizes of the cembeddings are not the same # utils.utils.run_command([\"gzip\", fasta_path + fasta_file[:-3]]) # m = AdaptiveAvgPool1d ( embedding_size ) prot_embeddings = pd . DataFrame ( data = m ( torch . tensor ( prot_embeddings . values )), index = prot_embeddings . index ) # rna_embeddings = pd.DataFrame( # data=m(torch.tensor(rna_embeddings.values)), index=rna_embeddings.index # ) # Concatenate the embeddings return prot_embeddings # pd.concat([prot_embeddings, rna_embeddings])","title":"protein_embeddings_generator"},{"location":"model/","text":"Documentation for the model model description scprint.model.model scPrint Bases: LightningModule , PyTorchModelHubMixin scPRINT transformer for single cell biology and the inference of Gene Regulatory networks Parameters: genes ( list ) \u2013 List of gene names the model will work with. precpt_gene_emb ( array , default: None ) \u2013 Gene embeddings of size (len(genes), d_model). Should be in the same order as the genes. Defaults to None. gene_pos_enc ( list , default: None ) \u2013 Gene position encoding of the same size as genes. Provides a location value for each gene in genes. Defaults to None. d_model ( int , default: 512 ) \u2013 Dimension of the model. Defaults to 512. nhead ( int , default: 8 ) \u2013 Number of heads in the multihead attention models. Defaults to 8. d_hid ( int , default: 512 ) \u2013 Dimension of the feedforward network model. Defaults to 512. nlayers ( int , default: 6 ) \u2013 Number of layers in the transformer model. Defaults to 6. expr_encoder_layers ( int , default: 2 ) \u2013 Number of layers in the expression encoder. Defaults to 2. layers_cls ( list [ int ] , default: [] ) \u2013 List specifying the number of layers in the classifier. Defaults to []. classes ( Dict [ str , int ] , default: {} ) \u2013 Classes to predict with the number of classes for each. Defaults to {}. labels_hierarchy ( Dict [ str , Dict [ int , list [ int ]]] , default: {} ) \u2013 Class hierarchy for classes with hierarchical classes. Defaults to {}. dropout ( float , default: 0.2 ) \u2013 Dropout value. Defaults to 0.2. transformer ( str , default: 'fast' ) \u2013 Transformer type to use. One of \"linear\", \"flash\", \"flashsparse\", \"scprint\". Defaults to \"fast\". domain_spec_batchnorm ( str , default: 'None' ) \u2013 Whether to apply domain-specific batch normalization. Defaults to \"None\". expr_emb_style ( str , default: 'continuous' ) \u2013 Style of input embedding. One of \"continuous\", \"binned_pos\", \"cont_pos\". Defaults to \"continuous\". mvc_decoder ( str , default: 'None' ) \u2013 Style of MVC decoder. One of \"None\", \"inner product\", \"concat query\", \"sum query\". Defaults to \"None\". pred_embedding ( list [ str ] , default: [] ) \u2013 List of classes to use for plotting embeddings. Defaults to []. cell_emb_style ( str , default: 'cls' ) \u2013 Style of cell embedding. One of \"cls\", \"avg-pool\", \"w-pool\". Defaults to \"cls\". freeze_embeddings ( bool , default: True ) \u2013 Whether to freeze the embeddings during training. Defaults to True. label_decoders ( Optional [ Dict [ str , Dict [ int , str ]]] , default: None ) \u2013 Label decoders to use for plotting the UMAP during validations. Defaults to None. zinb ( bool , default: True ) \u2013 Whether to use Zero-Inflated Negative Binomial distribution. Defaults to True. lr ( float , default: 0.0001 ) \u2013 Learning rate. Defaults to 0.0001. optim ( str , default: 'adamW' ) \u2013 Optimizer type. Defaults to \"adamW\". weight_decay ( float , default: 0.01 ) \u2013 Weight decay for the optimizer. Defaults to 0.01. **flash_attention_kwargs ( dict , default: {} ) \u2013 Additional keyword arguments for the model. see @flashformer.py Notes for other parameters of the model that are not part of its class definition, see @trainer.trainer.py Raises: ValueError \u2013 If the expr_emb_style is not one of \"continuous\", \"binned_pos\", \"cont_pos\". Source code in scprint/model/model.py 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 def __init__ ( self , genes : list , organisms : list = [ \"NCBITaxon:9606\" ], precpt_gene_emb : Optional [ str ] = None , gene_pos_enc : Optional [ list ] = None , normalization : str = \"sum\" , d_model : int = 512 , nhead : int = 8 , attn_bias : str = \"none\" , d_hid : int = 512 , edge_dim : int = 12 , nlayers : int = 6 , expr_encoder_layers : int = 2 , layers_cls : list [ int ] = [], classes : Dict [ str , int ] = {}, labels_hierarchy : Dict [ str , Dict [ int , list [ int ]]] = {}, dropout : float = 0.2 , transformer : str = \"fast\" , expr_emb_style : str = \"continuous\" , # \"binned_pos\", \"cont_pos\" domain_spec_batchnorm : str = \"None\" , n_input_bins : int = 0 , num_batch_labels : int = 0 , mvc_decoder : str = \"None\" , pred_embedding : list [ str ] = [], cell_emb_style : str = \"cls\" , freeze_embeddings : bool = True , label_decoders : Optional [ Dict [ str , Dict [ int , str ]]] = None , zinb : bool = True , lr : float = 0.0001 , optim = \"adamW\" , # TODEL weight_decay = 0.01 , # TODEL ** flash_attention_kwargs , ): \"\"\" scPRINT transformer for single cell biology and the inference of Gene Regulatory networks Args: genes (list): List of gene names the model will work with. precpt_gene_emb (np.array, optional): Gene embeddings of size (len(genes), d_model). Should be in the same order as the genes. Defaults to None. gene_pos_enc (list, optional): Gene position encoding of the same size as genes. Provides a location value for each gene in genes. Defaults to None. d_model (int, optional): Dimension of the model. Defaults to 512. nhead (int, optional): Number of heads in the multihead attention models. Defaults to 8. d_hid (int, optional): Dimension of the feedforward network model. Defaults to 512. nlayers (int, optional): Number of layers in the transformer model. Defaults to 6. expr_encoder_layers (int, optional): Number of layers in the expression encoder. Defaults to 2. layers_cls (list[int], optional): List specifying the number of layers in the classifier. Defaults to []. classes (Dict[str, int], optional): Classes to predict with the number of classes for each. Defaults to {}. labels_hierarchy (Dict[str, Dict[int, list[int]]], optional): Class hierarchy for classes with hierarchical classes. Defaults to {}. dropout (float, optional): Dropout value. Defaults to 0.2. transformer (str, optional): Transformer type to use. One of \"linear\", \"flash\", \"flashsparse\", \"scprint\". Defaults to \"fast\". domain_spec_batchnorm (str, optional): Whether to apply domain-specific batch normalization. Defaults to \"None\". expr_emb_style (str, optional): Style of input embedding. One of \"continuous\", \"binned_pos\", \"cont_pos\". Defaults to \"continuous\". mvc_decoder (str, optional): Style of MVC decoder. One of \"None\", \"inner product\", \"concat query\", \"sum query\". Defaults to \"None\". pred_embedding (list[str], optional): List of classes to use for plotting embeddings. Defaults to []. cell_emb_style (str, optional): Style of cell embedding. One of \"cls\", \"avg-pool\", \"w-pool\". Defaults to \"cls\". freeze_embeddings (bool, optional): Whether to freeze the embeddings during training. Defaults to True. label_decoders (Optional[Dict[str, Dict[int, str]]], optional): Label decoders to use for plotting the UMAP during validations. Defaults to None. zinb (bool, optional): Whether to use Zero-Inflated Negative Binomial distribution. Defaults to True. lr (float, optional): Learning rate. Defaults to 0.0001. optim (str, optional): Optimizer type. Defaults to \"adamW\". weight_decay (float, optional): Weight decay for the optimizer. Defaults to 0.01. **flash_attention_kwargs (dict): Additional keyword arguments for the model. see @flashformer.py Notes: for other parameters of the model that are not part of its class definition, see @trainer.trainer.py Raises: ValueError: If the expr_emb_style is not one of \"continuous\", \"binned_pos\", \"cont_pos\". \"\"\" super () . __init__ () # training flags self . do_denoise = True self . noise = [ 0.6 ] self . do_cce = False self . cce_sim = 0.5 self . cce_scale = 0.002 self . do_ecs = False self . ecs_threshold = 0.3 self . ecs_scale = 0.05 self . do_mvc = False self . mvc_scale = 1.0 self . class_embd_diss_scale = 0.2 self . do_adv_cls = False self . adv_class_scale = 0.1 self . do_cls = False self . mean_attn_tot = None self . mean_attn_tot_c = 0 self . do_adv_batch = False self . run_full_forward = True self . class_scale = 0.4 self . do_next_tp = False self . do_generate = False self . mask_ratio = [] self . warmup_duration = 500 self . weight_decay = 0.01 self . optim = \"adamW\" self . fused_adam = False self . lr_reduce_patience = 1 self . lr_reduce_factor = 0.6 self . lr_reduce_monitor = \"val_loss\" self . name = \"\" self . lr = lr self . lrfinder_steps = 0 self . doplot = True self . get_attention_layer = [] self . embs = None self . pred_log_adata = True self . attn = utils . Attention ( len ( classes ) + 2 + len ( genes )) self . predict_depth_mult = 3 self . predict_mode = \"none\" self . keep_all_cls_pred = False # should be stored somehow self . d_model = d_model self . normalization = normalization self . organisms = organisms self . edge_dim = edge_dim self . attn_bias = attn_bias self . nlayers = nlayers self . gene_pos_enc = gene_pos_enc self . mvc_decoder = mvc_decoder self . domain_spec_batchnorm = domain_spec_batchnorm # need to store self . n_input_bins = n_input_bins self . transformer = transformer self . label_counts = classes self . classes = list ( classes . keys ()) self . cell_emb_style = cell_emb_style self . label_decoders = label_decoders self . pred_embedding = pred_embedding # compute tensor for mat_labels_hierarchy self . mat_labels_hierarchy = {} self . labels_hierarchy = labels_hierarchy if \"strict_loading\" in flash_attention_kwargs : flash_attention_kwargs . pop ( \"strict_loading\" ) for k , v in labels_hierarchy . items (): tens = torch . zeros (( len ( v ), classes [ k ])) for k2 , v2 in v . items (): tens [ k2 - classes [ k ], v2 ] = 1 self . mat_labels_hierarchy [ k ] = tens . to ( bool ) self . expr_emb_style = expr_emb_style if self . expr_emb_style not in [ \"category\" , \"continuous\" , \"none\" ]: raise ValueError ( f \"expr_emb_style should be one of category, continuous, scaling, \" f \"got { expr_emb_style } \" ) if cell_emb_style not in [ \"cls\" , \"avg-pool\" , \"w-pool\" ]: raise ValueError ( f \"Unknown cell_emb_style: { cell_emb_style } \" ) self . genes = genes self . vocab = { i : n for i , n in enumerate ( genes )} # encoder # gene encoder if precpt_gene_emb is not None : embeddings = pd . read_parquet ( precpt_gene_emb ) . loc [ self . genes ] if len ( embeddings ) == 0 : raise ValueError ( f \"the gene embeddings file { precpt_gene_emb } does not contain any of the genes given to the model\" ) elif len ( embeddings ) < len ( self . genes ): print ( \"Warning: only a subset of the genes available in the embeddings file.\" ) print ( \"number of genes: \" , len ( embeddings )) sembeddings = torch . nn . AdaptiveAvgPool1d ( d_model )( torch . tensor ( embeddings . values ) ) self . gene_encoder = encoders . GeneEncoder ( len ( self . vocab ), d_model , weights = sembeddings , freeze = freeze_embeddings ) else : self . gene_encoder = encoders . GeneEncoder ( len ( self . vocab ), d_model ) # Value Encoder, NOTE: the scaling style is also handled in _encode method if expr_emb_style in [ \"continuous\" , \"full_pos\" ]: self . expr_encoder = encoders . ContinuousValueEncoder ( d_model , dropout , layers = expr_encoder_layers ) elif expr_emb_style == \"binned_pos\" : assert n_input_bins > 0 self . expr_encoder = encoders . CategoryValueEncoder ( n_input_bins , d_model ) else : self . expr_encoder = torch . nn . Identity () # Positional Encoding if self . gene_pos_enc is not None : max_len = max ( gene_pos_enc ) token_to_pos = { token : pos for token , pos in enumerate ( self . gene_pos_enc )} self . pos_encoder = encoders . PositionalEncoding ( d_model , max_len = max_len , token_to_pos = token_to_pos ) self . cell_embs_count = len ( self . classes ) + 2 # Class Encoder # always have [base_cell_emb, time_embedding, depth_embedding] + any other class info # base cell embedding will store other cell specific information self . class_encoder = encoders . CategoryValueEncoder ( self . cell_embs_count - 1 , d_model ) # self.time_encoder = encoders.ContinuousValueEncoder(d_model, dropout) self . depth_encoder = encoders . ContinuousValueEncoder ( d_model , dropout , layers = expr_encoder_layers ) # Transformer # Linear if transformer == \"linear\" : # linear transformer using the fast transformer package # self.transformer = FastTransformerEncoder( # d_model, nhead, d_hid, nlayers, dropout, \"linear\" # ) raise NotImplementedError ( \"Linear transformer is not implemented\" ) # regular or flash else : self . transformer = FlashTransformerEncoder ( d_model , nhead , nlayers , dropout = dropout , use_flash_attn = ( transformer == \"flash\" ), ** flash_attention_kwargs , ) # decoders # expression self . expr_decoder = decoders . ExprDecoder ( d_model , nfirst_tokens_to_skip = self . cell_embs_count , dropout = dropout , zinb = zinb , ) # cls decoder self . cls_decoders = torch . nn . ModuleDict () # should be a very simple classifier for most things # (maybe scale with the number of classes) should be 1 layer... for clss , n_cls in classes . items (): self . cls_decoders [ clss ] = decoders . ClsDecoder ( d_model , n_cls , layers = layers_cls , dropout = dropout ) # Batch effect correction via adversarial training on batch classes if num_batch_labels > 0 : self . grad_reverse_discriminator_loss = loss . AdversarialDiscriminatorLoss ( d_model , n_cls = num_batch_labels , ) else : self . grad_reverse_discriminator_loss = None # expression decoder from batch embbedding if mvc_decoder != \"None\" : self . mvc_decoder = decoders . MVCDecoder ( d_model , arch_style = mvc_decoder , ) else : self . mvc_decoder = None self . apply ( partial ( utils . _init_weights , n_layer = nlayers , ) ) for i , dec in self . cls_decoders . items (): torch . nn . init . constant_ ( dec . out_layer . bias , - 0.13 ) self . save_hyperparameters () configure_optimizers @see pl.LightningModule Source code in scprint/model/model.py 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 def configure_optimizers ( self ): \"\"\"@see pl.LightningModule\"\"\" # https://pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam # not working because of poor weight decay implem if self . optim == \"adam\" : optimizer = optim . Adam ( self . parameters (), lr = self . hparams . lr , betas = ( 0.9 , 0.999 ), eps = 1e-08 , weight_decay = self . weight_decay , amsgrad = False , fused = self . fused_adam , ) elif self . optim == \"adamW\" : optimizer = optim . AdamW ( self . parameters (), lr = self . hparams . lr , betas = ( 0.9 , 0.999 ), eps = 1e-08 , weight_decay = self . weight_decay , amsgrad = False , fused = self . fused_adam , ) elif self . optim == \"galore\" : raise NotImplementedError ( \"Galore optimizer not implemented\" ) param_groups = [ { \"params\" : [ v for k , v in self . named_parameters () if \"transformer\" not in k ] }, { \"params\" : [ v for k , v in self . named_parameters () if \"transformer\" in k ], \"rank\" : 128 , \"update_proj_gap\" : 200 , \"scale\" : 0.25 , \"proj_type\" : \"std\" , }, ] # optimizer = GaLoreAdamW(param_groups, lr=self.hparams.lr) else : raise ValueError ( f \"Unknown optimizer: { self . optim } \" ) lr_scheduler = optim . lr_scheduler . ReduceLROnPlateau ( optimizer , mode = \"min\" , patience = self . lr_reduce_patience , factor = self . lr_reduce_factor , verbose = True , ) lr_dict = { \"scheduler\" : lr_scheduler , # The unit of the scheduler's step size, could also be 'step'. # 'epoch' updates the scheduler on epoch end whereas 'step' # updates it after a optimizer update. \"interval\" : \"epoch\" , # How many epochs/steps should pass between calls to # `scheduler.step()`. 1 corresponds to updating the learning # rate after every epoch/step. \"frequency\" : 1 , # Metric to to monitor for schedulers like `ReduceLROnPlateau` \"monitor\" : self . lr_reduce_monitor , } self . lrfinder_steps = 0 for val in self . trainer . callbacks : if type ( val ) is _LRCallback : self . lrfinder_steps = val . num_training if type ( val ) is LearningRateFinder : self . lrfinder_steps = val . _num_training_steps return [ optimizer ], [ lr_dict ] forward forward also called on self(), a full forward pass on the model Parameters: gene_pos ( Tensor ) \u2013 A tensor of shape (minibatch, seq_len) representing the genes used for each cell in the minibatch. expression ( Tensor , default: None ) \u2013 A tensor of shape (minibatch, seq_len) representing the expression levels of genes in the minibatch. Defaults to None. mask ( Tensor , default: None ) \u2013 A tensor of shape (minibatch, seq_len) used to mask certain elements in the sequence during the forward pass. Defaults to None. full_depth ( Tensor , default: None ) \u2013 A tensor of shape (minibatch,) representing the full depth of each sequence in the minibatch. Defaults to None. timepoint ( Tensor , default: None ) \u2013 A tensor of shape (minibatch,) representing the timepoint associated with each sequence in the minibatch. Defaults to None. get_gene_emb ( bool , default: False ) \u2013 A flag indicating whether to return the gene embeddings. If True, the gene embeddings are included in the output. Defaults to False. do_sample ( bool , default: False ) \u2013 A flag indicating whether to sample the expression levels. If True, the expression levels are sampled during the forward pass. Defaults to False. get_attention_layer ( list , default: [] ) \u2013 A list indicating which attention layers to return. If not empty, the specified attention layers are included in the output. Defaults to []. Returns: \u2013 dict of output Tensors: A dictionary containing the output tensors from the forward pass. The keys of the dictionary depend on the input flags (get_gene_emb, do_sample, get_attention_layer). at minima, the dictionary codntains the following: - \"mean\": the mean expression levels - \"zero_logits\": the logits for zero-inflated expression levels - \"disp\": the dispersion parameter - \"cell_embs\": the cell embeddings per class - \"cell_emb\": the main cell embedding - \"cls_output\": the output of the classifier Source code in scprint/model/model.py 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 def forward ( self , gene_pos : Tensor , expression : Optional [ Tensor ] = None , mask : Optional [ Tensor ] = None , full_depth : Optional [ Tensor ] = None , timepoint : Optional [ Tensor ] = None , # (new_minibatch_of_nxt_cells,) get_gene_emb : bool = False , depth_mult : Optional [ Tensor ] = None , do_sample : bool = False , do_mvc : bool = False , do_class : bool = False , get_attention_layer : list = [], ): \"\"\" forward also called on self(), a full forward pass on the model Args: gene_pos (Tensor): A tensor of shape (minibatch, seq_len) representing the genes used for each cell in the minibatch. expression (Tensor, optional): A tensor of shape (minibatch, seq_len) representing the expression levels of genes in the minibatch. Defaults to None. mask (Tensor, optional): A tensor of shape (minibatch, seq_len) used to mask certain elements in the sequence during the forward pass. Defaults to None. full_depth (Tensor, optional): A tensor of shape (minibatch,) representing the full depth of each sequence in the minibatch. Defaults to None. timepoint (Tensor, optional): A tensor of shape (minibatch,) representing the timepoint associated with each sequence in the minibatch. Defaults to None. get_gene_emb (bool, optional): A flag indicating whether to return the gene embeddings. If True, the gene embeddings are included in the output. Defaults to False. do_sample (bool, optional): A flag indicating whether to sample the expression levels. If True, the expression levels are sampled during the forward pass. Defaults to False. get_attention_layer (list, optional): A list indicating which attention layers to return. If not empty, the specified attention layers are included in the output. Defaults to []. Returns: dict of output Tensors: A dictionary containing the output tensors from the forward pass. The keys of the dictionary depend on the input flags (get_gene_emb, do_sample, get_attention_layer). at minima, the dictionary codntains the following: - \"mean\": the mean expression levels - \"zero_logits\": the logits for zero-inflated expression levels - \"disp\": the dispersion parameter - \"cell_embs\": the cell embeddings per class - \"cell_emb\": the main cell embedding - \"cls_output\": the output of the classifier \"\"\" encoding = self . _encoder ( gene_pos , expression , mask , full_depth , timepoint ) if self . attn_bias != \"none\" : if not hasattr ( self , \"nbias\" ): self . nbias = torch . Tensor ( load_npz ( FILEDIR + \"/../../data/bias_sparse.npz\" ) . todense () ) . to ( device = gene_pos . device , dtype = torch . float16 ) num = len ( self . classes ) + 2 bias = torch . zeros ( ( gene_pos . shape [ 0 ], gene_pos . shape [ 1 ] + num , gene_pos . shape [ 1 ] + num , ), device = gene_pos . device , dtype = torch . float16 , ) bias [:, num :, : num ] = - 10_000 # do not pay attention to the cls embeddings bias [:, num :, num :] = self . nbias [ gene_pos [:, :, None ], gene_pos [:, None , :]] transformer_output = self . transformer ( encoding , return_qkv = get_attention_layer , bias = bias if self . attn_bias != \"none\" else None , bias_layer = list ( range ( self . nlayers - 1 )), ) depth_mult = expression . sum ( 1 ) if depth_mult is None else depth_mult if len ( get_attention_layer ) > 0 : transformer_output , qkvs = transformer_output return ( self . _decoder ( transformer_output , depth_mult , get_gene_emb , do_sample , do_mvc , do_class , ), qkvs , ) else : return self . _decoder ( transformer_output , depth_mult , get_gene_emb , do_sample , do_mvc , do_class , ) get_cell_embs get_cell_embs Parameters: layer_output ( Tensor ) \u2013 The output tensor from a layer in the model. Raises: ValueError \u2013 Raised when an unknown cell embedding style is encountered. Returns: Tensor \u2013 The cell embeddings tensor. Source code in scprint/model/model.py 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 def get_cell_embs ( self , layer_output ): \"\"\" get_cell_embs Args: layer_output (Tensor): The output tensor from a layer in the model. Raises: ValueError: Raised when an unknown cell embedding style is encountered. Returns: Tensor: The cell embeddings tensor. \"\"\" if self . cell_emb_style == \"cls\" and self . classes is not None : # (minibatch, embsize) cell_emb = layer_output [:, : 2 + len ( self . classes )] elif self . cell_emb_style == \"avg-pool\" : cell_emb = torch . mean ( layer_output , dim = 1 ) else : raise ValueError ( f \"Unknown cell_emb_style: { self . cell_emb_style } \" ) return cell_emb log_adata log_adata will log an adata from predictions. It will log to tensorboard and wandb if available see @utils.log_adata Source code in scprint/model/model.py 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 def log_adata ( self , gtclass = None , name = \"\" ): \"\"\" log_adata will log an adata from predictions. It will log to tensorboard and wandb if available see @utils.log_adata \"\"\" try : mdir = self . logger . save_dir if self . logger . save_dir is not None else \"/tmp\" except : mdir = \"data/\" if not os . path . exists ( mdir ): os . makedirs ( mdir ) adata , fig = utils . make_adata ( self . embs , self . classes , self . pred if not self . keep_all_cls_pred else None , self . attn . get (), self . global_step , self . label_decoders , self . labels_hierarchy , gtclass , self . name + \"_\" + name + \"_\" + str ( self . global_rank ), mdir , self . doplot , ) if self . doplot : try : self . logger . experiment . add_figure ( fig ) except : print ( \"couldn't log to tensorboard\" ) try : self . logger . log_image ( key = \"umaps\" , images = [ fig ]) except : print ( \"couldn't log to wandb\" ) return adata on_fit_start @see pl.LightningModule Source code in scprint/model/model.py 641 642 643 644 645 646 647 def on_fit_start ( self ): \"\"\"@see pl.LightningModule\"\"\" if type ( self . transformer ) is FlashTransformerEncoder : for encoder_layers in self . transformer . blocks : encoder_layers . set_seq_parallel ( True ) for k , v in self . mat_labels_hierarchy . items (): self . mat_labels_hierarchy [ k ] = v . to ( self . device ) on_predict_epoch_end @see pl.LightningModule will Source code in scprint/model/model.py 1325 1326 1327 1328 1329 1330 1331 def on_predict_epoch_end ( self ): \"\"\"@see pl.LightningModule will\"\"\" if self . pos . shape [ 0 ] < 100 : return if self . pred_log_adata : print ( \"adding on disk\" ) return self . log_adata ( name = \"predict_part_\" + str ( self . counter )) on_predict_epoch_start @see pl.LightningModule Source code in scprint/model/model.py 1126 1127 1128 1129 1130 1131 1132 1133 1134 def on_predict_epoch_start ( self ): \"\"\"@see pl.LightningModule\"\"\" self . embs = None self . attn . data = None self . attn . attn = None self . counter = 0 if type ( self . transformer ) is FlashTransformerEncoder : for encoder_layers in self . transformer . blocks : encoder_layers . set_seq_parallel ( False ) on_validation_epoch_end @see pl.LightningModule Source code in scprint/model/model.py 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 def on_validation_epoch_end ( self ): \"\"\"@see pl.LightningModule\"\"\" self . embs = self . all_gather ( self . embs ) . view ( - 1 , self . embs . shape [ - 1 ]) self . info = self . all_gather ( self . info ) . view ( - 1 , self . info . shape [ - 1 ]) self . pred = ( self . all_gather ( self . pred ) . view ( - 1 , self . pred . shape [ - 1 ]) if self . pred is not None else None ) self . pos = self . all_gather ( self . pos ) . view ( - 1 , self . pos . shape [ - 1 ]) if not self . trainer . is_global_zero : # print(\"you are not on the main node. cancelling logging step\") return if self . trainer . state . stage != \"sanity_check\" : sch = self . lr_schedulers () sch . step ( self . trainer . callback_metrics [ \"val_loss\" ]) # run the test function on specific dataset self . log_adata ( gtclass = self . info , name = \"validation_part_\" + str ( self . counter ) ) if ( self . current_epoch + 1 ) % 30 == 0 : self . on_test_epoch_end () optimizer_step @see pl.LightningModule Source code in scprint/model/model.py 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 def optimizer_step ( self , epoch , batch_idx , optimizer , optimizer_closure ): \"\"\"@see pl.LightningModule\"\"\" # update params optimizer . step ( closure = optimizer_closure ) # manually warm up lr without a scheduler # making sure that we don't do this during lrfinder for i , pg in enumerate ( optimizer . param_groups ): if ( self . global_step < self . warmup_duration + self . lrfinder_steps ) and self . lrfinder_steps < self . global_step : lr_scale = min ( 1.0 , float ( self . global_step + 1 ) / self . warmup_duration ) pg [ \"lr\" ] = lr_scale * self . hparams . lr for i , pg in enumerate ( optimizer . param_groups ): # if pg[\"lr\"] < 2e-5: # pg[\"lr\"] = 2e-5 self . log ( \"lr_\" + str ( i ), pg [ \"lr\" ]) predict_step embed given gene expression, encode the gene embedding and cell embedding. Returns: Tensor \u2013 description Source code in scprint/model/model.py 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 def predict_step ( self , batch , batch_idx ): \"\"\" embed given gene expression, encode the gene embedding and cell embedding. Args: batch @see training_step Returns: Tensor: _description_ \"\"\" return self . _predict ( batch [ \"genes\" ], batch [ \"x\" ], batch [ \"depth\" ], self . predict_mode , self . pred_embedding , self . get_attention_layer , self . predict_depth_mult , ) training_step training_step defines the train loop. It is independent of forward @see pl.LightningModule Returns: _type_ \u2013 description Source code in scprint/model/model.py 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 def training_step ( self , batch : Dict [ str , Tensor ], batch_idx , ): \"\"\" training_step defines the train loop. It is independent of forward @see pl.LightningModule Returns: _type_: _description_ \"\"\" # TASK 1 & 2 & 3 (first pass, expression reconstruction, label prediction) total_loss , losses = self . _full_training ( batch = batch , do_denoise = self . do_denoise , noise = self . noise , do_next_tp = self . do_next_tp , do_cce = self . do_cce , cce_sim = self . cce_sim , do_ecs = self . do_ecs , do_mvc = self . do_mvc , do_adv_cls = self . do_adv_cls , do_adv_batch = self . do_adv_batch , do_cls = self . do_cls , do_generate = self . do_generate , run_full_forward = self . run_full_forward , mask_ratio = self . mask_ratio , ) self . log ( \"train_loss\" , total_loss , prog_bar = True , sync_dist = True ) self . log_dict ( losses , prog_bar = True , sync_dist = True ) return total_loss validation_step validation_step defines the validation loop. It is independent of forward @see pl.LightningModule Parameters: batch ( list [ Tensor ] ) \u2013 @see training_step Source code in scprint/model/model.py 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 def validation_step ( self , batch , batch_idx , ): \"\"\" validation_step defines the validation loop. It is independent of forward @see pl.LightningModule Args: batch (list[Tensor]): @see training_step \"\"\" val_loss , losses = self . _full_training ( batch = batch , do_denoise = self . do_denoise , noise = self . noise , do_next_tp = self . do_next_tp , do_cce = self . do_cce , cce_sim = self . cce_sim , do_ecs = self . do_ecs , do_mvc = self . do_mvc , do_adv_cls = self . do_adv_cls , do_adv_batch = self . do_adv_batch , do_cls = self . do_cls , do_generate = self . do_generate , run_full_forward = self . run_full_forward , mask_ratio = self . mask_ratio , ) expression = batch [ \"x\" ] gene_pos = batch [ \"genes\" ] depth = batch [ \"depth\" ] # TODO: make this faster by only calling val loss if self . embs is not None : if self . embs . shape [ 0 ] < 100_000 : self . info = torch . cat ([ self . info , batch [ \"class\" ]]) self . _predict ( gene_pos , expression , depth , pred_embedding = self . pred_embedding , max_size_in_mem = 100_000 , ) else : self . info = batch [ \"class\" ] self . _predict ( gene_pos , expression , depth , pred_embedding = self . pred_embedding , max_size_in_mem = 100_000 , ) self . log ( \"val_loss\" , val_loss , sync_dist = True ) self . log_dict ( losses , sync_dist = True ) return val_loss losses scprint.model.loss AdversarialDiscriminatorLoss Bases: Module Discriminator for the adversarial training for batch correction. Parameters: d_model ( int ) \u2013 The size of the input tensor. n_cls ( int ) \u2013 The number of classes. nlayers ( int , default: 3 ) \u2013 The number of layers in the discriminator. Defaults to 3. activation ( callable , default: LeakyReLU ) \u2013 The activation function. Defaults to nn.LeakyReLU. reverse_grad ( bool , default: True ) \u2013 Whether to reverse the gradient. Defaults Source code in scprint/model/loss.py 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 def __init__ ( self , d_model : int , n_cls : int , nlayers : int = 3 , activation : callable = nn . LeakyReLU , reverse_grad : bool = True , ): \"\"\" Discriminator for the adversarial training for batch correction. Args: d_model (int): The size of the input tensor. n_cls (int): The number of classes. nlayers (int, optional): The number of layers in the discriminator. Defaults to 3. activation (callable, optional): The activation function. Defaults to nn.LeakyReLU. reverse_grad (bool, optional): Whether to reverse the gradient. Defaults \"\"\" super () . __init__ () # module list self . decoder = nn . ModuleList () for _ in range ( nlayers - 1 ): self . decoder . append ( nn . Linear ( d_model , d_model )) self . decoder . append ( nn . LayerNorm ( d_model )) self . decoder . append ( activation ()) self . out_layer = nn . Linear ( d_model , n_cls ) self . reverse_grad = reverse_grad forward Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, embsize] Source code in scprint/model/loss.py 302 303 304 305 306 307 308 309 310 311 312 def forward ( self , x : Tensor , batch_labels : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, embsize] \"\"\" if self . reverse_grad : x = grad_reverse ( x , lambd = 1.0 ) for layer in self . decoder : x = layer ( x ) x = self . out_layer ( x ) return F . cross_entropy ( x , batch_labels ) classification Computes the classification loss for a given batch of predictions and ground truth labels. Parameters: clsname ( str ) \u2013 The name of the label. pred ( Tensor ) \u2013 The predicted logits for the batch. cl ( Tensor ) \u2013 The ground truth labels for the batch. maxsize ( int ) \u2013 The number of possible labels. labels_hierarchy ( dict , default: {} ) \u2013 The hierarchical structure of the labels. Defaults to {}. Raises: ValueError \u2013 If the clsname is not found in the labels_hierarchy dictionary. Returns: Tensor ( Tensor ) \u2013 The computed binary cross entropy loss for the given batch. Source code in scprint/model/loss.py 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 def classification ( clsname : str , pred : torch . Tensor , cl : torch . Tensor , maxsize : int , labels_hierarchy : Optional [ Dict [ str , Dict [ int , list [ int ]]]] = {}, ) -> torch . Tensor : \"\"\" Computes the classification loss for a given batch of predictions and ground truth labels. Args: clsname (str): The name of the label. pred (Tensor): The predicted logits for the batch. cl (Tensor): The ground truth labels for the batch. maxsize (int): The number of possible labels. labels_hierarchy (dict, optional): The hierarchical structure of the labels. Defaults to {}. Raises: ValueError: If the clsname is not found in the labels_hierarchy dictionary. Returns: Tensor: The computed binary cross entropy loss for the given batch. \"\"\" newcl = torch . zeros ( ( cl . shape [ 0 ], maxsize ), device = cl . device ) # batchsize * n_labels # if we don't know the label we set the weight to 0 else to 1 valid_indices = ( cl != - 1 ) & ( cl < maxsize ) valid_cl = cl [ valid_indices ] newcl [ valid_indices , valid_cl ] = 1 weight = torch . ones_like ( newcl , device = cl . device ) weight [ cl == - 1 , :] = 0 inv = cl >= maxsize # if we have non leaf values, we don't know so we don't compute grad and set weight to 0 # and add labels that won't be counted but so that we can still use them if inv . any (): if clsname in labels_hierarchy . keys (): clhier = labels_hierarchy [ clsname ] inv_weight = weight [ inv ] # we set the weight of the elements that are not leaf to 0 # i.e. the elements where we will compute the max inv_weight [ clhier [ cl [ inv ] - maxsize ]] = 0 weight [ inv ] = inv_weight addnewcl = torch . ones ( weight . shape [ 0 ], device = pred . device ) # no need to set the other to 0 as the weight of the loss is set to 0 addweight = torch . zeros ( weight . shape [ 0 ], device = pred . device ) addweight [ inv ] = 1 # computing hierarchical labels and adding them to cl addpred = pred . clone () # we only keep the elements where we need to compute the max, # for the rest we set them to -inf, so that they won't have any impact on the max() inv_addpred = addpred [ inv ] inv_addpred [ inv_weight . to ( bool )] = torch . finfo ( pred . dtype ) . min addpred [ inv ] = inv_addpred # differentiable max addpred = torch . logsumexp ( addpred , dim =- 1 ) # we add the new labels to the cl newcl = torch . cat ([ newcl , addnewcl . unsqueeze ( 1 )], dim = 1 ) pred = torch . cat ([ pred , addpred . unsqueeze ( 1 )], dim = 1 ) weight = torch . cat ([ weight , addweight . unsqueeze ( 1 )], dim = 1 ) else : raise ValueError ( \"need to use labels_hierarchy for this usecase\" ) myloss = torch . nn . functional . binary_cross_entropy_with_logits ( pred , target = newcl , weight = weight ) return myloss criterion_neg_log_bernoulli Compute the negative log-likelihood of Bernoulli distribution Source code in scprint/model/loss.py 143 144 145 146 147 148 149 150 def criterion_neg_log_bernoulli ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the negative log-likelihood of Bernoulli distribution \"\"\" mask = mask . float () bernoulli = torch . distributions . Bernoulli ( probs = input ) masked_log_probs = bernoulli . log_prob (( target > 0 ) . float ()) * mask return - masked_log_probs . sum () / mask . sum () ecs ecs Computes the similarity of cell embeddings based on a threshold. Parameters: cell_emb ( Tensor ) \u2013 A tensor representing cell embeddings. ecs_threshold ( float , default: 0.5 ) \u2013 A threshold for determining similarity. Defaults to 0.5. Returns: Tensor ( Tensor ) \u2013 A tensor representing the mean of 1 minus the square of the difference between the cosine similarity and the threshold. Source code in scprint/model/loss.py 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 def ecs ( cell_emb : Tensor , ecs_threshold : float = 0.5 ) -> Tensor : \"\"\" ecs Computes the similarity of cell embeddings based on a threshold. Args: cell_emb (Tensor): A tensor representing cell embeddings. ecs_threshold (float, optional): A threshold for determining similarity. Defaults to 0.5. Returns: Tensor: A tensor representing the mean of 1 minus the square of the difference between the cosine similarity and the threshold. \"\"\" # Here using customized cosine similarity instead of F.cosine_similarity # to avoid the pytorch issue of similarity larger than 1.0, pytorch # 78064 # normalize the embedding cell_emb_normed = F . normalize ( cell_emb , p = 2 , dim = 1 ) cos_sim = torch . mm ( cell_emb_normed , cell_emb_normed . t ()) # mask out diagnal elements mask = torch . eye ( cos_sim . size ( 0 )) . bool () . to ( cos_sim . device ) cos_sim = cos_sim . masked_fill ( mask , 0.0 ) # only optimize positive similarities cos_sim = F . relu ( cos_sim ) return torch . mean ( 1 - ( cos_sim - ecs_threshold ) ** 2 ) grad_reverse grad_reverse Reverses the gradient of the input tensor. Parameters: x ( Tensor ) \u2013 The input tensor whose gradient is to be reversed. lambd ( float , default: 1.0 ) \u2013 The scaling factor for the reversed gradient. Defaults to 1.0. Returns: Tensor ( Tensor ) \u2013 The input tensor with its gradient reversed during the backward pass. Source code in scprint/model/loss.py 326 327 328 329 330 331 332 333 334 335 336 337 def grad_reverse ( x : Tensor , lambd : float = 1.0 ) -> Tensor : \"\"\" grad_reverse Reverses the gradient of the input tensor. Args: x (Tensor): The input tensor whose gradient is to be reversed. lambd (float, optional): The scaling factor for the reversed gradient. Defaults to 1.0. Returns: Tensor: The input tensor with its gradient reversed during the backward pass. \"\"\" return GradReverse . apply ( x , lambd ) masked_mae Compute the masked MAE loss between input and target. MAE = mean absolute error Source code in scprint/model/loss.py 29 30 31 32 33 34 35 36 def masked_mae ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked MAE loss between input and target. MAE = mean absolute error \"\"\" mask = mask . float () loss = F . l1_loss ( input * mask , target * mask , reduction = \"sum\" ) return loss / mask . sum () masked_mse Compute the masked MSE loss between input and target. Source code in scprint/model/loss.py 20 21 22 23 24 25 26 def masked_mse ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked MSE loss between input and target. \"\"\" mask = mask . float () loss = F . mse_loss ( input * mask , target * mask , reduction = \"sum\" ) return loss / mask . sum () masked_nb Compute the masked negative binomial loss between input and target. Source code in scprint/model/loss.py 39 40 41 42 43 44 45 46 def masked_nb ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked negative binomial loss between input and target. \"\"\" mask = mask . float () nb = torch . distributions . NegativeBinomial ( total_count = target , probs = input ) masked_log_probs = nb . log_prob ( target ) * mask return - masked_log_probs . sum () / mask . sum () masked_relative_error Compute the masked relative error between input and target. Source code in scprint/model/loss.py 153 154 155 156 157 158 159 160 161 def masked_relative_error ( input : Tensor , target : Tensor , mask : torch . LongTensor ) -> Tensor : \"\"\" Compute the masked relative error between input and target. \"\"\" assert mask . any () loss = torch . abs ( input [ mask ] - target [ mask ]) / ( target [ mask ] + 1e-6 ) return loss . mean () mse Compute the MSE loss between input and target. Source code in scprint/model/loss.py 9 10 11 12 13 14 15 16 17 def mse ( input : Tensor , target : Tensor ) -> Tensor : \"\"\" Compute the MSE loss between input and target. \"\"\" input = torch . log2 ( input + 1 ) input = ( input / torch . sum ( input , dim = 1 , keepdim = True )) * 10000 target = torch . log2 ( target + 1 ) target = target / torch . sum ( target , dim = 1 , keepdim = True ) * 10000 return F . mse_loss ( input , target , reduction = \"mean\" ) nb Computes the negative binomial (NB) loss. This function was adapted from scvi-tools. Parameters: target ( Tensor ) \u2013 Ground truth data. mu ( Tensor ) \u2013 Means of the negative binomial distribution (must have positive support). theta ( Tensor ) \u2013 Inverse dispersion parameter (must have positive support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 NB loss value. Source code in scprint/model/loss.py 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 def nb ( target : Tensor , mu : Tensor , theta : Tensor , eps = 1e-8 ): \"\"\" Computes the negative binomial (NB) loss. This function was adapted from scvi-tools. Args: target (Tensor): Ground truth data. mu (Tensor): Means of the negative binomial distribution (must have positive support). theta (Tensor): Inverse dispersion parameter (must have positive support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: NB loss value. \"\"\" if theta . ndimension () == 1 : theta = theta . view ( 1 , theta . size ( 0 )) log_theta_mu_eps = torch . log ( theta + mu + eps ) res = ( theta * ( torch . log ( theta + eps ) - log_theta_mu_eps ) + target * ( torch . log ( mu + eps ) - log_theta_mu_eps ) + torch . lgamma ( target + theta ) - torch . lgamma ( theta ) - torch . lgamma ( target + 1 ) ) return - res . mean () nb_dist nb_dist Computes the negative binomial distribution. Parameters: x ( Tensor ) \u2013 Torch Tensor of observed data. mu ( Tensor ) \u2013 Torch Tensor of means of the negative binomial distribution (must have positive support). theta ( Tensor ) \u2013 Torch Tensor of inverse dispersion parameter (must have positive support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 Negative binomial loss value. Source code in scprint/model/loss.py 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 def nb_dist ( x : Tensor , mu : Tensor , theta : Tensor , eps = 1e-8 ): \"\"\" nb_dist Computes the negative binomial distribution. Args: x (Tensor): Torch Tensor of observed data. mu (Tensor): Torch Tensor of means of the negative binomial distribution (must have positive support). theta (Tensor): Torch Tensor of inverse dispersion parameter (must have positive support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: Negative binomial loss value. \"\"\" loss = - NegativeBinomial ( mu = mu , theta = theta ) . log_prob ( x ) return loss similarity Dot product or cosine similarity Source code in scprint/model/loss.py 164 165 166 167 168 169 170 def similarity ( x : Tensor , y : Tensor , temp : float ) -> Tensor : \"\"\" Dot product or cosine similarity \"\"\" res = F . cosine_similarity ( x . unsqueeze ( 1 ), y . unsqueeze ( 0 )) / temp labels = torch . arange ( res . size ( 0 )) . long () . to ( device = res . device ) return F . cross_entropy ( res , labels ) zinb Computes zero-inflated negative binomial (ZINB) loss. This function was modified from scvi-tools. Parameters: target ( Tensor ) \u2013 Torch Tensor of ground truth data. mu ( Tensor ) \u2013 Torch Tensor of means of the negative binomial (must have positive support). theta ( Tensor ) \u2013 Torch Tensor of inverse dispersion parameter (must have positive support). pi ( Tensor ) \u2013 Torch Tensor of logits of the dropout parameter (real support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 ZINB loss value. Source code in scprint/model/loss.py 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 def zinb ( target : Tensor , mu : Tensor , theta : Tensor , pi : Tensor , eps = 1e-8 , ): \"\"\" Computes zero-inflated negative binomial (ZINB) loss. This function was modified from scvi-tools. Args: target (Tensor): Torch Tensor of ground truth data. mu (Tensor): Torch Tensor of means of the negative binomial (must have positive support). theta (Tensor): Torch Tensor of inverse dispersion parameter (must have positive support). pi (Tensor): Torch Tensor of logits of the dropout parameter (real support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: ZINB loss value. \"\"\" # uses log(sigmoid(x)) = -softplus(-x) softplus_pi = F . softplus ( - pi ) # eps to make it positive support and taking the log log_theta_mu_eps = torch . log ( theta + mu + eps ) pi_theta_log = - pi + theta * ( torch . log ( theta + eps ) - log_theta_mu_eps ) case_zero = F . softplus ( pi_theta_log ) - softplus_pi mul_case_zero = torch . mul (( target < eps ) . type ( torch . float32 ), case_zero ) case_non_zero = ( - softplus_pi + pi_theta_log + target * ( torch . log ( mu + eps ) - log_theta_mu_eps ) + torch . lgamma ( target + theta ) - torch . lgamma ( theta ) - torch . lgamma ( target + 1 ) ) mul_case_non_zero = torch . mul (( target > eps ) . type ( torch . float32 ), case_non_zero ) res = mul_case_zero + mul_case_non_zero # we want to minize the loss but maximize the log likelyhood return - res . mean () utils scprint.model.utils Attention Initialize the Attention class. Parameters: gene_dim ( int ) \u2013 The dimension of the gene. comp_attn ( bool , default: False ) \u2013 Whether to compute attention. Defaults to False. Source code in scprint/model/utils.py 472 473 474 475 476 477 478 479 480 481 482 483 484 def __init__ ( self , gene_dim : int , comp_attn : bool = False ): \"\"\" Initialize the Attention class. Args: gene_dim (int): The dimension of the gene. comp_attn (bool, optional): Whether to compute attention. Defaults to False. \"\"\" self . data : Optional [ Tensor ] = None self . gene_dim : int = gene_dim self . div : Optional [ Tensor ] = None self . attn : Optional [ Tensor ] = None self . comp_attn : bool = comp_attn add Add data to the internal storage. Parameters: x ( List [ Tensor ] ) \u2013 List of tensors to add. pos ( Tensor ) \u2013 Position tensor. Source code in scprint/model/utils.py 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 def add ( self , x : List [ Tensor ], pos : Tensor ) -> None : \"\"\" Add data to the internal storage. Args: x (List[Tensor]): List of tensors to add. pos (Tensor): Position tensor. \"\"\" pos = pos . detach () . to ( \"cpu\" ) if self . data is None : self . data = torch . zeros ([ len ( x ), self . gene_dim ] + list ( x [ 0 ] . shape [ 2 :])) self . div = torch . zeros ( self . gene_dim ) for i in range ( x [ 0 ] . shape [ 0 ]): # loc = torch.cat([torch.Tensor([r for r in range(8)]), pos[i] + 8]).int() self . data . append ( torch . cat ([ x [ j ][ i ] . detach () . to ( \"cpu\" ) for j in range ( len ( x ))]) ) agg Aggregate the attention or data based on the comp_attn flag. Parameters: x ( List [ Tensor ] ) \u2013 List of tensors to aggregate. pos ( Tensor ) \u2013 Position tensor. Source code in scprint/model/utils.py 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 def agg ( self , x : List [ Tensor ], pos : Tensor ) -> None : \"\"\" Aggregate the attention or data based on the comp_attn flag. Args: x (List[Tensor]): List of tensors to aggregate. pos (Tensor): Position tensor. \"\"\" if self . comp_attn : if self . attn is None : self . attn = torch . zeros ([ self . gene_dim , self . gene_dim ], device = \"cuda\" ) self . div = torch . zeros ( self . gene_dim , device = \"cuda\" ) for j in range ( x [ 0 ] . shape [ 0 ]): # \u2022cells, \u2022context, \u2022QK, \u2022heads, \u2022dim loc = torch . cat ([ torch . arange ( 8 , device = \"cuda\" ), pos [ j ] + 8 ]) . int () for i in range ( len ( x )): for k in range ( x [ 0 ] . shape [ 3 ]): self . attn [ loc [:, None ], loc ] += torch . nn . functional . softmax ( ( x [ i ][ j , :, 0 , k , :] @ x [ i ][ j , :, 1 , k , :] . T ) * ( x [ 0 ] . shape [ - 1 ] ** - 0.5 ), dim =- 1 , ) self . div [ loc ] += x [ 0 ] . shape [ 3 ] * len ( x ) torch . cuda . empty_cache () else : pos = pos . detach () . to ( \"cpu\" ) if self . data is None : self . data = torch . zeros ([ len ( x ), self . gene_dim ] + list ( x [ 0 ] . shape [ 2 :])) self . div = torch . zeros ( self . gene_dim ) for i in range ( x [ 0 ] . shape [ 0 ]): loc = torch . cat ([ torch . arange ( 8 ), pos [ i ] + 8 ]) . int () for j in range ( len ( x )): self . data [ j , loc , :, :, :] += x [ j ][ i ] . detach () . to ( \"cpu\" ) self . div [ loc ] += 1 get Get the aggregated attention or data. Returns: Optional [ ndarray ] \u2013 Optional[np.ndarray]: The aggregated attention or data. Source code in scprint/model/utils.py 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 def get ( self ) -> Optional [ np . ndarray ]: \"\"\" Get the aggregated attention or data. Returns: Optional[np.ndarray]: The aggregated attention or data. \"\"\" if self . comp_attn : loc = self . attn . sum ( 1 ) != 0 return ( ( self . attn [ loc ][:, loc ] / ( self . attn . sum ( 1 )[ loc ] + 0.0001 )) . detach () . cpu () . numpy () ) else : if self . data is None : return None # shape is (layers, genes, qkv, heads, emb) return self . data / self . div . view ( 1 , self . div . shape [ 0 ], 1 , 1 , 1 ) downsample_profile This function downsamples the expression profile of a given single cell RNA matrix. The noise is applied based on the renoise parameter, the total counts of the matrix, and the number of genes. The function first calculates the noise threshold (scaler) based on the renoise parameter. It then generates an initial matrix count by applying a Poisson distribution to a random tensor scaled by the total counts and the number of genes. The function then models the sampling zeros by applying a Poisson distribution to a random tensor scaled by the noise threshold, the total counts, and the number of genes. The function also models the technical zeros by generating a random tensor and comparing it to the noise threshold. The final matrix count is calculated by subtracting the sampling zeros from the initial matrix count and multiplying by the technical zeros. The function ensures that the final matrix count is not less than zero by taking the maximum of the final matrix count and a tensor of zeros. The function returns the final matrix count. Parameters: mat ( Tensor ) \u2013 The input matrix. dropout ( float ) \u2013 The renoise parameter. Returns: \u2013 torch.Tensor: The matrix count after applying noise. Source code in scprint/model/utils.py 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 def downsample_profile ( mat : Tensor , dropout : float , method = \"new\" ): \"\"\" This function downsamples the expression profile of a given single cell RNA matrix. The noise is applied based on the renoise parameter, the total counts of the matrix, and the number of genes. The function first calculates the noise threshold (scaler) based on the renoise parameter. It then generates an initial matrix count by applying a Poisson distribution to a random tensor scaled by the total counts and the number of genes. The function then models the sampling zeros by applying a Poisson distribution to a random tensor scaled by the noise threshold, the total counts, and the number of genes. The function also models the technical zeros by generating a random tensor and comparing it to the noise threshold. The final matrix count is calculated by subtracting the sampling zeros from the initial matrix count and multiplying by the technical zeros. The function ensures that the final matrix count is not less than zero by taking the maximum of the final matrix count and a tensor of zeros. The function returns the final matrix count. Args: mat (torch.Tensor): The input matrix. dropout (float): The renoise parameter. Returns: torch.Tensor: The matrix count after applying noise. \"\"\" # Randomly drop on average N counts to each element of expression using a heavy tail Gaussian distribution # here we try to get the scale of the distribution so as to remove the right number of counts from each gene # https://genomebiology.biomedcentral.com/articles/10.1186/s13059-022-02601-5#:~:text=Zero%20measurements%20in%20scRNA%2Dseq,generation%20of%20scRNA%2Dseq%20data. if method == \"old\" : totcounts = mat . sum ( 1 ) batch = mat . shape [ 0 ] ngenes = mat . shape [ 1 ] tnoise = 1 - ( 1 - dropout ) ** ( 1 / 2 ) # we model the sampling zeros (dropping 30% of the reads) res = torch . poisson ( torch . rand (( batch , ngenes )) . to ( device = mat . device ) * (( tnoise * totcounts . unsqueeze ( 1 )) / ( 0.5 * ngenes )) ) . int () # we model the technical zeros (dropping 50% of the genes) drop = ( torch . rand (( batch , ngenes )) > tnoise ) . int () . to ( device = mat . device ) mat = ( mat - res ) * drop return torch . maximum ( mat , torch . Tensor ([[ 0 ]]) . to ( device = mat . device )) . int () elif method == \"jules\" : scaler = ( 1 - dropout ) ** ( 1 / 2 ) notdrop = ( torch . rand ( mat . shape , device = mat . device , ) < scaler ) . int () notdrop [ mat == 0 ] = 0 # apply the dropout after the poisson, right? return notdrop * torch . poisson ( mat * scaler ) elif method == \"new\" : batch = mat . shape [ 0 ] ngenes = mat . shape [ 1 ] dropout = dropout * 1.1 # we model the sampling zeros (dropping 30% of the reads) res = torch . poisson (( mat * ( dropout / 2 ))) . int () # we model the technical zeros (dropping 50% of the genes) notdrop = ( torch . rand (( batch , ngenes ), device = mat . device ) >= ( dropout / 2 ) ) . int () mat = ( mat - res ) * notdrop return torch . maximum ( mat , torch . zeros (( 1 , 1 ), device = mat . device , dtype = torch . int ) ) else : raise ValueError ( f \"method { method } not recognized\" ) make_adata This function creates an AnnData object from the given input parameters. Parameters: embs ( Tensor ) \u2013 Embeddings of the cells. The shape of the tensor is (n_cells, n_features). labels ( list ) \u2013 List of labels for the predicted classes. pred ( Tensor , default: None ) \u2013 Predicted labels. The shape of the tensor is (n_cells, n_classes). Default is None. attention ( Tensor , default: None ) \u2013 Attention weights. Default is None. step ( int , default: 0 ) \u2013 Step number for storing the AnnData without overwriting others. Default is 0. label_decoders ( dict , default: None ) \u2013 Dictionary to map class codes to class names. Default is None. labels_hierarchy ( dict , default: {} ) \u2013 Dictionary representing the hierarchy of labels. Default is {}. gtclass ( Tensor , default: None ) \u2013 Ground truth class. Default is None. name ( str , default: '' ) \u2013 Name of the AnnData object. Default is an empty string. mdir ( str , default: '/tmp' ) \u2013 Directory to save the AnnData object. Default is \"/tmp\". doplot ( bool , default: True ) \u2013 Whether to generate plots. Default is True. Returns: \u2013 anndata.AnnData: The created AnnData object. Source code in scprint/model/utils.py 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 def make_adata ( embs : Tensor , labels : List [ str ], pred : Tensor = None , attention : Optional [ Tensor ] = None , step : int = 0 , label_decoders : Optional [ Dict ] = None , labels_hierarchy : Dict = {}, gtclass : Optional [ Tensor ] = None , name : str = \"\" , mdir : str = \"/tmp\" , doplot : bool = True , ): \"\"\" This function creates an AnnData object from the given input parameters. Args: embs (torch.Tensor): Embeddings of the cells. The shape of the tensor is (n_cells, n_features). labels (list): List of labels for the predicted classes. pred (torch.Tensor, optional): Predicted labels. The shape of the tensor is (n_cells, n_classes). Default is None. attention (torch.Tensor, optional): Attention weights. Default is None. step (int, optional): Step number for storing the AnnData without overwriting others. Default is 0. label_decoders (dict, optional): Dictionary to map class codes to class names. Default is None. labels_hierarchy (dict, optional): Dictionary representing the hierarchy of labels. Default is {}. gtclass (torch.Tensor, optional): Ground truth class. Default is None. name (str, optional): Name of the AnnData object. Default is an empty string. mdir (str, optional): Directory to save the AnnData object. Default is \"/tmp\". doplot (bool, optional): Whether to generate plots. Default is True. Returns: anndata.AnnData: The created AnnData object. \"\"\" colname = [ \"pred_\" + i for i in labels ] if pred is not None : obs = np . array ( pred . to ( device = \"cpu\" , dtype = torch . int32 )) # label decoders is not cls_decoders. one is a dict to map class codes (ints) # to class names the other is the module the predict the class if label_decoders is not None : obs = np . array ( [ [ label_decoders [ labels [ i ]][ n ] for n in name ] for i , name in enumerate ( obs . T ) ] ) . T if gtclass is not None : colname += labels nobs = np . array ( gtclass . to ( device = \"cpu\" , dtype = torch . int32 )) if label_decoders is not None : nobs = np . array ( [ [ label_decoders [ labels [ i ]][ n ] for n in name ] for i , name in enumerate ( nobs . T ) ] ) . T obs = np . hstack ([ obs , nobs ]) adata = AnnData ( np . array ( embs . to ( device = \"cpu\" , dtype = torch . float32 )), obs = pd . DataFrame ( obs , columns = colname , ), ) accuracy = {} for label in labels : if gtclass is not None : tr = translate ( adata . obs [ label ] . tolist (), label ) if tr is not None : adata . obs [ \"conv_\" + label ] = adata . obs [ label ] . replace ( tr ) tr = translate ( adata . obs [ \"pred_\" + label ] . tolist (), label ) if tr is not None : adata . obs [ \"conv_pred_\" + label ] = adata . obs [ \"pred_\" + label ] . replace ( tr ) res = [] if label_decoders is not None and gtclass is not None : class_topred = label_decoders [ label ] . values () if label in labels_hierarchy : cur_labels_hierarchy = { label_decoders [ label ][ k ]: [ label_decoders [ label ][ i ] for i in v ] for k , v in labels_hierarchy [ label ] . items () } else : cur_labels_hierarchy = {} for pred , true in adata . obs [[ \"pred_\" + label , label ]] . values : if pred == true : res . append ( True ) continue if len ( labels_hierarchy ) > 0 : if true in cur_labels_hierarchy : res . append ( pred in cur_labels_hierarchy [ true ]) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) else : pass accuracy [ \"pred_\" + label ] = sum ( res ) / len ( res ) if len ( res ) > 0 else 0 adata . obs = adata . obs . astype ( \"category\" ) else : adata = AnnData ( np . array ( embs . to ( device = \"cpu\" , dtype = torch . float32 )), ) if False : adata . varm [ \"Qs\" ] = ( attention [:, :, 0 , :, :] . permute ( 1 , 3 , 0 , 2 ) . view ( attention . shape [ 0 ], attention . shape [ 1 ], attention . shape [ 3 ] * attention . shape [ 4 ], ) . detach () . cpu () . numpy () ) adata . varm [ \"Ks\" ] = ( attention [:, :, 1 , :, :] . permute ( 1 , 3 , 0 , 2 ) . view ( attention . shape [ 0 ], attention . shape [ 1 ], attention . shape [ 3 ] * attention . shape [ 4 ], ) . detach () . cpu () . numpy () ) print ( adata ) if doplot and adata . shape [ 0 ] > 100 and pred is not None : sc . pp . neighbors ( adata , use_rep = \"X\" ) sc . tl . umap ( adata ) sc . tl . leiden ( adata , key_added = \"sprint_leiden\" ) if gtclass is not None : color = [ i for pair in zip ( [ \"conv_\" + i if \"conv_\" + i in adata . obs . columns else i for i in labels ], [ ( \"conv_pred_\" + i if \"conv_pred_\" + i in adata . obs . columns else \"pred_\" + i ) for i in labels ], ) for i in pair ] fig , axs = plt . subplots ( int ( len ( color ) / 2 ), 2 , figsize = ( 24 , len ( color ) * 4 ) ) plt . subplots_adjust ( wspace = 1 ) for i , col in enumerate ( color ): sc . pl . umap ( adata , color = col , ax = axs [ i // 2 , i % 2 ], show = False , ) acc = \"\" if \"_pred_\" in col and col . split ( \"conv_\" )[ - 1 ] in accuracy : acc = \" (accuracy: {:.2f} )\" . format ( accuracy [ col . split ( \"conv_\" )[ - 1 ]]) axs [ i // 2 , i % 2 ] . set_title ( col + \" UMAP\" + acc ) if \"cell_type\" in col : axs [ i // 2 , i % 2 ] . legend ( fontsize = \"x-small\" ) axs [ i // 2 , i % 2 ] . set_xlabel ( \"UMAP1\" ) axs [ i // 2 , i % 2 ] . set_ylabel ( \"UMAP2\" ) else : color = [ ( \"conv_pred_\" + i if \"conv_pred_\" + i in adata . obs . columns else \"pred_\" + i ) for i in labels ] fig , axs = plt . subplots ( len ( color ), 1 , figsize = ( 16 , len ( color ) * 8 )) for i , col in enumerate ( color ): sc . pl . umap ( adata , color = col , ax = axs [ i ], show = False , ) acc = \"\" if \"_pred_\" in col and col . split ( \"conv_\" )[ - 1 ] in accuracy : acc = \" (accuracy: {:.2f} )\" . format ( accuracy [ col . split ( \"conv_\" )[ - 1 ]]) axs [ i ] . set_title ( col + \" UMAP\" + acc ) axs [ i ] . set_xlabel ( \"UMAP1\" ) axs [ i ] . set_ylabel ( \"UMAP2\" ) plt . show () else : fig = None adata . write ( mdir + \"/step_\" + str ( step ) + \"_\" + name + \".h5ad\" ) return adata , fig simple_masker Randomly mask a batch of data. Parameters: shape ( list [ int ] ) \u2013 The shape of the data. mask_ratio ( float , default: 0.15 ) \u2013 The ratio of genes to mask, default to 0.15. Returns: Tensor \u2013 torch.Tensor: A tensor of masked data. Source code in scprint/model/utils.py 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 def simple_masker ( shape : list [ int ], mask_ratio : float = 0.15 , ) -> torch . Tensor : \"\"\" Randomly mask a batch of data. Args: shape (list[int]): The shape of the data. mask_ratio (float): The ratio of genes to mask, default to 0.15. Returns: torch.Tensor: A tensor of masked data. \"\"\" return torch . rand ( shape ) < mask_ratio test Test the given model on the full set of benchmarks and save the results to JSON files. Parameters: model ( Module ) \u2013 The model to be tested. name ( str ) \u2013 The name to be used for the output JSON files. filedir ( str ) \u2013 The directory where the data files are located. Returns: None \u2013 None Source code in scprint/model/utils.py 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 def test ( model : torch . nn . Module , name : str , filedir : str ) -> None : \"\"\" Test the given model on the full set of benchmarks and save the results to JSON files. Args: model (torch.nn.Module): The model to be tested. name (str): The name to be used for the output JSON files. filedir (str): The directory where the data files are located. Returns: None \"\"\" metrics = {} res = embbed_task . default_benchmark ( model , default_dataset = \"lung\" , do_class = True , coarse = False ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"embed_lung\" : res }, indent = 4 )) f . close () metrics . update ( { \"emb_lung/scib\" : float ( res [ \"scib\" ][ \"Total\" ]), \"emb_lung/ct_class\" : float ( res [ \"classif\" ][ \"cell_type_ontology_term_id\" ][ \"accuracy\" ] ), } ) print ( metrics ) res = embbed_task . default_benchmark ( model , default_dataset = \"pancreas\" , do_class = True , coarse = False ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"embed_panc\" : res }, indent = 4 )) f . close () metrics . update ( { \"emb_panc/scib\" : float ( res [ \"scib\" ][ \"Total\" ]), \"emb_panc/ct_class\" : float ( res [ \"classif\" ][ \"cell_type_ontology_term_id\" ][ \"accuracy\" ] ), } ) print ( metrics ) gc . collect () res = denoise_task . default_benchmark ( model , filedir + \"/../../data/gNNpgpo6gATjuxTE7CCp.h5ad\" ) metrics . update ( { \"denoise/reco2full_vs_noisy2full\" : float ( res [ \"reco2full\" ] - res [ \"noisy2full\" ] ), } ) gc . collect () print ( metrics ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"denoise\" : res }, indent = 4 )) f . close () res = grn_task . default_benchmark ( model , \"gwps\" , batch_size = 32 if model . d_model <= 512 else 8 ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_gwps\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_gwps/auprc_self\" : float ( res [ \"self\" ][ \"auprc\" ]), \"grn_gwps/epr_self\" : float ( res [ \"self\" ][ \"epr\" ]), \"grn_gwps/auprc_omni\" : float ( res [ \"omni\" ][ \"auprc\" ]), \"grn_gwps/epr_omni\" : float ( res [ \"omni\" ][ \"epr\" ]), \"grn_gwps/auprc\" : float ( res [ \"mean\" ][ \"auprc\" ]), \"grn_gwps/epr\" : float ( res [ \"mean\" ][ \"epr\" ]), } ) print ( metrics ) gc . collect () res = grn_task . default_benchmark ( model , \"sroy\" , batch_size = 32 if model . d_model <= 512 else 8 ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_sroy\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_sroy/auprc_self\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"self_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr_self\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"self_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/auprc_omni\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"omni_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr_omni\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"omni_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/auprc\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"mean_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"mean_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), } ) print ( metrics ) gc . collect () res = grn_task . default_benchmark ( model , filedir + \"/../../data/yBCKp6HmXuHa0cZptMo7.h5ad\" , batch_size = 32 if model . d_model <= 512 else 8 , ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_omni\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_omni/auprc_class\" : float ( np . mean ([ i [ \"auprc\" ] for k , i in res . items () if \"_class\" in k ]) ), \"grn_omni/epr_class\" : float ( np . mean ([ i [ \"epr\" ] for k , i in res . items () if \"_class\" in k ]) ), \"grn_omni/tf_enr_class\" : float ( np . sum ( [ i . get ( \"TF_enr\" , False ) for k , i in res . items () if \"_class\" in k ] ) ), \"grn_omni/tf_targ_enr_class\" : float ( np . mean ( [ i [ \"significant_enriched_TFtargets\" ] for k , i in res . items () if \"_class\" in k ] ) ), \"grn_omni/auprc\" : float ( np . mean ([ i [ \"auprc\" ] for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/epr\" : float ( np . mean ([ i [ \"epr\" ] for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/tf_enr\" : float ( np . sum ([ i . get ( \"TF_enr\" , False ) for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/tf_targ_enr\" : float ( np . mean ( [ i [ \"significant_enriched_TFtargets\" ] for k , i in res . items () if \"_mean\" in k ] ) ), # 'grn_omni/ct': res['classif']['cell_type_ontology_term_id']['accuracy'], } ) return metrics translate translate This function translates the given value based on the specified type. Parameters: val ( str / list / set / dict / Counter ) \u2013 The value to be translated. t ( str , default: 'cell_type_ontology_term_id' ) \u2013 The type of translation to be performed. Defaults to \"cell_type_ontology_term_id\". Returns: dict \u2013 A dictionary with the translated values. Source code in scprint/model/utils.py 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 def translate ( val : Union [ str , list , set , dict , Counter ], t : str = \"cell_type_ontology_term_id\" ): \"\"\" translate This function translates the given value based on the specified type. Args: val (str/list/set/dict/Counter): The value to be translated. t (str, optional): The type of translation to be performed. Defaults to \"cell_type_ontology_term_id\". Returns: dict: A dictionary with the translated values. \"\"\" if t == \"cell_type_ontology_term_id\" : obj = bt . CellType . df () . set_index ( \"ontology_id\" ) elif t == \"assay_ontology_term_id\" : obj = bt . ExperimentalFactor . df () . set_index ( \"ontology_id\" ) elif t == \"tissue_ontology_term_id\" : obj = bt . Tissue . df () . set_index ( \"ontology_id\" ) elif t == \"disease_ontology_term_id\" : obj = bt . Disease . df () . set_index ( \"ontology_id\" ) elif t == \"self_reported_ethnicity_ontology_term_id\" : obj = bt . Ethnicity . df () . set_index ( \"ontology_id\" ) else : return None if type ( val ) is str : if val == \"unknown\" : return { val : val } return { val : obj . loc [ val ][ \"name\" ]} elif type ( val ) is list or type ( val ) is set : return { i : obj . loc [ i ][ \"name\" ] if i != \"unknown\" else i for i in set ( val )} elif type ( val ) is dict or type ( val ) is Counter : return { obj . loc [ k ][ \"name\" ] if k != \"unknown\" else k : v for k , v in val . items ()} weighted_masker Randomly mask a batch of data. Parameters: shape ( list [ int ] ) \u2013 The shape of the data. mask_ratio ( float , default: 0.15 ) \u2013 The ratio of genes to mask, default to 0.15. mask_value ( int , default: 1 ) \u2013 The value to mask with, default to -1. pad_value ( int ) \u2013 The value of padding in the values, will be kept unchanged. Returns: Tensor \u2013 torch.Tensor: A tensor of masked data. Source code in scprint/model/utils.py 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 def weighted_masker ( shape : list [ int ], mask_ratio : float = 0.15 , mask_prob : Optional [ Union [ torch . Tensor , np . ndarray ]] = None , # n_features mask_value : int = 1 , ) -> torch . Tensor : \"\"\" Randomly mask a batch of data. Args: shape (list[int]): The shape of the data. mask_ratio (float): The ratio of genes to mask, default to 0.15. mask_value (int): The value to mask with, default to -1. pad_value (int): The value of padding in the values, will be kept unchanged. Returns: torch.Tensor: A tensor of masked data. \"\"\" mask = [] for _ in range ( shape [ 0 ]): m = np . zeros ( shape [ 1 ]) loc = np . random . choice ( a = shape [ 1 ], size = int ( shape [ 1 ] * mask_ratio ), replace = False , p = mask_prob ) m [ loc ] = mask_value mask . append ( m ) return torch . Tensor ( np . array ( mask )) . to ( torch . bool ) zinb_sample zinb_sample This function generates a sample from a Zero-Inflated Negative Binomial (ZINB) distribution. Parameters: mu ( Tensor ) \u2013 The mean of the Negative Binomial (NB) distribution. theta ( Tensor ) \u2013 The dispersion parameter of the NB distribution. zi_probs ( Tensor ) \u2013 The zero-inflation probabilities. sample_shape ( Size , default: Size ([]) ) \u2013 The output shape. Defaults to torch.Size([]). Returns: \u2013 torch.Tensor: A sample from the ZINB distribution. Source code in scprint/model/utils.py 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 def zinb_sample ( mu : torch . Tensor , theta : torch . Tensor , zi_probs : torch . Tensor , sample_shape : torch . Size = torch . Size ([]), ): \"\"\" zinb_sample This function generates a sample from a Zero-Inflated Negative Binomial (ZINB) distribution. Args: mu (torch.Tensor): The mean of the Negative Binomial (NB) distribution. theta (torch.Tensor): The dispersion parameter of the NB distribution. zi_probs (torch.Tensor): The zero-inflation probabilities. sample_shape (torch.Size, optional): The output shape. Defaults to torch.Size([]). Returns: torch.Tensor: A sample from the ZINB distribution. \"\"\" concentration = theta rate = theta / mu # Important remark: Gamma is parametrized by the rate = 1/scale! gamma_d = Gamma ( concentration = concentration , rate = rate ) p_means = gamma_d . sample ( sample_shape ) # Clamping as distributions objects can have buggy behaviors when # their parameters are too high l_train = torch . clamp ( p_means , max = 1e8 ) samp = Poisson ( l_train ) . sample () # Shape : (n_samples, n_cells_batch, n_vars) is_zero = torch . rand_like ( samp ) <= zi_probs samp_ = torch . where ( is_zero , torch . zeros_like ( samp ), samp ) return samp_ encoder and decoder modules scprint.model.encoders CategoryValueEncoder Bases: Module Encodes categorical values into a vector using an embedding layer and layer normalization. Parameters: num_embeddings ( int ) \u2013 The number of possible values. embedding_dim ( int ) \u2013 The dimension of the output vectors. padding_idx ( int , default: None ) \u2013 The index of the padding token. Defaults to None. Returns: \u2013 torch.Tensor: A tensor representing the encoded categorical values. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 def __init__ ( self , num_embeddings : int , embedding_dim : int , padding_idx : Optional [ int ] = None , ): \"\"\" Encodes categorical values into a vector using an embedding layer and layer normalization. Args: num_embeddings (int): The number of possible values. embedding_dim (int): The dimension of the output vectors. padding_idx (int, optional): The index of the padding token. Defaults to None. Returns: torch.Tensor: A tensor representing the encoded categorical values. Note: not used in the current version of scprint. \"\"\" super ( CategoryValueEncoder , self ) . __init__ () self . embedding = nn . Embedding ( num_embeddings , embedding_dim , padding_idx = padding_idx ) ContinuousValueEncoder Bases: Module Encode real number values to a vector using neural nets projection. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float , default: 0.1 ) \u2013 The dropout rate to apply to the output of the positional encoding. max_value ( int , default: 100000 ) \u2013 The maximum value of the input. Defaults to 100_000. layers ( int , default: 1 ) \u2013 The number of layers in the encoder. Defaults to 1. size ( int , default: 1 ) \u2013 The size of the input. Defaults to 1. Returns: \u2013 torch.Tensor: A tensor representing the encoded continuous values. Source code in scprint/model/encoders.py 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 def __init__ ( self , d_model : int , dropout : float = 0.1 , max_value : int = 100_000 , layers : int = 1 , size : int = 1 , ): \"\"\" Encode real number values to a vector using neural nets projection. Args: d_model (int): The dimension of the input vectors. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. max_value (int, optional): The maximum value of the input. Defaults to 100_000. layers (int, optional): The number of layers in the encoder. Defaults to 1. size (int, optional): The size of the input. Defaults to 1. Returns: torch.Tensor: A tensor representing the encoded continuous values. \"\"\" super ( ContinuousValueEncoder , self ) . __init__ () self . max_value = max_value self . encoder = nn . ModuleList () self . encoder . append ( nn . Linear ( size , d_model )) for _ in range ( layers - 1 ): self . encoder . append ( nn . LayerNorm ( d_model )) self . encoder . append ( nn . ReLU ()) self . encoder . append ( nn . Dropout ( p = dropout )) self . encoder . append ( nn . Linear ( d_model , d_model )) forward Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, seq_len] Source code in scprint/model/encoders.py 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 def forward ( self , x : Tensor , mask : Tensor = None ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, seq_len] \"\"\" # expand last dimension x = x . unsqueeze ( - 1 ) # use the mask embedding when x=-1 # mask = (x == -1).float() x = torch . clamp ( x , min = 0 , max = self . max_value ) for val in self . encoder : x = val ( x ) if mask is not None : x = x . masked_fill_ ( mask . unsqueeze ( - 1 ), 0 ) return x DPositionalEncoding Bases: Module The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. max_len ( int ) \u2013 The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 def __init__ ( self , d_model : int , max_len_x : int , max_len_y : int , maxvalue_x = 10000.0 , maxvalue_y = 10000.0 , ): super ( DPositionalEncoding , self ) . __init__ () position2 = torch . arange ( max_len_y ) . unsqueeze ( 1 ) position1 = torch . arange ( max_len_x ) . unsqueeze ( 1 ) half_n = d_model // 2 div_term2 = torch . exp ( torch . arange ( 0 , half_n , 2 ) * ( - math . log ( maxvalue_y ) / d_model ) ) div_term1 = torch . exp ( torch . arange ( 0 , half_n , 2 ) * ( - math . log ( maxvalue_x ) / d_model ) ) pe1 = torch . zeros ( max_len_x , 1 , d_model ) pe2 = torch . zeros ( max_len_y , 1 , d_model ) pe1 [:, 0 , 0 : half_n : 2 ] = torch . sin ( position1 * div_term1 ) pe1 [:, 0 , 1 : half_n : 2 ] = torch . cos ( position1 * div_term1 ) pe2 [:, 0 , half_n :: 2 ] = torch . sin ( position2 * div_term2 ) pe2 [:, 0 , 1 + half_n :: 2 ] = torch . cos ( position2 * div_term2 ) # https://github.com/tatp22/multidim-positional-encoding/blob/master/positional_encodings/torch_encodings.py self . register_buffer ( \"pe1\" , pe1 ) self . register_buffer ( \"pe2\" , pe2 ) forward Parameters: x ( Tensor ) \u2013 Tensor, shape [seq_len, batch_size, embedding_dim] Source code in scprint/model/encoders.py 148 149 150 151 152 153 154 155 def forward ( self , x : Tensor , pos_x : Tensor , pos_y : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] \"\"\" x = x + self . pe1 [ pos_x ] x = x + self . pe2 [ pos_y ] return x GeneEncoder Bases: Module Encodes gene sequences into a continuous vector space using an embedding layer. The output is then normalized using a LayerNorm. Parameters: num_embeddings ( int ) \u2013 The number of possible values. embedding_dim ( int ) \u2013 The dimension of the output vectors. padding_idx ( int , default: None ) \u2013 The index of the padding token. Defaults to None. weights ( Tensor , default: None ) \u2013 The initial weights for the embedding layer. Defaults to None. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. freeze ( bool , default: False ) \u2013 Whether to freeze the weights of the embedding layer. Defaults to False. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def __init__ ( self , num_embeddings : int , embedding_dim : int , padding_idx : Optional [ int ] = None , weights : Optional [ Tensor ] = None , freeze : bool = False , ): \"\"\" Encodes gene sequences into a continuous vector space using an embedding layer. The output is then normalized using a LayerNorm. Args: num_embeddings (int): The number of possible values. embedding_dim (int): The dimension of the output vectors. padding_idx (int, optional): The index of the padding token. Defaults to None. weights (Tensor, optional): The initial weights for the embedding layer. Defaults to None. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. freeze (bool, optional): Whether to freeze the weights of the embedding layer. Defaults to False. Note: not used in the current version of scprint. \"\"\" super ( GeneEncoder , self ) . __init__ () self . embedding = nn . Embedding ( num_embeddings , embedding_dim , padding_idx = padding_idx , _freeze = freeze ) if weights is not None : # concat a zero vector to the weight # this is to make the embedding of the padding token to be zero # weights = torch.cat( # [torch.Tensor(weights), torch.zeros(1, embedding_dim)], dim=0 # ) self . embedding . weight . data . copy_ ( torch . Tensor ( weights )) PositionalEncoding Bases: Module The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. max_len ( int ) \u2013 The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 def __init__ ( self , d_model : int , max_len : int , token_to_pos : dict [ str , int ], # [token, pos] maxval = 10000.0 , ): \"\"\" The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Args: d_model (int): The dimension of the input vectors. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. max_len (int, optional): The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. \"\"\" super ( PositionalEncoding , self ) . __init__ () position = torch . arange ( max_len ) . unsqueeze ( 1 ) # Create a dictionary to convert token to position div_term = torch . exp ( torch . arange ( 0 , d_model , 2 ) * ( - math . log ( maxval ) / d_model ) ) pe = torch . zeros ( max_len , 1 , d_model ) pe [:, 0 , 0 :: 2 ] = torch . sin ( position * div_term ) pe [:, 0 , 1 :: 2 ] = torch . cos ( position * div_term ) # we reorder them and map them to gene_id (position) arr = [] for _ , v in token_to_pos . items (): arr . append ( pe [ v - 1 ] . numpy ()) pe = torch . Tensor ( np . array ( arr )) self . register_buffer ( \"pe\" , pe ) forward Parameters: x \u2013 Tensor, shape [seq_len, batch_size, embedding_dim] Source code in scprint/model/encoders.py 88 89 90 91 92 93 94 95 def forward ( self , gene_pos : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] \"\"\" return torch . index_select ( self . pe , 0 , gene_pos . view ( - 1 )) . view ( gene_pos . shape + ( - 1 ,) ) scprint.model.decoders ClsDecoder Bases: Module ClsDecoder Decoder for classification task. Parameters: d_model ( int ) \u2013 int, dimension of the input. n_cls ( int ) \u2013 int, number of classes. layers ( list [ int ] , default: [256, 128] ) \u2013 list[int], list of hidden layers. activation ( Callable , default: ReLU ) \u2013 nn.Module, activation function. dropout ( float , default: 0.1 ) \u2013 float, dropout rate. Returns: \u2013 Tensor, shape [batch_size, n_cls] Source code in scprint/model/decoders.py 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 def __init__ ( self , d_model : int , n_cls : int , layers : list [ int ] = [ 256 , 128 ], activation : Callable = nn . ReLU , dropout : float = 0.1 , ): \"\"\" ClsDecoder Decoder for classification task. Args: d_model: int, dimension of the input. n_cls: int, number of classes. layers: list[int], list of hidden layers. activation: nn.Module, activation function. dropout: float, dropout rate. Returns: Tensor, shape [batch_size, n_cls] \"\"\" super ( ClsDecoder , self ) . __init__ () # module list layers = [ d_model ] + layers self . decoder = nn . Sequential () for i , l in enumerate ( layers [ 1 :]): self . decoder . append ( nn . Linear ( layers [ i ], l )) self . decoder . append ( nn . LayerNorm ( l )) self . decoder . append ( activation ()) self . decoder . append ( nn . Dropout ( dropout )) self . out_layer = nn . Linear ( layers [ - 1 ], n_cls ) forward Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, embsize] Source code in scprint/model/decoders.py 206 207 208 209 210 211 212 def forward ( self , x : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, embsize] \"\"\" x = self . decoder ( x ) return self . out_layer ( x ) ExprDecoder Bases: Module ExprDecoder Decoder for the gene expression prediction. Will output the mean, variance and zero logits, parameters of a zero inflated negative binomial distribution. Parameters: d_model ( int ) \u2013 The dimension of the model. This is the size of the input feature vector. nfirst_tokens_to_skip ( int , default: 0 ) \u2013 The number of initial labels to skip in the sequence. Defaults to 0. dropout ( float , default: 0.1 ) \u2013 The dropout rate applied during training to prevent overfitting. Defaults to 0.1. zinb ( bool , default: True ) \u2013 Whether to use a zero inflated negative binomial distribution. Defaults to True. Source code in scprint/model/decoders.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 def __init__ ( self , d_model : int , nfirst_tokens_to_skip : int = 0 , dropout : float = 0.1 , zinb : bool = True , ): \"\"\" ExprDecoder Decoder for the gene expression prediction. Will output the mean, variance and zero logits, parameters of a zero inflated negative binomial distribution. Args: d_model (int): The dimension of the model. This is the size of the input feature vector. nfirst_tokens_to_skip (int, optional): The number of initial labels to skip in the sequence. Defaults to 0. dropout (float, optional): The dropout rate applied during training to prevent overfitting. Defaults to 0.1. zinb (bool, optional): Whether to use a zero inflated negative binomial distribution. Defaults to True. \"\"\" super ( ExprDecoder , self ) . __init__ () self . nfirst_tokens_to_skip = nfirst_tokens_to_skip self . fc = nn . Sequential ( nn . Linear ( d_model , d_model ), nn . LayerNorm ( d_model ), nn . LeakyReLU (), nn . Dropout ( dropout ), nn . Linear ( d_model , d_model ), nn . LayerNorm ( d_model ), nn . LeakyReLU (), ) self . pred_var_zero = nn . Linear ( d_model , 3 if zinb else 1 ) self . zinb = zinb forward x is the output of the transformer, (batch, seq_len, d_model) Source code in scprint/model/decoders.py 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 def forward ( self , x : Tensor ) -> Dict [ str , Tensor ]: \"\"\"x is the output of the transformer, (batch, seq_len, d_model)\"\"\" # we don't do it on the labels x = self . fc ( x [:, self . nfirst_tokens_to_skip :, :]) if self . zinb : pred_value , var_value , zero_logits = self . pred_var_zero ( x ) . split ( 1 , dim =- 1 ) # (batch, seq_len) # The sigmoid function is used to map the zero_logits to a probability between 0 and 1. return dict ( mean = F . softmax ( pred_value . squeeze ( - 1 ), dim =- 1 ), disp = torch . exp ( torch . clamp ( var_value . squeeze ( - 1 ), max = 15 )), zero_logits = zero_logits . squeeze ( - 1 ), ) else : pred_value = self . pred_var_zero ( x ) return dict ( mean = F . softmax ( pred_value . squeeze ( - 1 ), dim =- 1 )) GraphSDEExprDecoder Bases: Module Initialize the ExprNeuralSDEDecoder module. Parameters: d_model ( int ) \u2013 The dimension of the model. drift ( Module ) \u2013 The drift component of the SDE. diffusion ( Module ) \u2013 The diffusion component of the SDE. Source code in scprint/model/decoders.py 8 9 10 11 12 13 14 15 16 17 18 19 20 def __init__ ( self , d_model : int , drift : nn . Module , diffusion : nn . Module ): \"\"\" Initialize the ExprNeuralSDEDecoder module. Args: d_model (int): The dimension of the model. drift (nn.Module): The drift component of the SDE. diffusion (nn.Module): The diffusion component of the SDE. \"\"\" super () . __init__ () self . d_model = d_model self . drift = drift self . diffusion = diffusion MVCDecoder Bases: Module MVCDecoder Decoder for the masked value prediction for cell embeddings. Will use the gene embeddings with the cell embeddings to predict the mean, variance and zero logits Parameters: d_model \u2013 obj: int ): dimension of the gene embedding. arch_style \u2013 obj: str ): architecture style of the decoder, choice from 1. \"inner product\" or 2. \"cell product\" 3. \"concat query\" or 4. \"sum query\". query_activation \u2013 obj: nn.Module ): activation function for the query vectors. Defaults to nn.Sigmoid. hidden_activation \u2013 obj: nn.Module ): activation function for the hidden layers. Defaults to nn.PReLU. Source code in scprint/model/decoders.py 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 def __init__ ( self , d_model : int , arch_style : str = \"inner product\" , tot_labels : int = 1 , query_activation : nn . Module = nn . Sigmoid , hidden_activation : nn . Module = nn . PReLU , ) -> None : \"\"\" MVCDecoder Decoder for the masked value prediction for cell embeddings. Will use the gene embeddings with the cell embeddings to predict the mean, variance and zero logits Args: d_model (:obj:`int`): dimension of the gene embedding. arch_style (:obj:`str`): architecture style of the decoder, choice from 1. \"inner product\" or 2. \"cell product\" 3. \"concat query\" or 4. \"sum query\". query_activation (:obj:`nn.Module`): activation function for the query vectors. Defaults to nn.Sigmoid. hidden_activation (:obj:`nn.Module`): activation function for the hidden layers. Defaults to nn.PReLU. \"\"\" super ( MVCDecoder , self ) . __init__ () if arch_style == \"inner product\" : self . gene2query = nn . Linear ( d_model , d_model ) self . norm = nn . LayerNorm ( d_model ) self . query_activation = query_activation () self . pred_var_zero = nn . Linear ( d_model , d_model * 3 , bias = False ) elif arch_style == \"concat query\" : self . gene2query = nn . Linear ( d_model , d_model ) self . query_activation = query_activation () self . fc1 = nn . Linear ( d_model * ( 1 + tot_labels ), d_model / 2 ) self . hidden_activation = hidden_activation () self . fc2 = nn . Linear ( d_model / 2 , 3 ) elif arch_style == \"sum query\" : self . gene2query = nn . Linear ( d_model , d_model ) self . query_activation = query_activation () self . fc1 = nn . Linear ( d_model , 64 ) self . hidden_activation = hidden_activation () self . fc2 = nn . Linear ( 64 , 3 ) else : raise ValueError ( f \"Unknown arch_style: { arch_style } \" ) self . arch_style = arch_style self . do_detach = arch_style . endswith ( \"detach\" ) self . d_model = d_model forward Parameters: cell_emb ( Tensor ) \u2013 Tensor, shape (batch, embsize=d_model) gene_embs ( Tensor ) \u2013 Tensor, shape (batch, seq_len, embsize=d_model) Source code in scprint/model/decoders.py 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 def forward ( self , cell_emb : Tensor , gene_embs : Tensor , ) -> Union [ Tensor , Dict [ str , Tensor ]]: \"\"\" Args: cell_emb: Tensor, shape (batch, embsize=d_model) gene_embs: Tensor, shape (batch, seq_len, embsize=d_model) \"\"\" if self . arch_style == \"inner product\" : query_vecs = self . query_activation ( self . norm ( self . gene2query ( gene_embs ))) pred , var , zero_logits = self . pred_var_zero ( query_vecs ) . split ( self . d_model , dim =- 1 ) cell_emb = cell_emb . unsqueeze ( 2 ) pred , var , zero_logits = ( torch . bmm ( pred , cell_emb ) . squeeze ( 2 ), torch . bmm ( var , cell_emb ) . squeeze ( 2 ), torch . bmm ( zero_logits , cell_emb ) . squeeze ( 2 ), ) # zero logits need to based on the cell_emb, because of input exprs elif self . arch_style == \"concat query\" : query_vecs = self . query_activation ( self . gene2query ( gene_embs )) # expand cell_emb to (batch, seq_len, embsize) cell_emb = cell_emb . unsqueeze ( 1 ) . expand ( - 1 , gene_embs . shape [ 1 ], - 1 ) h = self . hidden_activation ( self . fc1 ( torch . cat ([ cell_emb , query_vecs ], dim = 2 )) ) pred , var , zero_logits = self . fc2 ( h ) . split ( 1 , dim =- 1 ) elif self . arch_style == \"sum query\" : query_vecs = self . query_activation ( self . gene2query ( gene_embs )) cell_emb = cell_emb . unsqueeze ( 1 ) h = self . hidden_activation ( self . fc1 ( cell_emb + query_vecs )) pred , var , zero_logits = self . fc2 ( h ) . split ( 1 , dim =- 1 ) return dict ( mvc_mean = F . softmax ( pred , dim =- 1 ), mvc_disp = torch . exp ( torch . clamp ( var , max = 15 )), mvc_zero_logits = zero_logits , ) flashattention scprint.model.flash_attn.flashformer FlashTransformerEncoder Bases: Module FlashTransformerEncoder a transformer encoder with flash attention. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. nhead ( int ) \u2013 The number of attention heads. nlayers ( int ) \u2013 The number of layers in the transformer. dropout ( float , default: 0.1 ) \u2013 The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. residual_in_fp32 ( bool , default: True ) \u2013 Whether to force the residual to be in fp32 format. Defaults to True. num_heads_kv ( _type_ , default: None ) \u2013 The number of heads for key/value. Defaults to None. checkpointing ( bool , default: False ) \u2013 Whether to use gradient checkpointing. Defaults to False. fused_dropout_add_ln ( bool , default: False ) \u2013 Whether to fuse dropout, addition and layer normalization operations. Defaults to False. return_residual ( bool , default: False ) \u2013 Whether to return the residual. Defaults to False. prenorm ( bool , default: True ) \u2013 Whether to use pre-normalization. Defaults to True. mlp_ratio ( float , default: 4.0 ) \u2013 The ratio for MLP. Defaults to 4.0. fused_mlp ( bool , default: False ) \u2013 Whether to use fused MLP. Defaults to False. fused_bias_fc ( bool , default: False ) \u2013 Whether to fuse bias and fully connected layers. Defaults to False. sequence_parallel ( bool , default: False ) \u2013 Whether to use sequence parallelism. Defaults to False. drop_path_rate ( float , default: 0.0 ) \u2013 The drop path rate. Defaults to 0.0. weight_init ( str , default: '' ) \u2013 The weight initialization method. Defaults to \"\". Raises: ImportError \u2013 Raised when Triton is not installed but fused_dropout_add_ln is set to True. NotImplementedError \u2013 Raised when an unsupported operation is attempted. Source code in scprint/model/flash_attn/flashformer.py 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 def __init__ ( self , d_model : int , nhead : int , nlayers : int , dropout : float = 0.1 , residual_in_fp32 : bool = True , num_heads_kv : Optional [ int ] = None , checkpointing : bool = False , fused_dropout_add_ln : bool = False , return_residual : bool = False , prenorm : bool = True , mlp_ratio : float = 4.0 , fused_mlp : bool = False , fused_bias_fc : bool = False , sequence_parallel : bool = False , drop_path_rate : float = 0.0 , use_flash_attn : bool = True , weight_init : str = \"\" , ): \"\"\" FlashTransformerEncoder a transformer encoder with flash attention. Args: d_model (int): The dimension of the input vectors. nhead (int): The number of attention heads. nlayers (int): The number of layers in the transformer. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. residual_in_fp32 (bool, optional): Whether to force the residual to be in fp32 format. Defaults to True. num_heads_kv (_type_, optional): The number of heads for key/value. Defaults to None. checkpointing (bool, optional): Whether to use gradient checkpointing. Defaults to False. fused_dropout_add_ln (bool, optional): Whether to fuse dropout, addition and layer normalization operations. Defaults to False. return_residual (bool, optional): Whether to return the residual. Defaults to False. prenorm (bool, optional): Whether to use pre-normalization. Defaults to True. mlp_ratio (float, optional): The ratio for MLP. Defaults to 4.0. fused_mlp (bool, optional): Whether to use fused MLP. Defaults to False. fused_bias_fc (bool, optional): Whether to fuse bias and fully connected layers. Defaults to False. sequence_parallel (bool, optional): Whether to use sequence parallelism. Defaults to False. drop_path_rate (float, optional): The drop path rate. Defaults to 0.0. weight_init (str, optional): The weight initialization method. Defaults to \"\". Raises: ImportError: Raised when Triton is not installed but fused_dropout_add_ln is set to True. NotImplementedError: Raised when an unsupported operation is attempted. \"\"\" super ( FlashTransformerEncoder , self ) . __init__ () self . blocks = nn . ModuleList () dpr = [ x . item () for x in torch . linspace ( 0 , drop_path_rate , nlayers ) ] # stochastic depth decay rule for i in range ( nlayers ): mlp = create_mlp_cls ( d_model , mlp_ratio , nn . GELU , fused_mlp ) attention = partial ( MHA , num_heads = nhead , dropout = dropout , causal = False , use_flash_attn = use_flash_attn , num_heads_kv = num_heads_kv , checkpointing = checkpointing , fused_bias_fc = fused_bias_fc , layer_idx = i , ) # or use parallelBlock where attn & MLP are done in parallel encoder_layers = Block ( d_model , attention , mlp , prenorm = prenorm , # need to set it here for now although it hinders some performances as it returns the residual and I need to see what to do with it # TD [2022-07-30]: Force residual in fp32, seems to make fp16 training more stable residual_in_fp32 = residual_in_fp32 , sequence_parallel = sequence_parallel , # for more parallelism resid_dropout1 = dropout , resid_dropout2 = dropout , drop_path1 = dpr [ i - 1 ] if i > 0 else 0.0 , drop_path2 = dpr [ i ], fused_dropout_add_ln = fused_dropout_add_ln , return_residual = return_residual , ) self . blocks . append ( encoder_layers ) self . prenorm = prenorm self . dropout = nn . Dropout ( p = dropout ) self . drop_path = StochasticDepth ( p = dpr [ - 1 ], mode = \"row\" ) self . norm = torch . nn . LayerNorm ( d_model , eps = 1e-6 ) self . fused_dropout_add_ln = fused_dropout_add_ln if self . fused_dropout_add_ln and layer_norm_fn is None : raise ImportError ( \"Triton is not installed\" ) if sequence_parallel : # This seems to only be important when doing tensor parallelism across GPUs, to increase even more the context length I guess? # not really necessary here I think raise NotImplementedError ( \"sequence_parallel not implemented yet\" ) self . init_weights ( weight_init ) scprint.model.flash_attn.mha CrossAttention Bases: Module Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. Default to 1/sqrt(d_keys) where d_keys is computed at runtime attention_dropout: The dropout rate to apply to the attention. default to 0.0. Source code in scprint/model/flash_attn/mha.py 245 246 247 248 249 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 ): super () . __init__ () self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout ) forward Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, Sk) Source code in scprint/model/flash_attn/mha.py 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 def forward ( self , q , kv , causal = None , key_padding_mask = None , bias = None ): \"\"\"Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, Sk) \"\"\" batch_size , seqlen_q = q . shape [ 0 ], q . shape [ 1 ] causal = self . causal if causal is None else causal seqlen_k = kv . shape [ 1 ] assert kv . shape [ 0 ] == batch_size and kv . shape [ 4 ] == q . shape [ 3 ] if kv . shape [ 3 ] != q . shape [ 2 ]: # MQA/GQA kv = repeat ( kv , \"... hkv d -> ... (hkv g) d\" , g = q . shape [ 2 ] // kv . shape [ 3 ]) k , v = kv . unbind ( dim = 2 ) softmax_scale = self . softmax_scale or 1.0 / math . sqrt ( q . shape [ - 1 ]) scores = torch . einsum ( \"bthd,bshd->bhts\" , q , k * softmax_scale ) if key_padding_mask is not None : padding_mask = torch . full ( ( batch_size , seqlen_k ), - 10000.0 , dtype = scores . dtype , device = scores . device , ) padding_mask . masked_fill_ ( key_padding_mask , 0.0 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + rearrange ( padding_mask , \"b s -> b 1 1 s\" ) if causal : # causal mask needs to take into account the difference between seqlen_q and seqlen_k row_idx = rearrange ( torch . arange ( seqlen_q , device = q . device , dtype = torch . long ), \"s -> s 1\" ) col_idx = torch . arange ( seqlen_k , device = kv . device , dtype = torch . long ) sk = ( seqlen_k if key_padding_mask is None else rearrange ( key_padding_mask . sum ( - 1 ), \"b -> b 1 1 1\" ) ) causal_mask = col_idx > row_idx + sk - seqlen_q scores = scores . masked_fill ( causal_mask , - 10000.0 ) attention = torch . softmax ( scores , dim =- 1 , dtype = v . dtype ) attention_drop = self . drop ( attention ) output = torch . einsum ( \"bhts,bshd->bthd\" , attention_drop , v ) return output FlashCrossAttention Bases: Module Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The dropout rate to apply to the attention (default: 0.0) Source code in scprint/model/flash_attn/mha.py 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 , alibi_slopes = None , deterministic = False , ): \"\"\" Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The dropout rate to apply to the attention (default: 0.0) \"\"\" super () . __init__ () assert flash_attn_kvpacked_func is not None , \"FlashAttention is not installed\" assert flash_attn_kvpacked_func is not None , \"FlashAttention is not installed\" self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout ) self . register_buffer ( \"alibi_slopes\" , alibi_slopes , persistent = False ) self . deterministic = deterministic forward Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into q. max_seqlen: int. Maximum sequence length in the batch of q. cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into kv. max_seqlen_k: int. Maximum sequence length in the batch of k and v. Source code in scprint/model/flash_attn/mha.py 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 def forward ( self , q , kv , causal = None , cu_seqlens = None , max_seqlen = None , cu_seqlens_k = None , max_seqlen_k = None , ): \"\"\" Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into q. max_seqlen: int. Maximum sequence length in the batch of q. cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into kv. max_seqlen_k: int. Maximum sequence length in the batch of k and v. \"\"\" assert q . dtype in [ torch . float16 , torch . bfloat16 ] assert q . is_cuda and kv . is_cuda causal = self . causal if causal is None else causal batch_size , seqlen_q = q . shape [ 0 ], q . shape [ 1 ] assert kv . shape [ 0 ] == batch_size and kv . shape [ 4 ] == q . shape [ 3 ] return flash_attn_kvpacked_func ( q , kv , None , # self.drop.p if self.training else 0.0, causal , self . softmax_scale , # alibi_slopes=self.alibi_slopes, # deterministic=self.deterministic, ) FlashSelfAttention Bases: Module Implement the scaled dot product attention with softmax. Parameters: softmax_scale ( float , default: None ) \u2013 The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout ( float , default: 0.0 ) \u2013 The dropout rate to apply to the attention (default: 0.0) causal ( bool , default: False ) \u2013 Whether to use causal attention. Defaults to False. Source code in scprint/model/flash_attn/mha.py 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 def __init__ ( self , causal : bool = False , softmax_scale : Optional [ float ] = None , attention_dropout : float = 0.0 , alibi_slopes : Optional [ Any ] = None , deterministic : bool = False , use_triton : bool = False , ): \"\"\"Implement the scaled dot product attention with softmax. Args: softmax_scale (float, optional): The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout (float, optional): The dropout rate to apply to the attention (default: 0.0) causal (bool, optional): Whether to use causal attention. Defaults to False. \"\"\" super () . __init__ () if flash_attn_qkvpacked_func is None : print ( \"FlashAttention is not installed, using triton instead\" ) use_triton = True self . use_triton = use_triton self . causal = causal self . softmax_scale = softmax_scale forward Implements the multihead softmax attention. Args qkv (Tensor): The tensor containing the query, key, and value. If cu_seqlens is None and max_seqlen is None, then qkv has shape (B, S, 3, H, D). If cu_seqlens is not None and max_seqlen is not None, then qkv has shape (total, 3, H, D), where total is the sum of the sequence lengths in the batch. causal (bool): if passed, will override self.causal cu_seqlens (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into qkv. max_seqlen (int). Maximum sequence length in the batch. Returns: out: (total, H, D) if cu_seqlens is not None and max_seqlen is not None, else (B, S, H, D). Source code in scprint/model/flash_attn/mha.py 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 def forward ( self , qkv : torch . Tensor , causal : Optional [ bool ] = None , cu_seqlens : Optional [ torch . Tensor ] = None , max_seqlen : Optional [ int ] = None , cu_seqlens_k : Optional [ torch . Tensor ] = None , max_seqlen_k : Optional [ int ] = None , bias : Optional [ torch . Tensor ] = None , ** kwargs , ): \"\"\"Implements the multihead softmax attention. Args qkv (Tensor): The tensor containing the query, key, and value. If cu_seqlens is None and max_seqlen is None, then qkv has shape (B, S, 3, H, D). If cu_seqlens is not None and max_seqlen is not None, then qkv has shape (total, 3, H, D), where total is the sum of the sequence lengths in the batch. causal (bool): if passed, will override self.causal cu_seqlens (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into qkv. max_seqlen (int). Maximum sequence length in the batch. Returns: out: (total, H, D) if cu_seqlens is not None and max_seqlen is not None, else (B, S, H, D). \"\"\" assert qkv . dtype in [ torch . float16 , torch . bfloat16 ] assert qkv . is_cuda causal = self . causal if causal is None else causal if self . use_triton : raise NotImplementedError ( \"OpenAI's flashattention is not implemented\" ) if qkv . stride ( - 1 ) != 1 : qkv = qkv . contiguous () # return triton_attention( # qkv[:, :, 0], # qkv[:, :, 1], # qkv[:, :, 2], # bias, # causal, # self.softmax_scale, # ) else : return flash_attn_qkvpacked_func ( qkv , bias , # self.drop.p if self.training else 0.0, causal , self . softmax_scale , ) LinearResidual Bases: Linear Wrap nn.Linear to return the residual as well. For compatibility with FusedDense. MHA Bases: Module MHA Multi-head self-attention and cross-attention Parameters: num_heads_kv ( int , default: None ) \u2013 can be used to toggle MQA / GQA. If None, use num_heads. return_residual ( bool , default: False ) \u2013 whether to return the input x along with the output. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. checkpointing ( bool , default: False ) \u2013 whether to use checkpointing to save memory. Defaults to False. num_heads_kv ( int , default: None ) \u2013 can be used to toggle MQA / GQA. If None, use num_heads. cross_attn ( bool , default: False ) \u2013 whether to use cross-attention. Defaults to False. qkv_proj_bias ( bool , default: True ) \u2013 whether to use bias in the query, key, value projection. Defaults to True. out_proj_bias ( bool , default: True ) \u2013 whether to use bias in the output projection. Defaults to True. dropout ( float , default: 0.0 ) \u2013 dropout rate. Defaults to 0.0. softmax_scale ( float , default: None ) \u2013 The temperature to use for the softmax attention. causal ( bool , default: False ) \u2013 whether to use causal attention. Defaults to False. layer_idx ( int , default: None ) \u2013 layer index for inference cache. Defaults to None. dwconv ( bool , default: False ) \u2013 whether to use depthwise convolution. Defaults to False. fused_bias_fc ( bool , default: False ) \u2013 whether to use fused_bias_fc. Defaults to False. use_flash_attn ( bool , default: False ) \u2013 whether to use FlashAttention. Defaults to False. device ( device , default: None ) \u2013 device. Defaults to None. dtype ( dtype , default: None ) \u2013 dtype. Defaults to None. Source code in scprint/model/flash_attn/mha.py 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 def __init__ ( self , embed_dim : int , num_heads : int , num_heads_kv : Optional [ int ] = None , cross_attn : bool = False , qkv_proj_bias : bool = True , out_proj_bias : bool = True , dropout : float = 0.0 , softmax_scale : Optional [ float ] = None , causal : bool = False , layer_idx : Optional [ int ] = None , dwconv : bool = False , rotary_emb_dim : int = 0 , rotary_emb_base : float = 10000.0 , rotary_emb_scale_base : Optional [ float ] = None , rotary_emb_interleaved : bool = False , use_alibi : bool = False , fused_bias_fc : bool = False , use_flash_attn : bool = False , return_residual : bool = False , checkpointing : bool = False , device : Optional [ torch . device ] = None , dtype : Optional [ torch . dtype ] = None , ) -> None : \"\"\" MHA Multi-head self-attention and cross-attention Args: embed_dim num_heads_kv (int): can be used to toggle MQA / GQA. If None, use num_heads. return_residual (bool, optional): whether to return the input x along with the output. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. checkpointing (bool, optional): whether to use checkpointing to save memory. Defaults to False. num_heads_kv (int, optional): can be used to toggle MQA / GQA. If None, use num_heads. cross_attn (bool, optional): whether to use cross-attention. Defaults to False. qkv_proj_bias (bool, optional): whether to use bias in the query, key, value projection. Defaults to True. out_proj_bias (bool, optional): whether to use bias in the output projection. Defaults to True. dropout (float, optional): dropout rate. Defaults to 0.0. softmax_scale (float, optional): The temperature to use for the softmax attention. causal (bool, optional): whether to use causal attention. Defaults to False. layer_idx (int, optional): layer index for inference cache. Defaults to None. dwconv (bool, optional): whether to use depthwise convolution. Defaults to False. fused_bias_fc (bool, optional): whether to use fused_bias_fc. Defaults to False. use_flash_attn (bool, optional): whether to use FlashAttention. Defaults to False. device (torch.device, optional): device. Defaults to None. dtype (torch.dtype, optional): dtype. Defaults to None. \"\"\" factory_kwargs = { \"device\" : device , \"dtype\" : dtype } super () . __init__ () self . embed_dim = embed_dim self . cross_attn = cross_attn self . causal = causal self . layer_idx = layer_idx self . dwconv = dwconv self . rotary_emb_dim = rotary_emb_dim self . use_flash_attn = use_flash_attn if self . use_flash_attn and ( flash_attn_kvpacked_func is None ): print ( \"you requested flash transformer but it requires the flash package which is not installed\" ) print ( \"falling back to regular transformer...\" ) self . use_flash_attn = False # NOT flash transformer using the special tritton kernel # or parallelMHA (add the process group thing and faster) self . return_residual = return_residual self . checkpointing = checkpointing alibi_slopes = None self . num_heads = num_heads self . num_heads_kv = num_heads_kv if num_heads_kv is not None else num_heads assert ( self . num_heads % self . num_heads_kv == 0 ), \"num_heads must be divisible by num_heads_kv\" assert ( self . embed_dim % num_heads == 0 ), \"embed_dim must be divisible by num_heads\" self . head_dim = self . embed_dim // num_heads qkv_dim = self . head_dim * ( self . num_heads + 2 * self . num_heads_kv ) kv_dim = 2 * self . head_dim * self . num_heads_kv if self . rotary_emb_dim > 0 : assert ( not cross_attn ), \"MHA with rotary embedding does not support cross-attention yet\" assert RotaryEmbedding is not None , \"rotary_emb is not installed\" self . rotary_emb = RotaryEmbedding ( self . rotary_emb_dim , base = rotary_emb_base , scale_base = rotary_emb_scale_base , interleaved = rotary_emb_interleaved , device = device , ) if fused_bias_fc and FusedDense is None : raise ImportError ( \"fused_dense is not installed\" ) linear_cls = nn . Linear if not fused_bias_fc else FusedDense linear_resid_cls = ( LinearResidual if not fused_bias_fc else partial ( FusedDense , return_residual = True ) ) wqkv_cls = linear_cls if not self . return_residual else linear_resid_cls inner_attn_cls = ( partial ( FlashSelfAttention , alibi_slopes = alibi_slopes ) if self . use_flash_attn else SelfAttention ) inner_cross_attn_cls = ( partial ( FlashCrossAttention , alibi_slopes = alibi_slopes ) if self . use_flash_attn else CrossAttention ) if not self . cross_attn : self . Wqkv = wqkv_cls ( embed_dim , qkv_dim , bias = qkv_proj_bias , ** factory_kwargs ) else : self . Wq = linear_cls ( embed_dim , embed_dim , bias = qkv_proj_bias , ** factory_kwargs ) self . Wkv = wqkv_cls ( embed_dim , kv_dim , bias = qkv_proj_bias , ** factory_kwargs ) if self . dwconv : if self . num_heads_kv == self . num_heads : self . dwconv_qkv = nn . Conv1d ( qkv_dim , qkv_dim , kernel_size = 3 , padding = 2 , groups = qkv_dim ) else : self . dwconv_q = nn . Conv1d ( embed_dim , embed_dim , kernel_size = 3 , padding = 2 , groups = embed_dim ) self . dwconv_kv = nn . Conv1d ( kv_dim , kv_dim , kernel_size = 3 , padding = 2 , groups = kv_dim ) self . inner_attn = inner_attn_cls ( causal = causal , softmax_scale = softmax_scale , attention_dropout = dropout , ) self . inner_cross_attn = inner_cross_attn_cls ( causal = causal , softmax_scale = softmax_scale , attention_dropout = dropout ) self . out_proj = linear_cls ( embed_dim , embed_dim , bias = out_proj_bias , ** factory_kwargs ) forward Parameters: x ( Tensor ) \u2013 (batch, seqlen, hidden_dim) (where hidden_dim = num heads * head dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the is the sum of the sequence lengths in the batch. x_kv ( Optional [ Tensor ] , default: None ) \u2013 (batch, seqlen, hidden_dim), only applicable for cross-attention. If None, use x. cu_seqlens ( Optional [ Tensor ] , default: None ) \u2013 (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into x. Only applicable when using FlashAttention. max_seqlen ( Optional [ int ] , default: None ) \u2013 int. Maximum sequence length in the batch. key_padding_mask ( Optional [ Tensor ] , default: None ) \u2013 boolean mask, True means to keep, False means to mask out. (batch, seqlen). Only applicable when not using FlashAttention. mixer_subset ( Optional [ Tensor ] , default: None ) \u2013 for cross-attention only. If not None, will take a subset of x before applying the query projection. Useful for e.g., ViT where we only care about the CLS token in the last layer. inference_params ( Optional [ dict ] , default: None ) \u2013 for generation. Adapted from Megatron-LM (and Apex) https \u2013 //github.com/NVIDIA/apex/blob/3ff1a10f72ec07067c4e44759442329804ac5162/apex/transformer/testing/standalone_transformer_lm.py#L470 return_qkv ( bool , default: False ) \u2013 whether to return the qkv tensor. Defaults to False. Returns: out \u2013 (batch, seqlen, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the sum of the sequence lengths in the batch. qkv \u2013 (batch, seqlen, 3, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, 3, hidden_dim) where total is the sum of the sequence lengths in the batch. Source code in scprint/model/flash_attn/mha.py 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 def forward ( self , x : torch . Tensor , x_kv : Optional [ torch . Tensor ] = None , key_padding_mask : Optional [ torch . Tensor ] = None , cu_seqlens : Optional [ torch . Tensor ] = None , max_seqlen : Optional [ int ] = None , mixer_subset : Optional [ torch . Tensor ] = None , inference_params : Optional [ dict ] = None , return_qkv : bool = False , ** kwargs , ): \"\"\" Args: x: (batch, seqlen, hidden_dim) (where hidden_dim = num heads * head dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the is the sum of the sequence lengths in the batch. x_kv: (batch, seqlen, hidden_dim), only applicable for cross-attention. If None, use x. cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into x. Only applicable when using FlashAttention. max_seqlen: int. Maximum sequence length in the batch. key_padding_mask: boolean mask, True means to keep, False means to mask out. (batch, seqlen). Only applicable when not using FlashAttention. mixer_subset: for cross-attention only. If not None, will take a subset of x before applying the query projection. Useful for e.g., ViT where we only care about the CLS token in the last layer. inference_params: for generation. Adapted from Megatron-LM (and Apex) https://github.com/NVIDIA/apex/blob/3ff1a10f72ec07067c4e44759442329804ac5162/apex/transformer/testing/standalone_transformer_lm.py#L470 return_qkv: whether to return the qkv tensor. Defaults to False. Returns: out: (batch, seqlen, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the sum of the sequence lengths in the batch. qkv: (batch, seqlen, 3, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, 3, hidden_dim) where total is the sum of the sequence lengths in the batch. \"\"\" if cu_seqlens is not None : assert max_seqlen is not None assert key_padding_mask is None assert self . use_flash_attn assert not self . dwconv assert self . rotary_emb_dim == 0 if key_padding_mask is not None : assert cu_seqlens is None assert max_seqlen is None assert not self . use_flash_attn if inference_params is not None : assert key_padding_mask is None assert cu_seqlens is None and max_seqlen is None assert not self . dwconv kwargs = ( {} # \"cu_seqlens\": cu_seqlens, \"max_seqlen\": max_seqlen, **kwargs} if self . use_flash_attn else { \"key_padding_mask\" : key_padding_mask , ** kwargs } ) seqlen_offset = ( 0 if inference_params is None else ( inference_params . lengths_per_sample if inference_params . lengths_per_sample is not None else inference_params . seqlen_offset ) ) rotary_max_seqlen = ( inference_params . max_seqlen if inference_params is not None else None ) batch , seqlen = x . shape [: 2 ] if not self . cross_attn and self . num_heads_kv == self . num_heads : assert x_kv is None and mixer_subset is None if not self . return_residual : qkv = self . Wqkv ( x ) # .to(torch.float16, device=\"cuda\") else : qkv , x = self . Wqkv ( x ) if self . dwconv : qkv = rearrange ( self . dwconv_qkv ( rearrange ( qkv , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () qkv = rearrange ( qkv , \"... (three h d) -> ... three h d\" , three = 3 , d = self . head_dim ) if ( inference_params is None or inference_params . seqlen_offset == 0 or ( self . rotary_emb_dim == 0 or self . rotary_emb_dim % 16 != 0 ) or not self . use_flash_attn ): if self . rotary_emb_dim > 0 : qkv = self . rotary_emb ( qkv , seqlen_offset = seqlen_offset , max_seqlen = rotary_max_seqlen ) if inference_params is None : if not self . checkpointing : context = self . inner_attn ( qkv , ** kwargs ) else : context = torch . utils . checkpoint . checkpoint ( self . inner_attn , qkv , ** kwargs ) else : context = self . _update_kvcache_attention ( qkv [:, :, 0 ], qkv [:, :, 1 :], inference_params ) else : context = self . _apply_rotary_update_kvcache_attention ( qkv [:, :, 0 ], qkv [:, :, 1 :], inference_params ) else : if self . cross_attn : if not self . return_residual : q = self . Wq ( x if mixer_subset is None else x [:, mixer_subset ]) kv = self . Wkv ( x_kv if x_kv is not None else x ) else : if x_kv is not None : kv , x_kv = self . Wkv ( x_kv ) else : kv , x = self . Wkv ( x ) q = self . Wq ( x if mixer_subset is None else x [:, mixer_subset ]) else : assert self . num_heads_kv != self . num_heads if not self . return_residual : qkv = self . Wqkv ( x ) else : qkv , x = self . Wqkv ( x ) q = qkv [ ... , : self . num_heads * self . head_dim ] kv = qkv [ ... , self . num_heads * self . head_dim :] q = rearrange ( q , \"... (h d) -> ... h d\" , d = self . head_dim ) kv = rearrange ( kv , \"... (two hkv d) -> ... two hkv d\" , two = 2 , d = self . head_dim ) if self . dwconv : q = rearrange ( self . dwconv_q ( rearrange ( q , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () kv = rearrange ( self . dwconv_kv ( rearrange ( kv , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () if ( inference_params is None or inference_params . seqlen_offset == 0 or ( self . rotary_emb_dim == 0 or self . rotary_emb_dim % 16 != 0 ) or not self . use_flash_attn ): if self . rotary_emb_dim > 0 : q , kv = self . rotary_emb ( q , kv , seqlen_offset = seqlen_offset , max_seqlen = rotary_max_seqlen ) if inference_params is None : if not self . checkpointing : context = self . inner_cross_attn ( q , kv , ** kwargs ) else : context = torch . utils . checkpoint . checkpoint ( self . inner_cross_attn , q , kv , ** kwargs ) else : context = self . _update_kvcache_attention ( q , kv , inference_params ) else : context = self . _apply_rotary_update_kvcache_attention ( q , kv , inference_params ) out = self . out_proj ( rearrange ( context , \"... h d -> ... (h d)\" )) if return_qkv : return out if not self . return_residual else ( out , x ), qkv else : return out if not self . return_residual else ( out , x ) SelfAttention Bases: Module Implement the scaled dot product attention with softmax. Parameters: softmax_scale \u2013 The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout \u2013 The dropout rate to apply to the attention (default: 0.0) Source code in scprint/model/flash_attn/mha.py 195 196 197 198 199 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 ): super () . __init__ () self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout ) forward Implements the multihead softmax attention. Parameters: qkv \u2013 The tensor containing the query, key, and value. (B, S, 3, H, D) causal \u2013 if passed, will override self.causal key_padding_mask \u2013 boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, S) Source code in scprint/model/flash_attn/mha.py 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 def forward ( self , qkv , causal = None , key_padding_mask = None , bias = None ): \"\"\" Implements the multihead softmax attention. Args: qkv: The tensor containing the query, key, and value. (B, S, 3, H, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, S) \"\"\" batch_size , seqlen = qkv . shape [ 0 ], qkv . shape [ 1 ] causal = self . causal if causal is None else causal q , k , v = qkv . unbind ( dim = 2 ) softmax_scale = self . softmax_scale or 1.0 / math . sqrt ( q . shape [ - 1 ]) scores = torch . einsum ( \"bthd,bshd->bhts\" , q , k * softmax_scale ) if key_padding_mask is not None : padding_mask = torch . full ( ( batch_size , seqlen ), - 10000.0 , dtype = scores . dtype , device = scores . device ) padding_mask . masked_fill_ ( key_padding_mask , 0.0 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + rearrange ( padding_mask , \"b s -> b 1 1 s\" ) if causal : # \"triu_tril_cuda_template\" not implemented for 'BFloat16' # So we have to construct the mask in float causal_mask = torch . triu ( torch . full (( seqlen , seqlen ), - 10000.0 , device = scores . device ), 1 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + causal_mask . to ( dtype = scores . dtype ) attention = torch . softmax ( scores , dim =- 1 , dtype = v . dtype ) attention_drop = self . drop ( attention ) output = torch . einsum ( \"bhts,bshd->bthd\" , attention_drop , v ) return output scprint.model.flash_attn.mlp Mlp Bases: Module Multi-layer perceptron (MLP) module. Parameters: in_features ( int ) \u2013 Size of each input sample. hidden_features ( Optional [ int ] , default: None ) \u2013 Size of the hidden layer. Defaults to 4 * in_features. out_features ( Optional [ int ] , default: None ) \u2013 Size of each output sample. Defaults to in_features. activation ( Callable [[ Tensor ], Tensor ] , default: gelu ) \u2013 Activation function. Defaults to F.gelu. bias1 ( bool , default: True ) \u2013 If set to False, the first linear layer will not learn an additive bias. Defaults to True. bias2 ( bool , default: True ) \u2013 If set to False, the second linear layer will not learn an additive bias. Defaults to True. return_residual ( bool , default: False ) \u2013 If set to True, the forward method will return a tuple (output, input). Defaults to False. device ( Optional [ device ] , default: None ) \u2013 The desired device of the parameters. Defaults to None. dtype ( Optional [ dtype ] , default: None ) \u2013 The desired data type of the parameters. Defaults to None. Source code in scprint/model/flash_attn/mlp.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 def __init__ ( self , in_features : int , hidden_features : Optional [ int ] = None , out_features : Optional [ int ] = None , activation : Callable [[ torch . Tensor ], torch . Tensor ] = F . gelu , bias1 : bool = True , bias2 : bool = True , return_residual : bool = False , device : Optional [ torch . device ] = None , dtype : Optional [ torch . dtype ] = None , ) -> None : \"\"\" Multi-layer perceptron (MLP) module. Args: in_features (int): Size of each input sample. hidden_features (Optional[int], optional): Size of the hidden layer. Defaults to 4 * in_features. out_features (Optional[int], optional): Size of each output sample. Defaults to in_features. activation (Callable[[torch.Tensor], torch.Tensor], optional): Activation function. Defaults to F.gelu. bias1 (bool, optional): If set to False, the first linear layer will not learn an additive bias. Defaults to True. bias2 (bool, optional): If set to False, the second linear layer will not learn an additive bias. Defaults to True. return_residual (bool, optional): If set to True, the forward method will return a tuple (output, input). Defaults to False. device (Optional[torch.device], optional): The desired device of the parameters. Defaults to None. dtype (Optional[torch.dtype], optional): The desired data type of the parameters. Defaults to None. \"\"\" factory_kwargs = { \"device\" : device , \"dtype\" : dtype } super () . __init__ () out_features = out_features if out_features is not None else in_features hidden_features = ( hidden_features if hidden_features is not None else in_features * 4 ) self . return_residual = return_residual self . fc1 = nn . Linear ( in_features , hidden_features , bias = bias1 , ** factory_kwargs ) self . activation = activation self . fc2 = nn . Linear ( hidden_features , out_features , bias = bias2 , ** factory_kwargs ) forward Forward pass of the MLP. Parameters: x ( Tensor ) \u2013 Input tensor. Returns: Union [ Tensor , Tuple [ Tensor , Tensor ]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: Output tensor, or a tuple (output, input) if return_residual is True. Source code in scprint/model/flash_attn/mlp.py 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 def forward ( self , x : torch . Tensor ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , torch . Tensor ]]: \"\"\" Forward pass of the MLP. Args: x (torch.Tensor): Input tensor. Returns: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: Output tensor, or a tuple (output, input) if return_residual is True. \"\"\" y = self . fc1 ( x ) y = self . activation ( y ) y = self . fc2 ( y ) return y if not self . return_residual else ( y , x ) scprint.model.flash_attn.block Block Bases: Module For prenorm=True, this Block has a slightly different structure compared to a regular prenorm Transformer block. The standard block is: LN -> MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add. [Ref: https://arxiv.org/abs/2002.04745] Here we have: Dropout -> Add -> LN -> MHA -> Dropout -> Add -> LN -> MLP, returning both the hidden_states (output of the MLP) and the residual. This is for performance reasons, as we can fuse the dropout, add and LayerNorm. The residual needs to be provided (except for the very first block). For prenorm=False, this Block has the same structure as a regular postnorm Transformer block: MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add -> LN. Parameters: dim ( int ) \u2013 the number of features in the input. mixer_cls ( Optional [ Callable ] , default: None ) \u2013 the class to use for the mixer layer. Defaults to None. mlp_cls ( Optional [ Callable ] , default: None ) \u2013 the class to use for the mlp layer. Defaults to None. norm_cls ( Callable , default: partial ( LayerNorm , eps=1e-06) ) \u2013 the class to use for the layer norm. Defaults to partial(nn.LayerNorm, eps=1e-6). dropout_cls ( Type [ Dropout ] , default: Dropout ) \u2013 the class to use for the dropout. Defaults to nn.Dropout. prenorm ( bool , default: True ) \u2013 whether to use pre-norm or post-norm. Defaults to True. resid_dropout1 ( float , default: 0.0 ) \u2013 the dropout probability for the first dropout layer. Defaults to 0.0. resid_dropout2 ( float , default: 0.0 ) \u2013 the dropout probability for the second dropout layer. Defaults to 0.0. drop_path1 ( float , default: 0.0 ) \u2013 the drop path probability for the first drop path layer. Defaults to 0.0. drop_path2 ( float , default: 0.0 ) \u2013 the drop path probability for the second drop path layer. Defaults to 0.0. fused_dropout_add_ln ( bool , default: False ) \u2013 whether to fuse the dropout, add and layer norm. Defaults to False. return_residual ( bool , default: False ) \u2013 whether each of the sub-layers (mixer and mlp) will return the residual. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. residual_in_fp32 ( bool , default: False ) \u2013 whether to keep the residual in fp32. This is for performance reason: for post-norm architecture, keeping the residual in fp32 allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. sequence_parallel ( bool , default: False ) \u2013 whether to use sequence parallelism. Defaults to False. mark_shared_params ( bool , default: False ) \u2013 whether to mark the norm parameters as \"shared_params\". This is useful when we want to sync the norm parameters across workers. Defaults to False. Source code in scprint/model/flash_attn/block.py 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 def __init__ ( self , dim : int , mixer_cls : Optional [ Callable ] = None , mlp_cls : Optional [ Callable ] = None , norm_cls : Callable = partial ( nn . LayerNorm , eps = 1e-6 ), dropout_cls : Type [ nn . Dropout ] = nn . Dropout , prenorm : bool = True , resid_dropout1 : float = 0.0 , resid_dropout2 : float = 0.0 , drop_path1 : float = 0.0 , drop_path2 : float = 0.0 , fused_dropout_add_ln : bool = False , return_residual : bool = False , residual_in_fp32 : bool = False , sequence_parallel : bool = False , mark_shared_params : bool = False , ): \"\"\" For prenorm=True, this Block has a slightly different structure compared to a regular prenorm Transformer block. The standard block is: LN -> MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add. [Ref: https://arxiv.org/abs/2002.04745] Here we have: Dropout -> Add -> LN -> MHA -> Dropout -> Add -> LN -> MLP, returning both the hidden_states (output of the MLP) and the residual. This is for performance reasons, as we can fuse the dropout, add and LayerNorm. The residual needs to be provided (except for the very first block). For prenorm=False, this Block has the same structure as a regular postnorm Transformer block: MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add -> LN. Args: dim (int): the number of features in the input. mixer_cls (Optional[Callable], optional): the class to use for the mixer layer. Defaults to None. mlp_cls (Optional[Callable], optional): the class to use for the mlp layer. Defaults to None. norm_cls (Callable, optional): the class to use for the layer norm. Defaults to partial(nn.LayerNorm, eps=1e-6). dropout_cls (Type[nn.Dropout], optional): the class to use for the dropout. Defaults to nn.Dropout. prenorm (bool, optional): whether to use pre-norm or post-norm. Defaults to True. resid_dropout1 (float, optional): the dropout probability for the first dropout layer. Defaults to 0.0. resid_dropout2 (float, optional): the dropout probability for the second dropout layer. Defaults to 0.0. drop_path1 (float, optional): the drop path probability for the first drop path layer. Defaults to 0.0. drop_path2 (float, optional): the drop path probability for the second drop path layer. Defaults to 0.0. fused_dropout_add_ln (bool, optional): whether to fuse the dropout, add and layer norm. Defaults to False. return_residual (bool, optional): whether each of the sub-layers (mixer and mlp) will return the residual. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. residual_in_fp32 (bool, optional): whether to keep the residual in fp32. This is for performance reason: for post-norm architecture, keeping the residual in fp32 allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. sequence_parallel (bool, optional): whether to use sequence parallelism. Defaults to False. mark_shared_params (bool, optional): whether to mark the norm parameters as \"shared_params\". This is useful when we want to sync the norm parameters across workers. Defaults to False. \"\"\" super () . __init__ () self . prenorm = prenorm self . fused_dropout_add_ln = fused_dropout_add_ln self . return_residual = return_residual self . residual_in_fp32 = residual_in_fp32 if self . residual_in_fp32 : assert self . prenorm , \"residual_in_fp32 is only compatible with prenorm=True\" if mixer_cls is None : mixer_cls = partial ( MHA , num_heads = dim // 64 ) if mlp_cls is None : mlp_cls = partial ( Mlp , hidden_features = 4 * dim ) self . mixer = mixer_cls ( dim ) self . dropout1 = dropout_cls ( resid_dropout1 ) self . drop_path1 = StochasticDepth ( drop_path1 , mode = \"row\" ) self . norm1 = norm_cls ( dim ) self . mlp = mlp_cls ( dim ) if not isinstance ( self . mlp , nn . Identity ): self . dropout2 = dropout_cls ( resid_dropout2 ) self . drop_path2 = StochasticDepth ( drop_path2 , mode = \"row\" ) self . norm2 = norm_cls ( dim ) if self . fused_dropout_add_ln : assert layer_norm_fn is not None , \"Triton is not installed\" assert isinstance ( self . norm1 , ( nn . LayerNorm , RMSNorm )) and isinstance ( self . dropout1 , nn . Dropout ) # TD [2023-01-07]: TODO: During training, if sequence_parallel is False and dropout != 0.0, # then the input to each worker in the tensor parallel group will be different. # This would produce wrong outputs? Somehow we'd need to sync the RNG state across workers. # For now this is not an issue because we always use sequence_parallel=True during training # and only use sequence_parallel=False during inference. # Mark the norm parameters as \"sequence_parallel\" so that we run all-reduce on their grads. if sequence_parallel : for p in self . norm1 . parameters (): p . _sequence_parallel = True if hasattr ( self , \"norm2\" ): for p in self . norm2 . parameters (): p . _sequence_parallel = True # Mark the norm parameters as \"shared_params\" so that we sync their values at init. if mark_shared_params : for p in self . norm1 . parameters (): p . _shared_params = True if hasattr ( self , \"norm2\" ): for p in self . norm2 . parameters (): p . _shared_params = True forward Pass the input through the encoder layer. Parameters: hidden_states ( Tensor ) \u2013 The sequence to be passed to the encoder layer. This is a required argument. residual ( Optional [ Tensor ] , default: None ) \u2013 This argument is used differently based on the normalization method. If postnorm is used, residual should be None. If prenorm is used, hidden_states is updated as Attn/MLP(LN(residual)). mixer_subset ( Optional [ Tensor ] , default: None ) \u2013 This argument is used only for cross-attention. If not None, a subset of the input sequence 'x' is taken before applying the query projection. This is particularly useful for models like ViT where only the CLS token in the last layer is of interest. mixer_kwargs ( Optional [ Dict [ str , Any ]] , default: None ) \u2013 This argument is used only for cross-attention. It is a dictionary of additional arguments to be passed to the mixer. return_qkv ( bool , default: False ) \u2013 If True, the function will return the query, key, and value tensors. Returns: \u2013 Tensor or Tuple[Tensor, Tensor]: The output tensor of the encoder layer. \u2013 If return_qkv is True, the function will return a tuple of the output tensor and the query, key, and value tensors. Source code in scprint/model/flash_attn/block.py 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 def forward ( self , hidden_states : Tensor , residual : Optional [ Tensor ] = None , bias : Optional [ Tensor ] = None , src_mask : Optional [ Tensor ] = None , is_causal : Optional [ bool ] = None , src_key_padding_mask : Optional [ Tensor ] = None , mixer_subset : Optional [ Tensor ] = None , mixer_kwargs : Optional [ Dict [ str , Any ]] = None , return_qkv : bool = False , ): r \"\"\"Pass the input through the encoder layer. Args: hidden_states (Tensor): The sequence to be passed to the encoder layer. This is a required argument. residual (Optional[Tensor]): This argument is used differently based on the normalization method. If postnorm is used, residual should be None. If prenorm is used, hidden_states is updated as Attn/MLP(LN(residual)). mixer_subset: This argument is used only for cross-attention. If not None, a subset of the input sequence 'x' is taken before applying the query projection. This is particularly useful for models like ViT where only the CLS token in the last layer is of interest. mixer_kwargs: This argument is used only for cross-attention. It is a dictionary of additional arguments to be passed to the mixer. return_qkv: If True, the function will return the query, key, and value tensors. Returns: Tensor or Tuple[Tensor, Tensor]: The output tensor of the encoder layer. If return_qkv is True, the function will return a tuple of the output tensor and the query, key, and value tensors. \"\"\" if self . prenorm : if not self . fused_dropout_add_ln : dropped = self . drop_path1 ( self . dropout1 ( hidden_states )) residual = ( dropped + residual ) if residual is not None else dropped hidden_states = self . norm1 ( residual . to ( dtype = self . norm1 . weight . dtype )) if self . residual_in_fp32 : residual = residual . to ( torch . float32 ) else : if self . drop_path1 . p == 0 or not self . training : rowscale1 = None else : rowscale1 = self . drop_path1 ( torch . ones ( hidden_states . shape [: - 1 ], device = hidden_states . device , dtype = hidden_states . dtype , ) ) hidden_states , residual = layer_norm_fn ( hidden_states , self . norm1 . weight , self . norm1 . bias , residual = residual , eps = self . norm1 . eps , dropout_p = self . dropout1 . p if self . training else 0.0 , rowscale = rowscale1 , prenorm = True , residual_in_fp32 = self . residual_in_fp32 , is_rms_norm = isinstance ( self . norm1 , RMSNorm ), ) if mixer_kwargs is None : mixer_kwargs = {} if mixer_subset is not None : mixer_kwargs [ \"mixer_subset\" ] = mixer_subset hidden_states = self . mixer ( hidden_states , return_qkv = return_qkv , bias = bias , ** mixer_kwargs ) if return_qkv : qkv = hidden_states [ 1 ] hidden_states = hidden_states [ 0 ] if mixer_subset is not None : residual = residual [:, mixer_subset ] if not isinstance ( self . mlp , nn . Identity ): if not self . fused_dropout_add_ln : dropped = self . drop_path2 ( self . dropout2 ( hidden_states )) residual = ( dropped + residual ) if residual is not None else dropped hidden_states = self . norm2 ( residual . to ( dtype = self . norm2 . weight . dtype ) ) if self . residual_in_fp32 : residual = residual . to ( torch . float32 ) else : if self . drop_path2 . p == 0 or not self . training : rowscale2 = None else : rowscale2 = self . drop_path2 ( torch . ones ( hidden_states . shape [: - 1 ], device = hidden_states . device , dtype = hidden_states . dtype , ) ) hidden_states , residual = layer_norm_fn ( hidden_states , self . norm2 . weight , self . norm2 . bias , residual = residual , eps = self . norm2 . eps , dropout_p = self . dropout2 . p if self . training else 0.0 , rowscale = rowscale2 , prenorm = True , residual_in_fp32 = self . residual_in_fp32 , is_rms_norm = isinstance ( self . norm2 , RMSNorm ), ) hidden_states = self . mlp ( hidden_states ) return ( ( hidden_states , residual ) if not return_qkv else ( hidden_states , residual , qkv , ) ) # if not prenorm (disregard for scPRINT) else : assert residual is None mixer_out = self . mixer ( hidden_states , return_qkv = return_qkv , bias = bias , ** ( mixer_kwargs if mixer_kwargs is not None else {}) ) if return_qkv : qkv = mixer_out [ - 1 ] mixer_out = mixer_out [: - 1 ] if self . return_residual : # mixer out is actually a pair here mixer_out , hidden_states = mixer_out if not self . fused_dropout_add_ln : hidden_states = self . norm1 ( ( self . drop_path1 ( self . dropout1 ( mixer_out )) + hidden_states ) . to ( dtype = self . norm1 . weight . dtype ) ) else : if self . drop_path1 . p == 0 or not self . training : rowscale1 = None else : rowscale1 = self . drop_path1 ( torch . ones ( mixer_out . shape [: - 1 ], device = mixer_out . device , dtype = mixer_out . dtype , ) ) hidden_states = layer_norm_fn ( mixer_out , self . norm1 . weight , self . norm1 . bias , residual = hidden_states , eps = self . norm1 . eps , dropout_p = self . dropout1 . p if self . training else 0.0 , rowscale = rowscale1 , prenorm = False , is_rms_norm = isinstance ( self . norm1 , RMSNorm ), ) if not isinstance ( self . mlp , nn . Identity ): mlp_out = self . mlp ( hidden_states ) if self . return_residual : # mlp out is actually a pair here mlp_out , hidden_states = mlp_out if not self . fused_dropout_add_ln : hidden_states = self . norm2 ( ( self . drop_path2 ( self . dropout2 ( mlp_out )) + hidden_states ) . to ( dtype = self . norm2 . weight . dtype ) ) else : if self . drop_path2 . p == 0 or not self . training : rowscale2 = None else : rowscale2 = self . drop_path2 ( torch . ones ( mlp_out . shape [: - 1 ], device = mlp_out . device , dtype = mlp_out . dtype , ) ) hidden_states = layer_norm_fn ( mlp_out , self . norm2 . weight , self . norm2 . bias , residual = hidden_states , eps = self . norm2 . eps , dropout_p = self . dropout2 . p if self . training else 0.0 , rowscale = rowscale2 , prenorm = False , is_rms_norm = isinstance ( self . norm2 , RMSNorm ), ) return hidden_states if not return_qkv else ( hidden_states , qkv ) scprint.model.flash_attn.flashattention Experimental implementation of FlashAttention in Triton. Tested with triton==2.0.0.dev20221202. Triton 2.0 has a new backend (MLIR) but seems like it doesn't yet work for head dimensions other than 64: https://github.com/openai/triton/blob/d376020f90002757eea3ea9475d4f7cfc2ec5ead/python/triton/ops/flash_attention.py#L207 We'll update this implementation with the new Triton backend once this is fixed. We use the FlashAttention implementation from Phil Tillet a starting point. https://github.com/openai/triton/blob/master/python/tutorials/06-fused-attention.py Changes: - Implement both causal and non-causal attention. - Implement both self-attention and cross-attention. - Support arbitrary seqlens (not just multiples of 128), for both forward and backward. - Support all head dimensions up to 128 (not just 16, 32, 64, 128), for both forward and backward. - Support attention bias. - Speed up the forward pass a bit, and only store the LSE instead of m and l. - Make the backward for d=128 much faster by reducing register spilling. - Optionally parallelize the backward pass across seqlen_k, to deal with the case of small batch size * nheads. Caution: - This is an experimental implementation. The forward pass should be quite robust but I'm not 100% sure that the backward pass doesn't have race conditions (due to the Triton compiler). - This implementation has only been tested on A100. - If you plan to use headdim other than 64 and 128, you should test for race conditions (due to the Triton compiler), as done in tests/test_flash_attn.py \"test_flash_attn_triton_race_condition\". I've tested and fixed many race conditions for different head dimensions (40, 48, 64, 128, 80, 88, 96), but I'm still not 100% confident that there are none left for other head dimensions. Differences between this Triton version and the CUDA version: - Triton version doesn't support dropout. - Triton forward is generally faster than CUDA forward, while Triton backward is generally slower than CUDA backward. Overall Triton forward + backward is slightly slower than CUDA forward + backward. - Triton version doesn't support different sequence lengths in a batch (i.e., RaggedTensor/NestedTensor). - Triton version supports attention bias, while CUDA version doesn't. FlashAttnFunc Bases: Function forward staticmethod Perform the forward pass of FlashAttention. Parameters: q ( Tensor ) \u2013 Query tensor of shape (batch_size, seqlen_q, nheads, headdim). k ( Tensor ) \u2013 Key tensor of shape (batch_size, seqlen_k, nheads, headdim). v ( Tensor ) \u2013 Value tensor of shape (batch_size, seqlen_k, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor, shape broadcastible to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Scaling factor for the softmax operation. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 @staticmethod def forward ( ctx : torch . autograd . Function , q : torch . Tensor , k : torch . Tensor , v : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Perform the forward pass of FlashAttention. Args: q (torch.Tensor): Query tensor of shape (batch_size, seqlen_q, nheads, headdim). k (torch.Tensor): Key tensor of shape (batch_size, seqlen_k, nheads, headdim). v (torch.Tensor): Value tensor of shape (batch_size, seqlen_k, nheads, headdim). bias (Optional[torch.Tensor]): Bias tensor, shape broadcastible to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Scaling factor for the softmax operation. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous q , k , v = [ x if x . stride ( - 1 ) == 1 else x . contiguous () for x in [ q , k , v ]] o , lse , ctx . softmax_scale = _flash_attn_forward ( q , k , v , bias = bias , causal = causal , softmax_scale = softmax_scale ) ctx . save_for_backward ( q , k , v , o , lse , bias ) ctx . causal = causal return o FlashAttnKVPackedFunc Bases: Function forward staticmethod Perform the forward pass of FlashAttention with packed key and value tensors. Parameters: q ( Tensor ) \u2013 Query tensor of shape (batch, seqlen_q, nheads, headdim). kv ( Tensor ) \u2013 Key and value tensor of shape (batch, seqlen_k, 2, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor, shape broadcastable to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Scaling factor for the softmax operation. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 @staticmethod def forward ( ctx , q : torch . Tensor , kv : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Perform the forward pass of FlashAttention with packed key and value tensors. Args: q (torch.Tensor): Query tensor of shape (batch, seqlen_q, nheads, headdim). kv (torch.Tensor): Key and value tensor of shape (batch, seqlen_k, 2, nheads, headdim). bias (Optional[torch.Tensor]): Bias tensor, shape broadcastable to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Scaling factor for the softmax operation. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous q , kv = [ x if x . stride ( - 1 ) == 1 else x . contiguous () for x in [ q , kv ]] o , lse , ctx . softmax_scale = _flash_attn_forward ( q , kv [:, :, 0 ], kv [:, :, 1 ], bias = bias , causal = causal , softmax_scale = softmax_scale , ) ctx . save_for_backward ( q , kv , o , lse , bias ) ctx . causal = causal return o FlashAttnQKVPackedFunc Bases: Function forward staticmethod Forward pass for FlashAttention. Parameters: ctx ( Function ) \u2013 The context object to save information for backward computation. qkv ( Tensor ) \u2013 Input tensor of shape (batch, seqlen, 3, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Optional bias tensor, shape broadcastible to (batch, nheads, seqlen, seqlen). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen). ALiBi mask for non-causal would have shape (1, nheads, seqlen, seqlen). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Optional scaling factor for softmax. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 @staticmethod def forward ( ctx : torch . autograd . Function , qkv : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Forward pass for FlashAttention. Args: ctx (torch.autograd.Function): The context object to save information for backward computation. qkv (torch.Tensor): Input tensor of shape (batch, seqlen, 3, nheads, headdim). bias (Optional[torch.Tensor]): Optional bias tensor, shape broadcastible to (batch, nheads, seqlen, seqlen). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen). ALiBi mask for non-causal would have shape (1, nheads, seqlen, seqlen). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Optional scaling factor for softmax. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous if qkv . stride ( - 1 ) != 1 : qkv = qkv . contiguous () o , lse , ctx . softmax_scale = _flash_attn_forward ( qkv [:, :, 0 ], qkv [:, :, 1 ], qkv [:, :, 2 ], bias = bias , causal = causal , softmax_scale = softmax_scale , ) ctx . save_for_backward ( qkv , o , lse , bias ) ctx . causal = causal return o scprint.model.flash_attn.activations bias_gelu_back Assume that y has shape (B, D) and bias has shape (D) Source code in scprint/model/flash_attn/activations.py 24 25 26 27 28 29 30 31 32 33 34 @torch . jit . script def bias_gelu_back ( g , y , bias ): \"\"\"Assume that y has shape (B, D) and bias has shape (D)\"\"\" x = bias + y tanh_out = torch . tanh ( 0.79788456 * x * ( 1 + 0.044715 * x * x )) # sqrt(2/pi) * 3 * 0.044715 -> 0.1070322243 ff = 0.5 * x * ( ( 1 - tanh_out * tanh_out ) * ( 0.79788456 + 0.1070322243 * x * x ) ) + 0.5 * ( 1 + tanh_out ) grad_y = ff * g return grad_y . to ( dtype = y . dtype ), grad_y . sum ( dim = ( 0 ), dtype = bias . dtype ) scprint.model.flash_attn.layer_norm layer_norm_ref Reference implementation of Layer Normalization with optional dropout and residual connections. Parameters: x ( Tensor ) \u2013 Input tensor. weight ( Tensor ) \u2013 Weight tensor for normalization. bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor for normalization. residual ( Optional [ Tensor ] , default: None ) \u2013 Residual tensor to be added to the input. x1 ( Optional [ Tensor ] , default: None ) \u2013 Additional input tensor for parallel LayerNorm. weight1 ( Optional [ Tensor ] , default: None ) \u2013 Additional weight tensor for parallel LayerNorm. bias1 ( Optional [ Tensor ] , default: None ) \u2013 Additional bias tensor for parallel LayerNorm. eps ( float , default: 1e-06 ) \u2013 Epsilon value to avoid division by zero. dropout_p ( float , default: 0.0 ) \u2013 Dropout probability. rowscale ( Optional [ Tensor ] , default: None ) \u2013 Row scaling tensor. prenorm ( bool , default: False ) \u2013 Whether to return the prenormalized output. dropout_mask ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the input tensor. dropout_mask1 ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the additional input tensor. upcast ( bool , default: False ) \u2013 Whether to upcast the input tensors to float. Returns: Union [ Tensor , Tuple [ Tensor , ...]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). Source code in scprint/model/flash_attn/layer_norm.py 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 def layer_norm_ref ( x : torch . Tensor , weight : torch . Tensor , bias : Optional [ torch . Tensor ] = None , residual : Optional [ torch . Tensor ] = None , x1 : Optional [ torch . Tensor ] = None , weight1 : Optional [ torch . Tensor ] = None , bias1 : Optional [ torch . Tensor ] = None , eps : float = 1e-6 , dropout_p : float = 0.0 , rowscale : Optional [ torch . Tensor ] = None , prenorm : bool = False , dropout_mask : Optional [ torch . Tensor ] = None , dropout_mask1 : Optional [ torch . Tensor ] = None , upcast : bool = False , ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , ... ]]: \"\"\" Reference implementation of Layer Normalization with optional dropout and residual connections. Args: x (torch.Tensor): Input tensor. weight (torch.Tensor): Weight tensor for normalization. bias (Optional[torch.Tensor]): Bias tensor for normalization. residual (Optional[torch.Tensor]): Residual tensor to be added to the input. x1 (Optional[torch.Tensor]): Additional input tensor for parallel LayerNorm. weight1 (Optional[torch.Tensor]): Additional weight tensor for parallel LayerNorm. bias1 (Optional[torch.Tensor]): Additional bias tensor for parallel LayerNorm. eps (float): Epsilon value to avoid division by zero. dropout_p (float): Dropout probability. rowscale (Optional[torch.Tensor]): Row scaling tensor. prenorm (bool): Whether to return the prenormalized output. dropout_mask (Optional[torch.Tensor]): Dropout mask for the input tensor. dropout_mask1 (Optional[torch.Tensor]): Dropout mask for the additional input tensor. upcast (bool): Whether to upcast the input tensors to float. Returns: Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). \"\"\" dtype = x . dtype if upcast : x = x . float () weight = weight . float () bias = bias . float () if bias is not None else None residual = residual . float () if residual is not None else residual x1 = x1 . float () if x1 is not None else None weight1 = weight1 . float () if weight1 is not None else None bias1 = bias1 . float () if bias1 is not None else None if x1 is not None : assert rowscale is None , \"rowscale is not supported with parallel LayerNorm\" if rowscale is not None : x = x * rowscale [ ... , None ] if dropout_p > 0.0 : if dropout_mask is not None : x = x . masked_fill ( ~ dropout_mask , 0.0 ) / ( 1.0 - dropout_p ) else : x = F . dropout ( x , p = dropout_p ) if x1 is not None : if dropout_mask1 is not None : x1 = x1 . masked_fill ( ~ dropout_mask1 , 0.0 ) / ( 1.0 - dropout_p ) else : x1 = F . dropout ( x1 , p = dropout_p ) if x1 is not None : x = x + x1 if residual is not None : x = ( x + residual ) . to ( x . dtype ) out = F . layer_norm ( x . to ( weight . dtype ), x . shape [ - 1 :], weight = weight , bias = bias , eps = eps ) . to ( dtype ) if weight1 is None : return out if not prenorm else ( out , x ) else : out1 = F . layer_norm ( x . to ( weight1 . dtype ), x . shape [ - 1 :], weight = weight1 , bias = bias1 , eps = eps ) . to ( dtype ) return ( out , out1 ) if not prenorm else ( out , out1 , x ) rms_norm_ref Reference implementation of RMS Normalization with optional dropout and residual connections. Parameters: x ( Tensor ) \u2013 Input tensor. weight ( Tensor ) \u2013 Weight tensor for normalization. bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor for normalization. residual ( Optional [ Tensor ] , default: None ) \u2013 Residual tensor to be added to the input. x1 ( Optional [ Tensor ] , default: None ) \u2013 Additional input tensor for parallel RMSNorm. weight1 ( Optional [ Tensor ] , default: None ) \u2013 Additional weight tensor for parallel RMSNorm. bias1 ( Optional [ Tensor ] , default: None ) \u2013 Additional bias tensor for parallel RMSNorm. eps ( float , default: 1e-06 ) \u2013 Epsilon value to avoid division by zero. dropout_p ( float , default: 0.0 ) \u2013 Dropout probability. rowscale ( Optional [ Tensor ] , default: None ) \u2013 Row scaling tensor. prenorm ( bool , default: False ) \u2013 Whether to return the prenormalized output. dropout_mask ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the input tensor. dropout_mask1 ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the additional input tensor. upcast ( bool , default: False ) \u2013 Whether to upcast the input tensors to float. Returns: Union [ Tensor , Tuple [ Tensor , ...]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). Source code in scprint/model/flash_attn/layer_norm.py 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 def rms_norm_ref ( x : torch . Tensor , weight : torch . Tensor , bias : Optional [ torch . Tensor ] = None , residual : Optional [ torch . Tensor ] = None , x1 : Optional [ torch . Tensor ] = None , weight1 : Optional [ torch . Tensor ] = None , bias1 : Optional [ torch . Tensor ] = None , eps : float = 1e-6 , dropout_p : float = 0.0 , rowscale : Optional [ torch . Tensor ] = None , prenorm : bool = False , dropout_mask : Optional [ torch . Tensor ] = None , dropout_mask1 : Optional [ torch . Tensor ] = None , upcast : bool = False , ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , ... ]]: \"\"\" Reference implementation of RMS Normalization with optional dropout and residual connections. Args: x (torch.Tensor): Input tensor. weight (torch.Tensor): Weight tensor for normalization. bias (Optional[torch.Tensor]): Bias tensor for normalization. residual (Optional[torch.Tensor]): Residual tensor to be added to the input. x1 (Optional[torch.Tensor]): Additional input tensor for parallel RMSNorm. weight1 (Optional[torch.Tensor]): Additional weight tensor for parallel RMSNorm. bias1 (Optional[torch.Tensor]): Additional bias tensor for parallel RMSNorm. eps (float): Epsilon value to avoid division by zero. dropout_p (float): Dropout probability. rowscale (Optional[torch.Tensor]): Row scaling tensor. prenorm (bool): Whether to return the prenormalized output. dropout_mask (Optional[torch.Tensor]): Dropout mask for the input tensor. dropout_mask1 (Optional[torch.Tensor]): Dropout mask for the additional input tensor. upcast (bool): Whether to upcast the input tensors to float. Returns: Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). \"\"\" dtype = x . dtype if upcast : x = x . float () weight = weight . float () bias = bias . float () if bias is not None else None residual = residual . float () if residual is not None else residual x1 = x1 . float () if x1 is not None else None weight1 = weight1 . float () if weight1 is not None else None bias1 = bias1 . float () if bias1 is not None else None if x1 is not None : assert rowscale is None , \"rowscale is not supported with parallel LayerNorm\" if rowscale is not None : x = x * rowscale [ ... , None ] if dropout_p > 0.0 : if dropout_mask is not None : x = x . masked_fill ( ~ dropout_mask , 0.0 ) / ( 1.0 - dropout_p ) else : x = F . dropout ( x , p = dropout_p ) if x1 is not None : if dropout_mask1 is not None : x1 = x1 . masked_fill ( ~ dropout_mask1 , 0.0 ) / ( 1.0 - dropout_p ) else : x1 = F . dropout ( x1 , p = dropout_p ) if x1 is not None : x = x + x1 if residual is not None : x = ( x + residual ) . to ( x . dtype ) rstd = 1 / torch . sqrt (( x . square ()) . mean ( dim =- 1 , keepdim = True ) + eps ) out = (( x * rstd * weight ) + bias if bias is not None else ( x * rstd * weight )) . to ( dtype ) if weight1 is None : return out if not prenorm else ( out , x ) else : out1 = ( ( x * rstd * weight1 ) + bias1 if bias1 is not None else ( x * rstd * weight1 ) ) . to ( dtype ) return ( out , out1 ) if not prenorm else ( out , out1 , x )","title":"model"},{"location":"model/#documentation-for-the-model","text":"","title":"Documentation for the model"},{"location":"model/#model-description","text":"","title":"model description"},{"location":"model/#scprint.model.model","text":"","title":"model"},{"location":"model/#scprint.model.model.scPrint","text":"Bases: LightningModule , PyTorchModelHubMixin scPRINT transformer for single cell biology and the inference of Gene Regulatory networks Parameters: genes ( list ) \u2013 List of gene names the model will work with. precpt_gene_emb ( array , default: None ) \u2013 Gene embeddings of size (len(genes), d_model). Should be in the same order as the genes. Defaults to None. gene_pos_enc ( list , default: None ) \u2013 Gene position encoding of the same size as genes. Provides a location value for each gene in genes. Defaults to None. d_model ( int , default: 512 ) \u2013 Dimension of the model. Defaults to 512. nhead ( int , default: 8 ) \u2013 Number of heads in the multihead attention models. Defaults to 8. d_hid ( int , default: 512 ) \u2013 Dimension of the feedforward network model. Defaults to 512. nlayers ( int , default: 6 ) \u2013 Number of layers in the transformer model. Defaults to 6. expr_encoder_layers ( int , default: 2 ) \u2013 Number of layers in the expression encoder. Defaults to 2. layers_cls ( list [ int ] , default: [] ) \u2013 List specifying the number of layers in the classifier. Defaults to []. classes ( Dict [ str , int ] , default: {} ) \u2013 Classes to predict with the number of classes for each. Defaults to {}. labels_hierarchy ( Dict [ str , Dict [ int , list [ int ]]] , default: {} ) \u2013 Class hierarchy for classes with hierarchical classes. Defaults to {}. dropout ( float , default: 0.2 ) \u2013 Dropout value. Defaults to 0.2. transformer ( str , default: 'fast' ) \u2013 Transformer type to use. One of \"linear\", \"flash\", \"flashsparse\", \"scprint\". Defaults to \"fast\". domain_spec_batchnorm ( str , default: 'None' ) \u2013 Whether to apply domain-specific batch normalization. Defaults to \"None\". expr_emb_style ( str , default: 'continuous' ) \u2013 Style of input embedding. One of \"continuous\", \"binned_pos\", \"cont_pos\". Defaults to \"continuous\". mvc_decoder ( str , default: 'None' ) \u2013 Style of MVC decoder. One of \"None\", \"inner product\", \"concat query\", \"sum query\". Defaults to \"None\". pred_embedding ( list [ str ] , default: [] ) \u2013 List of classes to use for plotting embeddings. Defaults to []. cell_emb_style ( str , default: 'cls' ) \u2013 Style of cell embedding. One of \"cls\", \"avg-pool\", \"w-pool\". Defaults to \"cls\". freeze_embeddings ( bool , default: True ) \u2013 Whether to freeze the embeddings during training. Defaults to True. label_decoders ( Optional [ Dict [ str , Dict [ int , str ]]] , default: None ) \u2013 Label decoders to use for plotting the UMAP during validations. Defaults to None. zinb ( bool , default: True ) \u2013 Whether to use Zero-Inflated Negative Binomial distribution. Defaults to True. lr ( float , default: 0.0001 ) \u2013 Learning rate. Defaults to 0.0001. optim ( str , default: 'adamW' ) \u2013 Optimizer type. Defaults to \"adamW\". weight_decay ( float , default: 0.01 ) \u2013 Weight decay for the optimizer. Defaults to 0.01. **flash_attention_kwargs ( dict , default: {} ) \u2013 Additional keyword arguments for the model. see @flashformer.py Notes for other parameters of the model that are not part of its class definition, see @trainer.trainer.py Raises: ValueError \u2013 If the expr_emb_style is not one of \"continuous\", \"binned_pos\", \"cont_pos\". Source code in scprint/model/model.py 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 def __init__ ( self , genes : list , organisms : list = [ \"NCBITaxon:9606\" ], precpt_gene_emb : Optional [ str ] = None , gene_pos_enc : Optional [ list ] = None , normalization : str = \"sum\" , d_model : int = 512 , nhead : int = 8 , attn_bias : str = \"none\" , d_hid : int = 512 , edge_dim : int = 12 , nlayers : int = 6 , expr_encoder_layers : int = 2 , layers_cls : list [ int ] = [], classes : Dict [ str , int ] = {}, labels_hierarchy : Dict [ str , Dict [ int , list [ int ]]] = {}, dropout : float = 0.2 , transformer : str = \"fast\" , expr_emb_style : str = \"continuous\" , # \"binned_pos\", \"cont_pos\" domain_spec_batchnorm : str = \"None\" , n_input_bins : int = 0 , num_batch_labels : int = 0 , mvc_decoder : str = \"None\" , pred_embedding : list [ str ] = [], cell_emb_style : str = \"cls\" , freeze_embeddings : bool = True , label_decoders : Optional [ Dict [ str , Dict [ int , str ]]] = None , zinb : bool = True , lr : float = 0.0001 , optim = \"adamW\" , # TODEL weight_decay = 0.01 , # TODEL ** flash_attention_kwargs , ): \"\"\" scPRINT transformer for single cell biology and the inference of Gene Regulatory networks Args: genes (list): List of gene names the model will work with. precpt_gene_emb (np.array, optional): Gene embeddings of size (len(genes), d_model). Should be in the same order as the genes. Defaults to None. gene_pos_enc (list, optional): Gene position encoding of the same size as genes. Provides a location value for each gene in genes. Defaults to None. d_model (int, optional): Dimension of the model. Defaults to 512. nhead (int, optional): Number of heads in the multihead attention models. Defaults to 8. d_hid (int, optional): Dimension of the feedforward network model. Defaults to 512. nlayers (int, optional): Number of layers in the transformer model. Defaults to 6. expr_encoder_layers (int, optional): Number of layers in the expression encoder. Defaults to 2. layers_cls (list[int], optional): List specifying the number of layers in the classifier. Defaults to []. classes (Dict[str, int], optional): Classes to predict with the number of classes for each. Defaults to {}. labels_hierarchy (Dict[str, Dict[int, list[int]]], optional): Class hierarchy for classes with hierarchical classes. Defaults to {}. dropout (float, optional): Dropout value. Defaults to 0.2. transformer (str, optional): Transformer type to use. One of \"linear\", \"flash\", \"flashsparse\", \"scprint\". Defaults to \"fast\". domain_spec_batchnorm (str, optional): Whether to apply domain-specific batch normalization. Defaults to \"None\". expr_emb_style (str, optional): Style of input embedding. One of \"continuous\", \"binned_pos\", \"cont_pos\". Defaults to \"continuous\". mvc_decoder (str, optional): Style of MVC decoder. One of \"None\", \"inner product\", \"concat query\", \"sum query\". Defaults to \"None\". pred_embedding (list[str], optional): List of classes to use for plotting embeddings. Defaults to []. cell_emb_style (str, optional): Style of cell embedding. One of \"cls\", \"avg-pool\", \"w-pool\". Defaults to \"cls\". freeze_embeddings (bool, optional): Whether to freeze the embeddings during training. Defaults to True. label_decoders (Optional[Dict[str, Dict[int, str]]], optional): Label decoders to use for plotting the UMAP during validations. Defaults to None. zinb (bool, optional): Whether to use Zero-Inflated Negative Binomial distribution. Defaults to True. lr (float, optional): Learning rate. Defaults to 0.0001. optim (str, optional): Optimizer type. Defaults to \"adamW\". weight_decay (float, optional): Weight decay for the optimizer. Defaults to 0.01. **flash_attention_kwargs (dict): Additional keyword arguments for the model. see @flashformer.py Notes: for other parameters of the model that are not part of its class definition, see @trainer.trainer.py Raises: ValueError: If the expr_emb_style is not one of \"continuous\", \"binned_pos\", \"cont_pos\". \"\"\" super () . __init__ () # training flags self . do_denoise = True self . noise = [ 0.6 ] self . do_cce = False self . cce_sim = 0.5 self . cce_scale = 0.002 self . do_ecs = False self . ecs_threshold = 0.3 self . ecs_scale = 0.05 self . do_mvc = False self . mvc_scale = 1.0 self . class_embd_diss_scale = 0.2 self . do_adv_cls = False self . adv_class_scale = 0.1 self . do_cls = False self . mean_attn_tot = None self . mean_attn_tot_c = 0 self . do_adv_batch = False self . run_full_forward = True self . class_scale = 0.4 self . do_next_tp = False self . do_generate = False self . mask_ratio = [] self . warmup_duration = 500 self . weight_decay = 0.01 self . optim = \"adamW\" self . fused_adam = False self . lr_reduce_patience = 1 self . lr_reduce_factor = 0.6 self . lr_reduce_monitor = \"val_loss\" self . name = \"\" self . lr = lr self . lrfinder_steps = 0 self . doplot = True self . get_attention_layer = [] self . embs = None self . pred_log_adata = True self . attn = utils . Attention ( len ( classes ) + 2 + len ( genes )) self . predict_depth_mult = 3 self . predict_mode = \"none\" self . keep_all_cls_pred = False # should be stored somehow self . d_model = d_model self . normalization = normalization self . organisms = organisms self . edge_dim = edge_dim self . attn_bias = attn_bias self . nlayers = nlayers self . gene_pos_enc = gene_pos_enc self . mvc_decoder = mvc_decoder self . domain_spec_batchnorm = domain_spec_batchnorm # need to store self . n_input_bins = n_input_bins self . transformer = transformer self . label_counts = classes self . classes = list ( classes . keys ()) self . cell_emb_style = cell_emb_style self . label_decoders = label_decoders self . pred_embedding = pred_embedding # compute tensor for mat_labels_hierarchy self . mat_labels_hierarchy = {} self . labels_hierarchy = labels_hierarchy if \"strict_loading\" in flash_attention_kwargs : flash_attention_kwargs . pop ( \"strict_loading\" ) for k , v in labels_hierarchy . items (): tens = torch . zeros (( len ( v ), classes [ k ])) for k2 , v2 in v . items (): tens [ k2 - classes [ k ], v2 ] = 1 self . mat_labels_hierarchy [ k ] = tens . to ( bool ) self . expr_emb_style = expr_emb_style if self . expr_emb_style not in [ \"category\" , \"continuous\" , \"none\" ]: raise ValueError ( f \"expr_emb_style should be one of category, continuous, scaling, \" f \"got { expr_emb_style } \" ) if cell_emb_style not in [ \"cls\" , \"avg-pool\" , \"w-pool\" ]: raise ValueError ( f \"Unknown cell_emb_style: { cell_emb_style } \" ) self . genes = genes self . vocab = { i : n for i , n in enumerate ( genes )} # encoder # gene encoder if precpt_gene_emb is not None : embeddings = pd . read_parquet ( precpt_gene_emb ) . loc [ self . genes ] if len ( embeddings ) == 0 : raise ValueError ( f \"the gene embeddings file { precpt_gene_emb } does not contain any of the genes given to the model\" ) elif len ( embeddings ) < len ( self . genes ): print ( \"Warning: only a subset of the genes available in the embeddings file.\" ) print ( \"number of genes: \" , len ( embeddings )) sembeddings = torch . nn . AdaptiveAvgPool1d ( d_model )( torch . tensor ( embeddings . values ) ) self . gene_encoder = encoders . GeneEncoder ( len ( self . vocab ), d_model , weights = sembeddings , freeze = freeze_embeddings ) else : self . gene_encoder = encoders . GeneEncoder ( len ( self . vocab ), d_model ) # Value Encoder, NOTE: the scaling style is also handled in _encode method if expr_emb_style in [ \"continuous\" , \"full_pos\" ]: self . expr_encoder = encoders . ContinuousValueEncoder ( d_model , dropout , layers = expr_encoder_layers ) elif expr_emb_style == \"binned_pos\" : assert n_input_bins > 0 self . expr_encoder = encoders . CategoryValueEncoder ( n_input_bins , d_model ) else : self . expr_encoder = torch . nn . Identity () # Positional Encoding if self . gene_pos_enc is not None : max_len = max ( gene_pos_enc ) token_to_pos = { token : pos for token , pos in enumerate ( self . gene_pos_enc )} self . pos_encoder = encoders . PositionalEncoding ( d_model , max_len = max_len , token_to_pos = token_to_pos ) self . cell_embs_count = len ( self . classes ) + 2 # Class Encoder # always have [base_cell_emb, time_embedding, depth_embedding] + any other class info # base cell embedding will store other cell specific information self . class_encoder = encoders . CategoryValueEncoder ( self . cell_embs_count - 1 , d_model ) # self.time_encoder = encoders.ContinuousValueEncoder(d_model, dropout) self . depth_encoder = encoders . ContinuousValueEncoder ( d_model , dropout , layers = expr_encoder_layers ) # Transformer # Linear if transformer == \"linear\" : # linear transformer using the fast transformer package # self.transformer = FastTransformerEncoder( # d_model, nhead, d_hid, nlayers, dropout, \"linear\" # ) raise NotImplementedError ( \"Linear transformer is not implemented\" ) # regular or flash else : self . transformer = FlashTransformerEncoder ( d_model , nhead , nlayers , dropout = dropout , use_flash_attn = ( transformer == \"flash\" ), ** flash_attention_kwargs , ) # decoders # expression self . expr_decoder = decoders . ExprDecoder ( d_model , nfirst_tokens_to_skip = self . cell_embs_count , dropout = dropout , zinb = zinb , ) # cls decoder self . cls_decoders = torch . nn . ModuleDict () # should be a very simple classifier for most things # (maybe scale with the number of classes) should be 1 layer... for clss , n_cls in classes . items (): self . cls_decoders [ clss ] = decoders . ClsDecoder ( d_model , n_cls , layers = layers_cls , dropout = dropout ) # Batch effect correction via adversarial training on batch classes if num_batch_labels > 0 : self . grad_reverse_discriminator_loss = loss . AdversarialDiscriminatorLoss ( d_model , n_cls = num_batch_labels , ) else : self . grad_reverse_discriminator_loss = None # expression decoder from batch embbedding if mvc_decoder != \"None\" : self . mvc_decoder = decoders . MVCDecoder ( d_model , arch_style = mvc_decoder , ) else : self . mvc_decoder = None self . apply ( partial ( utils . _init_weights , n_layer = nlayers , ) ) for i , dec in self . cls_decoders . items (): torch . nn . init . constant_ ( dec . out_layer . bias , - 0.13 ) self . save_hyperparameters ()","title":"scPrint"},{"location":"model/#scprint.model.model.scPrint.configure_optimizers","text":"@see pl.LightningModule Source code in scprint/model/model.py 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 def configure_optimizers ( self ): \"\"\"@see pl.LightningModule\"\"\" # https://pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam # not working because of poor weight decay implem if self . optim == \"adam\" : optimizer = optim . Adam ( self . parameters (), lr = self . hparams . lr , betas = ( 0.9 , 0.999 ), eps = 1e-08 , weight_decay = self . weight_decay , amsgrad = False , fused = self . fused_adam , ) elif self . optim == \"adamW\" : optimizer = optim . AdamW ( self . parameters (), lr = self . hparams . lr , betas = ( 0.9 , 0.999 ), eps = 1e-08 , weight_decay = self . weight_decay , amsgrad = False , fused = self . fused_adam , ) elif self . optim == \"galore\" : raise NotImplementedError ( \"Galore optimizer not implemented\" ) param_groups = [ { \"params\" : [ v for k , v in self . named_parameters () if \"transformer\" not in k ] }, { \"params\" : [ v for k , v in self . named_parameters () if \"transformer\" in k ], \"rank\" : 128 , \"update_proj_gap\" : 200 , \"scale\" : 0.25 , \"proj_type\" : \"std\" , }, ] # optimizer = GaLoreAdamW(param_groups, lr=self.hparams.lr) else : raise ValueError ( f \"Unknown optimizer: { self . optim } \" ) lr_scheduler = optim . lr_scheduler . ReduceLROnPlateau ( optimizer , mode = \"min\" , patience = self . lr_reduce_patience , factor = self . lr_reduce_factor , verbose = True , ) lr_dict = { \"scheduler\" : lr_scheduler , # The unit of the scheduler's step size, could also be 'step'. # 'epoch' updates the scheduler on epoch end whereas 'step' # updates it after a optimizer update. \"interval\" : \"epoch\" , # How many epochs/steps should pass between calls to # `scheduler.step()`. 1 corresponds to updating the learning # rate after every epoch/step. \"frequency\" : 1 , # Metric to to monitor for schedulers like `ReduceLROnPlateau` \"monitor\" : self . lr_reduce_monitor , } self . lrfinder_steps = 0 for val in self . trainer . callbacks : if type ( val ) is _LRCallback : self . lrfinder_steps = val . num_training if type ( val ) is LearningRateFinder : self . lrfinder_steps = val . _num_training_steps return [ optimizer ], [ lr_dict ]","title":"configure_optimizers"},{"location":"model/#scprint.model.model.scPrint.forward","text":"forward also called on self(), a full forward pass on the model Parameters: gene_pos ( Tensor ) \u2013 A tensor of shape (minibatch, seq_len) representing the genes used for each cell in the minibatch. expression ( Tensor , default: None ) \u2013 A tensor of shape (minibatch, seq_len) representing the expression levels of genes in the minibatch. Defaults to None. mask ( Tensor , default: None ) \u2013 A tensor of shape (minibatch, seq_len) used to mask certain elements in the sequence during the forward pass. Defaults to None. full_depth ( Tensor , default: None ) \u2013 A tensor of shape (minibatch,) representing the full depth of each sequence in the minibatch. Defaults to None. timepoint ( Tensor , default: None ) \u2013 A tensor of shape (minibatch,) representing the timepoint associated with each sequence in the minibatch. Defaults to None. get_gene_emb ( bool , default: False ) \u2013 A flag indicating whether to return the gene embeddings. If True, the gene embeddings are included in the output. Defaults to False. do_sample ( bool , default: False ) \u2013 A flag indicating whether to sample the expression levels. If True, the expression levels are sampled during the forward pass. Defaults to False. get_attention_layer ( list , default: [] ) \u2013 A list indicating which attention layers to return. If not empty, the specified attention layers are included in the output. Defaults to []. Returns: \u2013 dict of output Tensors: A dictionary containing the output tensors from the forward pass. The keys of the dictionary depend on the input flags (get_gene_emb, do_sample, get_attention_layer). at minima, the dictionary codntains the following: - \"mean\": the mean expression levels - \"zero_logits\": the logits for zero-inflated expression levels - \"disp\": the dispersion parameter - \"cell_embs\": the cell embeddings per class - \"cell_emb\": the main cell embedding - \"cls_output\": the output of the classifier Source code in scprint/model/model.py 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 def forward ( self , gene_pos : Tensor , expression : Optional [ Tensor ] = None , mask : Optional [ Tensor ] = None , full_depth : Optional [ Tensor ] = None , timepoint : Optional [ Tensor ] = None , # (new_minibatch_of_nxt_cells,) get_gene_emb : bool = False , depth_mult : Optional [ Tensor ] = None , do_sample : bool = False , do_mvc : bool = False , do_class : bool = False , get_attention_layer : list = [], ): \"\"\" forward also called on self(), a full forward pass on the model Args: gene_pos (Tensor): A tensor of shape (minibatch, seq_len) representing the genes used for each cell in the minibatch. expression (Tensor, optional): A tensor of shape (minibatch, seq_len) representing the expression levels of genes in the minibatch. Defaults to None. mask (Tensor, optional): A tensor of shape (minibatch, seq_len) used to mask certain elements in the sequence during the forward pass. Defaults to None. full_depth (Tensor, optional): A tensor of shape (minibatch,) representing the full depth of each sequence in the minibatch. Defaults to None. timepoint (Tensor, optional): A tensor of shape (minibatch,) representing the timepoint associated with each sequence in the minibatch. Defaults to None. get_gene_emb (bool, optional): A flag indicating whether to return the gene embeddings. If True, the gene embeddings are included in the output. Defaults to False. do_sample (bool, optional): A flag indicating whether to sample the expression levels. If True, the expression levels are sampled during the forward pass. Defaults to False. get_attention_layer (list, optional): A list indicating which attention layers to return. If not empty, the specified attention layers are included in the output. Defaults to []. Returns: dict of output Tensors: A dictionary containing the output tensors from the forward pass. The keys of the dictionary depend on the input flags (get_gene_emb, do_sample, get_attention_layer). at minima, the dictionary codntains the following: - \"mean\": the mean expression levels - \"zero_logits\": the logits for zero-inflated expression levels - \"disp\": the dispersion parameter - \"cell_embs\": the cell embeddings per class - \"cell_emb\": the main cell embedding - \"cls_output\": the output of the classifier \"\"\" encoding = self . _encoder ( gene_pos , expression , mask , full_depth , timepoint ) if self . attn_bias != \"none\" : if not hasattr ( self , \"nbias\" ): self . nbias = torch . Tensor ( load_npz ( FILEDIR + \"/../../data/bias_sparse.npz\" ) . todense () ) . to ( device = gene_pos . device , dtype = torch . float16 ) num = len ( self . classes ) + 2 bias = torch . zeros ( ( gene_pos . shape [ 0 ], gene_pos . shape [ 1 ] + num , gene_pos . shape [ 1 ] + num , ), device = gene_pos . device , dtype = torch . float16 , ) bias [:, num :, : num ] = - 10_000 # do not pay attention to the cls embeddings bias [:, num :, num :] = self . nbias [ gene_pos [:, :, None ], gene_pos [:, None , :]] transformer_output = self . transformer ( encoding , return_qkv = get_attention_layer , bias = bias if self . attn_bias != \"none\" else None , bias_layer = list ( range ( self . nlayers - 1 )), ) depth_mult = expression . sum ( 1 ) if depth_mult is None else depth_mult if len ( get_attention_layer ) > 0 : transformer_output , qkvs = transformer_output return ( self . _decoder ( transformer_output , depth_mult , get_gene_emb , do_sample , do_mvc , do_class , ), qkvs , ) else : return self . _decoder ( transformer_output , depth_mult , get_gene_emb , do_sample , do_mvc , do_class , )","title":"forward"},{"location":"model/#scprint.model.model.scPrint.get_cell_embs","text":"get_cell_embs Parameters: layer_output ( Tensor ) \u2013 The output tensor from a layer in the model. Raises: ValueError \u2013 Raised when an unknown cell embedding style is encountered. Returns: Tensor \u2013 The cell embeddings tensor. Source code in scprint/model/model.py 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 def get_cell_embs ( self , layer_output ): \"\"\" get_cell_embs Args: layer_output (Tensor): The output tensor from a layer in the model. Raises: ValueError: Raised when an unknown cell embedding style is encountered. Returns: Tensor: The cell embeddings tensor. \"\"\" if self . cell_emb_style == \"cls\" and self . classes is not None : # (minibatch, embsize) cell_emb = layer_output [:, : 2 + len ( self . classes )] elif self . cell_emb_style == \"avg-pool\" : cell_emb = torch . mean ( layer_output , dim = 1 ) else : raise ValueError ( f \"Unknown cell_emb_style: { self . cell_emb_style } \" ) return cell_emb","title":"get_cell_embs"},{"location":"model/#scprint.model.model.scPrint.log_adata","text":"log_adata will log an adata from predictions. It will log to tensorboard and wandb if available see @utils.log_adata Source code in scprint/model/model.py 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 def log_adata ( self , gtclass = None , name = \"\" ): \"\"\" log_adata will log an adata from predictions. It will log to tensorboard and wandb if available see @utils.log_adata \"\"\" try : mdir = self . logger . save_dir if self . logger . save_dir is not None else \"/tmp\" except : mdir = \"data/\" if not os . path . exists ( mdir ): os . makedirs ( mdir ) adata , fig = utils . make_adata ( self . embs , self . classes , self . pred if not self . keep_all_cls_pred else None , self . attn . get (), self . global_step , self . label_decoders , self . labels_hierarchy , gtclass , self . name + \"_\" + name + \"_\" + str ( self . global_rank ), mdir , self . doplot , ) if self . doplot : try : self . logger . experiment . add_figure ( fig ) except : print ( \"couldn't log to tensorboard\" ) try : self . logger . log_image ( key = \"umaps\" , images = [ fig ]) except : print ( \"couldn't log to wandb\" ) return adata","title":"log_adata"},{"location":"model/#scprint.model.model.scPrint.on_fit_start","text":"@see pl.LightningModule Source code in scprint/model/model.py 641 642 643 644 645 646 647 def on_fit_start ( self ): \"\"\"@see pl.LightningModule\"\"\" if type ( self . transformer ) is FlashTransformerEncoder : for encoder_layers in self . transformer . blocks : encoder_layers . set_seq_parallel ( True ) for k , v in self . mat_labels_hierarchy . items (): self . mat_labels_hierarchy [ k ] = v . to ( self . device )","title":"on_fit_start"},{"location":"model/#scprint.model.model.scPrint.on_predict_epoch_end","text":"@see pl.LightningModule will Source code in scprint/model/model.py 1325 1326 1327 1328 1329 1330 1331 def on_predict_epoch_end ( self ): \"\"\"@see pl.LightningModule will\"\"\" if self . pos . shape [ 0 ] < 100 : return if self . pred_log_adata : print ( \"adding on disk\" ) return self . log_adata ( name = \"predict_part_\" + str ( self . counter ))","title":"on_predict_epoch_end"},{"location":"model/#scprint.model.model.scPrint.on_predict_epoch_start","text":"@see pl.LightningModule Source code in scprint/model/model.py 1126 1127 1128 1129 1130 1131 1132 1133 1134 def on_predict_epoch_start ( self ): \"\"\"@see pl.LightningModule\"\"\" self . embs = None self . attn . data = None self . attn . attn = None self . counter = 0 if type ( self . transformer ) is FlashTransformerEncoder : for encoder_layers in self . transformer . blocks : encoder_layers . set_seq_parallel ( False )","title":"on_predict_epoch_start"},{"location":"model/#scprint.model.model.scPrint.on_validation_epoch_end","text":"@see pl.LightningModule Source code in scprint/model/model.py 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 def on_validation_epoch_end ( self ): \"\"\"@see pl.LightningModule\"\"\" self . embs = self . all_gather ( self . embs ) . view ( - 1 , self . embs . shape [ - 1 ]) self . info = self . all_gather ( self . info ) . view ( - 1 , self . info . shape [ - 1 ]) self . pred = ( self . all_gather ( self . pred ) . view ( - 1 , self . pred . shape [ - 1 ]) if self . pred is not None else None ) self . pos = self . all_gather ( self . pos ) . view ( - 1 , self . pos . shape [ - 1 ]) if not self . trainer . is_global_zero : # print(\"you are not on the main node. cancelling logging step\") return if self . trainer . state . stage != \"sanity_check\" : sch = self . lr_schedulers () sch . step ( self . trainer . callback_metrics [ \"val_loss\" ]) # run the test function on specific dataset self . log_adata ( gtclass = self . info , name = \"validation_part_\" + str ( self . counter ) ) if ( self . current_epoch + 1 ) % 30 == 0 : self . on_test_epoch_end ()","title":"on_validation_epoch_end"},{"location":"model/#scprint.model.model.scPrint.optimizer_step","text":"@see pl.LightningModule Source code in scprint/model/model.py 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 def optimizer_step ( self , epoch , batch_idx , optimizer , optimizer_closure ): \"\"\"@see pl.LightningModule\"\"\" # update params optimizer . step ( closure = optimizer_closure ) # manually warm up lr without a scheduler # making sure that we don't do this during lrfinder for i , pg in enumerate ( optimizer . param_groups ): if ( self . global_step < self . warmup_duration + self . lrfinder_steps ) and self . lrfinder_steps < self . global_step : lr_scale = min ( 1.0 , float ( self . global_step + 1 ) / self . warmup_duration ) pg [ \"lr\" ] = lr_scale * self . hparams . lr for i , pg in enumerate ( optimizer . param_groups ): # if pg[\"lr\"] < 2e-5: # pg[\"lr\"] = 2e-5 self . log ( \"lr_\" + str ( i ), pg [ \"lr\" ])","title":"optimizer_step"},{"location":"model/#scprint.model.model.scPrint.predict_step","text":"embed given gene expression, encode the gene embedding and cell embedding. Returns: Tensor \u2013 description Source code in scprint/model/model.py 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 def predict_step ( self , batch , batch_idx ): \"\"\" embed given gene expression, encode the gene embedding and cell embedding. Args: batch @see training_step Returns: Tensor: _description_ \"\"\" return self . _predict ( batch [ \"genes\" ], batch [ \"x\" ], batch [ \"depth\" ], self . predict_mode , self . pred_embedding , self . get_attention_layer , self . predict_depth_mult , )","title":"predict_step"},{"location":"model/#scprint.model.model.scPrint.training_step","text":"training_step defines the train loop. It is independent of forward @see pl.LightningModule Returns: _type_ \u2013 description Source code in scprint/model/model.py 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 def training_step ( self , batch : Dict [ str , Tensor ], batch_idx , ): \"\"\" training_step defines the train loop. It is independent of forward @see pl.LightningModule Returns: _type_: _description_ \"\"\" # TASK 1 & 2 & 3 (first pass, expression reconstruction, label prediction) total_loss , losses = self . _full_training ( batch = batch , do_denoise = self . do_denoise , noise = self . noise , do_next_tp = self . do_next_tp , do_cce = self . do_cce , cce_sim = self . cce_sim , do_ecs = self . do_ecs , do_mvc = self . do_mvc , do_adv_cls = self . do_adv_cls , do_adv_batch = self . do_adv_batch , do_cls = self . do_cls , do_generate = self . do_generate , run_full_forward = self . run_full_forward , mask_ratio = self . mask_ratio , ) self . log ( \"train_loss\" , total_loss , prog_bar = True , sync_dist = True ) self . log_dict ( losses , prog_bar = True , sync_dist = True ) return total_loss","title":"training_step"},{"location":"model/#scprint.model.model.scPrint.validation_step","text":"validation_step defines the validation loop. It is independent of forward @see pl.LightningModule Parameters: batch ( list [ Tensor ] ) \u2013 @see training_step Source code in scprint/model/model.py 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 def validation_step ( self , batch , batch_idx , ): \"\"\" validation_step defines the validation loop. It is independent of forward @see pl.LightningModule Args: batch (list[Tensor]): @see training_step \"\"\" val_loss , losses = self . _full_training ( batch = batch , do_denoise = self . do_denoise , noise = self . noise , do_next_tp = self . do_next_tp , do_cce = self . do_cce , cce_sim = self . cce_sim , do_ecs = self . do_ecs , do_mvc = self . do_mvc , do_adv_cls = self . do_adv_cls , do_adv_batch = self . do_adv_batch , do_cls = self . do_cls , do_generate = self . do_generate , run_full_forward = self . run_full_forward , mask_ratio = self . mask_ratio , ) expression = batch [ \"x\" ] gene_pos = batch [ \"genes\" ] depth = batch [ \"depth\" ] # TODO: make this faster by only calling val loss if self . embs is not None : if self . embs . shape [ 0 ] < 100_000 : self . info = torch . cat ([ self . info , batch [ \"class\" ]]) self . _predict ( gene_pos , expression , depth , pred_embedding = self . pred_embedding , max_size_in_mem = 100_000 , ) else : self . info = batch [ \"class\" ] self . _predict ( gene_pos , expression , depth , pred_embedding = self . pred_embedding , max_size_in_mem = 100_000 , ) self . log ( \"val_loss\" , val_loss , sync_dist = True ) self . log_dict ( losses , sync_dist = True ) return val_loss","title":"validation_step"},{"location":"model/#losses","text":"","title":"losses"},{"location":"model/#scprint.model.loss","text":"","title":"loss"},{"location":"model/#scprint.model.loss.AdversarialDiscriminatorLoss","text":"Bases: Module Discriminator for the adversarial training for batch correction. Parameters: d_model ( int ) \u2013 The size of the input tensor. n_cls ( int ) \u2013 The number of classes. nlayers ( int , default: 3 ) \u2013 The number of layers in the discriminator. Defaults to 3. activation ( callable , default: LeakyReLU ) \u2013 The activation function. Defaults to nn.LeakyReLU. reverse_grad ( bool , default: True ) \u2013 Whether to reverse the gradient. Defaults Source code in scprint/model/loss.py 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 def __init__ ( self , d_model : int , n_cls : int , nlayers : int = 3 , activation : callable = nn . LeakyReLU , reverse_grad : bool = True , ): \"\"\" Discriminator for the adversarial training for batch correction. Args: d_model (int): The size of the input tensor. n_cls (int): The number of classes. nlayers (int, optional): The number of layers in the discriminator. Defaults to 3. activation (callable, optional): The activation function. Defaults to nn.LeakyReLU. reverse_grad (bool, optional): Whether to reverse the gradient. Defaults \"\"\" super () . __init__ () # module list self . decoder = nn . ModuleList () for _ in range ( nlayers - 1 ): self . decoder . append ( nn . Linear ( d_model , d_model )) self . decoder . append ( nn . LayerNorm ( d_model )) self . decoder . append ( activation ()) self . out_layer = nn . Linear ( d_model , n_cls ) self . reverse_grad = reverse_grad","title":"AdversarialDiscriminatorLoss"},{"location":"model/#scprint.model.loss.AdversarialDiscriminatorLoss.forward","text":"Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, embsize] Source code in scprint/model/loss.py 302 303 304 305 306 307 308 309 310 311 312 def forward ( self , x : Tensor , batch_labels : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, embsize] \"\"\" if self . reverse_grad : x = grad_reverse ( x , lambd = 1.0 ) for layer in self . decoder : x = layer ( x ) x = self . out_layer ( x ) return F . cross_entropy ( x , batch_labels )","title":"forward"},{"location":"model/#scprint.model.loss.classification","text":"Computes the classification loss for a given batch of predictions and ground truth labels. Parameters: clsname ( str ) \u2013 The name of the label. pred ( Tensor ) \u2013 The predicted logits for the batch. cl ( Tensor ) \u2013 The ground truth labels for the batch. maxsize ( int ) \u2013 The number of possible labels. labels_hierarchy ( dict , default: {} ) \u2013 The hierarchical structure of the labels. Defaults to {}. Raises: ValueError \u2013 If the clsname is not found in the labels_hierarchy dictionary. Returns: Tensor ( Tensor ) \u2013 The computed binary cross entropy loss for the given batch. Source code in scprint/model/loss.py 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 def classification ( clsname : str , pred : torch . Tensor , cl : torch . Tensor , maxsize : int , labels_hierarchy : Optional [ Dict [ str , Dict [ int , list [ int ]]]] = {}, ) -> torch . Tensor : \"\"\" Computes the classification loss for a given batch of predictions and ground truth labels. Args: clsname (str): The name of the label. pred (Tensor): The predicted logits for the batch. cl (Tensor): The ground truth labels for the batch. maxsize (int): The number of possible labels. labels_hierarchy (dict, optional): The hierarchical structure of the labels. Defaults to {}. Raises: ValueError: If the clsname is not found in the labels_hierarchy dictionary. Returns: Tensor: The computed binary cross entropy loss for the given batch. \"\"\" newcl = torch . zeros ( ( cl . shape [ 0 ], maxsize ), device = cl . device ) # batchsize * n_labels # if we don't know the label we set the weight to 0 else to 1 valid_indices = ( cl != - 1 ) & ( cl < maxsize ) valid_cl = cl [ valid_indices ] newcl [ valid_indices , valid_cl ] = 1 weight = torch . ones_like ( newcl , device = cl . device ) weight [ cl == - 1 , :] = 0 inv = cl >= maxsize # if we have non leaf values, we don't know so we don't compute grad and set weight to 0 # and add labels that won't be counted but so that we can still use them if inv . any (): if clsname in labels_hierarchy . keys (): clhier = labels_hierarchy [ clsname ] inv_weight = weight [ inv ] # we set the weight of the elements that are not leaf to 0 # i.e. the elements where we will compute the max inv_weight [ clhier [ cl [ inv ] - maxsize ]] = 0 weight [ inv ] = inv_weight addnewcl = torch . ones ( weight . shape [ 0 ], device = pred . device ) # no need to set the other to 0 as the weight of the loss is set to 0 addweight = torch . zeros ( weight . shape [ 0 ], device = pred . device ) addweight [ inv ] = 1 # computing hierarchical labels and adding them to cl addpred = pred . clone () # we only keep the elements where we need to compute the max, # for the rest we set them to -inf, so that they won't have any impact on the max() inv_addpred = addpred [ inv ] inv_addpred [ inv_weight . to ( bool )] = torch . finfo ( pred . dtype ) . min addpred [ inv ] = inv_addpred # differentiable max addpred = torch . logsumexp ( addpred , dim =- 1 ) # we add the new labels to the cl newcl = torch . cat ([ newcl , addnewcl . unsqueeze ( 1 )], dim = 1 ) pred = torch . cat ([ pred , addpred . unsqueeze ( 1 )], dim = 1 ) weight = torch . cat ([ weight , addweight . unsqueeze ( 1 )], dim = 1 ) else : raise ValueError ( \"need to use labels_hierarchy for this usecase\" ) myloss = torch . nn . functional . binary_cross_entropy_with_logits ( pred , target = newcl , weight = weight ) return myloss","title":"classification"},{"location":"model/#scprint.model.loss.criterion_neg_log_bernoulli","text":"Compute the negative log-likelihood of Bernoulli distribution Source code in scprint/model/loss.py 143 144 145 146 147 148 149 150 def criterion_neg_log_bernoulli ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the negative log-likelihood of Bernoulli distribution \"\"\" mask = mask . float () bernoulli = torch . distributions . Bernoulli ( probs = input ) masked_log_probs = bernoulli . log_prob (( target > 0 ) . float ()) * mask return - masked_log_probs . sum () / mask . sum ()","title":"criterion_neg_log_bernoulli"},{"location":"model/#scprint.model.loss.ecs","text":"ecs Computes the similarity of cell embeddings based on a threshold. Parameters: cell_emb ( Tensor ) \u2013 A tensor representing cell embeddings. ecs_threshold ( float , default: 0.5 ) \u2013 A threshold for determining similarity. Defaults to 0.5. Returns: Tensor ( Tensor ) \u2013 A tensor representing the mean of 1 minus the square of the difference between the cosine similarity and the threshold. Source code in scprint/model/loss.py 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 def ecs ( cell_emb : Tensor , ecs_threshold : float = 0.5 ) -> Tensor : \"\"\" ecs Computes the similarity of cell embeddings based on a threshold. Args: cell_emb (Tensor): A tensor representing cell embeddings. ecs_threshold (float, optional): A threshold for determining similarity. Defaults to 0.5. Returns: Tensor: A tensor representing the mean of 1 minus the square of the difference between the cosine similarity and the threshold. \"\"\" # Here using customized cosine similarity instead of F.cosine_similarity # to avoid the pytorch issue of similarity larger than 1.0, pytorch # 78064 # normalize the embedding cell_emb_normed = F . normalize ( cell_emb , p = 2 , dim = 1 ) cos_sim = torch . mm ( cell_emb_normed , cell_emb_normed . t ()) # mask out diagnal elements mask = torch . eye ( cos_sim . size ( 0 )) . bool () . to ( cos_sim . device ) cos_sim = cos_sim . masked_fill ( mask , 0.0 ) # only optimize positive similarities cos_sim = F . relu ( cos_sim ) return torch . mean ( 1 - ( cos_sim - ecs_threshold ) ** 2 )","title":"ecs"},{"location":"model/#scprint.model.loss.grad_reverse","text":"grad_reverse Reverses the gradient of the input tensor. Parameters: x ( Tensor ) \u2013 The input tensor whose gradient is to be reversed. lambd ( float , default: 1.0 ) \u2013 The scaling factor for the reversed gradient. Defaults to 1.0. Returns: Tensor ( Tensor ) \u2013 The input tensor with its gradient reversed during the backward pass. Source code in scprint/model/loss.py 326 327 328 329 330 331 332 333 334 335 336 337 def grad_reverse ( x : Tensor , lambd : float = 1.0 ) -> Tensor : \"\"\" grad_reverse Reverses the gradient of the input tensor. Args: x (Tensor): The input tensor whose gradient is to be reversed. lambd (float, optional): The scaling factor for the reversed gradient. Defaults to 1.0. Returns: Tensor: The input tensor with its gradient reversed during the backward pass. \"\"\" return GradReverse . apply ( x , lambd )","title":"grad_reverse"},{"location":"model/#scprint.model.loss.masked_mae","text":"Compute the masked MAE loss between input and target. MAE = mean absolute error Source code in scprint/model/loss.py 29 30 31 32 33 34 35 36 def masked_mae ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked MAE loss between input and target. MAE = mean absolute error \"\"\" mask = mask . float () loss = F . l1_loss ( input * mask , target * mask , reduction = \"sum\" ) return loss / mask . sum ()","title":"masked_mae"},{"location":"model/#scprint.model.loss.masked_mse","text":"Compute the masked MSE loss between input and target. Source code in scprint/model/loss.py 20 21 22 23 24 25 26 def masked_mse ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked MSE loss between input and target. \"\"\" mask = mask . float () loss = F . mse_loss ( input * mask , target * mask , reduction = \"sum\" ) return loss / mask . sum ()","title":"masked_mse"},{"location":"model/#scprint.model.loss.masked_nb","text":"Compute the masked negative binomial loss between input and target. Source code in scprint/model/loss.py 39 40 41 42 43 44 45 46 def masked_nb ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked negative binomial loss between input and target. \"\"\" mask = mask . float () nb = torch . distributions . NegativeBinomial ( total_count = target , probs = input ) masked_log_probs = nb . log_prob ( target ) * mask return - masked_log_probs . sum () / mask . sum ()","title":"masked_nb"},{"location":"model/#scprint.model.loss.masked_relative_error","text":"Compute the masked relative error between input and target. Source code in scprint/model/loss.py 153 154 155 156 157 158 159 160 161 def masked_relative_error ( input : Tensor , target : Tensor , mask : torch . LongTensor ) -> Tensor : \"\"\" Compute the masked relative error between input and target. \"\"\" assert mask . any () loss = torch . abs ( input [ mask ] - target [ mask ]) / ( target [ mask ] + 1e-6 ) return loss . mean ()","title":"masked_relative_error"},{"location":"model/#scprint.model.loss.mse","text":"Compute the MSE loss between input and target. Source code in scprint/model/loss.py 9 10 11 12 13 14 15 16 17 def mse ( input : Tensor , target : Tensor ) -> Tensor : \"\"\" Compute the MSE loss between input and target. \"\"\" input = torch . log2 ( input + 1 ) input = ( input / torch . sum ( input , dim = 1 , keepdim = True )) * 10000 target = torch . log2 ( target + 1 ) target = target / torch . sum ( target , dim = 1 , keepdim = True ) * 10000 return F . mse_loss ( input , target , reduction = \"mean\" )","title":"mse"},{"location":"model/#scprint.model.loss.nb","text":"Computes the negative binomial (NB) loss. This function was adapted from scvi-tools. Parameters: target ( Tensor ) \u2013 Ground truth data. mu ( Tensor ) \u2013 Means of the negative binomial distribution (must have positive support). theta ( Tensor ) \u2013 Inverse dispersion parameter (must have positive support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 NB loss value. Source code in scprint/model/loss.py 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 def nb ( target : Tensor , mu : Tensor , theta : Tensor , eps = 1e-8 ): \"\"\" Computes the negative binomial (NB) loss. This function was adapted from scvi-tools. Args: target (Tensor): Ground truth data. mu (Tensor): Means of the negative binomial distribution (must have positive support). theta (Tensor): Inverse dispersion parameter (must have positive support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: NB loss value. \"\"\" if theta . ndimension () == 1 : theta = theta . view ( 1 , theta . size ( 0 )) log_theta_mu_eps = torch . log ( theta + mu + eps ) res = ( theta * ( torch . log ( theta + eps ) - log_theta_mu_eps ) + target * ( torch . log ( mu + eps ) - log_theta_mu_eps ) + torch . lgamma ( target + theta ) - torch . lgamma ( theta ) - torch . lgamma ( target + 1 ) ) return - res . mean ()","title":"nb"},{"location":"model/#scprint.model.loss.nb_dist","text":"nb_dist Computes the negative binomial distribution. Parameters: x ( Tensor ) \u2013 Torch Tensor of observed data. mu ( Tensor ) \u2013 Torch Tensor of means of the negative binomial distribution (must have positive support). theta ( Tensor ) \u2013 Torch Tensor of inverse dispersion parameter (must have positive support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 Negative binomial loss value. Source code in scprint/model/loss.py 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 def nb_dist ( x : Tensor , mu : Tensor , theta : Tensor , eps = 1e-8 ): \"\"\" nb_dist Computes the negative binomial distribution. Args: x (Tensor): Torch Tensor of observed data. mu (Tensor): Torch Tensor of means of the negative binomial distribution (must have positive support). theta (Tensor): Torch Tensor of inverse dispersion parameter (must have positive support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: Negative binomial loss value. \"\"\" loss = - NegativeBinomial ( mu = mu , theta = theta ) . log_prob ( x ) return loss","title":"nb_dist"},{"location":"model/#scprint.model.loss.similarity","text":"Dot product or cosine similarity Source code in scprint/model/loss.py 164 165 166 167 168 169 170 def similarity ( x : Tensor , y : Tensor , temp : float ) -> Tensor : \"\"\" Dot product or cosine similarity \"\"\" res = F . cosine_similarity ( x . unsqueeze ( 1 ), y . unsqueeze ( 0 )) / temp labels = torch . arange ( res . size ( 0 )) . long () . to ( device = res . device ) return F . cross_entropy ( res , labels )","title":"similarity"},{"location":"model/#scprint.model.loss.zinb","text":"Computes zero-inflated negative binomial (ZINB) loss. This function was modified from scvi-tools. Parameters: target ( Tensor ) \u2013 Torch Tensor of ground truth data. mu ( Tensor ) \u2013 Torch Tensor of means of the negative binomial (must have positive support). theta ( Tensor ) \u2013 Torch Tensor of inverse dispersion parameter (must have positive support). pi ( Tensor ) \u2013 Torch Tensor of logits of the dropout parameter (real support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 ZINB loss value. Source code in scprint/model/loss.py 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 def zinb ( target : Tensor , mu : Tensor , theta : Tensor , pi : Tensor , eps = 1e-8 , ): \"\"\" Computes zero-inflated negative binomial (ZINB) loss. This function was modified from scvi-tools. Args: target (Tensor): Torch Tensor of ground truth data. mu (Tensor): Torch Tensor of means of the negative binomial (must have positive support). theta (Tensor): Torch Tensor of inverse dispersion parameter (must have positive support). pi (Tensor): Torch Tensor of logits of the dropout parameter (real support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: ZINB loss value. \"\"\" # uses log(sigmoid(x)) = -softplus(-x) softplus_pi = F . softplus ( - pi ) # eps to make it positive support and taking the log log_theta_mu_eps = torch . log ( theta + mu + eps ) pi_theta_log = - pi + theta * ( torch . log ( theta + eps ) - log_theta_mu_eps ) case_zero = F . softplus ( pi_theta_log ) - softplus_pi mul_case_zero = torch . mul (( target < eps ) . type ( torch . float32 ), case_zero ) case_non_zero = ( - softplus_pi + pi_theta_log + target * ( torch . log ( mu + eps ) - log_theta_mu_eps ) + torch . lgamma ( target + theta ) - torch . lgamma ( theta ) - torch . lgamma ( target + 1 ) ) mul_case_non_zero = torch . mul (( target > eps ) . type ( torch . float32 ), case_non_zero ) res = mul_case_zero + mul_case_non_zero # we want to minize the loss but maximize the log likelyhood return - res . mean ()","title":"zinb"},{"location":"model/#utils","text":"","title":"utils"},{"location":"model/#scprint.model.utils","text":"","title":"utils"},{"location":"model/#scprint.model.utils.Attention","text":"Initialize the Attention class. Parameters: gene_dim ( int ) \u2013 The dimension of the gene. comp_attn ( bool , default: False ) \u2013 Whether to compute attention. Defaults to False. Source code in scprint/model/utils.py 472 473 474 475 476 477 478 479 480 481 482 483 484 def __init__ ( self , gene_dim : int , comp_attn : bool = False ): \"\"\" Initialize the Attention class. Args: gene_dim (int): The dimension of the gene. comp_attn (bool, optional): Whether to compute attention. Defaults to False. \"\"\" self . data : Optional [ Tensor ] = None self . gene_dim : int = gene_dim self . div : Optional [ Tensor ] = None self . attn : Optional [ Tensor ] = None self . comp_attn : bool = comp_attn","title":"Attention"},{"location":"model/#scprint.model.utils.Attention.add","text":"Add data to the internal storage. Parameters: x ( List [ Tensor ] ) \u2013 List of tensors to add. pos ( Tensor ) \u2013 Position tensor. Source code in scprint/model/utils.py 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 def add ( self , x : List [ Tensor ], pos : Tensor ) -> None : \"\"\" Add data to the internal storage. Args: x (List[Tensor]): List of tensors to add. pos (Tensor): Position tensor. \"\"\" pos = pos . detach () . to ( \"cpu\" ) if self . data is None : self . data = torch . zeros ([ len ( x ), self . gene_dim ] + list ( x [ 0 ] . shape [ 2 :])) self . div = torch . zeros ( self . gene_dim ) for i in range ( x [ 0 ] . shape [ 0 ]): # loc = torch.cat([torch.Tensor([r for r in range(8)]), pos[i] + 8]).int() self . data . append ( torch . cat ([ x [ j ][ i ] . detach () . to ( \"cpu\" ) for j in range ( len ( x ))]) )","title":"add"},{"location":"model/#scprint.model.utils.Attention.agg","text":"Aggregate the attention or data based on the comp_attn flag. Parameters: x ( List [ Tensor ] ) \u2013 List of tensors to aggregate. pos ( Tensor ) \u2013 Position tensor. Source code in scprint/model/utils.py 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 def agg ( self , x : List [ Tensor ], pos : Tensor ) -> None : \"\"\" Aggregate the attention or data based on the comp_attn flag. Args: x (List[Tensor]): List of tensors to aggregate. pos (Tensor): Position tensor. \"\"\" if self . comp_attn : if self . attn is None : self . attn = torch . zeros ([ self . gene_dim , self . gene_dim ], device = \"cuda\" ) self . div = torch . zeros ( self . gene_dim , device = \"cuda\" ) for j in range ( x [ 0 ] . shape [ 0 ]): # \u2022cells, \u2022context, \u2022QK, \u2022heads, \u2022dim loc = torch . cat ([ torch . arange ( 8 , device = \"cuda\" ), pos [ j ] + 8 ]) . int () for i in range ( len ( x )): for k in range ( x [ 0 ] . shape [ 3 ]): self . attn [ loc [:, None ], loc ] += torch . nn . functional . softmax ( ( x [ i ][ j , :, 0 , k , :] @ x [ i ][ j , :, 1 , k , :] . T ) * ( x [ 0 ] . shape [ - 1 ] ** - 0.5 ), dim =- 1 , ) self . div [ loc ] += x [ 0 ] . shape [ 3 ] * len ( x ) torch . cuda . empty_cache () else : pos = pos . detach () . to ( \"cpu\" ) if self . data is None : self . data = torch . zeros ([ len ( x ), self . gene_dim ] + list ( x [ 0 ] . shape [ 2 :])) self . div = torch . zeros ( self . gene_dim ) for i in range ( x [ 0 ] . shape [ 0 ]): loc = torch . cat ([ torch . arange ( 8 ), pos [ i ] + 8 ]) . int () for j in range ( len ( x )): self . data [ j , loc , :, :, :] += x [ j ][ i ] . detach () . to ( \"cpu\" ) self . div [ loc ] += 1","title":"agg"},{"location":"model/#scprint.model.utils.Attention.get","text":"Get the aggregated attention or data. Returns: Optional [ ndarray ] \u2013 Optional[np.ndarray]: The aggregated attention or data. Source code in scprint/model/utils.py 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 def get ( self ) -> Optional [ np . ndarray ]: \"\"\" Get the aggregated attention or data. Returns: Optional[np.ndarray]: The aggregated attention or data. \"\"\" if self . comp_attn : loc = self . attn . sum ( 1 ) != 0 return ( ( self . attn [ loc ][:, loc ] / ( self . attn . sum ( 1 )[ loc ] + 0.0001 )) . detach () . cpu () . numpy () ) else : if self . data is None : return None # shape is (layers, genes, qkv, heads, emb) return self . data / self . div . view ( 1 , self . div . shape [ 0 ], 1 , 1 , 1 )","title":"get"},{"location":"model/#scprint.model.utils.downsample_profile","text":"This function downsamples the expression profile of a given single cell RNA matrix. The noise is applied based on the renoise parameter, the total counts of the matrix, and the number of genes. The function first calculates the noise threshold (scaler) based on the renoise parameter. It then generates an initial matrix count by applying a Poisson distribution to a random tensor scaled by the total counts and the number of genes. The function then models the sampling zeros by applying a Poisson distribution to a random tensor scaled by the noise threshold, the total counts, and the number of genes. The function also models the technical zeros by generating a random tensor and comparing it to the noise threshold. The final matrix count is calculated by subtracting the sampling zeros from the initial matrix count and multiplying by the technical zeros. The function ensures that the final matrix count is not less than zero by taking the maximum of the final matrix count and a tensor of zeros. The function returns the final matrix count. Parameters: mat ( Tensor ) \u2013 The input matrix. dropout ( float ) \u2013 The renoise parameter. Returns: \u2013 torch.Tensor: The matrix count after applying noise. Source code in scprint/model/utils.py 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 def downsample_profile ( mat : Tensor , dropout : float , method = \"new\" ): \"\"\" This function downsamples the expression profile of a given single cell RNA matrix. The noise is applied based on the renoise parameter, the total counts of the matrix, and the number of genes. The function first calculates the noise threshold (scaler) based on the renoise parameter. It then generates an initial matrix count by applying a Poisson distribution to a random tensor scaled by the total counts and the number of genes. The function then models the sampling zeros by applying a Poisson distribution to a random tensor scaled by the noise threshold, the total counts, and the number of genes. The function also models the technical zeros by generating a random tensor and comparing it to the noise threshold. The final matrix count is calculated by subtracting the sampling zeros from the initial matrix count and multiplying by the technical zeros. The function ensures that the final matrix count is not less than zero by taking the maximum of the final matrix count and a tensor of zeros. The function returns the final matrix count. Args: mat (torch.Tensor): The input matrix. dropout (float): The renoise parameter. Returns: torch.Tensor: The matrix count after applying noise. \"\"\" # Randomly drop on average N counts to each element of expression using a heavy tail Gaussian distribution # here we try to get the scale of the distribution so as to remove the right number of counts from each gene # https://genomebiology.biomedcentral.com/articles/10.1186/s13059-022-02601-5#:~:text=Zero%20measurements%20in%20scRNA%2Dseq,generation%20of%20scRNA%2Dseq%20data. if method == \"old\" : totcounts = mat . sum ( 1 ) batch = mat . shape [ 0 ] ngenes = mat . shape [ 1 ] tnoise = 1 - ( 1 - dropout ) ** ( 1 / 2 ) # we model the sampling zeros (dropping 30% of the reads) res = torch . poisson ( torch . rand (( batch , ngenes )) . to ( device = mat . device ) * (( tnoise * totcounts . unsqueeze ( 1 )) / ( 0.5 * ngenes )) ) . int () # we model the technical zeros (dropping 50% of the genes) drop = ( torch . rand (( batch , ngenes )) > tnoise ) . int () . to ( device = mat . device ) mat = ( mat - res ) * drop return torch . maximum ( mat , torch . Tensor ([[ 0 ]]) . to ( device = mat . device )) . int () elif method == \"jules\" : scaler = ( 1 - dropout ) ** ( 1 / 2 ) notdrop = ( torch . rand ( mat . shape , device = mat . device , ) < scaler ) . int () notdrop [ mat == 0 ] = 0 # apply the dropout after the poisson, right? return notdrop * torch . poisson ( mat * scaler ) elif method == \"new\" : batch = mat . shape [ 0 ] ngenes = mat . shape [ 1 ] dropout = dropout * 1.1 # we model the sampling zeros (dropping 30% of the reads) res = torch . poisson (( mat * ( dropout / 2 ))) . int () # we model the technical zeros (dropping 50% of the genes) notdrop = ( torch . rand (( batch , ngenes ), device = mat . device ) >= ( dropout / 2 ) ) . int () mat = ( mat - res ) * notdrop return torch . maximum ( mat , torch . zeros (( 1 , 1 ), device = mat . device , dtype = torch . int ) ) else : raise ValueError ( f \"method { method } not recognized\" )","title":"downsample_profile"},{"location":"model/#scprint.model.utils.make_adata","text":"This function creates an AnnData object from the given input parameters. Parameters: embs ( Tensor ) \u2013 Embeddings of the cells. The shape of the tensor is (n_cells, n_features). labels ( list ) \u2013 List of labels for the predicted classes. pred ( Tensor , default: None ) \u2013 Predicted labels. The shape of the tensor is (n_cells, n_classes). Default is None. attention ( Tensor , default: None ) \u2013 Attention weights. Default is None. step ( int , default: 0 ) \u2013 Step number for storing the AnnData without overwriting others. Default is 0. label_decoders ( dict , default: None ) \u2013 Dictionary to map class codes to class names. Default is None. labels_hierarchy ( dict , default: {} ) \u2013 Dictionary representing the hierarchy of labels. Default is {}. gtclass ( Tensor , default: None ) \u2013 Ground truth class. Default is None. name ( str , default: '' ) \u2013 Name of the AnnData object. Default is an empty string. mdir ( str , default: '/tmp' ) \u2013 Directory to save the AnnData object. Default is \"/tmp\". doplot ( bool , default: True ) \u2013 Whether to generate plots. Default is True. Returns: \u2013 anndata.AnnData: The created AnnData object. Source code in scprint/model/utils.py 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 def make_adata ( embs : Tensor , labels : List [ str ], pred : Tensor = None , attention : Optional [ Tensor ] = None , step : int = 0 , label_decoders : Optional [ Dict ] = None , labels_hierarchy : Dict = {}, gtclass : Optional [ Tensor ] = None , name : str = \"\" , mdir : str = \"/tmp\" , doplot : bool = True , ): \"\"\" This function creates an AnnData object from the given input parameters. Args: embs (torch.Tensor): Embeddings of the cells. The shape of the tensor is (n_cells, n_features). labels (list): List of labels for the predicted classes. pred (torch.Tensor, optional): Predicted labels. The shape of the tensor is (n_cells, n_classes). Default is None. attention (torch.Tensor, optional): Attention weights. Default is None. step (int, optional): Step number for storing the AnnData without overwriting others. Default is 0. label_decoders (dict, optional): Dictionary to map class codes to class names. Default is None. labels_hierarchy (dict, optional): Dictionary representing the hierarchy of labels. Default is {}. gtclass (torch.Tensor, optional): Ground truth class. Default is None. name (str, optional): Name of the AnnData object. Default is an empty string. mdir (str, optional): Directory to save the AnnData object. Default is \"/tmp\". doplot (bool, optional): Whether to generate plots. Default is True. Returns: anndata.AnnData: The created AnnData object. \"\"\" colname = [ \"pred_\" + i for i in labels ] if pred is not None : obs = np . array ( pred . to ( device = \"cpu\" , dtype = torch . int32 )) # label decoders is not cls_decoders. one is a dict to map class codes (ints) # to class names the other is the module the predict the class if label_decoders is not None : obs = np . array ( [ [ label_decoders [ labels [ i ]][ n ] for n in name ] for i , name in enumerate ( obs . T ) ] ) . T if gtclass is not None : colname += labels nobs = np . array ( gtclass . to ( device = \"cpu\" , dtype = torch . int32 )) if label_decoders is not None : nobs = np . array ( [ [ label_decoders [ labels [ i ]][ n ] for n in name ] for i , name in enumerate ( nobs . T ) ] ) . T obs = np . hstack ([ obs , nobs ]) adata = AnnData ( np . array ( embs . to ( device = \"cpu\" , dtype = torch . float32 )), obs = pd . DataFrame ( obs , columns = colname , ), ) accuracy = {} for label in labels : if gtclass is not None : tr = translate ( adata . obs [ label ] . tolist (), label ) if tr is not None : adata . obs [ \"conv_\" + label ] = adata . obs [ label ] . replace ( tr ) tr = translate ( adata . obs [ \"pred_\" + label ] . tolist (), label ) if tr is not None : adata . obs [ \"conv_pred_\" + label ] = adata . obs [ \"pred_\" + label ] . replace ( tr ) res = [] if label_decoders is not None and gtclass is not None : class_topred = label_decoders [ label ] . values () if label in labels_hierarchy : cur_labels_hierarchy = { label_decoders [ label ][ k ]: [ label_decoders [ label ][ i ] for i in v ] for k , v in labels_hierarchy [ label ] . items () } else : cur_labels_hierarchy = {} for pred , true in adata . obs [[ \"pred_\" + label , label ]] . values : if pred == true : res . append ( True ) continue if len ( labels_hierarchy ) > 0 : if true in cur_labels_hierarchy : res . append ( pred in cur_labels_hierarchy [ true ]) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) else : pass accuracy [ \"pred_\" + label ] = sum ( res ) / len ( res ) if len ( res ) > 0 else 0 adata . obs = adata . obs . astype ( \"category\" ) else : adata = AnnData ( np . array ( embs . to ( device = \"cpu\" , dtype = torch . float32 )), ) if False : adata . varm [ \"Qs\" ] = ( attention [:, :, 0 , :, :] . permute ( 1 , 3 , 0 , 2 ) . view ( attention . shape [ 0 ], attention . shape [ 1 ], attention . shape [ 3 ] * attention . shape [ 4 ], ) . detach () . cpu () . numpy () ) adata . varm [ \"Ks\" ] = ( attention [:, :, 1 , :, :] . permute ( 1 , 3 , 0 , 2 ) . view ( attention . shape [ 0 ], attention . shape [ 1 ], attention . shape [ 3 ] * attention . shape [ 4 ], ) . detach () . cpu () . numpy () ) print ( adata ) if doplot and adata . shape [ 0 ] > 100 and pred is not None : sc . pp . neighbors ( adata , use_rep = \"X\" ) sc . tl . umap ( adata ) sc . tl . leiden ( adata , key_added = \"sprint_leiden\" ) if gtclass is not None : color = [ i for pair in zip ( [ \"conv_\" + i if \"conv_\" + i in adata . obs . columns else i for i in labels ], [ ( \"conv_pred_\" + i if \"conv_pred_\" + i in adata . obs . columns else \"pred_\" + i ) for i in labels ], ) for i in pair ] fig , axs = plt . subplots ( int ( len ( color ) / 2 ), 2 , figsize = ( 24 , len ( color ) * 4 ) ) plt . subplots_adjust ( wspace = 1 ) for i , col in enumerate ( color ): sc . pl . umap ( adata , color = col , ax = axs [ i // 2 , i % 2 ], show = False , ) acc = \"\" if \"_pred_\" in col and col . split ( \"conv_\" )[ - 1 ] in accuracy : acc = \" (accuracy: {:.2f} )\" . format ( accuracy [ col . split ( \"conv_\" )[ - 1 ]]) axs [ i // 2 , i % 2 ] . set_title ( col + \" UMAP\" + acc ) if \"cell_type\" in col : axs [ i // 2 , i % 2 ] . legend ( fontsize = \"x-small\" ) axs [ i // 2 , i % 2 ] . set_xlabel ( \"UMAP1\" ) axs [ i // 2 , i % 2 ] . set_ylabel ( \"UMAP2\" ) else : color = [ ( \"conv_pred_\" + i if \"conv_pred_\" + i in adata . obs . columns else \"pred_\" + i ) for i in labels ] fig , axs = plt . subplots ( len ( color ), 1 , figsize = ( 16 , len ( color ) * 8 )) for i , col in enumerate ( color ): sc . pl . umap ( adata , color = col , ax = axs [ i ], show = False , ) acc = \"\" if \"_pred_\" in col and col . split ( \"conv_\" )[ - 1 ] in accuracy : acc = \" (accuracy: {:.2f} )\" . format ( accuracy [ col . split ( \"conv_\" )[ - 1 ]]) axs [ i ] . set_title ( col + \" UMAP\" + acc ) axs [ i ] . set_xlabel ( \"UMAP1\" ) axs [ i ] . set_ylabel ( \"UMAP2\" ) plt . show () else : fig = None adata . write ( mdir + \"/step_\" + str ( step ) + \"_\" + name + \".h5ad\" ) return adata , fig","title":"make_adata"},{"location":"model/#scprint.model.utils.simple_masker","text":"Randomly mask a batch of data. Parameters: shape ( list [ int ] ) \u2013 The shape of the data. mask_ratio ( float , default: 0.15 ) \u2013 The ratio of genes to mask, default to 0.15. Returns: Tensor \u2013 torch.Tensor: A tensor of masked data. Source code in scprint/model/utils.py 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 def simple_masker ( shape : list [ int ], mask_ratio : float = 0.15 , ) -> torch . Tensor : \"\"\" Randomly mask a batch of data. Args: shape (list[int]): The shape of the data. mask_ratio (float): The ratio of genes to mask, default to 0.15. Returns: torch.Tensor: A tensor of masked data. \"\"\" return torch . rand ( shape ) < mask_ratio","title":"simple_masker"},{"location":"model/#scprint.model.utils.test","text":"Test the given model on the full set of benchmarks and save the results to JSON files. Parameters: model ( Module ) \u2013 The model to be tested. name ( str ) \u2013 The name to be used for the output JSON files. filedir ( str ) \u2013 The directory where the data files are located. Returns: None \u2013 None Source code in scprint/model/utils.py 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 def test ( model : torch . nn . Module , name : str , filedir : str ) -> None : \"\"\" Test the given model on the full set of benchmarks and save the results to JSON files. Args: model (torch.nn.Module): The model to be tested. name (str): The name to be used for the output JSON files. filedir (str): The directory where the data files are located. Returns: None \"\"\" metrics = {} res = embbed_task . default_benchmark ( model , default_dataset = \"lung\" , do_class = True , coarse = False ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"embed_lung\" : res }, indent = 4 )) f . close () metrics . update ( { \"emb_lung/scib\" : float ( res [ \"scib\" ][ \"Total\" ]), \"emb_lung/ct_class\" : float ( res [ \"classif\" ][ \"cell_type_ontology_term_id\" ][ \"accuracy\" ] ), } ) print ( metrics ) res = embbed_task . default_benchmark ( model , default_dataset = \"pancreas\" , do_class = True , coarse = False ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"embed_panc\" : res }, indent = 4 )) f . close () metrics . update ( { \"emb_panc/scib\" : float ( res [ \"scib\" ][ \"Total\" ]), \"emb_panc/ct_class\" : float ( res [ \"classif\" ][ \"cell_type_ontology_term_id\" ][ \"accuracy\" ] ), } ) print ( metrics ) gc . collect () res = denoise_task . default_benchmark ( model , filedir + \"/../../data/gNNpgpo6gATjuxTE7CCp.h5ad\" ) metrics . update ( { \"denoise/reco2full_vs_noisy2full\" : float ( res [ \"reco2full\" ] - res [ \"noisy2full\" ] ), } ) gc . collect () print ( metrics ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"denoise\" : res }, indent = 4 )) f . close () res = grn_task . default_benchmark ( model , \"gwps\" , batch_size = 32 if model . d_model <= 512 else 8 ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_gwps\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_gwps/auprc_self\" : float ( res [ \"self\" ][ \"auprc\" ]), \"grn_gwps/epr_self\" : float ( res [ \"self\" ][ \"epr\" ]), \"grn_gwps/auprc_omni\" : float ( res [ \"omni\" ][ \"auprc\" ]), \"grn_gwps/epr_omni\" : float ( res [ \"omni\" ][ \"epr\" ]), \"grn_gwps/auprc\" : float ( res [ \"mean\" ][ \"auprc\" ]), \"grn_gwps/epr\" : float ( res [ \"mean\" ][ \"epr\" ]), } ) print ( metrics ) gc . collect () res = grn_task . default_benchmark ( model , \"sroy\" , batch_size = 32 if model . d_model <= 512 else 8 ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_sroy\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_sroy/auprc_self\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"self_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr_self\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"self_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/auprc_omni\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"omni_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr_omni\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"omni_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/auprc\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"mean_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"mean_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), } ) print ( metrics ) gc . collect () res = grn_task . default_benchmark ( model , filedir + \"/../../data/yBCKp6HmXuHa0cZptMo7.h5ad\" , batch_size = 32 if model . d_model <= 512 else 8 , ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_omni\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_omni/auprc_class\" : float ( np . mean ([ i [ \"auprc\" ] for k , i in res . items () if \"_class\" in k ]) ), \"grn_omni/epr_class\" : float ( np . mean ([ i [ \"epr\" ] for k , i in res . items () if \"_class\" in k ]) ), \"grn_omni/tf_enr_class\" : float ( np . sum ( [ i . get ( \"TF_enr\" , False ) for k , i in res . items () if \"_class\" in k ] ) ), \"grn_omni/tf_targ_enr_class\" : float ( np . mean ( [ i [ \"significant_enriched_TFtargets\" ] for k , i in res . items () if \"_class\" in k ] ) ), \"grn_omni/auprc\" : float ( np . mean ([ i [ \"auprc\" ] for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/epr\" : float ( np . mean ([ i [ \"epr\" ] for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/tf_enr\" : float ( np . sum ([ i . get ( \"TF_enr\" , False ) for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/tf_targ_enr\" : float ( np . mean ( [ i [ \"significant_enriched_TFtargets\" ] for k , i in res . items () if \"_mean\" in k ] ) ), # 'grn_omni/ct': res['classif']['cell_type_ontology_term_id']['accuracy'], } ) return metrics","title":"test"},{"location":"model/#scprint.model.utils.translate","text":"translate This function translates the given value based on the specified type. Parameters: val ( str / list / set / dict / Counter ) \u2013 The value to be translated. t ( str , default: 'cell_type_ontology_term_id' ) \u2013 The type of translation to be performed. Defaults to \"cell_type_ontology_term_id\". Returns: dict \u2013 A dictionary with the translated values. Source code in scprint/model/utils.py 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 def translate ( val : Union [ str , list , set , dict , Counter ], t : str = \"cell_type_ontology_term_id\" ): \"\"\" translate This function translates the given value based on the specified type. Args: val (str/list/set/dict/Counter): The value to be translated. t (str, optional): The type of translation to be performed. Defaults to \"cell_type_ontology_term_id\". Returns: dict: A dictionary with the translated values. \"\"\" if t == \"cell_type_ontology_term_id\" : obj = bt . CellType . df () . set_index ( \"ontology_id\" ) elif t == \"assay_ontology_term_id\" : obj = bt . ExperimentalFactor . df () . set_index ( \"ontology_id\" ) elif t == \"tissue_ontology_term_id\" : obj = bt . Tissue . df () . set_index ( \"ontology_id\" ) elif t == \"disease_ontology_term_id\" : obj = bt . Disease . df () . set_index ( \"ontology_id\" ) elif t == \"self_reported_ethnicity_ontology_term_id\" : obj = bt . Ethnicity . df () . set_index ( \"ontology_id\" ) else : return None if type ( val ) is str : if val == \"unknown\" : return { val : val } return { val : obj . loc [ val ][ \"name\" ]} elif type ( val ) is list or type ( val ) is set : return { i : obj . loc [ i ][ \"name\" ] if i != \"unknown\" else i for i in set ( val )} elif type ( val ) is dict or type ( val ) is Counter : return { obj . loc [ k ][ \"name\" ] if k != \"unknown\" else k : v for k , v in val . items ()}","title":"translate"},{"location":"model/#scprint.model.utils.weighted_masker","text":"Randomly mask a batch of data. Parameters: shape ( list [ int ] ) \u2013 The shape of the data. mask_ratio ( float , default: 0.15 ) \u2013 The ratio of genes to mask, default to 0.15. mask_value ( int , default: 1 ) \u2013 The value to mask with, default to -1. pad_value ( int ) \u2013 The value of padding in the values, will be kept unchanged. Returns: Tensor \u2013 torch.Tensor: A tensor of masked data. Source code in scprint/model/utils.py 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 def weighted_masker ( shape : list [ int ], mask_ratio : float = 0.15 , mask_prob : Optional [ Union [ torch . Tensor , np . ndarray ]] = None , # n_features mask_value : int = 1 , ) -> torch . Tensor : \"\"\" Randomly mask a batch of data. Args: shape (list[int]): The shape of the data. mask_ratio (float): The ratio of genes to mask, default to 0.15. mask_value (int): The value to mask with, default to -1. pad_value (int): The value of padding in the values, will be kept unchanged. Returns: torch.Tensor: A tensor of masked data. \"\"\" mask = [] for _ in range ( shape [ 0 ]): m = np . zeros ( shape [ 1 ]) loc = np . random . choice ( a = shape [ 1 ], size = int ( shape [ 1 ] * mask_ratio ), replace = False , p = mask_prob ) m [ loc ] = mask_value mask . append ( m ) return torch . Tensor ( np . array ( mask )) . to ( torch . bool )","title":"weighted_masker"},{"location":"model/#scprint.model.utils.zinb_sample","text":"zinb_sample This function generates a sample from a Zero-Inflated Negative Binomial (ZINB) distribution. Parameters: mu ( Tensor ) \u2013 The mean of the Negative Binomial (NB) distribution. theta ( Tensor ) \u2013 The dispersion parameter of the NB distribution. zi_probs ( Tensor ) \u2013 The zero-inflation probabilities. sample_shape ( Size , default: Size ([]) ) \u2013 The output shape. Defaults to torch.Size([]). Returns: \u2013 torch.Tensor: A sample from the ZINB distribution. Source code in scprint/model/utils.py 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 def zinb_sample ( mu : torch . Tensor , theta : torch . Tensor , zi_probs : torch . Tensor , sample_shape : torch . Size = torch . Size ([]), ): \"\"\" zinb_sample This function generates a sample from a Zero-Inflated Negative Binomial (ZINB) distribution. Args: mu (torch.Tensor): The mean of the Negative Binomial (NB) distribution. theta (torch.Tensor): The dispersion parameter of the NB distribution. zi_probs (torch.Tensor): The zero-inflation probabilities. sample_shape (torch.Size, optional): The output shape. Defaults to torch.Size([]). Returns: torch.Tensor: A sample from the ZINB distribution. \"\"\" concentration = theta rate = theta / mu # Important remark: Gamma is parametrized by the rate = 1/scale! gamma_d = Gamma ( concentration = concentration , rate = rate ) p_means = gamma_d . sample ( sample_shape ) # Clamping as distributions objects can have buggy behaviors when # their parameters are too high l_train = torch . clamp ( p_means , max = 1e8 ) samp = Poisson ( l_train ) . sample () # Shape : (n_samples, n_cells_batch, n_vars) is_zero = torch . rand_like ( samp ) <= zi_probs samp_ = torch . where ( is_zero , torch . zeros_like ( samp ), samp ) return samp_","title":"zinb_sample"},{"location":"model/#encoder-and-decoder-modules","text":"","title":"encoder and decoder modules"},{"location":"model/#scprint.model.encoders","text":"","title":"encoders"},{"location":"model/#scprint.model.encoders.CategoryValueEncoder","text":"Bases: Module Encodes categorical values into a vector using an embedding layer and layer normalization. Parameters: num_embeddings ( int ) \u2013 The number of possible values. embedding_dim ( int ) \u2013 The dimension of the output vectors. padding_idx ( int , default: None ) \u2013 The index of the padding token. Defaults to None. Returns: \u2013 torch.Tensor: A tensor representing the encoded categorical values. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 def __init__ ( self , num_embeddings : int , embedding_dim : int , padding_idx : Optional [ int ] = None , ): \"\"\" Encodes categorical values into a vector using an embedding layer and layer normalization. Args: num_embeddings (int): The number of possible values. embedding_dim (int): The dimension of the output vectors. padding_idx (int, optional): The index of the padding token. Defaults to None. Returns: torch.Tensor: A tensor representing the encoded categorical values. Note: not used in the current version of scprint. \"\"\" super ( CategoryValueEncoder , self ) . __init__ () self . embedding = nn . Embedding ( num_embeddings , embedding_dim , padding_idx = padding_idx )","title":"CategoryValueEncoder"},{"location":"model/#scprint.model.encoders.ContinuousValueEncoder","text":"Bases: Module Encode real number values to a vector using neural nets projection. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float , default: 0.1 ) \u2013 The dropout rate to apply to the output of the positional encoding. max_value ( int , default: 100000 ) \u2013 The maximum value of the input. Defaults to 100_000. layers ( int , default: 1 ) \u2013 The number of layers in the encoder. Defaults to 1. size ( int , default: 1 ) \u2013 The size of the input. Defaults to 1. Returns: \u2013 torch.Tensor: A tensor representing the encoded continuous values. Source code in scprint/model/encoders.py 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 def __init__ ( self , d_model : int , dropout : float = 0.1 , max_value : int = 100_000 , layers : int = 1 , size : int = 1 , ): \"\"\" Encode real number values to a vector using neural nets projection. Args: d_model (int): The dimension of the input vectors. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. max_value (int, optional): The maximum value of the input. Defaults to 100_000. layers (int, optional): The number of layers in the encoder. Defaults to 1. size (int, optional): The size of the input. Defaults to 1. Returns: torch.Tensor: A tensor representing the encoded continuous values. \"\"\" super ( ContinuousValueEncoder , self ) . __init__ () self . max_value = max_value self . encoder = nn . ModuleList () self . encoder . append ( nn . Linear ( size , d_model )) for _ in range ( layers - 1 ): self . encoder . append ( nn . LayerNorm ( d_model )) self . encoder . append ( nn . ReLU ()) self . encoder . append ( nn . Dropout ( p = dropout )) self . encoder . append ( nn . Linear ( d_model , d_model ))","title":"ContinuousValueEncoder"},{"location":"model/#scprint.model.encoders.ContinuousValueEncoder.forward","text":"Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, seq_len] Source code in scprint/model/encoders.py 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 def forward ( self , x : Tensor , mask : Tensor = None ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, seq_len] \"\"\" # expand last dimension x = x . unsqueeze ( - 1 ) # use the mask embedding when x=-1 # mask = (x == -1).float() x = torch . clamp ( x , min = 0 , max = self . max_value ) for val in self . encoder : x = val ( x ) if mask is not None : x = x . masked_fill_ ( mask . unsqueeze ( - 1 ), 0 ) return x","title":"forward"},{"location":"model/#scprint.model.encoders.DPositionalEncoding","text":"Bases: Module The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. max_len ( int ) \u2013 The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 def __init__ ( self , d_model : int , max_len_x : int , max_len_y : int , maxvalue_x = 10000.0 , maxvalue_y = 10000.0 , ): super ( DPositionalEncoding , self ) . __init__ () position2 = torch . arange ( max_len_y ) . unsqueeze ( 1 ) position1 = torch . arange ( max_len_x ) . unsqueeze ( 1 ) half_n = d_model // 2 div_term2 = torch . exp ( torch . arange ( 0 , half_n , 2 ) * ( - math . log ( maxvalue_y ) / d_model ) ) div_term1 = torch . exp ( torch . arange ( 0 , half_n , 2 ) * ( - math . log ( maxvalue_x ) / d_model ) ) pe1 = torch . zeros ( max_len_x , 1 , d_model ) pe2 = torch . zeros ( max_len_y , 1 , d_model ) pe1 [:, 0 , 0 : half_n : 2 ] = torch . sin ( position1 * div_term1 ) pe1 [:, 0 , 1 : half_n : 2 ] = torch . cos ( position1 * div_term1 ) pe2 [:, 0 , half_n :: 2 ] = torch . sin ( position2 * div_term2 ) pe2 [:, 0 , 1 + half_n :: 2 ] = torch . cos ( position2 * div_term2 ) # https://github.com/tatp22/multidim-positional-encoding/blob/master/positional_encodings/torch_encodings.py self . register_buffer ( \"pe1\" , pe1 ) self . register_buffer ( \"pe2\" , pe2 )","title":"DPositionalEncoding"},{"location":"model/#scprint.model.encoders.DPositionalEncoding.forward","text":"Parameters: x ( Tensor ) \u2013 Tensor, shape [seq_len, batch_size, embedding_dim] Source code in scprint/model/encoders.py 148 149 150 151 152 153 154 155 def forward ( self , x : Tensor , pos_x : Tensor , pos_y : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] \"\"\" x = x + self . pe1 [ pos_x ] x = x + self . pe2 [ pos_y ] return x","title":"forward"},{"location":"model/#scprint.model.encoders.GeneEncoder","text":"Bases: Module Encodes gene sequences into a continuous vector space using an embedding layer. The output is then normalized using a LayerNorm. Parameters: num_embeddings ( int ) \u2013 The number of possible values. embedding_dim ( int ) \u2013 The dimension of the output vectors. padding_idx ( int , default: None ) \u2013 The index of the padding token. Defaults to None. weights ( Tensor , default: None ) \u2013 The initial weights for the embedding layer. Defaults to None. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. freeze ( bool , default: False ) \u2013 Whether to freeze the weights of the embedding layer. Defaults to False. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def __init__ ( self , num_embeddings : int , embedding_dim : int , padding_idx : Optional [ int ] = None , weights : Optional [ Tensor ] = None , freeze : bool = False , ): \"\"\" Encodes gene sequences into a continuous vector space using an embedding layer. The output is then normalized using a LayerNorm. Args: num_embeddings (int): The number of possible values. embedding_dim (int): The dimension of the output vectors. padding_idx (int, optional): The index of the padding token. Defaults to None. weights (Tensor, optional): The initial weights for the embedding layer. Defaults to None. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. freeze (bool, optional): Whether to freeze the weights of the embedding layer. Defaults to False. Note: not used in the current version of scprint. \"\"\" super ( GeneEncoder , self ) . __init__ () self . embedding = nn . Embedding ( num_embeddings , embedding_dim , padding_idx = padding_idx , _freeze = freeze ) if weights is not None : # concat a zero vector to the weight # this is to make the embedding of the padding token to be zero # weights = torch.cat( # [torch.Tensor(weights), torch.zeros(1, embedding_dim)], dim=0 # ) self . embedding . weight . data . copy_ ( torch . Tensor ( weights ))","title":"GeneEncoder"},{"location":"model/#scprint.model.encoders.PositionalEncoding","text":"Bases: Module The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. max_len ( int ) \u2013 The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 def __init__ ( self , d_model : int , max_len : int , token_to_pos : dict [ str , int ], # [token, pos] maxval = 10000.0 , ): \"\"\" The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Args: d_model (int): The dimension of the input vectors. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. max_len (int, optional): The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. \"\"\" super ( PositionalEncoding , self ) . __init__ () position = torch . arange ( max_len ) . unsqueeze ( 1 ) # Create a dictionary to convert token to position div_term = torch . exp ( torch . arange ( 0 , d_model , 2 ) * ( - math . log ( maxval ) / d_model ) ) pe = torch . zeros ( max_len , 1 , d_model ) pe [:, 0 , 0 :: 2 ] = torch . sin ( position * div_term ) pe [:, 0 , 1 :: 2 ] = torch . cos ( position * div_term ) # we reorder them and map them to gene_id (position) arr = [] for _ , v in token_to_pos . items (): arr . append ( pe [ v - 1 ] . numpy ()) pe = torch . Tensor ( np . array ( arr )) self . register_buffer ( \"pe\" , pe )","title":"PositionalEncoding"},{"location":"model/#scprint.model.encoders.PositionalEncoding.forward","text":"Parameters: x \u2013 Tensor, shape [seq_len, batch_size, embedding_dim] Source code in scprint/model/encoders.py 88 89 90 91 92 93 94 95 def forward ( self , gene_pos : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] \"\"\" return torch . index_select ( self . pe , 0 , gene_pos . view ( - 1 )) . view ( gene_pos . shape + ( - 1 ,) )","title":"forward"},{"location":"model/#scprint.model.decoders","text":"","title":"decoders"},{"location":"model/#scprint.model.decoders.ClsDecoder","text":"Bases: Module ClsDecoder Decoder for classification task. Parameters: d_model ( int ) \u2013 int, dimension of the input. n_cls ( int ) \u2013 int, number of classes. layers ( list [ int ] , default: [256, 128] ) \u2013 list[int], list of hidden layers. activation ( Callable , default: ReLU ) \u2013 nn.Module, activation function. dropout ( float , default: 0.1 ) \u2013 float, dropout rate. Returns: \u2013 Tensor, shape [batch_size, n_cls] Source code in scprint/model/decoders.py 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 def __init__ ( self , d_model : int , n_cls : int , layers : list [ int ] = [ 256 , 128 ], activation : Callable = nn . ReLU , dropout : float = 0.1 , ): \"\"\" ClsDecoder Decoder for classification task. Args: d_model: int, dimension of the input. n_cls: int, number of classes. layers: list[int], list of hidden layers. activation: nn.Module, activation function. dropout: float, dropout rate. Returns: Tensor, shape [batch_size, n_cls] \"\"\" super ( ClsDecoder , self ) . __init__ () # module list layers = [ d_model ] + layers self . decoder = nn . Sequential () for i , l in enumerate ( layers [ 1 :]): self . decoder . append ( nn . Linear ( layers [ i ], l )) self . decoder . append ( nn . LayerNorm ( l )) self . decoder . append ( activation ()) self . decoder . append ( nn . Dropout ( dropout )) self . out_layer = nn . Linear ( layers [ - 1 ], n_cls )","title":"ClsDecoder"},{"location":"model/#scprint.model.decoders.ClsDecoder.forward","text":"Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, embsize] Source code in scprint/model/decoders.py 206 207 208 209 210 211 212 def forward ( self , x : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, embsize] \"\"\" x = self . decoder ( x ) return self . out_layer ( x )","title":"forward"},{"location":"model/#scprint.model.decoders.ExprDecoder","text":"Bases: Module ExprDecoder Decoder for the gene expression prediction. Will output the mean, variance and zero logits, parameters of a zero inflated negative binomial distribution. Parameters: d_model ( int ) \u2013 The dimension of the model. This is the size of the input feature vector. nfirst_tokens_to_skip ( int , default: 0 ) \u2013 The number of initial labels to skip in the sequence. Defaults to 0. dropout ( float , default: 0.1 ) \u2013 The dropout rate applied during training to prevent overfitting. Defaults to 0.1. zinb ( bool , default: True ) \u2013 Whether to use a zero inflated negative binomial distribution. Defaults to True. Source code in scprint/model/decoders.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 def __init__ ( self , d_model : int , nfirst_tokens_to_skip : int = 0 , dropout : float = 0.1 , zinb : bool = True , ): \"\"\" ExprDecoder Decoder for the gene expression prediction. Will output the mean, variance and zero logits, parameters of a zero inflated negative binomial distribution. Args: d_model (int): The dimension of the model. This is the size of the input feature vector. nfirst_tokens_to_skip (int, optional): The number of initial labels to skip in the sequence. Defaults to 0. dropout (float, optional): The dropout rate applied during training to prevent overfitting. Defaults to 0.1. zinb (bool, optional): Whether to use a zero inflated negative binomial distribution. Defaults to True. \"\"\" super ( ExprDecoder , self ) . __init__ () self . nfirst_tokens_to_skip = nfirst_tokens_to_skip self . fc = nn . Sequential ( nn . Linear ( d_model , d_model ), nn . LayerNorm ( d_model ), nn . LeakyReLU (), nn . Dropout ( dropout ), nn . Linear ( d_model , d_model ), nn . LayerNorm ( d_model ), nn . LeakyReLU (), ) self . pred_var_zero = nn . Linear ( d_model , 3 if zinb else 1 ) self . zinb = zinb","title":"ExprDecoder"},{"location":"model/#scprint.model.decoders.ExprDecoder.forward","text":"x is the output of the transformer, (batch, seq_len, d_model) Source code in scprint/model/decoders.py 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 def forward ( self , x : Tensor ) -> Dict [ str , Tensor ]: \"\"\"x is the output of the transformer, (batch, seq_len, d_model)\"\"\" # we don't do it on the labels x = self . fc ( x [:, self . nfirst_tokens_to_skip :, :]) if self . zinb : pred_value , var_value , zero_logits = self . pred_var_zero ( x ) . split ( 1 , dim =- 1 ) # (batch, seq_len) # The sigmoid function is used to map the zero_logits to a probability between 0 and 1. return dict ( mean = F . softmax ( pred_value . squeeze ( - 1 ), dim =- 1 ), disp = torch . exp ( torch . clamp ( var_value . squeeze ( - 1 ), max = 15 )), zero_logits = zero_logits . squeeze ( - 1 ), ) else : pred_value = self . pred_var_zero ( x ) return dict ( mean = F . softmax ( pred_value . squeeze ( - 1 ), dim =- 1 ))","title":"forward"},{"location":"model/#scprint.model.decoders.GraphSDEExprDecoder","text":"Bases: Module Initialize the ExprNeuralSDEDecoder module. Parameters: d_model ( int ) \u2013 The dimension of the model. drift ( Module ) \u2013 The drift component of the SDE. diffusion ( Module ) \u2013 The diffusion component of the SDE. Source code in scprint/model/decoders.py 8 9 10 11 12 13 14 15 16 17 18 19 20 def __init__ ( self , d_model : int , drift : nn . Module , diffusion : nn . Module ): \"\"\" Initialize the ExprNeuralSDEDecoder module. Args: d_model (int): The dimension of the model. drift (nn.Module): The drift component of the SDE. diffusion (nn.Module): The diffusion component of the SDE. \"\"\" super () . __init__ () self . d_model = d_model self . drift = drift self . diffusion = diffusion","title":"GraphSDEExprDecoder"},{"location":"model/#scprint.model.decoders.MVCDecoder","text":"Bases: Module MVCDecoder Decoder for the masked value prediction for cell embeddings. Will use the gene embeddings with the cell embeddings to predict the mean, variance and zero logits Parameters: d_model \u2013 obj: int ): dimension of the gene embedding. arch_style \u2013 obj: str ): architecture style of the decoder, choice from 1. \"inner product\" or 2. \"cell product\" 3. \"concat query\" or 4. \"sum query\". query_activation \u2013 obj: nn.Module ): activation function for the query vectors. Defaults to nn.Sigmoid. hidden_activation \u2013 obj: nn.Module ): activation function for the hidden layers. Defaults to nn.PReLU. Source code in scprint/model/decoders.py 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 def __init__ ( self , d_model : int , arch_style : str = \"inner product\" , tot_labels : int = 1 , query_activation : nn . Module = nn . Sigmoid , hidden_activation : nn . Module = nn . PReLU , ) -> None : \"\"\" MVCDecoder Decoder for the masked value prediction for cell embeddings. Will use the gene embeddings with the cell embeddings to predict the mean, variance and zero logits Args: d_model (:obj:`int`): dimension of the gene embedding. arch_style (:obj:`str`): architecture style of the decoder, choice from 1. \"inner product\" or 2. \"cell product\" 3. \"concat query\" or 4. \"sum query\". query_activation (:obj:`nn.Module`): activation function for the query vectors. Defaults to nn.Sigmoid. hidden_activation (:obj:`nn.Module`): activation function for the hidden layers. Defaults to nn.PReLU. \"\"\" super ( MVCDecoder , self ) . __init__ () if arch_style == \"inner product\" : self . gene2query = nn . Linear ( d_model , d_model ) self . norm = nn . LayerNorm ( d_model ) self . query_activation = query_activation () self . pred_var_zero = nn . Linear ( d_model , d_model * 3 , bias = False ) elif arch_style == \"concat query\" : self . gene2query = nn . Linear ( d_model , d_model ) self . query_activation = query_activation () self . fc1 = nn . Linear ( d_model * ( 1 + tot_labels ), d_model / 2 ) self . hidden_activation = hidden_activation () self . fc2 = nn . Linear ( d_model / 2 , 3 ) elif arch_style == \"sum query\" : self . gene2query = nn . Linear ( d_model , d_model ) self . query_activation = query_activation () self . fc1 = nn . Linear ( d_model , 64 ) self . hidden_activation = hidden_activation () self . fc2 = nn . Linear ( 64 , 3 ) else : raise ValueError ( f \"Unknown arch_style: { arch_style } \" ) self . arch_style = arch_style self . do_detach = arch_style . endswith ( \"detach\" ) self . d_model = d_model","title":"MVCDecoder"},{"location":"model/#scprint.model.decoders.MVCDecoder.forward","text":"Parameters: cell_emb ( Tensor ) \u2013 Tensor, shape (batch, embsize=d_model) gene_embs ( Tensor ) \u2013 Tensor, shape (batch, seq_len, embsize=d_model) Source code in scprint/model/decoders.py 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 def forward ( self , cell_emb : Tensor , gene_embs : Tensor , ) -> Union [ Tensor , Dict [ str , Tensor ]]: \"\"\" Args: cell_emb: Tensor, shape (batch, embsize=d_model) gene_embs: Tensor, shape (batch, seq_len, embsize=d_model) \"\"\" if self . arch_style == \"inner product\" : query_vecs = self . query_activation ( self . norm ( self . gene2query ( gene_embs ))) pred , var , zero_logits = self . pred_var_zero ( query_vecs ) . split ( self . d_model , dim =- 1 ) cell_emb = cell_emb . unsqueeze ( 2 ) pred , var , zero_logits = ( torch . bmm ( pred , cell_emb ) . squeeze ( 2 ), torch . bmm ( var , cell_emb ) . squeeze ( 2 ), torch . bmm ( zero_logits , cell_emb ) . squeeze ( 2 ), ) # zero logits need to based on the cell_emb, because of input exprs elif self . arch_style == \"concat query\" : query_vecs = self . query_activation ( self . gene2query ( gene_embs )) # expand cell_emb to (batch, seq_len, embsize) cell_emb = cell_emb . unsqueeze ( 1 ) . expand ( - 1 , gene_embs . shape [ 1 ], - 1 ) h = self . hidden_activation ( self . fc1 ( torch . cat ([ cell_emb , query_vecs ], dim = 2 )) ) pred , var , zero_logits = self . fc2 ( h ) . split ( 1 , dim =- 1 ) elif self . arch_style == \"sum query\" : query_vecs = self . query_activation ( self . gene2query ( gene_embs )) cell_emb = cell_emb . unsqueeze ( 1 ) h = self . hidden_activation ( self . fc1 ( cell_emb + query_vecs )) pred , var , zero_logits = self . fc2 ( h ) . split ( 1 , dim =- 1 ) return dict ( mvc_mean = F . softmax ( pred , dim =- 1 ), mvc_disp = torch . exp ( torch . clamp ( var , max = 15 )), mvc_zero_logits = zero_logits , )","title":"forward"},{"location":"model/#flashattention","text":"","title":"flashattention"},{"location":"model/#scprint.model.flash_attn.flashformer","text":"","title":"flashformer"},{"location":"model/#scprint.model.flash_attn.flashformer.FlashTransformerEncoder","text":"Bases: Module FlashTransformerEncoder a transformer encoder with flash attention. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. nhead ( int ) \u2013 The number of attention heads. nlayers ( int ) \u2013 The number of layers in the transformer. dropout ( float , default: 0.1 ) \u2013 The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. residual_in_fp32 ( bool , default: True ) \u2013 Whether to force the residual to be in fp32 format. Defaults to True. num_heads_kv ( _type_ , default: None ) \u2013 The number of heads for key/value. Defaults to None. checkpointing ( bool , default: False ) \u2013 Whether to use gradient checkpointing. Defaults to False. fused_dropout_add_ln ( bool , default: False ) \u2013 Whether to fuse dropout, addition and layer normalization operations. Defaults to False. return_residual ( bool , default: False ) \u2013 Whether to return the residual. Defaults to False. prenorm ( bool , default: True ) \u2013 Whether to use pre-normalization. Defaults to True. mlp_ratio ( float , default: 4.0 ) \u2013 The ratio for MLP. Defaults to 4.0. fused_mlp ( bool , default: False ) \u2013 Whether to use fused MLP. Defaults to False. fused_bias_fc ( bool , default: False ) \u2013 Whether to fuse bias and fully connected layers. Defaults to False. sequence_parallel ( bool , default: False ) \u2013 Whether to use sequence parallelism. Defaults to False. drop_path_rate ( float , default: 0.0 ) \u2013 The drop path rate. Defaults to 0.0. weight_init ( str , default: '' ) \u2013 The weight initialization method. Defaults to \"\". Raises: ImportError \u2013 Raised when Triton is not installed but fused_dropout_add_ln is set to True. NotImplementedError \u2013 Raised when an unsupported operation is attempted. Source code in scprint/model/flash_attn/flashformer.py 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 def __init__ ( self , d_model : int , nhead : int , nlayers : int , dropout : float = 0.1 , residual_in_fp32 : bool = True , num_heads_kv : Optional [ int ] = None , checkpointing : bool = False , fused_dropout_add_ln : bool = False , return_residual : bool = False , prenorm : bool = True , mlp_ratio : float = 4.0 , fused_mlp : bool = False , fused_bias_fc : bool = False , sequence_parallel : bool = False , drop_path_rate : float = 0.0 , use_flash_attn : bool = True , weight_init : str = \"\" , ): \"\"\" FlashTransformerEncoder a transformer encoder with flash attention. Args: d_model (int): The dimension of the input vectors. nhead (int): The number of attention heads. nlayers (int): The number of layers in the transformer. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. residual_in_fp32 (bool, optional): Whether to force the residual to be in fp32 format. Defaults to True. num_heads_kv (_type_, optional): The number of heads for key/value. Defaults to None. checkpointing (bool, optional): Whether to use gradient checkpointing. Defaults to False. fused_dropout_add_ln (bool, optional): Whether to fuse dropout, addition and layer normalization operations. Defaults to False. return_residual (bool, optional): Whether to return the residual. Defaults to False. prenorm (bool, optional): Whether to use pre-normalization. Defaults to True. mlp_ratio (float, optional): The ratio for MLP. Defaults to 4.0. fused_mlp (bool, optional): Whether to use fused MLP. Defaults to False. fused_bias_fc (bool, optional): Whether to fuse bias and fully connected layers. Defaults to False. sequence_parallel (bool, optional): Whether to use sequence parallelism. Defaults to False. drop_path_rate (float, optional): The drop path rate. Defaults to 0.0. weight_init (str, optional): The weight initialization method. Defaults to \"\". Raises: ImportError: Raised when Triton is not installed but fused_dropout_add_ln is set to True. NotImplementedError: Raised when an unsupported operation is attempted. \"\"\" super ( FlashTransformerEncoder , self ) . __init__ () self . blocks = nn . ModuleList () dpr = [ x . item () for x in torch . linspace ( 0 , drop_path_rate , nlayers ) ] # stochastic depth decay rule for i in range ( nlayers ): mlp = create_mlp_cls ( d_model , mlp_ratio , nn . GELU , fused_mlp ) attention = partial ( MHA , num_heads = nhead , dropout = dropout , causal = False , use_flash_attn = use_flash_attn , num_heads_kv = num_heads_kv , checkpointing = checkpointing , fused_bias_fc = fused_bias_fc , layer_idx = i , ) # or use parallelBlock where attn & MLP are done in parallel encoder_layers = Block ( d_model , attention , mlp , prenorm = prenorm , # need to set it here for now although it hinders some performances as it returns the residual and I need to see what to do with it # TD [2022-07-30]: Force residual in fp32, seems to make fp16 training more stable residual_in_fp32 = residual_in_fp32 , sequence_parallel = sequence_parallel , # for more parallelism resid_dropout1 = dropout , resid_dropout2 = dropout , drop_path1 = dpr [ i - 1 ] if i > 0 else 0.0 , drop_path2 = dpr [ i ], fused_dropout_add_ln = fused_dropout_add_ln , return_residual = return_residual , ) self . blocks . append ( encoder_layers ) self . prenorm = prenorm self . dropout = nn . Dropout ( p = dropout ) self . drop_path = StochasticDepth ( p = dpr [ - 1 ], mode = \"row\" ) self . norm = torch . nn . LayerNorm ( d_model , eps = 1e-6 ) self . fused_dropout_add_ln = fused_dropout_add_ln if self . fused_dropout_add_ln and layer_norm_fn is None : raise ImportError ( \"Triton is not installed\" ) if sequence_parallel : # This seems to only be important when doing tensor parallelism across GPUs, to increase even more the context length I guess? # not really necessary here I think raise NotImplementedError ( \"sequence_parallel not implemented yet\" ) self . init_weights ( weight_init )","title":"FlashTransformerEncoder"},{"location":"model/#scprint.model.flash_attn.mha","text":"","title":"mha"},{"location":"model/#scprint.model.flash_attn.mha.CrossAttention","text":"Bases: Module Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. Default to 1/sqrt(d_keys) where d_keys is computed at runtime attention_dropout: The dropout rate to apply to the attention. default to 0.0. Source code in scprint/model/flash_attn/mha.py 245 246 247 248 249 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 ): super () . __init__ () self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout )","title":"CrossAttention"},{"location":"model/#scprint.model.flash_attn.mha.CrossAttention.forward","text":"Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, Sk) Source code in scprint/model/flash_attn/mha.py 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 def forward ( self , q , kv , causal = None , key_padding_mask = None , bias = None ): \"\"\"Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, Sk) \"\"\" batch_size , seqlen_q = q . shape [ 0 ], q . shape [ 1 ] causal = self . causal if causal is None else causal seqlen_k = kv . shape [ 1 ] assert kv . shape [ 0 ] == batch_size and kv . shape [ 4 ] == q . shape [ 3 ] if kv . shape [ 3 ] != q . shape [ 2 ]: # MQA/GQA kv = repeat ( kv , \"... hkv d -> ... (hkv g) d\" , g = q . shape [ 2 ] // kv . shape [ 3 ]) k , v = kv . unbind ( dim = 2 ) softmax_scale = self . softmax_scale or 1.0 / math . sqrt ( q . shape [ - 1 ]) scores = torch . einsum ( \"bthd,bshd->bhts\" , q , k * softmax_scale ) if key_padding_mask is not None : padding_mask = torch . full ( ( batch_size , seqlen_k ), - 10000.0 , dtype = scores . dtype , device = scores . device , ) padding_mask . masked_fill_ ( key_padding_mask , 0.0 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + rearrange ( padding_mask , \"b s -> b 1 1 s\" ) if causal : # causal mask needs to take into account the difference between seqlen_q and seqlen_k row_idx = rearrange ( torch . arange ( seqlen_q , device = q . device , dtype = torch . long ), \"s -> s 1\" ) col_idx = torch . arange ( seqlen_k , device = kv . device , dtype = torch . long ) sk = ( seqlen_k if key_padding_mask is None else rearrange ( key_padding_mask . sum ( - 1 ), \"b -> b 1 1 1\" ) ) causal_mask = col_idx > row_idx + sk - seqlen_q scores = scores . masked_fill ( causal_mask , - 10000.0 ) attention = torch . softmax ( scores , dim =- 1 , dtype = v . dtype ) attention_drop = self . drop ( attention ) output = torch . einsum ( \"bhts,bshd->bthd\" , attention_drop , v ) return output","title":"forward"},{"location":"model/#scprint.model.flash_attn.mha.FlashCrossAttention","text":"Bases: Module Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The dropout rate to apply to the attention (default: 0.0) Source code in scprint/model/flash_attn/mha.py 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 , alibi_slopes = None , deterministic = False , ): \"\"\" Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The dropout rate to apply to the attention (default: 0.0) \"\"\" super () . __init__ () assert flash_attn_kvpacked_func is not None , \"FlashAttention is not installed\" assert flash_attn_kvpacked_func is not None , \"FlashAttention is not installed\" self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout ) self . register_buffer ( \"alibi_slopes\" , alibi_slopes , persistent = False ) self . deterministic = deterministic","title":"FlashCrossAttention"},{"location":"model/#scprint.model.flash_attn.mha.FlashCrossAttention.forward","text":"Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into q. max_seqlen: int. Maximum sequence length in the batch of q. cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into kv. max_seqlen_k: int. Maximum sequence length in the batch of k and v. Source code in scprint/model/flash_attn/mha.py 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 def forward ( self , q , kv , causal = None , cu_seqlens = None , max_seqlen = None , cu_seqlens_k = None , max_seqlen_k = None , ): \"\"\" Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into q. max_seqlen: int. Maximum sequence length in the batch of q. cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into kv. max_seqlen_k: int. Maximum sequence length in the batch of k and v. \"\"\" assert q . dtype in [ torch . float16 , torch . bfloat16 ] assert q . is_cuda and kv . is_cuda causal = self . causal if causal is None else causal batch_size , seqlen_q = q . shape [ 0 ], q . shape [ 1 ] assert kv . shape [ 0 ] == batch_size and kv . shape [ 4 ] == q . shape [ 3 ] return flash_attn_kvpacked_func ( q , kv , None , # self.drop.p if self.training else 0.0, causal , self . softmax_scale , # alibi_slopes=self.alibi_slopes, # deterministic=self.deterministic, )","title":"forward"},{"location":"model/#scprint.model.flash_attn.mha.FlashSelfAttention","text":"Bases: Module Implement the scaled dot product attention with softmax. Parameters: softmax_scale ( float , default: None ) \u2013 The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout ( float , default: 0.0 ) \u2013 The dropout rate to apply to the attention (default: 0.0) causal ( bool , default: False ) \u2013 Whether to use causal attention. Defaults to False. Source code in scprint/model/flash_attn/mha.py 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 def __init__ ( self , causal : bool = False , softmax_scale : Optional [ float ] = None , attention_dropout : float = 0.0 , alibi_slopes : Optional [ Any ] = None , deterministic : bool = False , use_triton : bool = False , ): \"\"\"Implement the scaled dot product attention with softmax. Args: softmax_scale (float, optional): The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout (float, optional): The dropout rate to apply to the attention (default: 0.0) causal (bool, optional): Whether to use causal attention. Defaults to False. \"\"\" super () . __init__ () if flash_attn_qkvpacked_func is None : print ( \"FlashAttention is not installed, using triton instead\" ) use_triton = True self . use_triton = use_triton self . causal = causal self . softmax_scale = softmax_scale","title":"FlashSelfAttention"},{"location":"model/#scprint.model.flash_attn.mha.FlashSelfAttention.forward","text":"Implements the multihead softmax attention. Args qkv (Tensor): The tensor containing the query, key, and value. If cu_seqlens is None and max_seqlen is None, then qkv has shape (B, S, 3, H, D). If cu_seqlens is not None and max_seqlen is not None, then qkv has shape (total, 3, H, D), where total is the sum of the sequence lengths in the batch. causal (bool): if passed, will override self.causal cu_seqlens (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into qkv. max_seqlen (int). Maximum sequence length in the batch. Returns: out: (total, H, D) if cu_seqlens is not None and max_seqlen is not None, else (B, S, H, D). Source code in scprint/model/flash_attn/mha.py 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 def forward ( self , qkv : torch . Tensor , causal : Optional [ bool ] = None , cu_seqlens : Optional [ torch . Tensor ] = None , max_seqlen : Optional [ int ] = None , cu_seqlens_k : Optional [ torch . Tensor ] = None , max_seqlen_k : Optional [ int ] = None , bias : Optional [ torch . Tensor ] = None , ** kwargs , ): \"\"\"Implements the multihead softmax attention. Args qkv (Tensor): The tensor containing the query, key, and value. If cu_seqlens is None and max_seqlen is None, then qkv has shape (B, S, 3, H, D). If cu_seqlens is not None and max_seqlen is not None, then qkv has shape (total, 3, H, D), where total is the sum of the sequence lengths in the batch. causal (bool): if passed, will override self.causal cu_seqlens (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into qkv. max_seqlen (int). Maximum sequence length in the batch. Returns: out: (total, H, D) if cu_seqlens is not None and max_seqlen is not None, else (B, S, H, D). \"\"\" assert qkv . dtype in [ torch . float16 , torch . bfloat16 ] assert qkv . is_cuda causal = self . causal if causal is None else causal if self . use_triton : raise NotImplementedError ( \"OpenAI's flashattention is not implemented\" ) if qkv . stride ( - 1 ) != 1 : qkv = qkv . contiguous () # return triton_attention( # qkv[:, :, 0], # qkv[:, :, 1], # qkv[:, :, 2], # bias, # causal, # self.softmax_scale, # ) else : return flash_attn_qkvpacked_func ( qkv , bias , # self.drop.p if self.training else 0.0, causal , self . softmax_scale , )","title":"forward"},{"location":"model/#scprint.model.flash_attn.mha.LinearResidual","text":"Bases: Linear Wrap nn.Linear to return the residual as well. For compatibility with FusedDense.","title":"LinearResidual"},{"location":"model/#scprint.model.flash_attn.mha.MHA","text":"Bases: Module MHA Multi-head self-attention and cross-attention Parameters: num_heads_kv ( int , default: None ) \u2013 can be used to toggle MQA / GQA. If None, use num_heads. return_residual ( bool , default: False ) \u2013 whether to return the input x along with the output. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. checkpointing ( bool , default: False ) \u2013 whether to use checkpointing to save memory. Defaults to False. num_heads_kv ( int , default: None ) \u2013 can be used to toggle MQA / GQA. If None, use num_heads. cross_attn ( bool , default: False ) \u2013 whether to use cross-attention. Defaults to False. qkv_proj_bias ( bool , default: True ) \u2013 whether to use bias in the query, key, value projection. Defaults to True. out_proj_bias ( bool , default: True ) \u2013 whether to use bias in the output projection. Defaults to True. dropout ( float , default: 0.0 ) \u2013 dropout rate. Defaults to 0.0. softmax_scale ( float , default: None ) \u2013 The temperature to use for the softmax attention. causal ( bool , default: False ) \u2013 whether to use causal attention. Defaults to False. layer_idx ( int , default: None ) \u2013 layer index for inference cache. Defaults to None. dwconv ( bool , default: False ) \u2013 whether to use depthwise convolution. Defaults to False. fused_bias_fc ( bool , default: False ) \u2013 whether to use fused_bias_fc. Defaults to False. use_flash_attn ( bool , default: False ) \u2013 whether to use FlashAttention. Defaults to False. device ( device , default: None ) \u2013 device. Defaults to None. dtype ( dtype , default: None ) \u2013 dtype. Defaults to None. Source code in scprint/model/flash_attn/mha.py 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 def __init__ ( self , embed_dim : int , num_heads : int , num_heads_kv : Optional [ int ] = None , cross_attn : bool = False , qkv_proj_bias : bool = True , out_proj_bias : bool = True , dropout : float = 0.0 , softmax_scale : Optional [ float ] = None , causal : bool = False , layer_idx : Optional [ int ] = None , dwconv : bool = False , rotary_emb_dim : int = 0 , rotary_emb_base : float = 10000.0 , rotary_emb_scale_base : Optional [ float ] = None , rotary_emb_interleaved : bool = False , use_alibi : bool = False , fused_bias_fc : bool = False , use_flash_attn : bool = False , return_residual : bool = False , checkpointing : bool = False , device : Optional [ torch . device ] = None , dtype : Optional [ torch . dtype ] = None , ) -> None : \"\"\" MHA Multi-head self-attention and cross-attention Args: embed_dim num_heads_kv (int): can be used to toggle MQA / GQA. If None, use num_heads. return_residual (bool, optional): whether to return the input x along with the output. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. checkpointing (bool, optional): whether to use checkpointing to save memory. Defaults to False. num_heads_kv (int, optional): can be used to toggle MQA / GQA. If None, use num_heads. cross_attn (bool, optional): whether to use cross-attention. Defaults to False. qkv_proj_bias (bool, optional): whether to use bias in the query, key, value projection. Defaults to True. out_proj_bias (bool, optional): whether to use bias in the output projection. Defaults to True. dropout (float, optional): dropout rate. Defaults to 0.0. softmax_scale (float, optional): The temperature to use for the softmax attention. causal (bool, optional): whether to use causal attention. Defaults to False. layer_idx (int, optional): layer index for inference cache. Defaults to None. dwconv (bool, optional): whether to use depthwise convolution. Defaults to False. fused_bias_fc (bool, optional): whether to use fused_bias_fc. Defaults to False. use_flash_attn (bool, optional): whether to use FlashAttention. Defaults to False. device (torch.device, optional): device. Defaults to None. dtype (torch.dtype, optional): dtype. Defaults to None. \"\"\" factory_kwargs = { \"device\" : device , \"dtype\" : dtype } super () . __init__ () self . embed_dim = embed_dim self . cross_attn = cross_attn self . causal = causal self . layer_idx = layer_idx self . dwconv = dwconv self . rotary_emb_dim = rotary_emb_dim self . use_flash_attn = use_flash_attn if self . use_flash_attn and ( flash_attn_kvpacked_func is None ): print ( \"you requested flash transformer but it requires the flash package which is not installed\" ) print ( \"falling back to regular transformer...\" ) self . use_flash_attn = False # NOT flash transformer using the special tritton kernel # or parallelMHA (add the process group thing and faster) self . return_residual = return_residual self . checkpointing = checkpointing alibi_slopes = None self . num_heads = num_heads self . num_heads_kv = num_heads_kv if num_heads_kv is not None else num_heads assert ( self . num_heads % self . num_heads_kv == 0 ), \"num_heads must be divisible by num_heads_kv\" assert ( self . embed_dim % num_heads == 0 ), \"embed_dim must be divisible by num_heads\" self . head_dim = self . embed_dim // num_heads qkv_dim = self . head_dim * ( self . num_heads + 2 * self . num_heads_kv ) kv_dim = 2 * self . head_dim * self . num_heads_kv if self . rotary_emb_dim > 0 : assert ( not cross_attn ), \"MHA with rotary embedding does not support cross-attention yet\" assert RotaryEmbedding is not None , \"rotary_emb is not installed\" self . rotary_emb = RotaryEmbedding ( self . rotary_emb_dim , base = rotary_emb_base , scale_base = rotary_emb_scale_base , interleaved = rotary_emb_interleaved , device = device , ) if fused_bias_fc and FusedDense is None : raise ImportError ( \"fused_dense is not installed\" ) linear_cls = nn . Linear if not fused_bias_fc else FusedDense linear_resid_cls = ( LinearResidual if not fused_bias_fc else partial ( FusedDense , return_residual = True ) ) wqkv_cls = linear_cls if not self . return_residual else linear_resid_cls inner_attn_cls = ( partial ( FlashSelfAttention , alibi_slopes = alibi_slopes ) if self . use_flash_attn else SelfAttention ) inner_cross_attn_cls = ( partial ( FlashCrossAttention , alibi_slopes = alibi_slopes ) if self . use_flash_attn else CrossAttention ) if not self . cross_attn : self . Wqkv = wqkv_cls ( embed_dim , qkv_dim , bias = qkv_proj_bias , ** factory_kwargs ) else : self . Wq = linear_cls ( embed_dim , embed_dim , bias = qkv_proj_bias , ** factory_kwargs ) self . Wkv = wqkv_cls ( embed_dim , kv_dim , bias = qkv_proj_bias , ** factory_kwargs ) if self . dwconv : if self . num_heads_kv == self . num_heads : self . dwconv_qkv = nn . Conv1d ( qkv_dim , qkv_dim , kernel_size = 3 , padding = 2 , groups = qkv_dim ) else : self . dwconv_q = nn . Conv1d ( embed_dim , embed_dim , kernel_size = 3 , padding = 2 , groups = embed_dim ) self . dwconv_kv = nn . Conv1d ( kv_dim , kv_dim , kernel_size = 3 , padding = 2 , groups = kv_dim ) self . inner_attn = inner_attn_cls ( causal = causal , softmax_scale = softmax_scale , attention_dropout = dropout , ) self . inner_cross_attn = inner_cross_attn_cls ( causal = causal , softmax_scale = softmax_scale , attention_dropout = dropout ) self . out_proj = linear_cls ( embed_dim , embed_dim , bias = out_proj_bias , ** factory_kwargs )","title":"MHA"},{"location":"model/#scprint.model.flash_attn.mha.MHA.forward","text":"Parameters: x ( Tensor ) \u2013 (batch, seqlen, hidden_dim) (where hidden_dim = num heads * head dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the is the sum of the sequence lengths in the batch. x_kv ( Optional [ Tensor ] , default: None ) \u2013 (batch, seqlen, hidden_dim), only applicable for cross-attention. If None, use x. cu_seqlens ( Optional [ Tensor ] , default: None ) \u2013 (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into x. Only applicable when using FlashAttention. max_seqlen ( Optional [ int ] , default: None ) \u2013 int. Maximum sequence length in the batch. key_padding_mask ( Optional [ Tensor ] , default: None ) \u2013 boolean mask, True means to keep, False means to mask out. (batch, seqlen). Only applicable when not using FlashAttention. mixer_subset ( Optional [ Tensor ] , default: None ) \u2013 for cross-attention only. If not None, will take a subset of x before applying the query projection. Useful for e.g., ViT where we only care about the CLS token in the last layer. inference_params ( Optional [ dict ] , default: None ) \u2013 for generation. Adapted from Megatron-LM (and Apex) https \u2013 //github.com/NVIDIA/apex/blob/3ff1a10f72ec07067c4e44759442329804ac5162/apex/transformer/testing/standalone_transformer_lm.py#L470 return_qkv ( bool , default: False ) \u2013 whether to return the qkv tensor. Defaults to False. Returns: out \u2013 (batch, seqlen, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the sum of the sequence lengths in the batch. qkv \u2013 (batch, seqlen, 3, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, 3, hidden_dim) where total is the sum of the sequence lengths in the batch. Source code in scprint/model/flash_attn/mha.py 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 def forward ( self , x : torch . Tensor , x_kv : Optional [ torch . Tensor ] = None , key_padding_mask : Optional [ torch . Tensor ] = None , cu_seqlens : Optional [ torch . Tensor ] = None , max_seqlen : Optional [ int ] = None , mixer_subset : Optional [ torch . Tensor ] = None , inference_params : Optional [ dict ] = None , return_qkv : bool = False , ** kwargs , ): \"\"\" Args: x: (batch, seqlen, hidden_dim) (where hidden_dim = num heads * head dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the is the sum of the sequence lengths in the batch. x_kv: (batch, seqlen, hidden_dim), only applicable for cross-attention. If None, use x. cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into x. Only applicable when using FlashAttention. max_seqlen: int. Maximum sequence length in the batch. key_padding_mask: boolean mask, True means to keep, False means to mask out. (batch, seqlen). Only applicable when not using FlashAttention. mixer_subset: for cross-attention only. If not None, will take a subset of x before applying the query projection. Useful for e.g., ViT where we only care about the CLS token in the last layer. inference_params: for generation. Adapted from Megatron-LM (and Apex) https://github.com/NVIDIA/apex/blob/3ff1a10f72ec07067c4e44759442329804ac5162/apex/transformer/testing/standalone_transformer_lm.py#L470 return_qkv: whether to return the qkv tensor. Defaults to False. Returns: out: (batch, seqlen, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the sum of the sequence lengths in the batch. qkv: (batch, seqlen, 3, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, 3, hidden_dim) where total is the sum of the sequence lengths in the batch. \"\"\" if cu_seqlens is not None : assert max_seqlen is not None assert key_padding_mask is None assert self . use_flash_attn assert not self . dwconv assert self . rotary_emb_dim == 0 if key_padding_mask is not None : assert cu_seqlens is None assert max_seqlen is None assert not self . use_flash_attn if inference_params is not None : assert key_padding_mask is None assert cu_seqlens is None and max_seqlen is None assert not self . dwconv kwargs = ( {} # \"cu_seqlens\": cu_seqlens, \"max_seqlen\": max_seqlen, **kwargs} if self . use_flash_attn else { \"key_padding_mask\" : key_padding_mask , ** kwargs } ) seqlen_offset = ( 0 if inference_params is None else ( inference_params . lengths_per_sample if inference_params . lengths_per_sample is not None else inference_params . seqlen_offset ) ) rotary_max_seqlen = ( inference_params . max_seqlen if inference_params is not None else None ) batch , seqlen = x . shape [: 2 ] if not self . cross_attn and self . num_heads_kv == self . num_heads : assert x_kv is None and mixer_subset is None if not self . return_residual : qkv = self . Wqkv ( x ) # .to(torch.float16, device=\"cuda\") else : qkv , x = self . Wqkv ( x ) if self . dwconv : qkv = rearrange ( self . dwconv_qkv ( rearrange ( qkv , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () qkv = rearrange ( qkv , \"... (three h d) -> ... three h d\" , three = 3 , d = self . head_dim ) if ( inference_params is None or inference_params . seqlen_offset == 0 or ( self . rotary_emb_dim == 0 or self . rotary_emb_dim % 16 != 0 ) or not self . use_flash_attn ): if self . rotary_emb_dim > 0 : qkv = self . rotary_emb ( qkv , seqlen_offset = seqlen_offset , max_seqlen = rotary_max_seqlen ) if inference_params is None : if not self . checkpointing : context = self . inner_attn ( qkv , ** kwargs ) else : context = torch . utils . checkpoint . checkpoint ( self . inner_attn , qkv , ** kwargs ) else : context = self . _update_kvcache_attention ( qkv [:, :, 0 ], qkv [:, :, 1 :], inference_params ) else : context = self . _apply_rotary_update_kvcache_attention ( qkv [:, :, 0 ], qkv [:, :, 1 :], inference_params ) else : if self . cross_attn : if not self . return_residual : q = self . Wq ( x if mixer_subset is None else x [:, mixer_subset ]) kv = self . Wkv ( x_kv if x_kv is not None else x ) else : if x_kv is not None : kv , x_kv = self . Wkv ( x_kv ) else : kv , x = self . Wkv ( x ) q = self . Wq ( x if mixer_subset is None else x [:, mixer_subset ]) else : assert self . num_heads_kv != self . num_heads if not self . return_residual : qkv = self . Wqkv ( x ) else : qkv , x = self . Wqkv ( x ) q = qkv [ ... , : self . num_heads * self . head_dim ] kv = qkv [ ... , self . num_heads * self . head_dim :] q = rearrange ( q , \"... (h d) -> ... h d\" , d = self . head_dim ) kv = rearrange ( kv , \"... (two hkv d) -> ... two hkv d\" , two = 2 , d = self . head_dim ) if self . dwconv : q = rearrange ( self . dwconv_q ( rearrange ( q , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () kv = rearrange ( self . dwconv_kv ( rearrange ( kv , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () if ( inference_params is None or inference_params . seqlen_offset == 0 or ( self . rotary_emb_dim == 0 or self . rotary_emb_dim % 16 != 0 ) or not self . use_flash_attn ): if self . rotary_emb_dim > 0 : q , kv = self . rotary_emb ( q , kv , seqlen_offset = seqlen_offset , max_seqlen = rotary_max_seqlen ) if inference_params is None : if not self . checkpointing : context = self . inner_cross_attn ( q , kv , ** kwargs ) else : context = torch . utils . checkpoint . checkpoint ( self . inner_cross_attn , q , kv , ** kwargs ) else : context = self . _update_kvcache_attention ( q , kv , inference_params ) else : context = self . _apply_rotary_update_kvcache_attention ( q , kv , inference_params ) out = self . out_proj ( rearrange ( context , \"... h d -> ... (h d)\" )) if return_qkv : return out if not self . return_residual else ( out , x ), qkv else : return out if not self . return_residual else ( out , x )","title":"forward"},{"location":"model/#scprint.model.flash_attn.mha.SelfAttention","text":"Bases: Module Implement the scaled dot product attention with softmax. Parameters: softmax_scale \u2013 The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout \u2013 The dropout rate to apply to the attention (default: 0.0) Source code in scprint/model/flash_attn/mha.py 195 196 197 198 199 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 ): super () . __init__ () self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout )","title":"SelfAttention"},{"location":"model/#scprint.model.flash_attn.mha.SelfAttention.forward","text":"Implements the multihead softmax attention. Parameters: qkv \u2013 The tensor containing the query, key, and value. (B, S, 3, H, D) causal \u2013 if passed, will override self.causal key_padding_mask \u2013 boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, S) Source code in scprint/model/flash_attn/mha.py 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 def forward ( self , qkv , causal = None , key_padding_mask = None , bias = None ): \"\"\" Implements the multihead softmax attention. Args: qkv: The tensor containing the query, key, and value. (B, S, 3, H, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, S) \"\"\" batch_size , seqlen = qkv . shape [ 0 ], qkv . shape [ 1 ] causal = self . causal if causal is None else causal q , k , v = qkv . unbind ( dim = 2 ) softmax_scale = self . softmax_scale or 1.0 / math . sqrt ( q . shape [ - 1 ]) scores = torch . einsum ( \"bthd,bshd->bhts\" , q , k * softmax_scale ) if key_padding_mask is not None : padding_mask = torch . full ( ( batch_size , seqlen ), - 10000.0 , dtype = scores . dtype , device = scores . device ) padding_mask . masked_fill_ ( key_padding_mask , 0.0 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + rearrange ( padding_mask , \"b s -> b 1 1 s\" ) if causal : # \"triu_tril_cuda_template\" not implemented for 'BFloat16' # So we have to construct the mask in float causal_mask = torch . triu ( torch . full (( seqlen , seqlen ), - 10000.0 , device = scores . device ), 1 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + causal_mask . to ( dtype = scores . dtype ) attention = torch . softmax ( scores , dim =- 1 , dtype = v . dtype ) attention_drop = self . drop ( attention ) output = torch . einsum ( \"bhts,bshd->bthd\" , attention_drop , v ) return output","title":"forward"},{"location":"model/#scprint.model.flash_attn.mlp","text":"","title":"mlp"},{"location":"model/#scprint.model.flash_attn.mlp.Mlp","text":"Bases: Module Multi-layer perceptron (MLP) module. Parameters: in_features ( int ) \u2013 Size of each input sample. hidden_features ( Optional [ int ] , default: None ) \u2013 Size of the hidden layer. Defaults to 4 * in_features. out_features ( Optional [ int ] , default: None ) \u2013 Size of each output sample. Defaults to in_features. activation ( Callable [[ Tensor ], Tensor ] , default: gelu ) \u2013 Activation function. Defaults to F.gelu. bias1 ( bool , default: True ) \u2013 If set to False, the first linear layer will not learn an additive bias. Defaults to True. bias2 ( bool , default: True ) \u2013 If set to False, the second linear layer will not learn an additive bias. Defaults to True. return_residual ( bool , default: False ) \u2013 If set to True, the forward method will return a tuple (output, input). Defaults to False. device ( Optional [ device ] , default: None ) \u2013 The desired device of the parameters. Defaults to None. dtype ( Optional [ dtype ] , default: None ) \u2013 The desired data type of the parameters. Defaults to None. Source code in scprint/model/flash_attn/mlp.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 def __init__ ( self , in_features : int , hidden_features : Optional [ int ] = None , out_features : Optional [ int ] = None , activation : Callable [[ torch . Tensor ], torch . Tensor ] = F . gelu , bias1 : bool = True , bias2 : bool = True , return_residual : bool = False , device : Optional [ torch . device ] = None , dtype : Optional [ torch . dtype ] = None , ) -> None : \"\"\" Multi-layer perceptron (MLP) module. Args: in_features (int): Size of each input sample. hidden_features (Optional[int], optional): Size of the hidden layer. Defaults to 4 * in_features. out_features (Optional[int], optional): Size of each output sample. Defaults to in_features. activation (Callable[[torch.Tensor], torch.Tensor], optional): Activation function. Defaults to F.gelu. bias1 (bool, optional): If set to False, the first linear layer will not learn an additive bias. Defaults to True. bias2 (bool, optional): If set to False, the second linear layer will not learn an additive bias. Defaults to True. return_residual (bool, optional): If set to True, the forward method will return a tuple (output, input). Defaults to False. device (Optional[torch.device], optional): The desired device of the parameters. Defaults to None. dtype (Optional[torch.dtype], optional): The desired data type of the parameters. Defaults to None. \"\"\" factory_kwargs = { \"device\" : device , \"dtype\" : dtype } super () . __init__ () out_features = out_features if out_features is not None else in_features hidden_features = ( hidden_features if hidden_features is not None else in_features * 4 ) self . return_residual = return_residual self . fc1 = nn . Linear ( in_features , hidden_features , bias = bias1 , ** factory_kwargs ) self . activation = activation self . fc2 = nn . Linear ( hidden_features , out_features , bias = bias2 , ** factory_kwargs )","title":"Mlp"},{"location":"model/#scprint.model.flash_attn.mlp.Mlp.forward","text":"Forward pass of the MLP. Parameters: x ( Tensor ) \u2013 Input tensor. Returns: Union [ Tensor , Tuple [ Tensor , Tensor ]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: Output tensor, or a tuple (output, input) if return_residual is True. Source code in scprint/model/flash_attn/mlp.py 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 def forward ( self , x : torch . Tensor ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , torch . Tensor ]]: \"\"\" Forward pass of the MLP. Args: x (torch.Tensor): Input tensor. Returns: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: Output tensor, or a tuple (output, input) if return_residual is True. \"\"\" y = self . fc1 ( x ) y = self . activation ( y ) y = self . fc2 ( y ) return y if not self . return_residual else ( y , x )","title":"forward"},{"location":"model/#scprint.model.flash_attn.block","text":"","title":"block"},{"location":"model/#scprint.model.flash_attn.block.Block","text":"Bases: Module For prenorm=True, this Block has a slightly different structure compared to a regular prenorm Transformer block. The standard block is: LN -> MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add. [Ref: https://arxiv.org/abs/2002.04745] Here we have: Dropout -> Add -> LN -> MHA -> Dropout -> Add -> LN -> MLP, returning both the hidden_states (output of the MLP) and the residual. This is for performance reasons, as we can fuse the dropout, add and LayerNorm. The residual needs to be provided (except for the very first block). For prenorm=False, this Block has the same structure as a regular postnorm Transformer block: MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add -> LN. Parameters: dim ( int ) \u2013 the number of features in the input. mixer_cls ( Optional [ Callable ] , default: None ) \u2013 the class to use for the mixer layer. Defaults to None. mlp_cls ( Optional [ Callable ] , default: None ) \u2013 the class to use for the mlp layer. Defaults to None. norm_cls ( Callable , default: partial ( LayerNorm , eps=1e-06) ) \u2013 the class to use for the layer norm. Defaults to partial(nn.LayerNorm, eps=1e-6). dropout_cls ( Type [ Dropout ] , default: Dropout ) \u2013 the class to use for the dropout. Defaults to nn.Dropout. prenorm ( bool , default: True ) \u2013 whether to use pre-norm or post-norm. Defaults to True. resid_dropout1 ( float , default: 0.0 ) \u2013 the dropout probability for the first dropout layer. Defaults to 0.0. resid_dropout2 ( float , default: 0.0 ) \u2013 the dropout probability for the second dropout layer. Defaults to 0.0. drop_path1 ( float , default: 0.0 ) \u2013 the drop path probability for the first drop path layer. Defaults to 0.0. drop_path2 ( float , default: 0.0 ) \u2013 the drop path probability for the second drop path layer. Defaults to 0.0. fused_dropout_add_ln ( bool , default: False ) \u2013 whether to fuse the dropout, add and layer norm. Defaults to False. return_residual ( bool , default: False ) \u2013 whether each of the sub-layers (mixer and mlp) will return the residual. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. residual_in_fp32 ( bool , default: False ) \u2013 whether to keep the residual in fp32. This is for performance reason: for post-norm architecture, keeping the residual in fp32 allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. sequence_parallel ( bool , default: False ) \u2013 whether to use sequence parallelism. Defaults to False. mark_shared_params ( bool , default: False ) \u2013 whether to mark the norm parameters as \"shared_params\". This is useful when we want to sync the norm parameters across workers. Defaults to False. Source code in scprint/model/flash_attn/block.py 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 def __init__ ( self , dim : int , mixer_cls : Optional [ Callable ] = None , mlp_cls : Optional [ Callable ] = None , norm_cls : Callable = partial ( nn . LayerNorm , eps = 1e-6 ), dropout_cls : Type [ nn . Dropout ] = nn . Dropout , prenorm : bool = True , resid_dropout1 : float = 0.0 , resid_dropout2 : float = 0.0 , drop_path1 : float = 0.0 , drop_path2 : float = 0.0 , fused_dropout_add_ln : bool = False , return_residual : bool = False , residual_in_fp32 : bool = False , sequence_parallel : bool = False , mark_shared_params : bool = False , ): \"\"\" For prenorm=True, this Block has a slightly different structure compared to a regular prenorm Transformer block. The standard block is: LN -> MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add. [Ref: https://arxiv.org/abs/2002.04745] Here we have: Dropout -> Add -> LN -> MHA -> Dropout -> Add -> LN -> MLP, returning both the hidden_states (output of the MLP) and the residual. This is for performance reasons, as we can fuse the dropout, add and LayerNorm. The residual needs to be provided (except for the very first block). For prenorm=False, this Block has the same structure as a regular postnorm Transformer block: MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add -> LN. Args: dim (int): the number of features in the input. mixer_cls (Optional[Callable], optional): the class to use for the mixer layer. Defaults to None. mlp_cls (Optional[Callable], optional): the class to use for the mlp layer. Defaults to None. norm_cls (Callable, optional): the class to use for the layer norm. Defaults to partial(nn.LayerNorm, eps=1e-6). dropout_cls (Type[nn.Dropout], optional): the class to use for the dropout. Defaults to nn.Dropout. prenorm (bool, optional): whether to use pre-norm or post-norm. Defaults to True. resid_dropout1 (float, optional): the dropout probability for the first dropout layer. Defaults to 0.0. resid_dropout2 (float, optional): the dropout probability for the second dropout layer. Defaults to 0.0. drop_path1 (float, optional): the drop path probability for the first drop path layer. Defaults to 0.0. drop_path2 (float, optional): the drop path probability for the second drop path layer. Defaults to 0.0. fused_dropout_add_ln (bool, optional): whether to fuse the dropout, add and layer norm. Defaults to False. return_residual (bool, optional): whether each of the sub-layers (mixer and mlp) will return the residual. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. residual_in_fp32 (bool, optional): whether to keep the residual in fp32. This is for performance reason: for post-norm architecture, keeping the residual in fp32 allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. sequence_parallel (bool, optional): whether to use sequence parallelism. Defaults to False. mark_shared_params (bool, optional): whether to mark the norm parameters as \"shared_params\". This is useful when we want to sync the norm parameters across workers. Defaults to False. \"\"\" super () . __init__ () self . prenorm = prenorm self . fused_dropout_add_ln = fused_dropout_add_ln self . return_residual = return_residual self . residual_in_fp32 = residual_in_fp32 if self . residual_in_fp32 : assert self . prenorm , \"residual_in_fp32 is only compatible with prenorm=True\" if mixer_cls is None : mixer_cls = partial ( MHA , num_heads = dim // 64 ) if mlp_cls is None : mlp_cls = partial ( Mlp , hidden_features = 4 * dim ) self . mixer = mixer_cls ( dim ) self . dropout1 = dropout_cls ( resid_dropout1 ) self . drop_path1 = StochasticDepth ( drop_path1 , mode = \"row\" ) self . norm1 = norm_cls ( dim ) self . mlp = mlp_cls ( dim ) if not isinstance ( self . mlp , nn . Identity ): self . dropout2 = dropout_cls ( resid_dropout2 ) self . drop_path2 = StochasticDepth ( drop_path2 , mode = \"row\" ) self . norm2 = norm_cls ( dim ) if self . fused_dropout_add_ln : assert layer_norm_fn is not None , \"Triton is not installed\" assert isinstance ( self . norm1 , ( nn . LayerNorm , RMSNorm )) and isinstance ( self . dropout1 , nn . Dropout ) # TD [2023-01-07]: TODO: During training, if sequence_parallel is False and dropout != 0.0, # then the input to each worker in the tensor parallel group will be different. # This would produce wrong outputs? Somehow we'd need to sync the RNG state across workers. # For now this is not an issue because we always use sequence_parallel=True during training # and only use sequence_parallel=False during inference. # Mark the norm parameters as \"sequence_parallel\" so that we run all-reduce on their grads. if sequence_parallel : for p in self . norm1 . parameters (): p . _sequence_parallel = True if hasattr ( self , \"norm2\" ): for p in self . norm2 . parameters (): p . _sequence_parallel = True # Mark the norm parameters as \"shared_params\" so that we sync their values at init. if mark_shared_params : for p in self . norm1 . parameters (): p . _shared_params = True if hasattr ( self , \"norm2\" ): for p in self . norm2 . parameters (): p . _shared_params = True","title":"Block"},{"location":"model/#scprint.model.flash_attn.block.Block.forward","text":"Pass the input through the encoder layer. Parameters: hidden_states ( Tensor ) \u2013 The sequence to be passed to the encoder layer. This is a required argument. residual ( Optional [ Tensor ] , default: None ) \u2013 This argument is used differently based on the normalization method. If postnorm is used, residual should be None. If prenorm is used, hidden_states is updated as Attn/MLP(LN(residual)). mixer_subset ( Optional [ Tensor ] , default: None ) \u2013 This argument is used only for cross-attention. If not None, a subset of the input sequence 'x' is taken before applying the query projection. This is particularly useful for models like ViT where only the CLS token in the last layer is of interest. mixer_kwargs ( Optional [ Dict [ str , Any ]] , default: None ) \u2013 This argument is used only for cross-attention. It is a dictionary of additional arguments to be passed to the mixer. return_qkv ( bool , default: False ) \u2013 If True, the function will return the query, key, and value tensors. Returns: \u2013 Tensor or Tuple[Tensor, Tensor]: The output tensor of the encoder layer. \u2013 If return_qkv is True, the function will return a tuple of the output tensor and the query, key, and value tensors. Source code in scprint/model/flash_attn/block.py 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 def forward ( self , hidden_states : Tensor , residual : Optional [ Tensor ] = None , bias : Optional [ Tensor ] = None , src_mask : Optional [ Tensor ] = None , is_causal : Optional [ bool ] = None , src_key_padding_mask : Optional [ Tensor ] = None , mixer_subset : Optional [ Tensor ] = None , mixer_kwargs : Optional [ Dict [ str , Any ]] = None , return_qkv : bool = False , ): r \"\"\"Pass the input through the encoder layer. Args: hidden_states (Tensor): The sequence to be passed to the encoder layer. This is a required argument. residual (Optional[Tensor]): This argument is used differently based on the normalization method. If postnorm is used, residual should be None. If prenorm is used, hidden_states is updated as Attn/MLP(LN(residual)). mixer_subset: This argument is used only for cross-attention. If not None, a subset of the input sequence 'x' is taken before applying the query projection. This is particularly useful for models like ViT where only the CLS token in the last layer is of interest. mixer_kwargs: This argument is used only for cross-attention. It is a dictionary of additional arguments to be passed to the mixer. return_qkv: If True, the function will return the query, key, and value tensors. Returns: Tensor or Tuple[Tensor, Tensor]: The output tensor of the encoder layer. If return_qkv is True, the function will return a tuple of the output tensor and the query, key, and value tensors. \"\"\" if self . prenorm : if not self . fused_dropout_add_ln : dropped = self . drop_path1 ( self . dropout1 ( hidden_states )) residual = ( dropped + residual ) if residual is not None else dropped hidden_states = self . norm1 ( residual . to ( dtype = self . norm1 . weight . dtype )) if self . residual_in_fp32 : residual = residual . to ( torch . float32 ) else : if self . drop_path1 . p == 0 or not self . training : rowscale1 = None else : rowscale1 = self . drop_path1 ( torch . ones ( hidden_states . shape [: - 1 ], device = hidden_states . device , dtype = hidden_states . dtype , ) ) hidden_states , residual = layer_norm_fn ( hidden_states , self . norm1 . weight , self . norm1 . bias , residual = residual , eps = self . norm1 . eps , dropout_p = self . dropout1 . p if self . training else 0.0 , rowscale = rowscale1 , prenorm = True , residual_in_fp32 = self . residual_in_fp32 , is_rms_norm = isinstance ( self . norm1 , RMSNorm ), ) if mixer_kwargs is None : mixer_kwargs = {} if mixer_subset is not None : mixer_kwargs [ \"mixer_subset\" ] = mixer_subset hidden_states = self . mixer ( hidden_states , return_qkv = return_qkv , bias = bias , ** mixer_kwargs ) if return_qkv : qkv = hidden_states [ 1 ] hidden_states = hidden_states [ 0 ] if mixer_subset is not None : residual = residual [:, mixer_subset ] if not isinstance ( self . mlp , nn . Identity ): if not self . fused_dropout_add_ln : dropped = self . drop_path2 ( self . dropout2 ( hidden_states )) residual = ( dropped + residual ) if residual is not None else dropped hidden_states = self . norm2 ( residual . to ( dtype = self . norm2 . weight . dtype ) ) if self . residual_in_fp32 : residual = residual . to ( torch . float32 ) else : if self . drop_path2 . p == 0 or not self . training : rowscale2 = None else : rowscale2 = self . drop_path2 ( torch . ones ( hidden_states . shape [: - 1 ], device = hidden_states . device , dtype = hidden_states . dtype , ) ) hidden_states , residual = layer_norm_fn ( hidden_states , self . norm2 . weight , self . norm2 . bias , residual = residual , eps = self . norm2 . eps , dropout_p = self . dropout2 . p if self . training else 0.0 , rowscale = rowscale2 , prenorm = True , residual_in_fp32 = self . residual_in_fp32 , is_rms_norm = isinstance ( self . norm2 , RMSNorm ), ) hidden_states = self . mlp ( hidden_states ) return ( ( hidden_states , residual ) if not return_qkv else ( hidden_states , residual , qkv , ) ) # if not prenorm (disregard for scPRINT) else : assert residual is None mixer_out = self . mixer ( hidden_states , return_qkv = return_qkv , bias = bias , ** ( mixer_kwargs if mixer_kwargs is not None else {}) ) if return_qkv : qkv = mixer_out [ - 1 ] mixer_out = mixer_out [: - 1 ] if self . return_residual : # mixer out is actually a pair here mixer_out , hidden_states = mixer_out if not self . fused_dropout_add_ln : hidden_states = self . norm1 ( ( self . drop_path1 ( self . dropout1 ( mixer_out )) + hidden_states ) . to ( dtype = self . norm1 . weight . dtype ) ) else : if self . drop_path1 . p == 0 or not self . training : rowscale1 = None else : rowscale1 = self . drop_path1 ( torch . ones ( mixer_out . shape [: - 1 ], device = mixer_out . device , dtype = mixer_out . dtype , ) ) hidden_states = layer_norm_fn ( mixer_out , self . norm1 . weight , self . norm1 . bias , residual = hidden_states , eps = self . norm1 . eps , dropout_p = self . dropout1 . p if self . training else 0.0 , rowscale = rowscale1 , prenorm = False , is_rms_norm = isinstance ( self . norm1 , RMSNorm ), ) if not isinstance ( self . mlp , nn . Identity ): mlp_out = self . mlp ( hidden_states ) if self . return_residual : # mlp out is actually a pair here mlp_out , hidden_states = mlp_out if not self . fused_dropout_add_ln : hidden_states = self . norm2 ( ( self . drop_path2 ( self . dropout2 ( mlp_out )) + hidden_states ) . to ( dtype = self . norm2 . weight . dtype ) ) else : if self . drop_path2 . p == 0 or not self . training : rowscale2 = None else : rowscale2 = self . drop_path2 ( torch . ones ( mlp_out . shape [: - 1 ], device = mlp_out . device , dtype = mlp_out . dtype , ) ) hidden_states = layer_norm_fn ( mlp_out , self . norm2 . weight , self . norm2 . bias , residual = hidden_states , eps = self . norm2 . eps , dropout_p = self . dropout2 . p if self . training else 0.0 , rowscale = rowscale2 , prenorm = False , is_rms_norm = isinstance ( self . norm2 , RMSNorm ), ) return hidden_states if not return_qkv else ( hidden_states , qkv )","title":"forward"},{"location":"model/#scprint.model.flash_attn.flashattention","text":"Experimental implementation of FlashAttention in Triton. Tested with triton==2.0.0.dev20221202. Triton 2.0 has a new backend (MLIR) but seems like it doesn't yet work for head dimensions other than 64: https://github.com/openai/triton/blob/d376020f90002757eea3ea9475d4f7cfc2ec5ead/python/triton/ops/flash_attention.py#L207 We'll update this implementation with the new Triton backend once this is fixed. We use the FlashAttention implementation from Phil Tillet a starting point. https://github.com/openai/triton/blob/master/python/tutorials/06-fused-attention.py Changes: - Implement both causal and non-causal attention. - Implement both self-attention and cross-attention. - Support arbitrary seqlens (not just multiples of 128), for both forward and backward. - Support all head dimensions up to 128 (not just 16, 32, 64, 128), for both forward and backward. - Support attention bias. - Speed up the forward pass a bit, and only store the LSE instead of m and l. - Make the backward for d=128 much faster by reducing register spilling. - Optionally parallelize the backward pass across seqlen_k, to deal with the case of small batch size * nheads. Caution: - This is an experimental implementation. The forward pass should be quite robust but I'm not 100% sure that the backward pass doesn't have race conditions (due to the Triton compiler). - This implementation has only been tested on A100. - If you plan to use headdim other than 64 and 128, you should test for race conditions (due to the Triton compiler), as done in tests/test_flash_attn.py \"test_flash_attn_triton_race_condition\". I've tested and fixed many race conditions for different head dimensions (40, 48, 64, 128, 80, 88, 96), but I'm still not 100% confident that there are none left for other head dimensions. Differences between this Triton version and the CUDA version: - Triton version doesn't support dropout. - Triton forward is generally faster than CUDA forward, while Triton backward is generally slower than CUDA backward. Overall Triton forward + backward is slightly slower than CUDA forward + backward. - Triton version doesn't support different sequence lengths in a batch (i.e., RaggedTensor/NestedTensor). - Triton version supports attention bias, while CUDA version doesn't.","title":"flashattention"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnFunc","text":"Bases: Function","title":"FlashAttnFunc"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnFunc.forward","text":"Perform the forward pass of FlashAttention. Parameters: q ( Tensor ) \u2013 Query tensor of shape (batch_size, seqlen_q, nheads, headdim). k ( Tensor ) \u2013 Key tensor of shape (batch_size, seqlen_k, nheads, headdim). v ( Tensor ) \u2013 Value tensor of shape (batch_size, seqlen_k, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor, shape broadcastible to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Scaling factor for the softmax operation. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 @staticmethod def forward ( ctx : torch . autograd . Function , q : torch . Tensor , k : torch . Tensor , v : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Perform the forward pass of FlashAttention. Args: q (torch.Tensor): Query tensor of shape (batch_size, seqlen_q, nheads, headdim). k (torch.Tensor): Key tensor of shape (batch_size, seqlen_k, nheads, headdim). v (torch.Tensor): Value tensor of shape (batch_size, seqlen_k, nheads, headdim). bias (Optional[torch.Tensor]): Bias tensor, shape broadcastible to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Scaling factor for the softmax operation. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous q , k , v = [ x if x . stride ( - 1 ) == 1 else x . contiguous () for x in [ q , k , v ]] o , lse , ctx . softmax_scale = _flash_attn_forward ( q , k , v , bias = bias , causal = causal , softmax_scale = softmax_scale ) ctx . save_for_backward ( q , k , v , o , lse , bias ) ctx . causal = causal return o","title":"forward"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnKVPackedFunc","text":"Bases: Function","title":"FlashAttnKVPackedFunc"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnKVPackedFunc.forward","text":"Perform the forward pass of FlashAttention with packed key and value tensors. Parameters: q ( Tensor ) \u2013 Query tensor of shape (batch, seqlen_q, nheads, headdim). kv ( Tensor ) \u2013 Key and value tensor of shape (batch, seqlen_k, 2, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor, shape broadcastable to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Scaling factor for the softmax operation. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 @staticmethod def forward ( ctx , q : torch . Tensor , kv : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Perform the forward pass of FlashAttention with packed key and value tensors. Args: q (torch.Tensor): Query tensor of shape (batch, seqlen_q, nheads, headdim). kv (torch.Tensor): Key and value tensor of shape (batch, seqlen_k, 2, nheads, headdim). bias (Optional[torch.Tensor]): Bias tensor, shape broadcastable to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Scaling factor for the softmax operation. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous q , kv = [ x if x . stride ( - 1 ) == 1 else x . contiguous () for x in [ q , kv ]] o , lse , ctx . softmax_scale = _flash_attn_forward ( q , kv [:, :, 0 ], kv [:, :, 1 ], bias = bias , causal = causal , softmax_scale = softmax_scale , ) ctx . save_for_backward ( q , kv , o , lse , bias ) ctx . causal = causal return o","title":"forward"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnQKVPackedFunc","text":"Bases: Function","title":"FlashAttnQKVPackedFunc"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnQKVPackedFunc.forward","text":"Forward pass for FlashAttention. Parameters: ctx ( Function ) \u2013 The context object to save information for backward computation. qkv ( Tensor ) \u2013 Input tensor of shape (batch, seqlen, 3, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Optional bias tensor, shape broadcastible to (batch, nheads, seqlen, seqlen). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen). ALiBi mask for non-causal would have shape (1, nheads, seqlen, seqlen). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Optional scaling factor for softmax. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 @staticmethod def forward ( ctx : torch . autograd . Function , qkv : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Forward pass for FlashAttention. Args: ctx (torch.autograd.Function): The context object to save information for backward computation. qkv (torch.Tensor): Input tensor of shape (batch, seqlen, 3, nheads, headdim). bias (Optional[torch.Tensor]): Optional bias tensor, shape broadcastible to (batch, nheads, seqlen, seqlen). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen). ALiBi mask for non-causal would have shape (1, nheads, seqlen, seqlen). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Optional scaling factor for softmax. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous if qkv . stride ( - 1 ) != 1 : qkv = qkv . contiguous () o , lse , ctx . softmax_scale = _flash_attn_forward ( qkv [:, :, 0 ], qkv [:, :, 1 ], qkv [:, :, 2 ], bias = bias , causal = causal , softmax_scale = softmax_scale , ) ctx . save_for_backward ( qkv , o , lse , bias ) ctx . causal = causal return o","title":"forward"},{"location":"model/#scprint.model.flash_attn.activations","text":"","title":"activations"},{"location":"model/#scprint.model.flash_attn.activations.bias_gelu_back","text":"Assume that y has shape (B, D) and bias has shape (D) Source code in scprint/model/flash_attn/activations.py 24 25 26 27 28 29 30 31 32 33 34 @torch . jit . script def bias_gelu_back ( g , y , bias ): \"\"\"Assume that y has shape (B, D) and bias has shape (D)\"\"\" x = bias + y tanh_out = torch . tanh ( 0.79788456 * x * ( 1 + 0.044715 * x * x )) # sqrt(2/pi) * 3 * 0.044715 -> 0.1070322243 ff = 0.5 * x * ( ( 1 - tanh_out * tanh_out ) * ( 0.79788456 + 0.1070322243 * x * x ) ) + 0.5 * ( 1 + tanh_out ) grad_y = ff * g return grad_y . to ( dtype = y . dtype ), grad_y . sum ( dim = ( 0 ), dtype = bias . dtype )","title":"bias_gelu_back"},{"location":"model/#scprint.model.flash_attn.layer_norm","text":"","title":"layer_norm"},{"location":"model/#scprint.model.flash_attn.layer_norm.layer_norm_ref","text":"Reference implementation of Layer Normalization with optional dropout and residual connections. Parameters: x ( Tensor ) \u2013 Input tensor. weight ( Tensor ) \u2013 Weight tensor for normalization. bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor for normalization. residual ( Optional [ Tensor ] , default: None ) \u2013 Residual tensor to be added to the input. x1 ( Optional [ Tensor ] , default: None ) \u2013 Additional input tensor for parallel LayerNorm. weight1 ( Optional [ Tensor ] , default: None ) \u2013 Additional weight tensor for parallel LayerNorm. bias1 ( Optional [ Tensor ] , default: None ) \u2013 Additional bias tensor for parallel LayerNorm. eps ( float , default: 1e-06 ) \u2013 Epsilon value to avoid division by zero. dropout_p ( float , default: 0.0 ) \u2013 Dropout probability. rowscale ( Optional [ Tensor ] , default: None ) \u2013 Row scaling tensor. prenorm ( bool , default: False ) \u2013 Whether to return the prenormalized output. dropout_mask ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the input tensor. dropout_mask1 ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the additional input tensor. upcast ( bool , default: False ) \u2013 Whether to upcast the input tensors to float. Returns: Union [ Tensor , Tuple [ Tensor , ...]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). Source code in scprint/model/flash_attn/layer_norm.py 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 def layer_norm_ref ( x : torch . Tensor , weight : torch . Tensor , bias : Optional [ torch . Tensor ] = None , residual : Optional [ torch . Tensor ] = None , x1 : Optional [ torch . Tensor ] = None , weight1 : Optional [ torch . Tensor ] = None , bias1 : Optional [ torch . Tensor ] = None , eps : float = 1e-6 , dropout_p : float = 0.0 , rowscale : Optional [ torch . Tensor ] = None , prenorm : bool = False , dropout_mask : Optional [ torch . Tensor ] = None , dropout_mask1 : Optional [ torch . Tensor ] = None , upcast : bool = False , ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , ... ]]: \"\"\" Reference implementation of Layer Normalization with optional dropout and residual connections. Args: x (torch.Tensor): Input tensor. weight (torch.Tensor): Weight tensor for normalization. bias (Optional[torch.Tensor]): Bias tensor for normalization. residual (Optional[torch.Tensor]): Residual tensor to be added to the input. x1 (Optional[torch.Tensor]): Additional input tensor for parallel LayerNorm. weight1 (Optional[torch.Tensor]): Additional weight tensor for parallel LayerNorm. bias1 (Optional[torch.Tensor]): Additional bias tensor for parallel LayerNorm. eps (float): Epsilon value to avoid division by zero. dropout_p (float): Dropout probability. rowscale (Optional[torch.Tensor]): Row scaling tensor. prenorm (bool): Whether to return the prenormalized output. dropout_mask (Optional[torch.Tensor]): Dropout mask for the input tensor. dropout_mask1 (Optional[torch.Tensor]): Dropout mask for the additional input tensor. upcast (bool): Whether to upcast the input tensors to float. Returns: Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). \"\"\" dtype = x . dtype if upcast : x = x . float () weight = weight . float () bias = bias . float () if bias is not None else None residual = residual . float () if residual is not None else residual x1 = x1 . float () if x1 is not None else None weight1 = weight1 . float () if weight1 is not None else None bias1 = bias1 . float () if bias1 is not None else None if x1 is not None : assert rowscale is None , \"rowscale is not supported with parallel LayerNorm\" if rowscale is not None : x = x * rowscale [ ... , None ] if dropout_p > 0.0 : if dropout_mask is not None : x = x . masked_fill ( ~ dropout_mask , 0.0 ) / ( 1.0 - dropout_p ) else : x = F . dropout ( x , p = dropout_p ) if x1 is not None : if dropout_mask1 is not None : x1 = x1 . masked_fill ( ~ dropout_mask1 , 0.0 ) / ( 1.0 - dropout_p ) else : x1 = F . dropout ( x1 , p = dropout_p ) if x1 is not None : x = x + x1 if residual is not None : x = ( x + residual ) . to ( x . dtype ) out = F . layer_norm ( x . to ( weight . dtype ), x . shape [ - 1 :], weight = weight , bias = bias , eps = eps ) . to ( dtype ) if weight1 is None : return out if not prenorm else ( out , x ) else : out1 = F . layer_norm ( x . to ( weight1 . dtype ), x . shape [ - 1 :], weight = weight1 , bias = bias1 , eps = eps ) . to ( dtype ) return ( out , out1 ) if not prenorm else ( out , out1 , x )","title":"layer_norm_ref"},{"location":"model/#scprint.model.flash_attn.layer_norm.rms_norm_ref","text":"Reference implementation of RMS Normalization with optional dropout and residual connections. Parameters: x ( Tensor ) \u2013 Input tensor. weight ( Tensor ) \u2013 Weight tensor for normalization. bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor for normalization. residual ( Optional [ Tensor ] , default: None ) \u2013 Residual tensor to be added to the input. x1 ( Optional [ Tensor ] , default: None ) \u2013 Additional input tensor for parallel RMSNorm. weight1 ( Optional [ Tensor ] , default: None ) \u2013 Additional weight tensor for parallel RMSNorm. bias1 ( Optional [ Tensor ] , default: None ) \u2013 Additional bias tensor for parallel RMSNorm. eps ( float , default: 1e-06 ) \u2013 Epsilon value to avoid division by zero. dropout_p ( float , default: 0.0 ) \u2013 Dropout probability. rowscale ( Optional [ Tensor ] , default: None ) \u2013 Row scaling tensor. prenorm ( bool , default: False ) \u2013 Whether to return the prenormalized output. dropout_mask ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the input tensor. dropout_mask1 ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the additional input tensor. upcast ( bool , default: False ) \u2013 Whether to upcast the input tensors to float. Returns: Union [ Tensor , Tuple [ Tensor , ...]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). Source code in scprint/model/flash_attn/layer_norm.py 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 def rms_norm_ref ( x : torch . Tensor , weight : torch . Tensor , bias : Optional [ torch . Tensor ] = None , residual : Optional [ torch . Tensor ] = None , x1 : Optional [ torch . Tensor ] = None , weight1 : Optional [ torch . Tensor ] = None , bias1 : Optional [ torch . Tensor ] = None , eps : float = 1e-6 , dropout_p : float = 0.0 , rowscale : Optional [ torch . Tensor ] = None , prenorm : bool = False , dropout_mask : Optional [ torch . Tensor ] = None , dropout_mask1 : Optional [ torch . Tensor ] = None , upcast : bool = False , ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , ... ]]: \"\"\" Reference implementation of RMS Normalization with optional dropout and residual connections. Args: x (torch.Tensor): Input tensor. weight (torch.Tensor): Weight tensor for normalization. bias (Optional[torch.Tensor]): Bias tensor for normalization. residual (Optional[torch.Tensor]): Residual tensor to be added to the input. x1 (Optional[torch.Tensor]): Additional input tensor for parallel RMSNorm. weight1 (Optional[torch.Tensor]): Additional weight tensor for parallel RMSNorm. bias1 (Optional[torch.Tensor]): Additional bias tensor for parallel RMSNorm. eps (float): Epsilon value to avoid division by zero. dropout_p (float): Dropout probability. rowscale (Optional[torch.Tensor]): Row scaling tensor. prenorm (bool): Whether to return the prenormalized output. dropout_mask (Optional[torch.Tensor]): Dropout mask for the input tensor. dropout_mask1 (Optional[torch.Tensor]): Dropout mask for the additional input tensor. upcast (bool): Whether to upcast the input tensors to float. Returns: Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). \"\"\" dtype = x . dtype if upcast : x = x . float () weight = weight . float () bias = bias . float () if bias is not None else None residual = residual . float () if residual is not None else residual x1 = x1 . float () if x1 is not None else None weight1 = weight1 . float () if weight1 is not None else None bias1 = bias1 . float () if bias1 is not None else None if x1 is not None : assert rowscale is None , \"rowscale is not supported with parallel LayerNorm\" if rowscale is not None : x = x * rowscale [ ... , None ] if dropout_p > 0.0 : if dropout_mask is not None : x = x . masked_fill ( ~ dropout_mask , 0.0 ) / ( 1.0 - dropout_p ) else : x = F . dropout ( x , p = dropout_p ) if x1 is not None : if dropout_mask1 is not None : x1 = x1 . masked_fill ( ~ dropout_mask1 , 0.0 ) / ( 1.0 - dropout_p ) else : x1 = F . dropout ( x1 , p = dropout_p ) if x1 is not None : x = x + x1 if residual is not None : x = ( x + residual ) . to ( x . dtype ) rstd = 1 / torch . sqrt (( x . square ()) . mean ( dim =- 1 , keepdim = True ) + eps ) out = (( x * rstd * weight ) + bias if bias is not None else ( x * rstd * weight )) . to ( dtype ) if weight1 is None : return out if not prenorm else ( out , x ) else : out1 = ( ( x * rstd * weight1 ) + bias1 if bias1 is not None else ( x * rstd * weight1 ) ) . to ( dtype ) return ( out , out1 ) if not prenorm else ( out , out1 , x )","title":"rms_norm_ref"},{"location":"pretrain/","text":"Pre-training scPRINT scPRINT is a large model that can be pre-trained on a large dataset of single cell data. This pre-training is quite efficient for scPRINT and smaller models can be pretrained on any hardware with a 20GB NVIDIA GPU. Setup of the database To perform pretraining you will need a large dataset. We recommend using the laminDB to assemble such a large database of dataset and to use our scdataloader package to perform the data loading to the model. In addition, you will need to preprocess your datasets. To make sure that the fields are all here, the genes are in the right format, the raw counts are used, etc... We recommend using the Preprocessor class of the scdataloader package. Moreover scdataloader works with a set of ontologies. To install these, use the function populate_my_ontologies from the scdataloader package. If you do not have your own database of anndatas, we recommend the cellxgene database and our associated helper function to download and preprocess all of cellxgene in a single command with scdataloader . Finally you might want to generate gene embeddings to use with scPRINT instead of learning these tokens from scratch. For this you can use the gene_embedders module of scPRINT, which usage is detailed in the notebooks/generate_gene_embeddings.ipynb notebook. Pre-training to pretrain scPRINT we strongly recommend using command line as it can take multiple days (and using some HPC plateform like slurm or others). If on your own machine, use something like screen at least \ud83d\ude09. Most of the pre-training usage follows from pytorch lightning with scprint fit you will launch a training run. It will populate both the datamodule (see scdataloader ), the model (see model.py ), the trainer (see pytorch lightning ) and the various callbacks. But you might want to use additional parameters. For this, you can use the config folder and the yaml files in it. These files are used to store the main hyperparameters of the model and the training scheme. More hyperparameters are given to the scPRINT model via a Trainer callback I created (see trainer/trainer.py ). This is used to specify parameters to scPRINT that are used solely during training and are not part of the model definition itself, like lr, schedulers, optimizers, etc.. I use a callback as it is how pytorch lightning requires us to send training parameters to the model. Thus a full command line to train scPRINT on a slurm cluster might look like this: conda activate scprint ### slurm level stuff module load cuda/11.7 srun -p gpu #gpu partition -q gpu #gpu queue --gres=gpu:A40:4,gmem:40G #gpu type (4 A40 with 40GB of GPU mem) --cpus-per-task 16 --mem-per-gpu 90G #RAM per GPU --ntasks-per-node=1 #### # actuall scprint command scprint fit --config config/base.yml #base config file (see below) --config config/pretrain_large.yml #the differences when training a large model --model.nhead 8 # changing this parameter from the large model directly in command line (cannot do 4 heads of 128dim with A40 GPUs...) --scprint_training.name o2uniqsx #an id for the model (not needed but useful) --trainer.strategy auto #here the strategy selected will be \"ddp_find_unused_parameters_true\" with the base yaml file containing: # general params project: scprint_scale #project name for saving data and wandb seed_everything: 42 ckpt_path: null #we don't have a checkpoint weights as we train from scratch set_float32_matmul_precision: True wandblog: all #we use wandb here log_freq: 200 log_graph: True trainer: #training level params precision: 16-mixed #we use mixed precision 16bit for training gradient_clip_val: 100 #needed log_every_n_steps: 100 .... logger: #we can add multiple loggers (see below) - class_path: lightning.pytorch.loggers.WandbLogger callbacks: #you can create your own callback and add it here or use lightning's callbacks - class_path: lightning.pytorch.callbacks.StochasticWeightAveraging init_args: swa_lrs: 0.03 ... model: # model params dropout: 0.1 transformer: flash #flashattention is used mvc_decoder: inner product residual_in_fp32: True ... data: #datamodule params organisms: #we will use these 2 species - NCBITaxon:9606 - NCBITaxon:10090 gene_position_tolerance: 10_000 #gene location: if genes are closer than 10kb, they are considered as the same location gene_embeddings: ./data/main/gene_embeddings.parquet #the embeddings of genes (see above ) collection_name: all no zhang13M # the name of the laminDB collection we will use how: random expr # how we collate the expression data (here random expressed genes) max_len: 2200 #how many genes we use in the model context during training weight_scaler: 50 #how do we scale the weighted random sampling procedure (see our manuscript) ... We use wanDB in our case and our previous wandb training runs are available here , however scPRINT and pytorch lightning support a breadth of logging tools: see loggers . We use slurm in our usecase here but scPRINT and pytorch lightning has been made to work in a breadth of environments e.g. . Fine-tuning For now scPRINT doesn't have a fine-tuning script. But PRs are very welcome on using LoRA and its alternatives to fine-tune scPRINT on novel tasks!","title":"pre-training"},{"location":"pretrain/#pre-training-scprint","text":"scPRINT is a large model that can be pre-trained on a large dataset of single cell data. This pre-training is quite efficient for scPRINT and smaller models can be pretrained on any hardware with a 20GB NVIDIA GPU.","title":"Pre-training scPRINT"},{"location":"pretrain/#setup-of-the-database","text":"To perform pretraining you will need a large dataset. We recommend using the laminDB to assemble such a large database of dataset and to use our scdataloader package to perform the data loading to the model. In addition, you will need to preprocess your datasets. To make sure that the fields are all here, the genes are in the right format, the raw counts are used, etc... We recommend using the Preprocessor class of the scdataloader package. Moreover scdataloader works with a set of ontologies. To install these, use the function populate_my_ontologies from the scdataloader package. If you do not have your own database of anndatas, we recommend the cellxgene database and our associated helper function to download and preprocess all of cellxgene in a single command with scdataloader . Finally you might want to generate gene embeddings to use with scPRINT instead of learning these tokens from scratch. For this you can use the gene_embedders module of scPRINT, which usage is detailed in the notebooks/generate_gene_embeddings.ipynb notebook.","title":"Setup of the database"},{"location":"pretrain/#pre-training","text":"to pretrain scPRINT we strongly recommend using command line as it can take multiple days (and using some HPC plateform like slurm or others). If on your own machine, use something like screen at least \ud83d\ude09. Most of the pre-training usage follows from pytorch lightning with scprint fit you will launch a training run. It will populate both the datamodule (see scdataloader ), the model (see model.py ), the trainer (see pytorch lightning ) and the various callbacks. But you might want to use additional parameters. For this, you can use the config folder and the yaml files in it. These files are used to store the main hyperparameters of the model and the training scheme. More hyperparameters are given to the scPRINT model via a Trainer callback I created (see trainer/trainer.py ). This is used to specify parameters to scPRINT that are used solely during training and are not part of the model definition itself, like lr, schedulers, optimizers, etc.. I use a callback as it is how pytorch lightning requires us to send training parameters to the model. Thus a full command line to train scPRINT on a slurm cluster might look like this: conda activate scprint ### slurm level stuff module load cuda/11.7 srun -p gpu #gpu partition -q gpu #gpu queue --gres=gpu:A40:4,gmem:40G #gpu type (4 A40 with 40GB of GPU mem) --cpus-per-task 16 --mem-per-gpu 90G #RAM per GPU --ntasks-per-node=1 #### # actuall scprint command scprint fit --config config/base.yml #base config file (see below) --config config/pretrain_large.yml #the differences when training a large model --model.nhead 8 # changing this parameter from the large model directly in command line (cannot do 4 heads of 128dim with A40 GPUs...) --scprint_training.name o2uniqsx #an id for the model (not needed but useful) --trainer.strategy auto #here the strategy selected will be \"ddp_find_unused_parameters_true\" with the base yaml file containing: # general params project: scprint_scale #project name for saving data and wandb seed_everything: 42 ckpt_path: null #we don't have a checkpoint weights as we train from scratch set_float32_matmul_precision: True wandblog: all #we use wandb here log_freq: 200 log_graph: True trainer: #training level params precision: 16-mixed #we use mixed precision 16bit for training gradient_clip_val: 100 #needed log_every_n_steps: 100 .... logger: #we can add multiple loggers (see below) - class_path: lightning.pytorch.loggers.WandbLogger callbacks: #you can create your own callback and add it here or use lightning's callbacks - class_path: lightning.pytorch.callbacks.StochasticWeightAveraging init_args: swa_lrs: 0.03 ... model: # model params dropout: 0.1 transformer: flash #flashattention is used mvc_decoder: inner product residual_in_fp32: True ... data: #datamodule params organisms: #we will use these 2 species - NCBITaxon:9606 - NCBITaxon:10090 gene_position_tolerance: 10_000 #gene location: if genes are closer than 10kb, they are considered as the same location gene_embeddings: ./data/main/gene_embeddings.parquet #the embeddings of genes (see above ) collection_name: all no zhang13M # the name of the laminDB collection we will use how: random expr # how we collate the expression data (here random expressed genes) max_len: 2200 #how many genes we use in the model context during training weight_scaler: 50 #how do we scale the weighted random sampling procedure (see our manuscript) ... We use wanDB in our case and our previous wandb training runs are available here , however scPRINT and pytorch lightning support a breadth of logging tools: see loggers . We use slurm in our usecase here but scPRINT and pytorch lightning has been made to work in a breadth of environments e.g. .","title":"Pre-training"},{"location":"pretrain/#fine-tuning","text":"For now scPRINT doesn't have a fine-tuning script. But PRs are very welcome on using LoRA and its alternatives to fine-tune scPRINT on novel tasks!","title":"Fine-tuning"},{"location":"structure/","text":"structure gene embedders Function to get embeddings from a set of genes, given their ensembl ids. For now use 2 different models: RNABert : for non coding genes ESM2 : for protein coding genes given ids, a fasta file, will use the models to compute an embedding of each gene. This could be potentially applied to genes with mutations and from different species. data_loaders From scDataloader. (see more in the available readmes and website https://jkobject.com/scDataLoader) For now can work with either one to many AnnData's or a laminDB Collection of AnnDatas allows you to preprocess your anndatas too. They can be stored locally or remotely stores them in a Dataset class. Creates the DataLoaders from a Datamodule Class. Collates the results using a Collator function. model Extends from lightning data module to implement all the necessary functions to do: training validation testing prediction (inference) is subdivided into multiple parts: encoder transformer decoder trainer & cli the model uses lightning's training toolkit and CLI tools. to use CLI, just call scprint ... (will call the __main__.py function). Additional, training-specific informations are passed to the model using the trainer.py function. specific training schemes are available under the config folder as yaml files. Moreover the model can be trained on multiple compute types. SLURM scripts are available under the slurm folder. tasks Implement different tasks that a pretrained model would perform. for now: GRN prediction: given a single cell dataset and a group (cell type, cluster, ...) will output a GRnnData completed with a predicted GRN from the attention of the model. denoising: from a single cell dataset, will modify the count matrices to predict what it would have looked like if it had been sequenced deeper, according to the model. embedding: from a single cell dataset, will create embeddings (low dimensional representations) of each cells, as well as prediction of the cell labels the model has been trained on (cell type, disease, ethnicity, sex...). It will also output a umap and predicted expression from the zinb, post bottleneck (similar to a VAE decoder prediction)","title":"structure"},{"location":"structure/#structure","text":"","title":"structure"},{"location":"structure/#gene-embedders","text":"Function to get embeddings from a set of genes, given their ensembl ids. For now use 2 different models: RNABert : for non coding genes ESM2 : for protein coding genes given ids, a fasta file, will use the models to compute an embedding of each gene. This could be potentially applied to genes with mutations and from different species.","title":"gene embedders"},{"location":"structure/#data_loaders","text":"From scDataloader. (see more in the available readmes and website https://jkobject.com/scDataLoader) For now can work with either one to many AnnData's or a laminDB Collection of AnnDatas allows you to preprocess your anndatas too. They can be stored locally or remotely stores them in a Dataset class. Creates the DataLoaders from a Datamodule Class. Collates the results using a Collator function.","title":"data_loaders"},{"location":"structure/#model","text":"Extends from lightning data module to implement all the necessary functions to do: training validation testing prediction (inference) is subdivided into multiple parts: encoder transformer decoder","title":"model"},{"location":"structure/#trainer-cli","text":"the model uses lightning's training toolkit and CLI tools. to use CLI, just call scprint ... (will call the __main__.py function). Additional, training-specific informations are passed to the model using the trainer.py function. specific training schemes are available under the config folder as yaml files. Moreover the model can be trained on multiple compute types. SLURM scripts are available under the slurm folder.","title":"trainer & cli"},{"location":"structure/#tasks","text":"Implement different tasks that a pretrained model would perform. for now: GRN prediction: given a single cell dataset and a group (cell type, cluster, ...) will output a GRnnData completed with a predicted GRN from the attention of the model. denoising: from a single cell dataset, will modify the count matrices to predict what it would have looked like if it had been sequenced deeper, according to the model. embedding: from a single cell dataset, will create embeddings (low dimensional representations) of each cells, as well as prediction of the cell labels the model has been trained on (cell type, disease, ethnicity, sex...). It will also output a umap and predicted expression from the zinb, post bottleneck (similar to a VAE decoder prediction)","title":"tasks"},{"location":"tasks/","text":"Documentation for the tasks scprint.tasks.cell_emb Embedder Embedder a class to embed and annotate cells using a model Parameters: batch_size ( int , default: 64 ) \u2013 The size of the batches to be used in the DataLoader. Defaults to 64. num_workers ( int , default: 8 ) \u2013 The number of worker processes to use for data loading. Defaults to 8. how ( str , default: 'random expr' ) \u2013 The method to be used for selecting valid genes. Defaults to \"most expr\". max_len ( int , default: 2000 ) \u2013 The maximum length of the gene sequence. Defaults to 1000. add_zero_genes ( int , default: 0 ) \u2013 The number of zero genes to add to the gene sequence. Defaults to 100. precision ( str , default: '16-mixed' ) \u2013 The precision to be used in the Trainer. Defaults to \"16-mixed\". pred_embedding ( List [ str ] , default: ['cell_type_ontology_term_id', 'disease_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'sex_ontology_term_id'] ) \u2013 The list of labels to be used for plotting embeddings. Defaults to [ \"cell_type_ontology_term_id\", \"disease_ontology_term_id\", \"self_reported_ethnicity_ontology_term_id\", \"sex_ontology_term_id\", ]. doclass ( bool , default: True ) \u2013 Whether to perform classification. Defaults to True. doplot ( bool , default: True ) \u2013 Whether to generate plots. Defaults to True. keep_all_cls_pred ( bool , default: False ) \u2013 Whether to keep all class predictions. Defaults to False. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. output_expression ( str , default: 'none' ) \u2013 The method to output expression data. Options are \"none\", \"all\", \"sample\". Defaults to \"none\". Source code in scprint/tasks/cell_emb.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 def __init__ ( self , batch_size : int = 64 , num_workers : int = 8 , how : str = \"random expr\" , max_len : int = 2000 , doclass : bool = True , add_zero_genes : int = 0 , precision : str = \"16-mixed\" , pred_embedding : List [ str ] = [ \"cell_type_ontology_term_id\" , \"disease_ontology_term_id\" , \"self_reported_ethnicity_ontology_term_id\" , \"sex_ontology_term_id\" , ], plot_corr_size : int = 64 , doplot : bool = True , keep_all_cls_pred : bool = False , devices : List [ int ] = [ 0 ], dtype : torch . dtype = torch . float16 , output_expression : str = \"none\" , ): \"\"\" Embedder a class to embed and annotate cells using a model Args: batch_size (int, optional): The size of the batches to be used in the DataLoader. Defaults to 64. num_workers (int, optional): The number of worker processes to use for data loading. Defaults to 8. how (str, optional): The method to be used for selecting valid genes. Defaults to \"most expr\". max_len (int, optional): The maximum length of the gene sequence. Defaults to 1000. add_zero_genes (int, optional): The number of zero genes to add to the gene sequence. Defaults to 100. precision (str, optional): The precision to be used in the Trainer. Defaults to \"16-mixed\". pred_embedding (List[str], optional): The list of labels to be used for plotting embeddings. Defaults to [ \"cell_type_ontology_term_id\", \"disease_ontology_term_id\", \"self_reported_ethnicity_ontology_term_id\", \"sex_ontology_term_id\", ]. doclass (bool, optional): Whether to perform classification. Defaults to True. doplot (bool, optional): Whether to generate plots. Defaults to True. keep_all_cls_pred (bool, optional): Whether to keep all class predictions. Defaults to False. devices (List[int], optional): List of device IDs to use. Defaults to [0]. dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. output_expression (str, optional): The method to output expression data. Options are \"none\", \"all\", \"sample\". Defaults to \"none\". \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . how = how self . max_len = max_len self . add_zero_genes = add_zero_genes self . pred_embedding = pred_embedding self . keep_all_cls_pred = keep_all_cls_pred self . plot_corr_size = plot_corr_size self . precision = precision self . doplot = doplot self . doclass = doclass self . trainer = Trainer ( precision = precision , devices = devices ) self . output_expression = output_expression __call__ call function to call the embedding Parameters: model ( Module ) \u2013 The scPRINT model to be used for embedding and annotation. adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. cache ( bool , default: False ) \u2013 Whether to use cached results if available. Defaults to False. Raises: ValueError \u2013 If the model does not have a logger attribute. ValueError \u2013 If the model does not have a global_step attribute. Returns: AnnData \u2013 The annotated data matrix with embedded cell representations. \u2013 List[str]: List of gene names used in the embedding. \u2013 np.ndarray: The predicted expression values if output_expression is not \"none\". dict \u2013 Additional metrics and information from the embedding process. Source code in scprint/tasks/cell_emb.py 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 def __call__ ( self , model : torch . nn . Module , adata : AnnData , cache = False ): \"\"\" __call__ function to call the embedding Args: model (torch.nn.Module): The scPRINT model to be used for embedding and annotation. adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. cache (bool, optional): Whether to use cached results if available. Defaults to False. Raises: ValueError: If the model does not have a logger attribute. ValueError: If the model does not have a global_step attribute. Returns: AnnData: The annotated data matrix with embedded cell representations. List[str]: List of gene names used in the embedding. np.ndarray: The predicted expression values if output_expression is not \"none\". dict: Additional metrics and information from the embedding process. \"\"\" # one of \"all\" \"sample\" \"none\" try : mdir = ( model . logger . save_dir if model . logger . save_dir is not None else \"data\" ) except : mdir = \"data\" try : file = ( mdir + \"/step_\" + str ( model . global_step ) + \"_predict_part_\" + str ( model . counter ) + \"_\" + str ( model . global_rank ) + \".h5ad\" ) hasfile = os . path . exists ( file ) except : hasfile = False if not cache or not hasfile : model . predict_mode = \"none\" model . keep_all_cls_pred = self . keep_all_cls_pred # Add at least the organism you are working with if self . how == \"most var\" : sc . pp . highly_variable_genes ( adata , flavor = \"seurat_v3\" , n_top_genes = self . max_len ) curr_genes = adata . var . index [ adata . var . highly_variable ] adataset = SimpleAnnDataset ( adata , obs_to_output = [ \"organism_ontology_term_id\" ] ) col = Collator ( organisms = model . organisms , valid_genes = model . genes , how = self . how if self . how != \"most var\" else \"some\" , max_len = self . max_len , add_zero_genes = self . add_zero_genes , genelist = [] if self . how != \"most var\" else curr_genes , ) dataloader = DataLoader ( adataset , collate_fn = col , batch_size = self . batch_size , num_workers = self . num_workers , shuffle = False , ) model . eval () model . on_predict_epoch_start () device = model . device . type model . doplot = self . doplot with torch . no_grad (), torch . autocast ( device_type = device , dtype = torch . float16 ): for batch in tqdm ( dataloader ): gene_pos , expression , depth = ( batch [ \"genes\" ] . to ( device ), batch [ \"x\" ] . to ( device ), batch [ \"depth\" ] . to ( device ), ) model . _predict ( gene_pos , expression , depth , predict_mode = \"none\" , pred_embedding = self . pred_embedding , ) torch . cuda . empty_cache () model . log_adata ( name = \"predict_part_\" + str ( model . counter )) try : mdir = ( model . logger . save_dir if model . logger . save_dir is not None else \"data\" ) except : mdir = \"data\" file = ( mdir + \"/step_\" + str ( model . global_step ) + \"_\" + model . name + \"_predict_part_\" + str ( model . counter ) + \"_\" + str ( model . global_rank ) + \".h5ad\" ) pred_adata = sc . read_h5ad ( file ) if self . output_expression == \"all\" : adata . obsm [ \"scprint_mu\" ] = model . expr_pred [ 0 ] adata . obsm [ \"scprint_theta\" ] = model . expr_pred [ 1 ] adata . obsm [ \"scprint_pi\" ] = model . expr_pred [ 2 ] adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () elif self . output_expression == \"sample\" : adata . obsm [ \"scprint_expr\" ] = ( utils . zinb_sample ( model . expr_pred [ 0 ], model . expr_pred [ 1 ], model . expr_pred [ 2 ], ) . cpu () . numpy () ) adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () elif self . output_expression == \"old\" : expr = np . array ( model . expr_pred [ 0 ]) expr [ np . random . binomial ( 1 , p = np . array ( torch . nn . functional . sigmoid ( model . expr_pred [ 2 ] . to ( torch . float32 ) ) ), ) . astype ( bool ) ] = 0 expr [ expr <= 0.3 ] = 0 expr [( expr >= 0.3 ) & ( expr <= 1 )] = 1 adata . obsm [ \"scprint_expr\" ] = expr . astype ( int ) adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () else : pass pred_adata . obs . index = adata . obs . index adata . obsm [ \"scprint_umap\" ] = pred_adata . obsm [ \"X_umap\" ] # adata.obsm[\"scprint_leiden\"] = pred_adata.obsm[\"leiden\"] adata . obsm [ \"scprint\" ] = pred_adata . X pred_adata . obs . index = adata . obs . index adata . obs = pd . concat ([ adata . obs , pred_adata . obs ], axis = 1 ) if self . keep_all_cls_pred : allclspred = model . pred columns = [] for cl in model . classes : n = model . label_counts [ cl ] columns += [ model . label_decoders [ cl ][ i ] for i in range ( n )] allclspred = pd . DataFrame ( allclspred , columns = columns , index = adata . obs . index ) adata . obs = pd . concat ( adata . obs , allclspred ) metrics = {} if self . doclass and not self . keep_all_cls_pred : for cl in model . classes : res = [] if cl not in adata . obs . columns : continue class_topred = model . label_decoders [ cl ] . values () if cl in model . labels_hierarchy : # class_groupings = { # k: [ # i.ontology_id # for i in bt.CellType.filter(k).first().children.all() # ] # for k in set(adata.obs[cl].unique()) - set(class_topred) # } cur_labels_hierarchy = { model . label_decoders [ cl ][ k ]: [ model . label_decoders [ cl ][ i ] for i in v ] for k , v in model . labels_hierarchy [ cl ] . items () } else : cur_labels_hierarchy = {} for pred , true in adata . obs [[ \"pred_\" + cl , cl ]] . values : if pred == true : res . append ( True ) continue if len ( cur_labels_hierarchy ) > 0 : if true in cur_labels_hierarchy : res . append ( pred in cur_labels_hierarchy [ true ]) continue elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) # else true is unknown # else we pass if len ( res ) == 0 : # true was always unknown res = [ 1 ] if self . doplot : print ( \" \" , cl ) print ( \" accuracy:\" , sum ( res ) / len ( res )) print ( \" \" ) metrics . update ({ cl + \"_accuracy\" : sum ( res ) / len ( res )}) # m = self.compute_reconstruction(adata, plot_corr_size=self.plot_corr_size) # metrics.update(m) return adata , metrics compute_classification Compute classification metrics for the given annotated data. Parameters: adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. classes ( List [ str ] ) \u2013 List of class labels to be used for classification. label_decoders ( Dict [ str , Any ] ) \u2013 Dictionary of label decoders for each class. labels_hierarchy ( Dict [ str , Any ] ) \u2013 Dictionary representing the hierarchy of labels. metric_type ( List [ str ] , default: ['macro', 'micro', 'weighted'] ) \u2013 List of metric types to compute. Defaults to [\"macro\", \"micro\", \"weighted\"]. Returns: Dict [ str , Dict [ str , float ]] \u2013 Dict[str, Dict[str, float]]: A dictionary containing classification metrics for each class. Source code in scprint/tasks/cell_emb.py 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 def compute_classification ( adata : AnnData , classes : List [ str ], label_decoders : Dict [ str , Any ], labels_hierarchy : Dict [ str , Any ], metric_type : List [ str ] = [ \"macro\" , \"micro\" , \"weighted\" ], ) -> Dict [ str , Dict [ str , float ]]: \"\"\" Compute classification metrics for the given annotated data. Args: adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. classes (List[str]): List of class labels to be used for classification. label_decoders (Dict[str, Any]): Dictionary of label decoders for each class. labels_hierarchy (Dict[str, Any]): Dictionary representing the hierarchy of labels. metric_type (List[str], optional): List of metric types to compute. Defaults to [\"macro\", \"micro\", \"weighted\"]. Returns: Dict[str, Dict[str, float]]: A dictionary containing classification metrics for each class. \"\"\" metrics = {} for label in classes : res = [] if label not in adata . obs . columns : continue labels_topred = label_decoders [ label ] . values () if label in labels_hierarchy : parentdf = ( bt . CellType . filter () . df ( include = [ \"parents__ontology_id\" ]) . set_index ( \"ontology_id\" )[[ \"parents__ontology_id\" ]] ) parentdf . parents__ontology_id = parentdf . parents__ontology_id . astype ( str ) class_groupings = { k : get_descendants ( k , parentdf ) for k in set ( adata . obs [ label ] . unique ()) } for pred , true in adata . obs [[ \"pred_\" + label , label ]] . values : if pred == true : res . append ( true ) continue if label in labels_hierarchy : if true in class_groupings : res . append ( true if pred in class_groupings [ true ] else \"\" ) continue elif true not in labels_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true not in labels_topred : raise ValueError ( f \"true label { true } not in available classes\" ) res . append ( \"\" ) metrics [ label ] = {} metrics [ label ][ \"accuracy\" ] = np . mean ( np . array ( res ) == adata . obs [ label ] . values ) for x in metric_type : metrics [ label ][ x ] = f1_score ( np . array ( res ), adata . obs [ label ] . values , average = x ) return metrics compute_corr Compute the correlation between the output and target matrices. Parameters: out ( ndarray ) \u2013 The output matrix. to ( ndarray ) \u2013 The target matrix. doplot ( bool , default: True ) \u2013 Whether to generate a plot of the correlation coefficients. Defaults to True. compute_mean_regress ( bool , default: False ) \u2013 Whether to compute mean regression. Defaults to False. plot_corr_size ( int , default: 64 ) \u2013 The size of the plot for correlation. Defaults to 64. Returns: dict ( dict ) \u2013 A dictionary containing the computed metrics. Source code in scprint/tasks/cell_emb.py 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 def compute_corr ( out : np . ndarray , to : np . ndarray , doplot : bool = True , compute_mean_regress : bool = False , plot_corr_size : int = 64 , ) -> dict : \"\"\" Compute the correlation between the output and target matrices. Args: out (np.ndarray): The output matrix. to (np.ndarray): The target matrix. doplot (bool, optional): Whether to generate a plot of the correlation coefficients. Defaults to True. compute_mean_regress (bool, optional): Whether to compute mean regression. Defaults to False. plot_corr_size (int, optional): The size of the plot for correlation. Defaults to 64. Returns: dict: A dictionary containing the computed metrics. \"\"\" metrics = {} corr_coef , p_value = spearmanr ( out , to . T , ) corr_coef [ p_value > 0.05 ] = 0 # corr_coef[] # only on non zero values, # compare a1-b1 corr with a1-b(n) corr. should be higher # Plot correlation coefficient val = plot_corr_size + 2 if compute_mean_regress else plot_corr_size metrics . update ( { \"recons_corr\" : np . mean ( corr_coef [ val :, : plot_corr_size ] . diagonal ())} ) if compute_mean_regress : metrics . update ( { \"mean_regress\" : np . mean ( corr_coef [ plot_corr_size : plot_corr_size + 2 , : plot_corr_size , ] . flatten () ) } ) if doplot : plt . figure ( figsize = ( 10 , 5 )) plt . imshow ( corr_coef , cmap = \"coolwarm\" , interpolation = \"none\" , vmin =- 1 , vmax = 1 ) plt . colorbar () plt . title ( 'Correlation Coefficient of expr and i[\"x\"]' ) plt . show () return metrics default_benchmark Run the default benchmark for embedding and annotation using the scPRINT model. Parameters: model ( Module ) \u2013 The scPRINT model to be used for embedding and annotation. default_dataset ( str , default: 'pancreas' ) \u2013 The default dataset to use for benchmarking. Options are \"pancreas\", \"lung\", or a path to a dataset. Defaults to \"pancreas\". do_class ( bool , default: True ) \u2013 Whether to perform classification. Defaults to True. coarse ( bool , default: False ) \u2013 Whether to use coarse cell type annotations. Defaults to False. Returns: dict ( dict ) \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/cell_emb.py 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 def default_benchmark ( model : torch . nn . Module , default_dataset : str = \"pancreas\" , do_class : bool = True , coarse : bool = False , ) -> dict : \"\"\" Run the default benchmark for embedding and annotation using the scPRINT model. Args: model (torch.nn.Module): The scPRINT model to be used for embedding and annotation. default_dataset (str, optional): The default dataset to use for benchmarking. Options are \"pancreas\", \"lung\", or a path to a dataset. Defaults to \"pancreas\". do_class (bool, optional): Whether to perform classification. Defaults to True. coarse (bool, optional): Whether to use coarse cell type annotations. Defaults to False. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" if default_dataset == \"pancreas\" : adata = sc . read ( FILE_LOC + \"/../../data/pancreas_atlas.h5ad\" , backup_url = \"https://figshare.com/ndownloader/files/24539828\" , ) adata . obs [ \"cell_type_ontology_term_id\" ] = adata . obs [ \"celltype\" ] . replace ( COARSE if coarse else FINE ) adata . obs [ \"assay_ontology_term_id\" ] = adata . obs [ \"tech\" ] . replace ( COARSE if coarse else FINE ) elif default_dataset == \"lung\" : adata = sc . read ( FILE_LOC + \"/../../data/lung_atlas.h5ad\" , backup_url = \"https://figshare.com/ndownloader/files/24539942\" , ) adata . obs [ \"cell_type_ontology_term_id\" ] = adata . obs [ \"cell_type\" ] . replace ( COARSE if coarse else FINE ) else : adata = sc . read_h5ad ( default_dataset ) adata . obs [ \"batch\" ] = adata . obs [ \"assay_ontology_term_id\" ] adata . obs [ \"cell_type\" ] = adata . obs [ \"cell_type_ontology_term_id\" ] preprocessor = Preprocessor ( use_layer = \"counts\" , is_symbol = True , force_preprocess = True , skip_validate = True , do_postp = False , ) adata . obs [ \"organism_ontology_term_id\" ] = \"NCBITaxon:9606\" adata = preprocessor ( adata . copy ()) embedder = Embedder ( pred_embedding = [ \"cell_type_ontology_term_id\" ], doclass = ( default_dataset not in [ \"pancreas\" , \"lung\" ]), devices = 1 , ) embed_adata , metrics = embedder ( model , adata . copy ()) bm = Benchmarker ( embed_adata , batch_key = \"tech\" if default_dataset == \"pancreas\" else \"batch\" , label_key = \"celltype\" if default_dataset == \"pancreas\" else \"cell_type\" , embedding_obsm_keys = [ \"scprint\" ], n_jobs = 6 , ) bm . benchmark () metrics . update ({ \"scib\" : bm . get_results ( min_max_scale = False ) . T . to_dict ()[ \"scprint\" ]}) metrics [ \"classif\" ] = compute_classification ( embed_adata , model . classes , model . label_decoders , model . labels_hierarchy ) return metrics scprint.tasks.grn GNInfer GNInfer a class to infer gene regulatory networks from a dataset using a scPRINT model. Parameters: layer ( Optional [ list [ int ]] , default: None ) \u2013 List of layers to use for the inference. Defaults to None. batch_size ( int , default: 64 ) \u2013 Batch size for processing. Defaults to 64. num_workers ( int , default: 8 ) \u2013 Number of workers for data loading. Defaults to 8. drop_unexpressed ( bool , default: False ) \u2013 Whether to drop unexpressed genes. Defaults to False. num_genes ( int , default: 3000 ) \u2013 Number of genes to consider. Defaults to 3000. precision ( str , default: '16-mixed' ) \u2013 Precision type for computations. Defaults to \"16-mixed\". cell_type_col ( str , default: 'cell_type' ) \u2013 Column name for cell type information. Defaults to \"cell_type\". how ( str , default: 'random expr' ) \u2013 Method to select genes. Options are \"random expr\", \"most var within\", \"most var across\", \"given\". Defaults to \"random expr\". preprocess ( str , default: 'softmax' ) \u2013 Preprocessing method. Options are \"softmax\", \"sinkhorn\", \"none\". Defaults to \"softmax\". head_agg ( str , default: 'mean' ) \u2013 Aggregation method for heads. Options are \"mean\", \"sum\", \"none\". Defaults to \"mean\". filtration ( str , default: 'thresh' ) \u2013 Filtration method for the adjacency matrix. Options are \"thresh\", \"top-k\", \"mst\", \"known\", \"none\". Defaults to \"thresh\". k ( int , default: 10 ) \u2013 Number of top connections to keep if filtration is \"top-k\". Defaults to 10. apc ( bool , default: False ) \u2013 Whether to apply Average Product Correction. Defaults to False. known_grn ( optional , default: None ) \u2013 Known gene regulatory network to use as a reference. Defaults to None. symmetrize ( bool , default: False ) \u2013 Whether to symmetrize the adjacency matrix. Defaults to False. doplot ( bool , default: True ) \u2013 Whether to generate plots. Defaults to True. max_cells ( int , default: 0 ) \u2013 Maximum number of cells to consider. Defaults to 0. forward_mode ( str , default: 'none' ) \u2013 Mode for forward pass. Defaults to \"none\". genes ( list , default: [] ) \u2013 List of genes to consider. Defaults to an empty list. loc ( str , default: './' ) \u2013 Location to save results. Defaults to \"./\". dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. locname ( str , default: '' ) \u2013 Name for the location. Defaults to an empty string. Source code in scprint/tasks/grn.py 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 def __init__ ( self , layer : Optional [ List [ int ]] = None , batch_size : int = 64 , num_workers : int = 8 , drop_unexpressed : bool = False , num_genes : int = 3000 , precision : str = \"16-mixed\" , cell_type_col : str = \"cell_type\" , how : str = \"random expr\" , # random expr, most var within, most var across, given preprocess : str = \"softmax\" , # sinkhorn, softmax, none head_agg : str = \"mean\" , # mean, sum, none filtration : str = \"thresh\" , # thresh, top-k, mst, known, none k : int = 10 , apc : bool = False , known_grn : Optional [ any ] = None , symmetrize : bool = False , doplot : bool = True , max_cells : int = 0 , forward_mode : str = \"none\" , genes : List [ str ] = [], loc : str = \"./\" , dtype : torch . dtype = torch . float16 , devices : List [ int ] = [ 0 ], locname : str = \"\" , ): \"\"\" GNInfer a class to infer gene regulatory networks from a dataset using a scPRINT model. Args: layer (Optional[list[int]], optional): List of layers to use for the inference. Defaults to None. batch_size (int, optional): Batch size for processing. Defaults to 64. num_workers (int, optional): Number of workers for data loading. Defaults to 8. drop_unexpressed (bool, optional): Whether to drop unexpressed genes. Defaults to False. num_genes (int, optional): Number of genes to consider. Defaults to 3000. precision (str, optional): Precision type for computations. Defaults to \"16-mixed\". cell_type_col (str, optional): Column name for cell type information. Defaults to \"cell_type\". how (str, optional): Method to select genes. Options are \"random expr\", \"most var within\", \"most var across\", \"given\". Defaults to \"random expr\". preprocess (str, optional): Preprocessing method. Options are \"softmax\", \"sinkhorn\", \"none\". Defaults to \"softmax\". head_agg (str, optional): Aggregation method for heads. Options are \"mean\", \"sum\", \"none\". Defaults to \"mean\". filtration (str, optional): Filtration method for the adjacency matrix. Options are \"thresh\", \"top-k\", \"mst\", \"known\", \"none\". Defaults to \"thresh\". k (int, optional): Number of top connections to keep if filtration is \"top-k\". Defaults to 10. apc (bool, optional): Whether to apply Average Product Correction. Defaults to False. known_grn (optional): Known gene regulatory network to use as a reference. Defaults to None. symmetrize (bool, optional): Whether to symmetrize the adjacency matrix. Defaults to False. doplot (bool, optional): Whether to generate plots. Defaults to True. max_cells (int, optional): Maximum number of cells to consider. Defaults to 0. forward_mode (str, optional): Mode for forward pass. Defaults to \"none\". genes (list, optional): List of genes to consider. Defaults to an empty list. loc (str, optional): Location to save results. Defaults to \"./\". dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. devices (List[int], optional): List of device IDs to use. Defaults to [0]. locname (str, optional): Name for the location. Defaults to an empty string. \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . layer = layer self . locname = locname self . how = how assert self . how in [ \"most var within\" , \"most var across\" , \"random expr\" , \"given\" , ], \"how must be one of 'most var within', 'most var across', 'random expr', 'given'\" self . num_genes = num_genes self . preprocess = preprocess self . cell_type_col = cell_type_col self . filtration = filtration self . doplot = doplot self . genes = genes self . apc = apc self . dtype = dtype self . forward_mode = forward_mode self . k = k self . symmetrize = symmetrize self . known_grn = known_grn self . head_agg = head_agg self . max_cells = max_cells self . curr_genes = None self . drop_unexpressed = drop_unexpressed self . precision = precision __call__ call runs the method Parameters: model ( Module ) \u2013 The model to be used for generating the network adata ( AnnData ) \u2013 Annotated data matrix of shape n_obs \u00d7 n_vars . n_obs is the number of cells and n_vars is the number of genes. cell_type ( str , default: None ) \u2013 Specific cell type to filter the data. Defaults to None. Returns: AnnData \u2013 Annotated data matrix with predictions and annotations. \u2013 np.ndarray: Filtered adjacency matrix. Source code in scprint/tasks/grn.py 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 def __call__ ( self , model : torch . nn . Module , adata : AnnData , cell_type = None ): \"\"\" __call__ runs the method Args: model (torch.nn.Module): The model to be used for generating the network adata (AnnData): Annotated data matrix of shape `n_obs` \u00d7 `n_vars`. `n_obs` is the number of cells and `n_vars` is the number of genes. cell_type (str, optional): Specific cell type to filter the data. Defaults to None. Returns: AnnData: Annotated data matrix with predictions and annotations. np.ndarray: Filtered adjacency matrix. \"\"\" # Add at least the organism you are working with if self . layer is None : self . layer = list ( range ( model . nlayers )) subadata = self . predict ( model , adata , self . layer , cell_type ) adjacencies = self . aggregate ( model . attn . get (), model . genes ) if self . head_agg == \"none\" : return self . save ( adjacencies [ 8 :, 8 :, :], subadata ) else : return self . save ( self . filter ( adjacencies )[ 8 :, 8 :], subadata ) default_benchmark default_benchmark function to run the default scPRINT GRN benchmark Parameters: model ( Any ) \u2013 The scPRINT model to be used for the benchmark. default_dataset ( str , default: 'sroy' ) \u2013 The default dataset to use for benchmarking. Defaults to \"sroy\". cell_types ( List [ str ] , default: ['kidney distal convoluted tubule epithelial cell', 'kidney loop of Henle thick ascending limb epithelial cell', 'kidney collecting duct principal cell', 'mesangial cell', 'blood vessel smooth muscle cell', 'podocyte', 'macrophage', 'leukocyte', 'kidney interstitial fibroblast', 'endothelial cell'] ) \u2013 List of cell types to include in the benchmark. Defaults to [ \"kidney distal convoluted tubule epithelial cell\", \"kidney loop of Henle thick ascending limb epithelial cell\", \"kidney collecting duct principal cell\", \"mesangial cell\", \"blood vessel smooth muscle cell\", \"podocyte\", \"macrophage\", \"leukocyte\", \"kidney interstitial fibroblast\", \"endothelial cell\", maxlayers ( int , default: 16 ) \u2013 Maximum number of layers to use from the model. Defaults to 16. maxgenes ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. batch_size ( int , default: 32 ) \u2013 Batch size for processing. Defaults to 32. maxcells ( int , default: 1024 ) \u2013 Maximum number of cells to consider. Defaults to 1024. Returns: dict \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/grn.py 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 def default_benchmark ( model : Any , default_dataset : str = \"sroy\" , cell_types : List [ str ] = [ \"kidney distal convoluted tubule epithelial cell\" , \"kidney loop of Henle thick ascending limb epithelial cell\" , \"kidney collecting duct principal cell\" , \"mesangial cell\" , \"blood vessel smooth muscle cell\" , \"podocyte\" , \"macrophage\" , \"leukocyte\" , \"kidney interstitial fibroblast\" , \"endothelial cell\" , ], maxlayers : int = 16 , maxgenes : int = 5000 , batch_size : int = 32 , maxcells : int = 1024 , ): \"\"\" default_benchmark function to run the default scPRINT GRN benchmark Args: model (Any): The scPRINT model to be used for the benchmark. default_dataset (str, optional): The default dataset to use for benchmarking. Defaults to \"sroy\". cell_types (List[str], optional): List of cell types to include in the benchmark. Defaults to [ \"kidney distal convoluted tubule epithelial cell\", \"kidney loop of Henle thick ascending limb epithelial cell\", \"kidney collecting duct principal cell\", \"mesangial cell\", \"blood vessel smooth muscle cell\", \"podocyte\", \"macrophage\", \"leukocyte\", \"kidney interstitial fibroblast\", \"endothelial cell\", ]. maxlayers (int, optional): Maximum number of layers to use from the model. Defaults to 16. maxgenes (int, optional): Maximum number of genes to consider. Defaults to 5000. batch_size (int, optional): Batch size for processing. Defaults to 32. maxcells (int, optional): Maximum number of cells to consider. Defaults to 1024. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" metrics = {} layers = list ( range ( model . nlayers ))[ max ( 0 , model . nlayers - maxlayers ) :] clf_omni = None if default_dataset == \"sroy\" : preprocessor = Preprocessor ( is_symbol = True , force_preprocess = True , skip_validate = True , do_postp = False , min_valid_genes_id = 5000 , min_dataset_size = 64 , ) clf_self = None todo = [ ( \"han\" , \"human\" , \"full\" ), ( \"mine\" , \"human\" , \"full\" ), ( \"han\" , \"human\" , \"chip\" ), ( \"han\" , \"human\" , \"ko\" ), ( \"tran\" , \"mouse\" , \"full\" ), ( \"zhao\" , \"mouse\" , \"full\" ), ( \"tran\" , \"mouse\" , \"chip\" ), ( \"tran\" , \"mouse\" , \"ko\" ), ] for da , spe , gt in todo : if gt != \"full\" : continue print ( da + \"_\" + gt ) preadata = get_sroy_gt ( get = da , species = spe , gt = gt ) adata = preprocessor ( preadata . copy ()) grn_inferer = GNInfer ( layer = layers , how = \"most var within\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_genes = maxgenes , num_workers = 8 , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata ) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . var [ \"ensembl_id\" ] = grn . var . index grn . var [ \"symbol\" ] = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T if spe == \"human\" : metrics [ \"mean_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () ## OMNI if clf_omni is None : grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.9 , class_weight = { 1 : 800 , 0 : 1 }, shuffle = True , return_full = False , ) joblib . dump ( clf_omni , \"clf_omni.pkl\" ) metrics [ \"omni_classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) if spe == \"human\" : metrics [ \"omni_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = True ) . scprint_benchmark () grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"omni_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) ## SELF if clf_self is None : grn . varp [ \"GRN\" ] = np . transpose ( grn . varp [ \"all\" ], ( 1 , 0 , 2 )) _ , m , clf_self = train_classifier ( grn , other = preadata , C = 1 , train_size = 0.5 , class_weight = { 1 : 40 , 0 : 1 }, shuffle = False , return_full = False , ) metrics [ \"self_classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"self_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) if spe == \"human\" : grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"self_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = True ) . scprint_benchmark () ## chip / ko if ( da , spe , \"chip\" ) in todo : preadata = get_sroy_gt ( get = da , species = spe , gt = \"chip\" ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"omni_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"self_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) if ( da , spe , \"ko\" ) in todo : preadata = get_sroy_gt ( get = da , species = spe , gt = \"ko\" ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"omni_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"self_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) del grn elif default_dataset == \"gwps\" : if not os . path . exists ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ): adata = get_perturb_gt () adata . write_h5ad ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ) else : adata = read_h5ad ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ) preprocessor = Preprocessor ( force_preprocess = True , skip_validate = True , do_postp = False , min_valid_genes_id = maxgenes , min_dataset_size = 64 , ) nadata = preprocessor ( adata . copy ()) adata . var [ \"isTF\" ] = False adata . var . loc [ adata . var . gene_name . isin ( grnutils . TF ), \"isTF\" ] = True adata . var [ \"isTF\" ] . sum () grn_inferer = GNInfer ( layer = layers , how = \"most var within\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_genes = maxgenes , max_cells = maxcells , doplot = False , num_workers = 8 , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , nadata ) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) grn . var [ \"ensembl_id\" ] = grn . var . index grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) metrics [ \"mean_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] grn . var . index = grn . var [ \"ensembl_id\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.9 , class_weight = { 1 : 800 , 0 : 1 }, shuffle = True , doplot = False , return_full = False , use_col = \"gene_name\" , ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"omni\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) metrics [ \"omni_classifier\" ] = m grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"omni_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () grn . varp [ \"GRN\" ] = np . transpose ( grn . varp [ \"all\" ], ( 1 , 0 , 2 )) grn . var . index = grn . var [ \"ensembl_id\" ] _ , m , clf_self = train_classifier ( grn , other = adata , C = 1 , train_size = 0.5 , class_weight = { 1 : 40 , 0 : 1 }, doplot = False , shuffle = False , return_full = False , use_col = \"ensembl_id\" , ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"self\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) metrics [ \"self_classifier\" ] = m grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"self_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () else : # max_genes=4000 adata = sc . read_h5ad ( default_dataset ) adata . var [ \"isTF\" ] = False adata . var . loc [ adata . var . symbol . isin ( grnutils . TF ), \"isTF\" ] = True for celltype in cell_types : print ( celltype ) grn_inferer = GNInfer ( layer = layers , how = \"random expr\" , preprocess = \"softmax\" , head_agg = \"max\" , filtration = \"none\" , forward_mode = \"none\" , num_workers = 8 , num_genes = 2200 , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata [ adata . X . sum ( 1 ) > 500 ], cell_type = celltype ) grn . var . index = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) metrics [ celltype + \"_scprint\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () del grn gc . collect () grn_inferer = GNInfer ( layer = layers , how = \"most var across\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_workers = 8 , num_genes = maxgenes , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata [ adata . X . sum ( 1 ) > 500 ], cell_type = celltype ) grn . var . index = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . mean ( - 1 ) metrics [ celltype + \"_scprint_mean\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () if clf_omni is None : grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.6 , max_iter = 300 , class_weight = { 1 : 800 , 0 : 1 }, return_full = False , shuffle = True , doplot = False , ) joblib . dump ( clf_omni , \"clf_omni.pkl\" ) metrics [ \"classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) metrics [ celltype + \"_scprint_class\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () del grn gc . collect () return metrics scprint.tasks.denoise Denoiser Denoiser class for denoising scRNA-seq data using a scPRINT model Parameters: batch_size ( int , default: 10 ) \u2013 Batch size for processing. Defaults to 10. num_workers ( int , default: 1 ) \u2013 Number of workers for data loading. Defaults to 1. max_len ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. precision ( str , default: '16-mixed' ) \u2013 Precision type for computations. Defaults to \"16-mixed\". how ( str , default: 'most var' ) \u2013 Method to select genes. Options are \"most var\". Defaults to \"most var\". plot_corr_size ( int , default: 10000 ) \u2013 Number of cells to use for plotting correlation. Defaults to 10000. doplot ( bool , default: False ) \u2013 Whether to generate plots. Defaults to False. predict_depth_mult ( int , default: 4 ) \u2013 Multiplier for prediction depth. Defaults to 4. downsample ( Optional [ float ] , default: None ) \u2013 Fraction of data to downsample. Defaults to None. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. Source code in scprint/tasks/denoise.py 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 def __init__ ( self , batch_size : int = 10 , num_workers : int = 1 , max_len : int = 5_000 , precision : str = \"16-mixed\" , how : str = \"most var\" , plot_corr_size : int = 10_000 , doplot : bool = False , predict_depth_mult : int = 4 , downsample : Optional [ float ] = None , devices : List [ int ] = [ 0 ], dtype : torch . dtype = torch . float16 , ): \"\"\" Denoiser class for denoising scRNA-seq data using a scPRINT model Args: batch_size (int, optional): Batch size for processing. Defaults to 10. num_workers (int, optional): Number of workers for data loading. Defaults to 1. max_len (int, optional): Maximum number of genes to consider. Defaults to 5000. precision (str, optional): Precision type for computations. Defaults to \"16-mixed\". how (str, optional): Method to select genes. Options are \"most var\". Defaults to \"most var\". plot_corr_size (int, optional): Number of cells to use for plotting correlation. Defaults to 10000. doplot (bool, optional): Whether to generate plots. Defaults to False. predict_depth_mult (int, optional): Multiplier for prediction depth. Defaults to 4. downsample (Optional[float], optional): Fraction of data to downsample. Defaults to None. devices (List[int], optional): List of device IDs to use. Defaults to [0]. dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . max_len = max_len self . plot_corr_size = plot_corr_size self . doplot = doplot self . predict_depth_mult = predict_depth_mult self . how = how self . downsample = downsample self . precision = precision self . dtype = dtype __call__ call calling the function Parameters: model ( Module ) \u2013 The scPRINT model to be used for denoising. adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. Returns: AnnData \u2013 The denoised annotated data matrix. Source code in scprint/tasks/denoise.py 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 def __call__ ( self , model : torch . nn . Module , adata : AnnData ): \"\"\" __call__ calling the function Args: model (torch.nn.Module): The scPRINT model to be used for denoising. adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. Returns: AnnData: The denoised annotated data matrix. \"\"\" if os . path . exists ( \"collator_output.txt\" ): os . remove ( \"collator_output.txt\" ) random_indices = None if self . plot_corr_size < adata . shape [ 0 ]: random_indices = np . random . randint ( low = 0 , high = adata . shape [ 0 ], size = self . plot_corr_size ) adataset = SimpleAnnDataset ( adata [ random_indices ], obs_to_output = [ \"organism_ontology_term_id\" ] ) else : adataset = SimpleAnnDataset ( adata , obs_to_output = [ \"organism_ontology_term_id\" ] ) if self . how == \"most var\" : sc . pp . highly_variable_genes ( adata , flavor = \"seurat_v3\" , n_top_genes = self . max_len , span = 0.99 ) genelist = adata . var . index [ adata . var . highly_variable ] print ( len ( genelist )) col = Collator ( organisms = model . organisms , valid_genes = model . genes , max_len = self . max_len , how = \"some\" if self . how == \"most var\" else self . how , genelist = genelist if self . how == \"most var\" else [], downsample = self . downsample , save_output = True , ) dataloader = DataLoader ( adataset , collate_fn = col , batch_size = self . batch_size , num_workers = self . num_workers , shuffle = False , ) model . doplot = self . doplot model . on_predict_epoch_start () model . eval () device = model . device . type with torch . no_grad (), torch . autocast ( device_type = device , dtype = self . dtype ): for batch in tqdm ( dataloader ): gene_pos , expression , depth = ( batch [ \"genes\" ] . to ( device ), batch [ \"x\" ] . to ( device ), batch [ \"depth\" ] . to ( device ), ) model . _predict ( gene_pos , expression , depth , predict_mode = \"denoise\" , depth_mult = self . predict_depth_mult , ) torch . cuda . empty_cache () self . genes = ( model . pos . cpu () . numpy () if self . how != \"most var\" else list ( set ( model . genes ) & set ( genelist )) ) tokeep = None metrics = None if self . downsample is not None : reco = model . expr_pred [ 0 ] reco = reco . cpu () . numpy () tokeep = np . isnan ( reco ) . sum ( 1 ) == 0 reco = reco [ tokeep ] noisy = np . loadtxt ( \"collator_output.txt\" )[ tokeep ] if random_indices is not None : true = adata . X [ random_indices ][ tokeep ] else : true = adata . X [ tokeep ] true = true . toarray () if issparse ( true ) else true if self . how == \"most var\" : true = true [:, adata . var . index . isin ( self . genes )] # noisy[true==0]=0 else : true = np . vstack ( [ true [ i , adata . var . index . get_indexer ( np . array ( model . genes )[ val ]), ] . copy () for i , val in enumerate ( self . genes ) ] ) # reco[true==0] = 0 # import pdb # pdb.set_trace() # reco[reco!=0] = 2 # corr_coef = np.corrcoef( # np.vstack([reco[true!=0], noisy[true!=0], true[true!=0]]) # ) corr_coef , p_value = spearmanr ( np . vstack ([ reco [ true != 0 ], noisy [ true != 0 ], true [ true != 0 ]]) . T ) metrics = { \"reco2noisy\" : corr_coef [ 0 , 1 ], \"reco2full\" : corr_coef [ 0 , 2 ], \"noisy2full\" : corr_coef [ 1 , 2 ], } # corr_coef[p_value > 0.05] = 0 # if self.doplot: # plt.figure(figsize=(10, 5)) # plt.imshow( # corr_coef, cmap=\"coolwarm\", interpolation=\"none\", vmin=-1, vmax=1 # ) # plt.colorbar() # plt.title(\"Expression Correlation Coefficient\") # plt.show() # metrics = { # \"reco2noisy\": np.mean( # corr_coef[ # self.plot_corr_size : self.plot_corr_size * 2, : self.plot_corr_size # ].diagonal() # ), # \"reco2full\": np.mean( # corr_coef[self.plot_corr_size * 2 :, : self.plot_corr_size].diagonal() # ), # \"noisy2full\": np.mean( # corr_coef[ # self.plot_corr_size * 2 :, # self.plot_corr_size : self.plot_corr_size * 2, # ].diagonal() # ), # } return ( metrics , ( random_indices [ tokeep ] if random_indices is not None and tokeep is not None else random_indices ), self . genes , ( model . expr_pred [ 0 ][ tokeep ] . cpu () . numpy () if tokeep is not None else model . expr_pred [ 0 ] . cpu () . numpy () ), ) default_benchmark default_benchmark function used to run the default denoising benchmark of scPRINT Parameters: model ( Any ) \u2013 The scPRINT model to be used for the benchmark. default_dataset ( str , default: FILE_DIR + '/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad' ) \u2013 Path to the default dataset to use for benchmarking. Defaults to FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\". max_len ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. Returns: dict \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/denoise.py 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 def default_benchmark ( model : Any , default_dataset : str = FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\" , max_len : int = 5000 , ): \"\"\" default_benchmark function used to run the default denoising benchmark of scPRINT Args: model (Any): The scPRINT model to be used for the benchmark. default_dataset (str, optional): Path to the default dataset to use for benchmarking. Defaults to FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\". max_len (int, optional): Maximum number of genes to consider. Defaults to 5000. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" adata = sc . read_h5ad ( default_dataset ) denoise = Denoiser ( model , batch_size = 40 , max_len = max_len , plot_corr_size = 10_000 , doplot = False , num_workers = 8 , predict_depth_mult = 10 , downsample = 0.7 , devices = 1 , ) return denoise ( adata )[ 0 ] split_molecules Splits molecules into two (potentially overlapping) groups. :param umis: Array of molecules to split :param data_split: Proportion of molecules to assign to the first group :param overlap_factor: Overlap correction factor, if desired :param random_state: For reproducible sampling :return: umis_X and umis_Y, representing split and ~(1 - split) counts sampled from the input array Source code in scprint/tasks/denoise.py 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 def split_molecules ( umis : np . ndarray , data_split : float , overlap_factor : float = 0.0 , random_state : np . random . RandomState = None , ) -> Tuple [ np . ndarray , np . ndarray ]: \"\"\"Splits molecules into two (potentially overlapping) groups. :param umis: Array of molecules to split :param data_split: Proportion of molecules to assign to the first group :param overlap_factor: Overlap correction factor, if desired :param random_state: For reproducible sampling :return: umis_X and umis_Y, representing ``split`` and ``~(1 - split)`` counts sampled from the input array \"\"\" if random_state is None : random_state = np . random . RandomState () umis_X_disjoint = random_state . binomial ( umis , data_split - overlap_factor ) umis_Y_disjoint = random_state . binomial ( umis - umis_X_disjoint , ( 1 - data_split ) / ( 1 - data_split + overlap_factor ) ) overlap_factor = umis - umis_X_disjoint - umis_Y_disjoint umis_X = umis_X_disjoint + overlap_factor umis_Y = umis_Y_disjoint + overlap_factor return umis_X , umis_Y","title":"tasks"},{"location":"tasks/#documentation-for-the-tasks","text":"","title":"Documentation for the tasks"},{"location":"tasks/#scprint.tasks.cell_emb","text":"","title":"cell_emb"},{"location":"tasks/#scprint.tasks.cell_emb.Embedder","text":"Embedder a class to embed and annotate cells using a model Parameters: batch_size ( int , default: 64 ) \u2013 The size of the batches to be used in the DataLoader. Defaults to 64. num_workers ( int , default: 8 ) \u2013 The number of worker processes to use for data loading. Defaults to 8. how ( str , default: 'random expr' ) \u2013 The method to be used for selecting valid genes. Defaults to \"most expr\". max_len ( int , default: 2000 ) \u2013 The maximum length of the gene sequence. Defaults to 1000. add_zero_genes ( int , default: 0 ) \u2013 The number of zero genes to add to the gene sequence. Defaults to 100. precision ( str , default: '16-mixed' ) \u2013 The precision to be used in the Trainer. Defaults to \"16-mixed\". pred_embedding ( List [ str ] , default: ['cell_type_ontology_term_id', 'disease_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'sex_ontology_term_id'] ) \u2013 The list of labels to be used for plotting embeddings. Defaults to [ \"cell_type_ontology_term_id\", \"disease_ontology_term_id\", \"self_reported_ethnicity_ontology_term_id\", \"sex_ontology_term_id\", ]. doclass ( bool , default: True ) \u2013 Whether to perform classification. Defaults to True. doplot ( bool , default: True ) \u2013 Whether to generate plots. Defaults to True. keep_all_cls_pred ( bool , default: False ) \u2013 Whether to keep all class predictions. Defaults to False. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. output_expression ( str , default: 'none' ) \u2013 The method to output expression data. Options are \"none\", \"all\", \"sample\". Defaults to \"none\". Source code in scprint/tasks/cell_emb.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 def __init__ ( self , batch_size : int = 64 , num_workers : int = 8 , how : str = \"random expr\" , max_len : int = 2000 , doclass : bool = True , add_zero_genes : int = 0 , precision : str = \"16-mixed\" , pred_embedding : List [ str ] = [ \"cell_type_ontology_term_id\" , \"disease_ontology_term_id\" , \"self_reported_ethnicity_ontology_term_id\" , \"sex_ontology_term_id\" , ], plot_corr_size : int = 64 , doplot : bool = True , keep_all_cls_pred : bool = False , devices : List [ int ] = [ 0 ], dtype : torch . dtype = torch . float16 , output_expression : str = \"none\" , ): \"\"\" Embedder a class to embed and annotate cells using a model Args: batch_size (int, optional): The size of the batches to be used in the DataLoader. Defaults to 64. num_workers (int, optional): The number of worker processes to use for data loading. Defaults to 8. how (str, optional): The method to be used for selecting valid genes. Defaults to \"most expr\". max_len (int, optional): The maximum length of the gene sequence. Defaults to 1000. add_zero_genes (int, optional): The number of zero genes to add to the gene sequence. Defaults to 100. precision (str, optional): The precision to be used in the Trainer. Defaults to \"16-mixed\". pred_embedding (List[str], optional): The list of labels to be used for plotting embeddings. Defaults to [ \"cell_type_ontology_term_id\", \"disease_ontology_term_id\", \"self_reported_ethnicity_ontology_term_id\", \"sex_ontology_term_id\", ]. doclass (bool, optional): Whether to perform classification. Defaults to True. doplot (bool, optional): Whether to generate plots. Defaults to True. keep_all_cls_pred (bool, optional): Whether to keep all class predictions. Defaults to False. devices (List[int], optional): List of device IDs to use. Defaults to [0]. dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. output_expression (str, optional): The method to output expression data. Options are \"none\", \"all\", \"sample\". Defaults to \"none\". \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . how = how self . max_len = max_len self . add_zero_genes = add_zero_genes self . pred_embedding = pred_embedding self . keep_all_cls_pred = keep_all_cls_pred self . plot_corr_size = plot_corr_size self . precision = precision self . doplot = doplot self . doclass = doclass self . trainer = Trainer ( precision = precision , devices = devices ) self . output_expression = output_expression","title":"Embedder"},{"location":"tasks/#scprint.tasks.cell_emb.Embedder.__call__","text":"call function to call the embedding Parameters: model ( Module ) \u2013 The scPRINT model to be used for embedding and annotation. adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. cache ( bool , default: False ) \u2013 Whether to use cached results if available. Defaults to False. Raises: ValueError \u2013 If the model does not have a logger attribute. ValueError \u2013 If the model does not have a global_step attribute. Returns: AnnData \u2013 The annotated data matrix with embedded cell representations. \u2013 List[str]: List of gene names used in the embedding. \u2013 np.ndarray: The predicted expression values if output_expression is not \"none\". dict \u2013 Additional metrics and information from the embedding process. Source code in scprint/tasks/cell_emb.py 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 def __call__ ( self , model : torch . nn . Module , adata : AnnData , cache = False ): \"\"\" __call__ function to call the embedding Args: model (torch.nn.Module): The scPRINT model to be used for embedding and annotation. adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. cache (bool, optional): Whether to use cached results if available. Defaults to False. Raises: ValueError: If the model does not have a logger attribute. ValueError: If the model does not have a global_step attribute. Returns: AnnData: The annotated data matrix with embedded cell representations. List[str]: List of gene names used in the embedding. np.ndarray: The predicted expression values if output_expression is not \"none\". dict: Additional metrics and information from the embedding process. \"\"\" # one of \"all\" \"sample\" \"none\" try : mdir = ( model . logger . save_dir if model . logger . save_dir is not None else \"data\" ) except : mdir = \"data\" try : file = ( mdir + \"/step_\" + str ( model . global_step ) + \"_predict_part_\" + str ( model . counter ) + \"_\" + str ( model . global_rank ) + \".h5ad\" ) hasfile = os . path . exists ( file ) except : hasfile = False if not cache or not hasfile : model . predict_mode = \"none\" model . keep_all_cls_pred = self . keep_all_cls_pred # Add at least the organism you are working with if self . how == \"most var\" : sc . pp . highly_variable_genes ( adata , flavor = \"seurat_v3\" , n_top_genes = self . max_len ) curr_genes = adata . var . index [ adata . var . highly_variable ] adataset = SimpleAnnDataset ( adata , obs_to_output = [ \"organism_ontology_term_id\" ] ) col = Collator ( organisms = model . organisms , valid_genes = model . genes , how = self . how if self . how != \"most var\" else \"some\" , max_len = self . max_len , add_zero_genes = self . add_zero_genes , genelist = [] if self . how != \"most var\" else curr_genes , ) dataloader = DataLoader ( adataset , collate_fn = col , batch_size = self . batch_size , num_workers = self . num_workers , shuffle = False , ) model . eval () model . on_predict_epoch_start () device = model . device . type model . doplot = self . doplot with torch . no_grad (), torch . autocast ( device_type = device , dtype = torch . float16 ): for batch in tqdm ( dataloader ): gene_pos , expression , depth = ( batch [ \"genes\" ] . to ( device ), batch [ \"x\" ] . to ( device ), batch [ \"depth\" ] . to ( device ), ) model . _predict ( gene_pos , expression , depth , predict_mode = \"none\" , pred_embedding = self . pred_embedding , ) torch . cuda . empty_cache () model . log_adata ( name = \"predict_part_\" + str ( model . counter )) try : mdir = ( model . logger . save_dir if model . logger . save_dir is not None else \"data\" ) except : mdir = \"data\" file = ( mdir + \"/step_\" + str ( model . global_step ) + \"_\" + model . name + \"_predict_part_\" + str ( model . counter ) + \"_\" + str ( model . global_rank ) + \".h5ad\" ) pred_adata = sc . read_h5ad ( file ) if self . output_expression == \"all\" : adata . obsm [ \"scprint_mu\" ] = model . expr_pred [ 0 ] adata . obsm [ \"scprint_theta\" ] = model . expr_pred [ 1 ] adata . obsm [ \"scprint_pi\" ] = model . expr_pred [ 2 ] adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () elif self . output_expression == \"sample\" : adata . obsm [ \"scprint_expr\" ] = ( utils . zinb_sample ( model . expr_pred [ 0 ], model . expr_pred [ 1 ], model . expr_pred [ 2 ], ) . cpu () . numpy () ) adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () elif self . output_expression == \"old\" : expr = np . array ( model . expr_pred [ 0 ]) expr [ np . random . binomial ( 1 , p = np . array ( torch . nn . functional . sigmoid ( model . expr_pred [ 2 ] . to ( torch . float32 ) ) ), ) . astype ( bool ) ] = 0 expr [ expr <= 0.3 ] = 0 expr [( expr >= 0.3 ) & ( expr <= 1 )] = 1 adata . obsm [ \"scprint_expr\" ] = expr . astype ( int ) adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () else : pass pred_adata . obs . index = adata . obs . index adata . obsm [ \"scprint_umap\" ] = pred_adata . obsm [ \"X_umap\" ] # adata.obsm[\"scprint_leiden\"] = pred_adata.obsm[\"leiden\"] adata . obsm [ \"scprint\" ] = pred_adata . X pred_adata . obs . index = adata . obs . index adata . obs = pd . concat ([ adata . obs , pred_adata . obs ], axis = 1 ) if self . keep_all_cls_pred : allclspred = model . pred columns = [] for cl in model . classes : n = model . label_counts [ cl ] columns += [ model . label_decoders [ cl ][ i ] for i in range ( n )] allclspred = pd . DataFrame ( allclspred , columns = columns , index = adata . obs . index ) adata . obs = pd . concat ( adata . obs , allclspred ) metrics = {} if self . doclass and not self . keep_all_cls_pred : for cl in model . classes : res = [] if cl not in adata . obs . columns : continue class_topred = model . label_decoders [ cl ] . values () if cl in model . labels_hierarchy : # class_groupings = { # k: [ # i.ontology_id # for i in bt.CellType.filter(k).first().children.all() # ] # for k in set(adata.obs[cl].unique()) - set(class_topred) # } cur_labels_hierarchy = { model . label_decoders [ cl ][ k ]: [ model . label_decoders [ cl ][ i ] for i in v ] for k , v in model . labels_hierarchy [ cl ] . items () } else : cur_labels_hierarchy = {} for pred , true in adata . obs [[ \"pred_\" + cl , cl ]] . values : if pred == true : res . append ( True ) continue if len ( cur_labels_hierarchy ) > 0 : if true in cur_labels_hierarchy : res . append ( pred in cur_labels_hierarchy [ true ]) continue elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) # else true is unknown # else we pass if len ( res ) == 0 : # true was always unknown res = [ 1 ] if self . doplot : print ( \" \" , cl ) print ( \" accuracy:\" , sum ( res ) / len ( res )) print ( \" \" ) metrics . update ({ cl + \"_accuracy\" : sum ( res ) / len ( res )}) # m = self.compute_reconstruction(adata, plot_corr_size=self.plot_corr_size) # metrics.update(m) return adata , metrics","title":"__call__"},{"location":"tasks/#scprint.tasks.cell_emb.compute_classification","text":"Compute classification metrics for the given annotated data. Parameters: adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. classes ( List [ str ] ) \u2013 List of class labels to be used for classification. label_decoders ( Dict [ str , Any ] ) \u2013 Dictionary of label decoders for each class. labels_hierarchy ( Dict [ str , Any ] ) \u2013 Dictionary representing the hierarchy of labels. metric_type ( List [ str ] , default: ['macro', 'micro', 'weighted'] ) \u2013 List of metric types to compute. Defaults to [\"macro\", \"micro\", \"weighted\"]. Returns: Dict [ str , Dict [ str , float ]] \u2013 Dict[str, Dict[str, float]]: A dictionary containing classification metrics for each class. Source code in scprint/tasks/cell_emb.py 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 def compute_classification ( adata : AnnData , classes : List [ str ], label_decoders : Dict [ str , Any ], labels_hierarchy : Dict [ str , Any ], metric_type : List [ str ] = [ \"macro\" , \"micro\" , \"weighted\" ], ) -> Dict [ str , Dict [ str , float ]]: \"\"\" Compute classification metrics for the given annotated data. Args: adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. classes (List[str]): List of class labels to be used for classification. label_decoders (Dict[str, Any]): Dictionary of label decoders for each class. labels_hierarchy (Dict[str, Any]): Dictionary representing the hierarchy of labels. metric_type (List[str], optional): List of metric types to compute. Defaults to [\"macro\", \"micro\", \"weighted\"]. Returns: Dict[str, Dict[str, float]]: A dictionary containing classification metrics for each class. \"\"\" metrics = {} for label in classes : res = [] if label not in adata . obs . columns : continue labels_topred = label_decoders [ label ] . values () if label in labels_hierarchy : parentdf = ( bt . CellType . filter () . df ( include = [ \"parents__ontology_id\" ]) . set_index ( \"ontology_id\" )[[ \"parents__ontology_id\" ]] ) parentdf . parents__ontology_id = parentdf . parents__ontology_id . astype ( str ) class_groupings = { k : get_descendants ( k , parentdf ) for k in set ( adata . obs [ label ] . unique ()) } for pred , true in adata . obs [[ \"pred_\" + label , label ]] . values : if pred == true : res . append ( true ) continue if label in labels_hierarchy : if true in class_groupings : res . append ( true if pred in class_groupings [ true ] else \"\" ) continue elif true not in labels_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true not in labels_topred : raise ValueError ( f \"true label { true } not in available classes\" ) res . append ( \"\" ) metrics [ label ] = {} metrics [ label ][ \"accuracy\" ] = np . mean ( np . array ( res ) == adata . obs [ label ] . values ) for x in metric_type : metrics [ label ][ x ] = f1_score ( np . array ( res ), adata . obs [ label ] . values , average = x ) return metrics","title":"compute_classification"},{"location":"tasks/#scprint.tasks.cell_emb.compute_corr","text":"Compute the correlation between the output and target matrices. Parameters: out ( ndarray ) \u2013 The output matrix. to ( ndarray ) \u2013 The target matrix. doplot ( bool , default: True ) \u2013 Whether to generate a plot of the correlation coefficients. Defaults to True. compute_mean_regress ( bool , default: False ) \u2013 Whether to compute mean regression. Defaults to False. plot_corr_size ( int , default: 64 ) \u2013 The size of the plot for correlation. Defaults to 64. Returns: dict ( dict ) \u2013 A dictionary containing the computed metrics. Source code in scprint/tasks/cell_emb.py 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 def compute_corr ( out : np . ndarray , to : np . ndarray , doplot : bool = True , compute_mean_regress : bool = False , plot_corr_size : int = 64 , ) -> dict : \"\"\" Compute the correlation between the output and target matrices. Args: out (np.ndarray): The output matrix. to (np.ndarray): The target matrix. doplot (bool, optional): Whether to generate a plot of the correlation coefficients. Defaults to True. compute_mean_regress (bool, optional): Whether to compute mean regression. Defaults to False. plot_corr_size (int, optional): The size of the plot for correlation. Defaults to 64. Returns: dict: A dictionary containing the computed metrics. \"\"\" metrics = {} corr_coef , p_value = spearmanr ( out , to . T , ) corr_coef [ p_value > 0.05 ] = 0 # corr_coef[] # only on non zero values, # compare a1-b1 corr with a1-b(n) corr. should be higher # Plot correlation coefficient val = plot_corr_size + 2 if compute_mean_regress else plot_corr_size metrics . update ( { \"recons_corr\" : np . mean ( corr_coef [ val :, : plot_corr_size ] . diagonal ())} ) if compute_mean_regress : metrics . update ( { \"mean_regress\" : np . mean ( corr_coef [ plot_corr_size : plot_corr_size + 2 , : plot_corr_size , ] . flatten () ) } ) if doplot : plt . figure ( figsize = ( 10 , 5 )) plt . imshow ( corr_coef , cmap = \"coolwarm\" , interpolation = \"none\" , vmin =- 1 , vmax = 1 ) plt . colorbar () plt . title ( 'Correlation Coefficient of expr and i[\"x\"]' ) plt . show () return metrics","title":"compute_corr"},{"location":"tasks/#scprint.tasks.cell_emb.default_benchmark","text":"Run the default benchmark for embedding and annotation using the scPRINT model. Parameters: model ( Module ) \u2013 The scPRINT model to be used for embedding and annotation. default_dataset ( str , default: 'pancreas' ) \u2013 The default dataset to use for benchmarking. Options are \"pancreas\", \"lung\", or a path to a dataset. Defaults to \"pancreas\". do_class ( bool , default: True ) \u2013 Whether to perform classification. Defaults to True. coarse ( bool , default: False ) \u2013 Whether to use coarse cell type annotations. Defaults to False. Returns: dict ( dict ) \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/cell_emb.py 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 def default_benchmark ( model : torch . nn . Module , default_dataset : str = \"pancreas\" , do_class : bool = True , coarse : bool = False , ) -> dict : \"\"\" Run the default benchmark for embedding and annotation using the scPRINT model. Args: model (torch.nn.Module): The scPRINT model to be used for embedding and annotation. default_dataset (str, optional): The default dataset to use for benchmarking. Options are \"pancreas\", \"lung\", or a path to a dataset. Defaults to \"pancreas\". do_class (bool, optional): Whether to perform classification. Defaults to True. coarse (bool, optional): Whether to use coarse cell type annotations. Defaults to False. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" if default_dataset == \"pancreas\" : adata = sc . read ( FILE_LOC + \"/../../data/pancreas_atlas.h5ad\" , backup_url = \"https://figshare.com/ndownloader/files/24539828\" , ) adata . obs [ \"cell_type_ontology_term_id\" ] = adata . obs [ \"celltype\" ] . replace ( COARSE if coarse else FINE ) adata . obs [ \"assay_ontology_term_id\" ] = adata . obs [ \"tech\" ] . replace ( COARSE if coarse else FINE ) elif default_dataset == \"lung\" : adata = sc . read ( FILE_LOC + \"/../../data/lung_atlas.h5ad\" , backup_url = \"https://figshare.com/ndownloader/files/24539942\" , ) adata . obs [ \"cell_type_ontology_term_id\" ] = adata . obs [ \"cell_type\" ] . replace ( COARSE if coarse else FINE ) else : adata = sc . read_h5ad ( default_dataset ) adata . obs [ \"batch\" ] = adata . obs [ \"assay_ontology_term_id\" ] adata . obs [ \"cell_type\" ] = adata . obs [ \"cell_type_ontology_term_id\" ] preprocessor = Preprocessor ( use_layer = \"counts\" , is_symbol = True , force_preprocess = True , skip_validate = True , do_postp = False , ) adata . obs [ \"organism_ontology_term_id\" ] = \"NCBITaxon:9606\" adata = preprocessor ( adata . copy ()) embedder = Embedder ( pred_embedding = [ \"cell_type_ontology_term_id\" ], doclass = ( default_dataset not in [ \"pancreas\" , \"lung\" ]), devices = 1 , ) embed_adata , metrics = embedder ( model , adata . copy ()) bm = Benchmarker ( embed_adata , batch_key = \"tech\" if default_dataset == \"pancreas\" else \"batch\" , label_key = \"celltype\" if default_dataset == \"pancreas\" else \"cell_type\" , embedding_obsm_keys = [ \"scprint\" ], n_jobs = 6 , ) bm . benchmark () metrics . update ({ \"scib\" : bm . get_results ( min_max_scale = False ) . T . to_dict ()[ \"scprint\" ]}) metrics [ \"classif\" ] = compute_classification ( embed_adata , model . classes , model . label_decoders , model . labels_hierarchy ) return metrics","title":"default_benchmark"},{"location":"tasks/#scprint.tasks.grn","text":"","title":"grn"},{"location":"tasks/#scprint.tasks.grn.GNInfer","text":"GNInfer a class to infer gene regulatory networks from a dataset using a scPRINT model. Parameters: layer ( Optional [ list [ int ]] , default: None ) \u2013 List of layers to use for the inference. Defaults to None. batch_size ( int , default: 64 ) \u2013 Batch size for processing. Defaults to 64. num_workers ( int , default: 8 ) \u2013 Number of workers for data loading. Defaults to 8. drop_unexpressed ( bool , default: False ) \u2013 Whether to drop unexpressed genes. Defaults to False. num_genes ( int , default: 3000 ) \u2013 Number of genes to consider. Defaults to 3000. precision ( str , default: '16-mixed' ) \u2013 Precision type for computations. Defaults to \"16-mixed\". cell_type_col ( str , default: 'cell_type' ) \u2013 Column name for cell type information. Defaults to \"cell_type\". how ( str , default: 'random expr' ) \u2013 Method to select genes. Options are \"random expr\", \"most var within\", \"most var across\", \"given\". Defaults to \"random expr\". preprocess ( str , default: 'softmax' ) \u2013 Preprocessing method. Options are \"softmax\", \"sinkhorn\", \"none\". Defaults to \"softmax\". head_agg ( str , default: 'mean' ) \u2013 Aggregation method for heads. Options are \"mean\", \"sum\", \"none\". Defaults to \"mean\". filtration ( str , default: 'thresh' ) \u2013 Filtration method for the adjacency matrix. Options are \"thresh\", \"top-k\", \"mst\", \"known\", \"none\". Defaults to \"thresh\". k ( int , default: 10 ) \u2013 Number of top connections to keep if filtration is \"top-k\". Defaults to 10. apc ( bool , default: False ) \u2013 Whether to apply Average Product Correction. Defaults to False. known_grn ( optional , default: None ) \u2013 Known gene regulatory network to use as a reference. Defaults to None. symmetrize ( bool , default: False ) \u2013 Whether to symmetrize the adjacency matrix. Defaults to False. doplot ( bool , default: True ) \u2013 Whether to generate plots. Defaults to True. max_cells ( int , default: 0 ) \u2013 Maximum number of cells to consider. Defaults to 0. forward_mode ( str , default: 'none' ) \u2013 Mode for forward pass. Defaults to \"none\". genes ( list , default: [] ) \u2013 List of genes to consider. Defaults to an empty list. loc ( str , default: './' ) \u2013 Location to save results. Defaults to \"./\". dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. locname ( str , default: '' ) \u2013 Name for the location. Defaults to an empty string. Source code in scprint/tasks/grn.py 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 def __init__ ( self , layer : Optional [ List [ int ]] = None , batch_size : int = 64 , num_workers : int = 8 , drop_unexpressed : bool = False , num_genes : int = 3000 , precision : str = \"16-mixed\" , cell_type_col : str = \"cell_type\" , how : str = \"random expr\" , # random expr, most var within, most var across, given preprocess : str = \"softmax\" , # sinkhorn, softmax, none head_agg : str = \"mean\" , # mean, sum, none filtration : str = \"thresh\" , # thresh, top-k, mst, known, none k : int = 10 , apc : bool = False , known_grn : Optional [ any ] = None , symmetrize : bool = False , doplot : bool = True , max_cells : int = 0 , forward_mode : str = \"none\" , genes : List [ str ] = [], loc : str = \"./\" , dtype : torch . dtype = torch . float16 , devices : List [ int ] = [ 0 ], locname : str = \"\" , ): \"\"\" GNInfer a class to infer gene regulatory networks from a dataset using a scPRINT model. Args: layer (Optional[list[int]], optional): List of layers to use for the inference. Defaults to None. batch_size (int, optional): Batch size for processing. Defaults to 64. num_workers (int, optional): Number of workers for data loading. Defaults to 8. drop_unexpressed (bool, optional): Whether to drop unexpressed genes. Defaults to False. num_genes (int, optional): Number of genes to consider. Defaults to 3000. precision (str, optional): Precision type for computations. Defaults to \"16-mixed\". cell_type_col (str, optional): Column name for cell type information. Defaults to \"cell_type\". how (str, optional): Method to select genes. Options are \"random expr\", \"most var within\", \"most var across\", \"given\". Defaults to \"random expr\". preprocess (str, optional): Preprocessing method. Options are \"softmax\", \"sinkhorn\", \"none\". Defaults to \"softmax\". head_agg (str, optional): Aggregation method for heads. Options are \"mean\", \"sum\", \"none\". Defaults to \"mean\". filtration (str, optional): Filtration method for the adjacency matrix. Options are \"thresh\", \"top-k\", \"mst\", \"known\", \"none\". Defaults to \"thresh\". k (int, optional): Number of top connections to keep if filtration is \"top-k\". Defaults to 10. apc (bool, optional): Whether to apply Average Product Correction. Defaults to False. known_grn (optional): Known gene regulatory network to use as a reference. Defaults to None. symmetrize (bool, optional): Whether to symmetrize the adjacency matrix. Defaults to False. doplot (bool, optional): Whether to generate plots. Defaults to True. max_cells (int, optional): Maximum number of cells to consider. Defaults to 0. forward_mode (str, optional): Mode for forward pass. Defaults to \"none\". genes (list, optional): List of genes to consider. Defaults to an empty list. loc (str, optional): Location to save results. Defaults to \"./\". dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. devices (List[int], optional): List of device IDs to use. Defaults to [0]. locname (str, optional): Name for the location. Defaults to an empty string. \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . layer = layer self . locname = locname self . how = how assert self . how in [ \"most var within\" , \"most var across\" , \"random expr\" , \"given\" , ], \"how must be one of 'most var within', 'most var across', 'random expr', 'given'\" self . num_genes = num_genes self . preprocess = preprocess self . cell_type_col = cell_type_col self . filtration = filtration self . doplot = doplot self . genes = genes self . apc = apc self . dtype = dtype self . forward_mode = forward_mode self . k = k self . symmetrize = symmetrize self . known_grn = known_grn self . head_agg = head_agg self . max_cells = max_cells self . curr_genes = None self . drop_unexpressed = drop_unexpressed self . precision = precision","title":"GNInfer"},{"location":"tasks/#scprint.tasks.grn.GNInfer.__call__","text":"call runs the method Parameters: model ( Module ) \u2013 The model to be used for generating the network adata ( AnnData ) \u2013 Annotated data matrix of shape n_obs \u00d7 n_vars . n_obs is the number of cells and n_vars is the number of genes. cell_type ( str , default: None ) \u2013 Specific cell type to filter the data. Defaults to None. Returns: AnnData \u2013 Annotated data matrix with predictions and annotations. \u2013 np.ndarray: Filtered adjacency matrix. Source code in scprint/tasks/grn.py 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 def __call__ ( self , model : torch . nn . Module , adata : AnnData , cell_type = None ): \"\"\" __call__ runs the method Args: model (torch.nn.Module): The model to be used for generating the network adata (AnnData): Annotated data matrix of shape `n_obs` \u00d7 `n_vars`. `n_obs` is the number of cells and `n_vars` is the number of genes. cell_type (str, optional): Specific cell type to filter the data. Defaults to None. Returns: AnnData: Annotated data matrix with predictions and annotations. np.ndarray: Filtered adjacency matrix. \"\"\" # Add at least the organism you are working with if self . layer is None : self . layer = list ( range ( model . nlayers )) subadata = self . predict ( model , adata , self . layer , cell_type ) adjacencies = self . aggregate ( model . attn . get (), model . genes ) if self . head_agg == \"none\" : return self . save ( adjacencies [ 8 :, 8 :, :], subadata ) else : return self . save ( self . filter ( adjacencies )[ 8 :, 8 :], subadata )","title":"__call__"},{"location":"tasks/#scprint.tasks.grn.default_benchmark","text":"default_benchmark function to run the default scPRINT GRN benchmark Parameters: model ( Any ) \u2013 The scPRINT model to be used for the benchmark. default_dataset ( str , default: 'sroy' ) \u2013 The default dataset to use for benchmarking. Defaults to \"sroy\". cell_types ( List [ str ] , default: ['kidney distal convoluted tubule epithelial cell', 'kidney loop of Henle thick ascending limb epithelial cell', 'kidney collecting duct principal cell', 'mesangial cell', 'blood vessel smooth muscle cell', 'podocyte', 'macrophage', 'leukocyte', 'kidney interstitial fibroblast', 'endothelial cell'] ) \u2013 List of cell types to include in the benchmark. Defaults to [ \"kidney distal convoluted tubule epithelial cell\", \"kidney loop of Henle thick ascending limb epithelial cell\", \"kidney collecting duct principal cell\", \"mesangial cell\", \"blood vessel smooth muscle cell\", \"podocyte\", \"macrophage\", \"leukocyte\", \"kidney interstitial fibroblast\", \"endothelial cell\", maxlayers ( int , default: 16 ) \u2013 Maximum number of layers to use from the model. Defaults to 16. maxgenes ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. batch_size ( int , default: 32 ) \u2013 Batch size for processing. Defaults to 32. maxcells ( int , default: 1024 ) \u2013 Maximum number of cells to consider. Defaults to 1024. Returns: dict \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/grn.py 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 def default_benchmark ( model : Any , default_dataset : str = \"sroy\" , cell_types : List [ str ] = [ \"kidney distal convoluted tubule epithelial cell\" , \"kidney loop of Henle thick ascending limb epithelial cell\" , \"kidney collecting duct principal cell\" , \"mesangial cell\" , \"blood vessel smooth muscle cell\" , \"podocyte\" , \"macrophage\" , \"leukocyte\" , \"kidney interstitial fibroblast\" , \"endothelial cell\" , ], maxlayers : int = 16 , maxgenes : int = 5000 , batch_size : int = 32 , maxcells : int = 1024 , ): \"\"\" default_benchmark function to run the default scPRINT GRN benchmark Args: model (Any): The scPRINT model to be used for the benchmark. default_dataset (str, optional): The default dataset to use for benchmarking. Defaults to \"sroy\". cell_types (List[str], optional): List of cell types to include in the benchmark. Defaults to [ \"kidney distal convoluted tubule epithelial cell\", \"kidney loop of Henle thick ascending limb epithelial cell\", \"kidney collecting duct principal cell\", \"mesangial cell\", \"blood vessel smooth muscle cell\", \"podocyte\", \"macrophage\", \"leukocyte\", \"kidney interstitial fibroblast\", \"endothelial cell\", ]. maxlayers (int, optional): Maximum number of layers to use from the model. Defaults to 16. maxgenes (int, optional): Maximum number of genes to consider. Defaults to 5000. batch_size (int, optional): Batch size for processing. Defaults to 32. maxcells (int, optional): Maximum number of cells to consider. Defaults to 1024. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" metrics = {} layers = list ( range ( model . nlayers ))[ max ( 0 , model . nlayers - maxlayers ) :] clf_omni = None if default_dataset == \"sroy\" : preprocessor = Preprocessor ( is_symbol = True , force_preprocess = True , skip_validate = True , do_postp = False , min_valid_genes_id = 5000 , min_dataset_size = 64 , ) clf_self = None todo = [ ( \"han\" , \"human\" , \"full\" ), ( \"mine\" , \"human\" , \"full\" ), ( \"han\" , \"human\" , \"chip\" ), ( \"han\" , \"human\" , \"ko\" ), ( \"tran\" , \"mouse\" , \"full\" ), ( \"zhao\" , \"mouse\" , \"full\" ), ( \"tran\" , \"mouse\" , \"chip\" ), ( \"tran\" , \"mouse\" , \"ko\" ), ] for da , spe , gt in todo : if gt != \"full\" : continue print ( da + \"_\" + gt ) preadata = get_sroy_gt ( get = da , species = spe , gt = gt ) adata = preprocessor ( preadata . copy ()) grn_inferer = GNInfer ( layer = layers , how = \"most var within\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_genes = maxgenes , num_workers = 8 , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata ) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . var [ \"ensembl_id\" ] = grn . var . index grn . var [ \"symbol\" ] = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T if spe == \"human\" : metrics [ \"mean_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () ## OMNI if clf_omni is None : grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.9 , class_weight = { 1 : 800 , 0 : 1 }, shuffle = True , return_full = False , ) joblib . dump ( clf_omni , \"clf_omni.pkl\" ) metrics [ \"omni_classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) if spe == \"human\" : metrics [ \"omni_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = True ) . scprint_benchmark () grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"omni_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) ## SELF if clf_self is None : grn . varp [ \"GRN\" ] = np . transpose ( grn . varp [ \"all\" ], ( 1 , 0 , 2 )) _ , m , clf_self = train_classifier ( grn , other = preadata , C = 1 , train_size = 0.5 , class_weight = { 1 : 40 , 0 : 1 }, shuffle = False , return_full = False , ) metrics [ \"self_classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"self_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) if spe == \"human\" : grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"self_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = True ) . scprint_benchmark () ## chip / ko if ( da , spe , \"chip\" ) in todo : preadata = get_sroy_gt ( get = da , species = spe , gt = \"chip\" ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"omni_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"self_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) if ( da , spe , \"ko\" ) in todo : preadata = get_sroy_gt ( get = da , species = spe , gt = \"ko\" ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"omni_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"self_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) del grn elif default_dataset == \"gwps\" : if not os . path . exists ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ): adata = get_perturb_gt () adata . write_h5ad ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ) else : adata = read_h5ad ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ) preprocessor = Preprocessor ( force_preprocess = True , skip_validate = True , do_postp = False , min_valid_genes_id = maxgenes , min_dataset_size = 64 , ) nadata = preprocessor ( adata . copy ()) adata . var [ \"isTF\" ] = False adata . var . loc [ adata . var . gene_name . isin ( grnutils . TF ), \"isTF\" ] = True adata . var [ \"isTF\" ] . sum () grn_inferer = GNInfer ( layer = layers , how = \"most var within\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_genes = maxgenes , max_cells = maxcells , doplot = False , num_workers = 8 , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , nadata ) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) grn . var [ \"ensembl_id\" ] = grn . var . index grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) metrics [ \"mean_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] grn . var . index = grn . var [ \"ensembl_id\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.9 , class_weight = { 1 : 800 , 0 : 1 }, shuffle = True , doplot = False , return_full = False , use_col = \"gene_name\" , ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"omni\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) metrics [ \"omni_classifier\" ] = m grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"omni_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () grn . varp [ \"GRN\" ] = np . transpose ( grn . varp [ \"all\" ], ( 1 , 0 , 2 )) grn . var . index = grn . var [ \"ensembl_id\" ] _ , m , clf_self = train_classifier ( grn , other = adata , C = 1 , train_size = 0.5 , class_weight = { 1 : 40 , 0 : 1 }, doplot = False , shuffle = False , return_full = False , use_col = \"ensembl_id\" , ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"self\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) metrics [ \"self_classifier\" ] = m grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"self_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () else : # max_genes=4000 adata = sc . read_h5ad ( default_dataset ) adata . var [ \"isTF\" ] = False adata . var . loc [ adata . var . symbol . isin ( grnutils . TF ), \"isTF\" ] = True for celltype in cell_types : print ( celltype ) grn_inferer = GNInfer ( layer = layers , how = \"random expr\" , preprocess = \"softmax\" , head_agg = \"max\" , filtration = \"none\" , forward_mode = \"none\" , num_workers = 8 , num_genes = 2200 , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata [ adata . X . sum ( 1 ) > 500 ], cell_type = celltype ) grn . var . index = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) metrics [ celltype + \"_scprint\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () del grn gc . collect () grn_inferer = GNInfer ( layer = layers , how = \"most var across\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_workers = 8 , num_genes = maxgenes , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata [ adata . X . sum ( 1 ) > 500 ], cell_type = celltype ) grn . var . index = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . mean ( - 1 ) metrics [ celltype + \"_scprint_mean\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () if clf_omni is None : grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.6 , max_iter = 300 , class_weight = { 1 : 800 , 0 : 1 }, return_full = False , shuffle = True , doplot = False , ) joblib . dump ( clf_omni , \"clf_omni.pkl\" ) metrics [ \"classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) metrics [ celltype + \"_scprint_class\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () del grn gc . collect () return metrics","title":"default_benchmark"},{"location":"tasks/#scprint.tasks.denoise","text":"","title":"denoise"},{"location":"tasks/#scprint.tasks.denoise.Denoiser","text":"Denoiser class for denoising scRNA-seq data using a scPRINT model Parameters: batch_size ( int , default: 10 ) \u2013 Batch size for processing. Defaults to 10. num_workers ( int , default: 1 ) \u2013 Number of workers for data loading. Defaults to 1. max_len ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. precision ( str , default: '16-mixed' ) \u2013 Precision type for computations. Defaults to \"16-mixed\". how ( str , default: 'most var' ) \u2013 Method to select genes. Options are \"most var\". Defaults to \"most var\". plot_corr_size ( int , default: 10000 ) \u2013 Number of cells to use for plotting correlation. Defaults to 10000. doplot ( bool , default: False ) \u2013 Whether to generate plots. Defaults to False. predict_depth_mult ( int , default: 4 ) \u2013 Multiplier for prediction depth. Defaults to 4. downsample ( Optional [ float ] , default: None ) \u2013 Fraction of data to downsample. Defaults to None. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. Source code in scprint/tasks/denoise.py 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 def __init__ ( self , batch_size : int = 10 , num_workers : int = 1 , max_len : int = 5_000 , precision : str = \"16-mixed\" , how : str = \"most var\" , plot_corr_size : int = 10_000 , doplot : bool = False , predict_depth_mult : int = 4 , downsample : Optional [ float ] = None , devices : List [ int ] = [ 0 ], dtype : torch . dtype = torch . float16 , ): \"\"\" Denoiser class for denoising scRNA-seq data using a scPRINT model Args: batch_size (int, optional): Batch size for processing. Defaults to 10. num_workers (int, optional): Number of workers for data loading. Defaults to 1. max_len (int, optional): Maximum number of genes to consider. Defaults to 5000. precision (str, optional): Precision type for computations. Defaults to \"16-mixed\". how (str, optional): Method to select genes. Options are \"most var\". Defaults to \"most var\". plot_corr_size (int, optional): Number of cells to use for plotting correlation. Defaults to 10000. doplot (bool, optional): Whether to generate plots. Defaults to False. predict_depth_mult (int, optional): Multiplier for prediction depth. Defaults to 4. downsample (Optional[float], optional): Fraction of data to downsample. Defaults to None. devices (List[int], optional): List of device IDs to use. Defaults to [0]. dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . max_len = max_len self . plot_corr_size = plot_corr_size self . doplot = doplot self . predict_depth_mult = predict_depth_mult self . how = how self . downsample = downsample self . precision = precision self . dtype = dtype","title":"Denoiser"},{"location":"tasks/#scprint.tasks.denoise.Denoiser.__call__","text":"call calling the function Parameters: model ( Module ) \u2013 The scPRINT model to be used for denoising. adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. Returns: AnnData \u2013 The denoised annotated data matrix. Source code in scprint/tasks/denoise.py 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 def __call__ ( self , model : torch . nn . Module , adata : AnnData ): \"\"\" __call__ calling the function Args: model (torch.nn.Module): The scPRINT model to be used for denoising. adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. Returns: AnnData: The denoised annotated data matrix. \"\"\" if os . path . exists ( \"collator_output.txt\" ): os . remove ( \"collator_output.txt\" ) random_indices = None if self . plot_corr_size < adata . shape [ 0 ]: random_indices = np . random . randint ( low = 0 , high = adata . shape [ 0 ], size = self . plot_corr_size ) adataset = SimpleAnnDataset ( adata [ random_indices ], obs_to_output = [ \"organism_ontology_term_id\" ] ) else : adataset = SimpleAnnDataset ( adata , obs_to_output = [ \"organism_ontology_term_id\" ] ) if self . how == \"most var\" : sc . pp . highly_variable_genes ( adata , flavor = \"seurat_v3\" , n_top_genes = self . max_len , span = 0.99 ) genelist = adata . var . index [ adata . var . highly_variable ] print ( len ( genelist )) col = Collator ( organisms = model . organisms , valid_genes = model . genes , max_len = self . max_len , how = \"some\" if self . how == \"most var\" else self . how , genelist = genelist if self . how == \"most var\" else [], downsample = self . downsample , save_output = True , ) dataloader = DataLoader ( adataset , collate_fn = col , batch_size = self . batch_size , num_workers = self . num_workers , shuffle = False , ) model . doplot = self . doplot model . on_predict_epoch_start () model . eval () device = model . device . type with torch . no_grad (), torch . autocast ( device_type = device , dtype = self . dtype ): for batch in tqdm ( dataloader ): gene_pos , expression , depth = ( batch [ \"genes\" ] . to ( device ), batch [ \"x\" ] . to ( device ), batch [ \"depth\" ] . to ( device ), ) model . _predict ( gene_pos , expression , depth , predict_mode = \"denoise\" , depth_mult = self . predict_depth_mult , ) torch . cuda . empty_cache () self . genes = ( model . pos . cpu () . numpy () if self . how != \"most var\" else list ( set ( model . genes ) & set ( genelist )) ) tokeep = None metrics = None if self . downsample is not None : reco = model . expr_pred [ 0 ] reco = reco . cpu () . numpy () tokeep = np . isnan ( reco ) . sum ( 1 ) == 0 reco = reco [ tokeep ] noisy = np . loadtxt ( \"collator_output.txt\" )[ tokeep ] if random_indices is not None : true = adata . X [ random_indices ][ tokeep ] else : true = adata . X [ tokeep ] true = true . toarray () if issparse ( true ) else true if self . how == \"most var\" : true = true [:, adata . var . index . isin ( self . genes )] # noisy[true==0]=0 else : true = np . vstack ( [ true [ i , adata . var . index . get_indexer ( np . array ( model . genes )[ val ]), ] . copy () for i , val in enumerate ( self . genes ) ] ) # reco[true==0] = 0 # import pdb # pdb.set_trace() # reco[reco!=0] = 2 # corr_coef = np.corrcoef( # np.vstack([reco[true!=0], noisy[true!=0], true[true!=0]]) # ) corr_coef , p_value = spearmanr ( np . vstack ([ reco [ true != 0 ], noisy [ true != 0 ], true [ true != 0 ]]) . T ) metrics = { \"reco2noisy\" : corr_coef [ 0 , 1 ], \"reco2full\" : corr_coef [ 0 , 2 ], \"noisy2full\" : corr_coef [ 1 , 2 ], } # corr_coef[p_value > 0.05] = 0 # if self.doplot: # plt.figure(figsize=(10, 5)) # plt.imshow( # corr_coef, cmap=\"coolwarm\", interpolation=\"none\", vmin=-1, vmax=1 # ) # plt.colorbar() # plt.title(\"Expression Correlation Coefficient\") # plt.show() # metrics = { # \"reco2noisy\": np.mean( # corr_coef[ # self.plot_corr_size : self.plot_corr_size * 2, : self.plot_corr_size # ].diagonal() # ), # \"reco2full\": np.mean( # corr_coef[self.plot_corr_size * 2 :, : self.plot_corr_size].diagonal() # ), # \"noisy2full\": np.mean( # corr_coef[ # self.plot_corr_size * 2 :, # self.plot_corr_size : self.plot_corr_size * 2, # ].diagonal() # ), # } return ( metrics , ( random_indices [ tokeep ] if random_indices is not None and tokeep is not None else random_indices ), self . genes , ( model . expr_pred [ 0 ][ tokeep ] . cpu () . numpy () if tokeep is not None else model . expr_pred [ 0 ] . cpu () . numpy () ), )","title":"__call__"},{"location":"tasks/#scprint.tasks.denoise.default_benchmark","text":"default_benchmark function used to run the default denoising benchmark of scPRINT Parameters: model ( Any ) \u2013 The scPRINT model to be used for the benchmark. default_dataset ( str , default: FILE_DIR + '/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad' ) \u2013 Path to the default dataset to use for benchmarking. Defaults to FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\". max_len ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. Returns: dict \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/denoise.py 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 def default_benchmark ( model : Any , default_dataset : str = FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\" , max_len : int = 5000 , ): \"\"\" default_benchmark function used to run the default denoising benchmark of scPRINT Args: model (Any): The scPRINT model to be used for the benchmark. default_dataset (str, optional): Path to the default dataset to use for benchmarking. Defaults to FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\". max_len (int, optional): Maximum number of genes to consider. Defaults to 5000. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" adata = sc . read_h5ad ( default_dataset ) denoise = Denoiser ( model , batch_size = 40 , max_len = max_len , plot_corr_size = 10_000 , doplot = False , num_workers = 8 , predict_depth_mult = 10 , downsample = 0.7 , devices = 1 , ) return denoise ( adata )[ 0 ]","title":"default_benchmark"},{"location":"tasks/#scprint.tasks.denoise.split_molecules","text":"Splits molecules into two (potentially overlapping) groups. :param umis: Array of molecules to split :param data_split: Proportion of molecules to assign to the first group :param overlap_factor: Overlap correction factor, if desired :param random_state: For reproducible sampling :return: umis_X and umis_Y, representing split and ~(1 - split) counts sampled from the input array Source code in scprint/tasks/denoise.py 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 def split_molecules ( umis : np . ndarray , data_split : float , overlap_factor : float = 0.0 , random_state : np . random . RandomState = None , ) -> Tuple [ np . ndarray , np . ndarray ]: \"\"\"Splits molecules into two (potentially overlapping) groups. :param umis: Array of molecules to split :param data_split: Proportion of molecules to assign to the first group :param overlap_factor: Overlap correction factor, if desired :param random_state: For reproducible sampling :return: umis_X and umis_Y, representing ``split`` and ``~(1 - split)`` counts sampled from the input array \"\"\" if random_state is None : random_state = np . random . RandomState () umis_X_disjoint = random_state . binomial ( umis , data_split - overlap_factor ) umis_Y_disjoint = random_state . binomial ( umis - umis_X_disjoint , ( 1 - data_split ) / ( 1 - data_split + overlap_factor ) ) overlap_factor = umis - umis_X_disjoint - umis_Y_disjoint umis_X = umis_X_disjoint + overlap_factor umis_Y = umis_Y_disjoint + overlap_factor return umis_X , umis_Y","title":"split_molecules"},{"location":"usage/","text":"scPRINT usage scPRINT can be used to denoise / embed (& predict labels) / infer gene networks on single-cell data. Example of doing these tasks on a dataset is given in our manuscript and the example notebooks . But in a nutshell, here is the most minimal example of how scPRINT works: once you have loaded an anndata object, make sure you preprocess it so everything is checked out. (number of genes mentioned, gene format, raw counts used, etc...) more information on the Preprocessor is available in the scDataLoader package () Then you can denoise / embed / infer gn on this anndata using scPRINT and its helper classes. These classes follow a similar pattern to the trainer class in pytorch-lightning. Here is an example for denoising: from scprint import scPrint from scdataloader import Preprocessor import scanpy as sc from scprint.tasks import Denoiser #better to do it in lower precision import torch torch.set_float32_matmul_precision('medium') adata = sc.read_h5ad(\"../data/temp.h5ad\") #make sure we have this metadata adata.obs['organism_ontology_term_id'] = \"NCBITaxon:9606\" # load the model model = scPrint.load_from_checkpoint('../data/temp/last.ckpt', precpt_gene_emb=None) # preprocess to make sure it looks good preprocessor = Preprocessor(do_postp=False) adata = preprocessor(adata) #instanciate the denoiser with params (see the class in tasks/denoiser.py) how=\"most var\" denoiser = Denoiser( model, batch_size=20, max_len=2000, plot_corr_size=100_000, doplot=False, num_workers=1, predict_depth_mult=10, how=how, dtype=torch.bfloat16, ) #denoise metrics, idxs, genes, expr = denoise(model, adata) print(metrics) # apply the denoising to the anndata adata.layers['before'] = adata.X.copy() adata.X = adata.X.tolil() idxs = idxs if idxs is not None else range(adata.shape[0]) for i, idx in enumerate(idxs): adata.X[ idx, adata.var.index.get_indexer( np.array(model.genes)[genes[i]] if how != \"most var\" else genes ), ] = expr_pred[i] adata.X = adata.X.tocsr() But you can do the same thing with a bash command line: $ scprint denoise --ckpt_path ../data/temp/last.ckpt --adata ../data/temp.h5ad --how \"most var\" --dtype \"torch.bfloat16\" --batch_size 20 --max_len 2000 --plot_corr_size 100000 --num_workers 1 --predict_depth_mult 10 --doplot false --species \"NCBITaxon:9606\" However in this context you might have somewhat less options for the preprocessing of the anndataset. However, all parameters of the denoiser, embedder and gninfer classes are available in the cli interface as well!","title":"usage example"},{"location":"usage/#scprint-usage","text":"scPRINT can be used to denoise / embed (& predict labels) / infer gene networks on single-cell data. Example of doing these tasks on a dataset is given in our manuscript and the example notebooks . But in a nutshell, here is the most minimal example of how scPRINT works: once you have loaded an anndata object, make sure you preprocess it so everything is checked out. (number of genes mentioned, gene format, raw counts used, etc...) more information on the Preprocessor is available in the scDataLoader package () Then you can denoise / embed / infer gn on this anndata using scPRINT and its helper classes. These classes follow a similar pattern to the trainer class in pytorch-lightning. Here is an example for denoising: from scprint import scPrint from scdataloader import Preprocessor import scanpy as sc from scprint.tasks import Denoiser #better to do it in lower precision import torch torch.set_float32_matmul_precision('medium') adata = sc.read_h5ad(\"../data/temp.h5ad\") #make sure we have this metadata adata.obs['organism_ontology_term_id'] = \"NCBITaxon:9606\" # load the model model = scPrint.load_from_checkpoint('../data/temp/last.ckpt', precpt_gene_emb=None) # preprocess to make sure it looks good preprocessor = Preprocessor(do_postp=False) adata = preprocessor(adata) #instanciate the denoiser with params (see the class in tasks/denoiser.py) how=\"most var\" denoiser = Denoiser( model, batch_size=20, max_len=2000, plot_corr_size=100_000, doplot=False, num_workers=1, predict_depth_mult=10, how=how, dtype=torch.bfloat16, ) #denoise metrics, idxs, genes, expr = denoise(model, adata) print(metrics) # apply the denoising to the anndata adata.layers['before'] = adata.X.copy() adata.X = adata.X.tolil() idxs = idxs if idxs is not None else range(adata.shape[0]) for i, idx in enumerate(idxs): adata.X[ idx, adata.var.index.get_indexer( np.array(model.genes)[genes[i]] if how != \"most var\" else genes ), ] = expr_pred[i] adata.X = adata.X.tocsr() But you can do the same thing with a bash command line: $ scprint denoise --ckpt_path ../data/temp/last.ckpt --adata ../data/temp.h5ad --how \"most var\" --dtype \"torch.bfloat16\" --batch_size 20 --max_len 2000 --plot_corr_size 100000 --num_workers 1 --predict_depth_mult 10 --doplot false --species \"NCBITaxon:9606\" However in this context you might have somewhat less options for the preprocessing of the anndataset. However, all parameters of the denoiser, embedder and gninfer classes are available in the cli interface as well!","title":"scPRINT usage"},{"location":"utils/","text":"Documentation for the utils modules scprint.utils.sinkhorn SinkhornDistance Bases: Module SinkhornDistance Initialize the SinkhornDistance class Parameters: eps ( float , default: 0.01 ) \u2013 Regularization parameter. Defaults to 1e-2. max_iter ( int , default: 100 ) \u2013 Maximum number of Sinkhorn iterations. Defaults to 100. reduction ( str , default: 'none' ) \u2013 Specifies the reduction to apply to the output. Defaults to \"none\". Source code in scprint/utils/sinkhorn.py 8 9 10 11 12 13 14 15 16 17 18 19 20 def __init__ ( self , eps : float = 1e-2 , max_iter : int = 100 , reduction : str = \"none\" ): \"\"\" SinkhornDistance Initialize the SinkhornDistance class Args: eps (float, optional): Regularization parameter. Defaults to 1e-2. max_iter (int, optional): Maximum number of Sinkhorn iterations. Defaults to 100. reduction (str, optional): Specifies the reduction to apply to the output. Defaults to \"none\". \"\"\" super ( SinkhornDistance , self ) . __init__ () self . eps = eps self . max_iter = max_iter self . reduction = reduction M Modified cost for logarithmic updates Source code in scprint/utils/sinkhorn.py 99 100 101 102 def M ( self , C , u , v ): \"Modified cost for logarithmic updates\" \"\"\"$M_{ij} = (-c_{ij} + u_i + v_j) / epsilon$\"\"\" return ( - C + u . unsqueeze ( - 1 ) + v . unsqueeze ( 1 )) / self . eps ave staticmethod Barycenter subroutine, used by kinetic acceleration through extrapolation. Source code in scprint/utils/sinkhorn.py 104 105 106 107 @staticmethod def ave ( u , u1 , tau ): \"Barycenter subroutine, used by kinetic acceleration through extrapolation.\" return tau * u + ( 1 - tau ) * u1 forward forward Compute the Sinkhorn distance between two measures with cost matrix c Parameters: c ( Tensor ) \u2013 The cost matrix between the two measures. Returns: \u2013 torch.Tensor: The computed Sinkhorn distance. Source code in scprint/utils/sinkhorn.py 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 def forward ( self , c : torch . Tensor ): \"\"\" forward Compute the Sinkhorn distance between two measures with cost matrix c Args: c (torch.Tensor): The cost matrix between the two measures. Returns: torch.Tensor: The computed Sinkhorn distance. \"\"\" C = - c x_points = C . shape [ - 2 ] batch_size = C . shape [ 0 ] # both marginals are fixed with equal weights mu = ( torch . empty ( batch_size , x_points , dtype = C . dtype , requires_grad = False , device = C . device , ) . fill_ ( 1.0 / x_points ) . squeeze () ) nu = ( torch . empty ( batch_size , x_points , dtype = C . dtype , requires_grad = False , device = C . device , ) . fill_ ( 1.0 / x_points ) . squeeze () ) u = torch . zeros_like ( mu ) v = torch . zeros_like ( nu ) # Stopping criterion thresh = 1e-12 # Sinkhorn iterations for i in range ( self . max_iter ): if i % 2 == 0 : u1 = u # useful to check the update u = ( self . eps * ( torch . log ( mu ) - torch . logsumexp ( self . M ( C , u , v ), dim =- 1 )) + u ) err = ( u - u1 ) . abs () . sum ( - 1 ) . mean () else : v = ( self . eps * ( torch . log ( nu ) - torch . logsumexp ( self . M ( C , u , v ) . transpose ( - 2 , - 1 ), dim =- 1 ) ) + v ) v = v . detach () . requires_grad_ ( False ) v [ v > 9 * 1e8 ] = 0.0 v = v . detach () . requires_grad_ ( True ) if err . item () < thresh : break U , V = u , v # Transport plan pi = diag(a)*K*diag(b) pi = torch . exp ( self . M ( C , U , V )) # Sinkhorn distance return pi , C , U , V scprint.utils.utils category_str2int category_str2int converts a list of category strings to a list of category integers. Parameters: category_strs ( List [ str ] ) \u2013 A list of category strings to be converted. Returns: List [ int ] \u2013 List[int]: A list of integers corresponding to the input category strings. Source code in scprint/utils/utils.py 99 100 101 102 103 104 105 106 107 108 109 110 111 def category_str2int ( category_strs : List [ str ]) -> List [ int ]: \"\"\" category_str2int converts a list of category strings to a list of category integers. Args: category_strs (List[str]): A list of category strings to be converted. Returns: List[int]: A list of integers corresponding to the input category strings. \"\"\" set_category_strs = set ( category_strs ) name2id = { name : i for i , name in enumerate ( set_category_strs )} return [ name2id [ name ] for name in category_strs ] createFoldersFor will recursively create folders if needed until having all the folders required to save the file in this filepath Source code in scprint/utils/utils.py 88 89 90 91 92 93 94 95 96 def createFoldersFor ( filepath ): \"\"\" will recursively create folders if needed until having all the folders required to save the file in this filepath \"\"\" prevval = \"\" for val in os . path . expanduser ( filepath ) . split ( \"/\" )[: - 1 ]: prevval += val + \"/\" if not os . path . exists ( prevval ): os . mkdir ( prevval ) fileToList loads an input file with a\\n b\\n.. into a list [a,b,..] Parameters: input_str ( str ) \u2013 The input string to be completed. Returns: str ( list ) \u2013 The completed string with 'complete' appended. Source code in scprint/utils/utils.py 46 47 48 49 50 51 52 53 54 55 56 57 def fileToList ( filename : str , strconv : callable = lambda x : x ) -> list : \"\"\" loads an input file with a\\\\n b\\\\n.. into a list [a,b,..] Args: input_str (str): The input string to be completed. Returns: str: The completed string with 'complete' appended. \"\"\" with open ( filename ) as f : return [ strconv ( val [: - 1 ]) for val in f . readlines ()] get_free_gpu get_free_gpu finds the GPU with the most free memory using nvidia-smi. Returns: int \u2013 The index of the GPU with the most free memory. Source code in scprint/utils/utils.py 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 def get_free_gpu (): \"\"\" get_free_gpu finds the GPU with the most free memory using nvidia-smi. Returns: int: The index of the GPU with the most free memory. \"\"\" import subprocess import sys from io import StringIO import pandas as pd gpu_stats = subprocess . check_output ( [ \"nvidia-smi\" , \"--format=csv\" , \"--query-gpu=memory.used,memory.free\" , ] ) . decode ( \"utf-8\" ) gpu_df = pd . read_csv ( StringIO ( gpu_stats ), names = [ \"memory.used\" , \"memory.free\" ], skiprows = 1 ) print ( \"GPU usage: \\n {} \" . format ( gpu_df )) gpu_df [ \"memory.free\" ] = gpu_df [ \"memory.free\" ] . map ( lambda x : int ( x . rstrip ( \" [MiB]\" ))) idx = gpu_df [ \"memory.free\" ] . idxmax () print ( \"Find free GPU {} with {} free MiB\" . format ( idx , gpu_df . iloc [ idx ][ \"memory.free\" ]) ) return idx get_git_commit get_git_commit gets the current git commit hash. Returns: str \u2013 The current git commit Source code in scprint/utils/utils.py 196 197 198 199 200 201 202 203 def get_git_commit (): \"\"\" get_git_commit gets the current git commit hash. Returns: str: The current git commit \"\"\" return subprocess . check_output ([ \"git\" , \"rev-parse\" , \"HEAD\" ]) . decode ( \"utf-8\" ) . strip () inf_loop wrapper function for endless data loader. Source code in scprint/utils/utils.py 224 225 226 227 def inf_loop ( data_loader ): \"\"\"wrapper function for endless data loader.\"\"\" for loader in repeat ( data_loader ): yield from loader isnotebook check whether excuting in jupyter notebook. Source code in scprint/utils/utils.py 114 115 116 117 118 119 120 121 122 123 124 125 def isnotebook () -> bool : \"\"\"check whether excuting in jupyter notebook.\"\"\" try : shell = get_ipython () . __class__ . __name__ if shell == \"ZMQInteractiveShell\" : return True # Jupyter notebook or qtconsole elif shell == \"TerminalInteractiveShell\" : return True # Terminal running IPython else : return False # Other type (?) except NameError : return False # Probably standard Python interpreter listToFile listToFile loads a list with [a,b,..] into an input file a\\n b\\n.. Parameters: l ( list ) \u2013 The list of elements to be written to the file. filename ( str ) \u2013 The name of the file where the list will be written. strconv ( callable , default: lambda x: str ( x ) ) \u2013 A function to convert each element of the list to a string. Defaults to str. Returns: None \u2013 None Source code in scprint/utils/utils.py 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 def listToFile ( li : list , filename : str , strconv : callable = lambda x : str ( x )) -> None : \"\"\" listToFile loads a list with [a,b,..] into an input file a\\\\n b\\\\n.. Args: l (list): The list of elements to be written to the file. filename (str): The name of the file where the list will be written. strconv (callable, optional): A function to convert each element of the list to a string. Defaults to str. Returns: None \"\"\" with open ( filename , \"w\" ) as f : for item in li : f . write ( \" %s \\n \" % strconv ( item )) load_genes load_genes loads the genes for a given organism. Parameters: organisms ( Union [ str , list ] , default: 'NCBITaxon:9606' ) \u2013 A string or list of strings representing the organism(s) to load genes for. Defaults to \"NCBITaxon:9606\". Returns: \u2013 pd.DataFrame: A DataFrame containing gene information for the specified organism(s). Source code in scprint/utils/utils.py 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 def load_genes ( organisms : Union [ str , list ] = \"NCBITaxon:9606\" ): # \"NCBITaxon:10090\", \"\"\" load_genes loads the genes for a given organism. Args: organisms (Union[str, list], optional): A string or list of strings representing the organism(s) to load genes for. Defaults to \"NCBITaxon:9606\". Returns: pd.DataFrame: A DataFrame containing gene information for the specified organism(s). \"\"\" organismdf = [] if type ( organisms ) is str : organisms = [ organisms ] for organism in organisms : genesdf = bt . Gene . filter ( organism_id = bt . Organism . filter ( ontology_id = organism ) . first () . id ) . df () genesdf = genesdf [ ~ genesdf [ \"public_source_id\" ] . isna ()] genesdf = genesdf . drop_duplicates ( subset = \"ensembl_gene_id\" ) genesdf = genesdf . set_index ( \"ensembl_gene_id\" ) . sort_index () # mitochondrial genes genesdf [ \"mt\" ] = genesdf . symbol . astype ( str ) . str . startswith ( \"MT-\" ) # ribosomal genes genesdf [ \"ribo\" ] = genesdf . symbol . astype ( str ) . str . startswith (( \"RPS\" , \"RPL\" )) # hemoglobin genes. genesdf [ \"hb\" ] = genesdf . symbol . astype ( str ) . str . contains (( \"^HB[^(P)]\" )) genesdf [ \"organism\" ] = organism organismdf . append ( genesdf ) organismdf = pd . concat ( organismdf ) organismdf . drop ( columns = [ \"source_id\" , \"stable_id\" , \"run_id\" , \"created_by_id\" , \"updated_at\" ], inplace = True , ) return organismdf prepare_device setup GPU device if available. get gpu device indices which are used for DataParallel Source code in scprint/utils/utils.py 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 def prepare_device ( n_gpu_use ): \"\"\" setup GPU device if available. get gpu device indices which are used for DataParallel \"\"\" n_gpu = torch . cuda . device_count () if n_gpu_use > 0 and n_gpu == 0 : print ( \"Warning: There's no GPU available on this machine,\" \"training will be performed on CPU.\" ) n_gpu_use = 0 if n_gpu_use > n_gpu : print ( f \"Warning: The number of GPU's configured to use is { n_gpu_use } , but only { n_gpu } are \" \"available on this machine.\" ) n_gpu_use = n_gpu device = torch . device ( \"cuda:0\" if n_gpu_use > 0 else \"cpu\" ) list_ids = list ( range ( n_gpu_use )) return device , list_ids run_command run_command runs a command in the shell and prints the output. Parameters: command ( str ) \u2013 The command to be executed in the shell. Returns: int \u2013 The return code of the command executed. Source code in scprint/utils/utils.py 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def run_command ( command : str , ** kwargs ): \"\"\" run_command runs a command in the shell and prints the output. Args: command (str): The command to be executed in the shell. Returns: int: The return code of the command executed. \"\"\" process = subprocess . Popen ( command , stdout = subprocess . PIPE , ** kwargs ) while True : if process . poll () is not None : break output = process . stdout . readline () if output : print ( output . strip ()) rc = process . poll () return rc set_seed set random seed. Source code in scprint/utils/utils.py 77 78 79 80 81 82 83 def set_seed ( seed : int = 42 ): \"\"\"set random seed.\"\"\" random . seed ( seed ) np . random . seed ( seed ) torch . manual_seed ( seed ) torch . backends . cudnn . deterministic = True torch . backends . cudnn . benchmark = False scprint.utils.get_seq load_fasta_species Downloads and caches FASTA files for a given species from the Ensembl FTP server. Parameters: species ( str , default: 'homo_sapiens' ) \u2013 The species name for which to download FASTA files. Defaults to \"homo_sapiens\". output_path ( str , default: '/tmp/data/fasta/' ) \u2013 The local directory path where the FASTA files will be saved. Defaults to \"/tmp/data/fasta/\". cache ( bool , default: True ) \u2013 If True, use cached files if they exist. If False, re-download the files. Defaults to True. Source code in scprint/utils/get_seq.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 def load_fasta_species ( species : str = \"homo_sapiens\" , output_path : str = \"/tmp/data/fasta/\" , cache : bool = True , ) -> None : \"\"\" Downloads and caches FASTA files for a given species from the Ensembl FTP server. Args: species (str, optional): The species name for which to download FASTA files. Defaults to \"homo_sapiens\". output_path (str, optional): The local directory path where the FASTA files will be saved. Defaults to \"/tmp/data/fasta/\". cache (bool, optional): If True, use cached files if they exist. If False, re-download the files. Defaults to True. \"\"\" ftp = ftplib . FTP ( \"ftp.ensembl.org\" ) ftp . login () ftp . cwd ( \"/pub/release-110/fasta/\" + species + \"/pep/\" ) file = list_files ( ftp , \".all.fa.gz\" )[ 0 ] local_file_path = output_path + file if not os . path . exists ( local_file_path ) or not cache : os . makedirs ( os . path . dirname ( local_file_path ), exist_ok = True ) with open ( local_file_path , \"wb\" ) as local_file : ftp . retrbinary ( \"RETR \" + file , local_file . write ) ftp . cwd ( \"/pub/release-110/fasta/\" + species + \"/ncrna/\" ) file = list_files ( ftp , \".ncrna.fa.gz\" )[ 0 ] local_file_path = output_path + file if not os . path . exists ( local_file_path ) or not cache : with open ( local_file_path , \"wb\" ) as local_file : ftp . retrbinary ( \"RETR \" + file , local_file . write ) ftp . quit () seq Fetch nucleotide or amino acid sequence (FASTA) of a gene (and all its isoforms) or transcript by Ensembl, WormBase, or FlyBase ID. Parameters: ens_ids ( Union [ str , List [ str ]] ) \u2013 One or more Ensembl IDs (passed as string or list of strings). Also supports WormBase and FlyBase IDs. translate ( bool , default: False ) \u2013 Defines whether nucleotide or amino acid sequences are returned. Defaults to False (returns nucleotide sequences). Nucleotide sequences are fetched from the Ensembl REST API server. Amino acid sequences are fetched from the UniProt REST API server. isoforms ( bool , default: False ) \u2013 If True, returns the sequences of all known transcripts. Defaults to False. (Only for gene IDs.) parallel ( bool , default: True ) \u2013 If True, fetches sequences in parallel. Defaults to True. save ( bool , default: False ) \u2013 If True, saves output FASTA to current directory. Defaults to False. transcribe ( bool , default: None ) \u2013 Deprecated. Use 'translate' instead. seqtype ( str , default: None ) \u2013 Deprecated. Use 'translate' instead. verbose ( bool , default: True ) \u2013 If True, prints progress information. Defaults to True. Returns: List [ str ] \u2013 List[str]: A list containing the requested sequences, or a FASTA file if 'save' is True. Raises: ValueError \u2013 If an invalid Ensembl ID is provided. Source code in scprint/utils/get_seq.py 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 def seq ( ens_ids : Union [ str , List [ str ]], translate : bool = False , isoforms : bool = False , parallel : bool = True , save : bool = False , transcribe : Optional [ bool ] = None , seqtype : Optional [ str ] = None , verbose : bool = True , ) -> List [ str ]: \"\"\" Fetch nucleotide or amino acid sequence (FASTA) of a gene (and all its isoforms) or transcript by Ensembl, WormBase, or FlyBase ID. Args: ens_ids (Union[str, List[str]]): One or more Ensembl IDs (passed as string or list of strings). Also supports WormBase and FlyBase IDs. translate (bool, optional): Defines whether nucleotide or amino acid sequences are returned. Defaults to False (returns nucleotide sequences). Nucleotide sequences are fetched from the Ensembl REST API server. Amino acid sequences are fetched from the UniProt REST API server. isoforms (bool, optional): If True, returns the sequences of all known transcripts. Defaults to False. (Only for gene IDs.) parallel (bool, optional): If True, fetches sequences in parallel. Defaults to True. save (bool, optional): If True, saves output FASTA to current directory. Defaults to False. transcribe (bool, optional): Deprecated. Use 'translate' instead. seqtype (str, optional): Deprecated. Use 'translate' instead. verbose (bool, optional): If True, prints progress information. Defaults to True. Returns: List[str]: A list containing the requested sequences, or a FASTA file if 'save' is True. Raises: ValueError: If an invalid Ensembl ID is provided. \"\"\" # Handle deprecated arguments if seqtype : logging . error ( \"'seqtype' argument deprecated! Please use True/False argument 'translate' instead.\" ) return if transcribe : translate = transcribe ## Clean up arguments # Clean up Ensembl IDs # If single Ensembl ID passed as string, convert to list if type ( ens_ids ) is str : ens_ids = [ ens_ids ] # Remove Ensembl ID version if passed ens_ids_clean = [] temp = 0 for ensembl_ID in ens_ids : # But only for Ensembl ID (and not for flybase/wormbase IDs) if ensembl_ID . startswith ( \"ENS\" ): ens_ids_clean . append ( ensembl_ID . split ( \".\" )[ 0 ]) if \".\" in ensembl_ID and temp == 0 : if verbose : logging . info ( \"We noticed that you may have passed a version number with your Ensembl ID. \\n \" \"Please note that gget seq will return information linked to the latest Ensembl ID version.\" ) temp = + 1 else : ens_ids_clean . append ( ensembl_ID ) # Initiate empty 'fasta' fasta = [] ## Fetch nucleotide sequece if translate is False : # Define Ensembl REST API server server = ENSEMBL_REST_API # Define type of returned content from REST content_type = \"application/json\" # Initiate dictionary to save results for all IDs in master_dict = {} # Query REST APIs from https://rest.ensembl.org/ for ensembl_ID in ens_ids_clean : # Create dict to save query results results_dict = { ensembl_ID : {}} # If isoforms False, just fetch sequences of passed Ensembl ID if isoforms is False : # sequence/id/ query: Request sequence by stable identifier query = \"sequence/id/\" + ensembl_ID + \"?\" # Try if query valid try : # Submit query; this will throw RuntimeError if ID not found df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"id\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ({ \"seq\" : df_temp }) if verbose : logging . info ( f \"Requesting nucleotide sequence of { ensembl_ID } from Ensembl.\" ) except RuntimeError : logging . error ( f \"ID { ensembl_ID } not found. Please double-check spelling/arguments and try again.\" ) # If isoforms true, fetch sequences of isoforms instead if isoforms is True : # Get ID type (gene, transcript, ...) using gget info info_df = info ( ensembl_ID , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check if Ensembl ID was found if isinstance ( info_df , type ( None )): logging . warning ( f \"ID ' { ensembl_ID } ' not found. Please double-check spelling/arguments and try again.\" ) continue ens_ID_type = info_df . loc [ ensembl_ID ][ \"object_type\" ] # If the ID is a gene, get the IDs of all its transcripts if ens_ID_type == \"Gene\" : if verbose : logging . info ( f \"Requesting nucleotide sequences of all transcripts of { ensembl_ID } from Ensembl.\" ) for transcipt_id in info_df . loc [ ensembl_ID ][ \"all_transcripts\" ]: # Remove version number for Ensembl IDs (not for flybase/wormbase IDs) if transcipt_id . startswith ( \"ENS\" ): transcipt_id = transcipt_id . split ( \".\" )[ 0 ] # Try if query is valid try : # Define the REST query query = \"sequence/id/\" + transcipt_id + \"?\" # Submit query df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ( { f \" { transcipt_id } \" : df_temp } ) except RuntimeError : logging . error ( f \"ID { transcipt_id } not found. \" \"Please double-check spelling/arguments and try again.\" ) # If isoform true, but ID is not a gene; ignore the isoform parameter else : # Try if query is valid try : # Define the REST query query = \"sequence/id/\" + ensembl_ID + \"?\" # Submit query df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"id\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ({ \"seq\" : df_temp }) logging . info ( f \"Requesting nucleotide sequence of { ensembl_ID } from Ensembl.\" ) logging . warning ( \"The isoform option only applies to gene IDs.\" ) except RuntimeError : logging . error ( f \"ID { ensembl_ID } not found. \" \"Please double-check spelling/arguments and try again.\" ) # Add results to master dict master_dict . update ( results_dict ) # Build FASTA file for ens_ID in master_dict : for key in master_dict [ ens_ID ] . keys (): if key == \"seq\" : fasta . append ( \">\" + ens_ID + \" \" + master_dict [ ens_ID ][ key ][ \"desc\" ]) fasta . append ( master_dict [ ens_ID ][ key ][ \"seq\" ]) else : fasta . append ( \">\" + master_dict [ ens_ID ][ key ][ \"id\" ] + \" \" + master_dict [ ens_ID ][ key ][ \"desc\" ] ) fasta . append ( master_dict [ ens_ID ][ key ][ \"seq\" ]) ## Fetch amino acid sequences from UniProt if translate is True : if isoforms is False : # List to collect transcript IDs trans_ids = [] # Get ID type (gene, transcript, ...) using gget info info_df = info ( ens_ids_clean , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check that Ensembl ID was found missing = set ( ens_ids_clean ) - set ( info_df . index . values ) if len ( missing ) > 0 : logging . warning ( f \" { str ( missing ) } IDs not found. Please double-check spelling/arguments.\" ) ens_ID_type = info_df . loc [ ens_ids_clean [ 0 ]][ \"object_type\" ] # If the ID is a gene, use the ID of its canonical transcript if ens_ID_type == \"Gene\" : # Get ID of canonical transcript for ensembl_ID in info_df . index . values : can_trans = info_df . loc [ ensembl_ID ][ \"canonical_transcript\" ] if ensembl_ID . startswith ( \"ENS\" ): # Remove Ensembl ID version from transcript IDs and append to transcript IDs list temp_trans_id = can_trans . split ( \".\" )[ 0 ] trans_ids . append ( temp_trans_id ) elif ensembl_ID . startswith ( \"WB\" ): # Remove added \".\" at the end of transcript IDs temp_trans_id = \".\" . join ( can_trans . split ( \".\" )[: - 1 ]) # # For WormBase transcript IDs, also remove the version number for submission to UniProt API # temp_trans_id = \".\".join(temp_trans_id1.split(\".\")[:-1]) trans_ids . append ( temp_trans_id ) else : # Remove added \".\" at the end of other transcript IDs temp_trans_id = \".\" . join ( can_trans . split ( \".\" )[: - 1 ]) trans_ids . append ( temp_trans_id ) if verbose : logging . info ( f \"Requesting amino acid sequence of the canonical transcript { temp_trans_id } of gene { ensembl_ID } from UniProt.\" ) # If the ID is a transcript, append the ID directly elif ens_ID_type == \"Transcript\" : # # For WormBase transcript IDs, remove the version number for submission to UniProt API # if ensembl_ID.startswith(\"T\"): # trans_ids.append(\".\".join(ensembl_ID.split(\".\")[:-1])) # else: trans_ids = ens_ids_clean if verbose : logging . info ( f \"Requesting amino acid sequence of { trans_ids } from UniProt.\" ) else : logging . warning ( \"ensembl_IDs not recognized as either a gene or transcript ID. It will not be included in the UniProt query.\" ) # Fetch the amino acid sequences of the transcript Ensembl IDs df_uniprot = get_uniprot_seqs ( UNIPROT_REST_API , trans_ids ) # Add info_df.loc[ensembl_ID] to df_uniprot by joining on \"canonical_transcript\" / \"gene_name\" respectively import pdb pdb . set_trace () info_df . set_index ( \"canonical_transcript\" , inplace = True ) df_uniprot . loc [:, \"gene_id\" ] = info_df . loc [ df_uniprot [ \"query\" ], \"gene_name\" ] . values if isoforms is True : # List to collect transcript IDs trans_ids = [] for ensembl_ID in ens_ids_clean : # Get ID type (gene, transcript, ...) using gget info info_df = info ( ensembl_ID , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check that Ensembl ID was found if isinstance ( info_df , type ( None )): logging . warning ( f \"ID ' { ensembl_ID } ' not found. Please double-check spelling/arguments.\" ) continue ens_ID_type = info_df . loc [ ensembl_ID ][ \"object_type\" ] # If the ID is a gene, get the IDs of all isoforms if ens_ID_type == \"Gene\" : # Get the IDs of all transcripts from the gget info results for transcipt_id in info_df . loc [ ensembl_ID ][ \"all_transcripts\" ]: if ensembl_ID . startswith ( \"ENS\" ): # Append transcript ID (without Ensembl version number) to list of transcripts to fetch trans_ids . append ( transcipt_id . split ( \".\" )[ 0 ]) # elif ensembl_ID.startswith(\"WB\"): # # For WormBase transcript IDs, remove the version number for submission to UniProt API # temp_trans_id = \".\".join(transcipt_id.split(\".\")[:-1]) # trans_ids.append(temp_trans_id) else : # Note: No need to remove the added \".\" at the end of unversioned transcripts here, because \"all_transcripts\" are returned without it trans_ids . append ( transcipt_id ) if verbose : logging . info ( f \"Requesting amino acid sequences of all transcripts of gene { ensembl_ID } from UniProt.\" ) elif ens_ID_type == \"Transcript\" : # # For WormBase transcript IDs, remove the version number for submission to UniProt API # if ensembl_ID.startswith(\"T\"): # trans_ids.append(\".\".join(ensembl_ID.split(\".\")[:-1])) # else: trans_ids . append ( ensembl_ID ) if verbose : logging . info ( f \"Requesting amino acid sequence of { ensembl_ID } from UniProt.\" ) logging . warning ( \"The isoform option only applies to gene IDs.\" ) else : logging . warning ( f \" { ensembl_ID } not recognized as either a gene or transcript ID. It will not be included in the UniProt query.\" ) # Fetch amino acid sequences of all isoforms from the UniProt REST API df_uniprot = get_uniprot_seqs ( UNIPROT_REST_API , trans_ids ) # Check if any results were found if len ( df_uniprot ) < 1 : logging . error ( \"No UniProt amino acid sequences were found for these ID(s).\" ) else : # Build FASTA file from UniProt results for ( uniprot_id , query_ensembl_id , gene_name , organism , sequence_length , uniprot_seq , ) in zip ( df_uniprot [ \"uniprot_id\" ] . values , df_uniprot [ \"query\" ] . values , df_uniprot [ \"gene_name\" ] . values , df_uniprot [ \"gene_id\" ] . values , df_uniprot [ \"organism\" ] . values , df_uniprot [ \"sequence_length\" ] . values , df_uniprot [ \"sequence\" ] . values , ): fasta . append ( \">\" + str ( query_ensembl_id ) + \" uniprot_id: \" + str ( uniprot_id ) + \" ensembl_id: \" + str ( query_ensembl_id ) + \" gene_name: \" + str ( gene_name ) + \" organism: \" + str ( organism ) + \" sequence_length: \" + str ( sequence_length ) ) fasta . append ( str ( uniprot_seq )) # Save if save : file = open ( \"gget_seq_results.fa\" , \"w\" ) for element in fasta : file . write ( element + \" \\n \" ) file . close () # missed samples return ( set ( trans_ids ) - set ( df_uniprot [ \"query\" ] . values )) | set ( missing ) return fasta subset_fasta subset_fasta: creates a new fasta file with only the sequence which names contain one of gene_names Parameters: gene_tosubset ( set ) \u2013 A set of gene names to subset from the original FASTA file. fasta_path ( str ) \u2013 The path to the original FASTA file. subfasta_path ( str , default: './data/fasta/subset.fa' ) \u2013 The path to save the subsetted FASTA file. Defaults to \"./data/fasta/subset.fa\". drop_unknown_seq ( bool , default: True ) \u2013 If True, drop sequences containing unknown amino acids (denoted by '*'). Defaults to True. Returns: set ( set ) \u2013 A set of gene names that were found and included in the subsetted FASTA file. Raises: ValueError \u2013 If a gene name does not start with \"ENS\". Source code in scprint/utils/get_seq.py 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 def subset_fasta ( gene_tosubset : set , fasta_path : str , subfasta_path : str = \"./data/fasta/subset.fa\" , drop_unknown_seq : bool = True , ) -> set : \"\"\" subset_fasta: creates a new fasta file with only the sequence which names contain one of gene_names Args: gene_tosubset (set): A set of gene names to subset from the original FASTA file. fasta_path (str): The path to the original FASTA file. subfasta_path (str, optional): The path to save the subsetted FASTA file. Defaults to \"./data/fasta/subset.fa\". drop_unknown_seq (bool, optional): If True, drop sequences containing unknown amino acids (denoted by '*'). Defaults to True. Returns: set: A set of gene names that were found and included in the subsetted FASTA file. Raises: ValueError: If a gene name does not start with \"ENS\". \"\"\" dup = set () weird = 0 genes_found = set () gene_tosubset = set ( gene_tosubset ) with open ( fasta_path , \"r\" ) as original_fasta , open ( subfasta_path , \"w\" ) as subset_fasta : for record in SeqIO . parse ( original_fasta , \"fasta\" ): gene_name = ( record . description . split ( \" gene:\" )[ 1 ] . split ( \" transcript\" )[ 0 ] . split ( \".\" )[ 0 ] ) if gene_name in gene_tosubset : if drop_unknown_seq : if \"*\" in record . seq : weird += 1 continue if not gene_name . startswith ( \"ENS\" ): raise ValueError ( \"issue\" , gene_name ) if gene_name in genes_found : dup . add ( gene_name ) continue record . description = \"\" record . id = gene_name SeqIO . write ( record , subset_fasta , \"fasta\" ) genes_found . add ( gene_name ) print ( len ( dup ), \" genes had duplicates\" ) print ( \"dropped\" , weird , \"weird sequences\" ) return genes_found","title":"utils"},{"location":"utils/#documentation-for-the-utils-modules","text":"","title":"Documentation for the utils modules"},{"location":"utils/#scprint.utils.sinkhorn","text":"","title":"sinkhorn"},{"location":"utils/#scprint.utils.sinkhorn.SinkhornDistance","text":"Bases: Module SinkhornDistance Initialize the SinkhornDistance class Parameters: eps ( float , default: 0.01 ) \u2013 Regularization parameter. Defaults to 1e-2. max_iter ( int , default: 100 ) \u2013 Maximum number of Sinkhorn iterations. Defaults to 100. reduction ( str , default: 'none' ) \u2013 Specifies the reduction to apply to the output. Defaults to \"none\". Source code in scprint/utils/sinkhorn.py 8 9 10 11 12 13 14 15 16 17 18 19 20 def __init__ ( self , eps : float = 1e-2 , max_iter : int = 100 , reduction : str = \"none\" ): \"\"\" SinkhornDistance Initialize the SinkhornDistance class Args: eps (float, optional): Regularization parameter. Defaults to 1e-2. max_iter (int, optional): Maximum number of Sinkhorn iterations. Defaults to 100. reduction (str, optional): Specifies the reduction to apply to the output. Defaults to \"none\". \"\"\" super ( SinkhornDistance , self ) . __init__ () self . eps = eps self . max_iter = max_iter self . reduction = reduction","title":"SinkhornDistance"},{"location":"utils/#scprint.utils.sinkhorn.SinkhornDistance.M","text":"Modified cost for logarithmic updates Source code in scprint/utils/sinkhorn.py 99 100 101 102 def M ( self , C , u , v ): \"Modified cost for logarithmic updates\" \"\"\"$M_{ij} = (-c_{ij} + u_i + v_j) / epsilon$\"\"\" return ( - C + u . unsqueeze ( - 1 ) + v . unsqueeze ( 1 )) / self . eps","title":"M"},{"location":"utils/#scprint.utils.sinkhorn.SinkhornDistance.ave","text":"Barycenter subroutine, used by kinetic acceleration through extrapolation. Source code in scprint/utils/sinkhorn.py 104 105 106 107 @staticmethod def ave ( u , u1 , tau ): \"Barycenter subroutine, used by kinetic acceleration through extrapolation.\" return tau * u + ( 1 - tau ) * u1","title":"ave"},{"location":"utils/#scprint.utils.sinkhorn.SinkhornDistance.forward","text":"forward Compute the Sinkhorn distance between two measures with cost matrix c Parameters: c ( Tensor ) \u2013 The cost matrix between the two measures. Returns: \u2013 torch.Tensor: The computed Sinkhorn distance. Source code in scprint/utils/sinkhorn.py 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 def forward ( self , c : torch . Tensor ): \"\"\" forward Compute the Sinkhorn distance between two measures with cost matrix c Args: c (torch.Tensor): The cost matrix between the two measures. Returns: torch.Tensor: The computed Sinkhorn distance. \"\"\" C = - c x_points = C . shape [ - 2 ] batch_size = C . shape [ 0 ] # both marginals are fixed with equal weights mu = ( torch . empty ( batch_size , x_points , dtype = C . dtype , requires_grad = False , device = C . device , ) . fill_ ( 1.0 / x_points ) . squeeze () ) nu = ( torch . empty ( batch_size , x_points , dtype = C . dtype , requires_grad = False , device = C . device , ) . fill_ ( 1.0 / x_points ) . squeeze () ) u = torch . zeros_like ( mu ) v = torch . zeros_like ( nu ) # Stopping criterion thresh = 1e-12 # Sinkhorn iterations for i in range ( self . max_iter ): if i % 2 == 0 : u1 = u # useful to check the update u = ( self . eps * ( torch . log ( mu ) - torch . logsumexp ( self . M ( C , u , v ), dim =- 1 )) + u ) err = ( u - u1 ) . abs () . sum ( - 1 ) . mean () else : v = ( self . eps * ( torch . log ( nu ) - torch . logsumexp ( self . M ( C , u , v ) . transpose ( - 2 , - 1 ), dim =- 1 ) ) + v ) v = v . detach () . requires_grad_ ( False ) v [ v > 9 * 1e8 ] = 0.0 v = v . detach () . requires_grad_ ( True ) if err . item () < thresh : break U , V = u , v # Transport plan pi = diag(a)*K*diag(b) pi = torch . exp ( self . M ( C , U , V )) # Sinkhorn distance return pi , C , U , V","title":"forward"},{"location":"utils/#scprint.utils.utils","text":"","title":"utils"},{"location":"utils/#scprint.utils.utils.category_str2int","text":"category_str2int converts a list of category strings to a list of category integers. Parameters: category_strs ( List [ str ] ) \u2013 A list of category strings to be converted. Returns: List [ int ] \u2013 List[int]: A list of integers corresponding to the input category strings. Source code in scprint/utils/utils.py 99 100 101 102 103 104 105 106 107 108 109 110 111 def category_str2int ( category_strs : List [ str ]) -> List [ int ]: \"\"\" category_str2int converts a list of category strings to a list of category integers. Args: category_strs (List[str]): A list of category strings to be converted. Returns: List[int]: A list of integers corresponding to the input category strings. \"\"\" set_category_strs = set ( category_strs ) name2id = { name : i for i , name in enumerate ( set_category_strs )} return [ name2id [ name ] for name in category_strs ]","title":"category_str2int"},{"location":"utils/#scprint.utils.utils.createFoldersFor","text":"will recursively create folders if needed until having all the folders required to save the file in this filepath Source code in scprint/utils/utils.py 88 89 90 91 92 93 94 95 96 def createFoldersFor ( filepath ): \"\"\" will recursively create folders if needed until having all the folders required to save the file in this filepath \"\"\" prevval = \"\" for val in os . path . expanduser ( filepath ) . split ( \"/\" )[: - 1 ]: prevval += val + \"/\" if not os . path . exists ( prevval ): os . mkdir ( prevval )","title":"createFoldersFor"},{"location":"utils/#scprint.utils.utils.fileToList","text":"loads an input file with a\\n b\\n.. into a list [a,b,..] Parameters: input_str ( str ) \u2013 The input string to be completed. Returns: str ( list ) \u2013 The completed string with 'complete' appended. Source code in scprint/utils/utils.py 46 47 48 49 50 51 52 53 54 55 56 57 def fileToList ( filename : str , strconv : callable = lambda x : x ) -> list : \"\"\" loads an input file with a\\\\n b\\\\n.. into a list [a,b,..] Args: input_str (str): The input string to be completed. Returns: str: The completed string with 'complete' appended. \"\"\" with open ( filename ) as f : return [ strconv ( val [: - 1 ]) for val in f . readlines ()]","title":"fileToList"},{"location":"utils/#scprint.utils.utils.get_free_gpu","text":"get_free_gpu finds the GPU with the most free memory using nvidia-smi. Returns: int \u2013 The index of the GPU with the most free memory. Source code in scprint/utils/utils.py 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 def get_free_gpu (): \"\"\" get_free_gpu finds the GPU with the most free memory using nvidia-smi. Returns: int: The index of the GPU with the most free memory. \"\"\" import subprocess import sys from io import StringIO import pandas as pd gpu_stats = subprocess . check_output ( [ \"nvidia-smi\" , \"--format=csv\" , \"--query-gpu=memory.used,memory.free\" , ] ) . decode ( \"utf-8\" ) gpu_df = pd . read_csv ( StringIO ( gpu_stats ), names = [ \"memory.used\" , \"memory.free\" ], skiprows = 1 ) print ( \"GPU usage: \\n {} \" . format ( gpu_df )) gpu_df [ \"memory.free\" ] = gpu_df [ \"memory.free\" ] . map ( lambda x : int ( x . rstrip ( \" [MiB]\" ))) idx = gpu_df [ \"memory.free\" ] . idxmax () print ( \"Find free GPU {} with {} free MiB\" . format ( idx , gpu_df . iloc [ idx ][ \"memory.free\" ]) ) return idx","title":"get_free_gpu"},{"location":"utils/#scprint.utils.utils.get_git_commit","text":"get_git_commit gets the current git commit hash. Returns: str \u2013 The current git commit Source code in scprint/utils/utils.py 196 197 198 199 200 201 202 203 def get_git_commit (): \"\"\" get_git_commit gets the current git commit hash. Returns: str: The current git commit \"\"\" return subprocess . check_output ([ \"git\" , \"rev-parse\" , \"HEAD\" ]) . decode ( \"utf-8\" ) . strip ()","title":"get_git_commit"},{"location":"utils/#scprint.utils.utils.inf_loop","text":"wrapper function for endless data loader. Source code in scprint/utils/utils.py 224 225 226 227 def inf_loop ( data_loader ): \"\"\"wrapper function for endless data loader.\"\"\" for loader in repeat ( data_loader ): yield from loader","title":"inf_loop"},{"location":"utils/#scprint.utils.utils.isnotebook","text":"check whether excuting in jupyter notebook. Source code in scprint/utils/utils.py 114 115 116 117 118 119 120 121 122 123 124 125 def isnotebook () -> bool : \"\"\"check whether excuting in jupyter notebook.\"\"\" try : shell = get_ipython () . __class__ . __name__ if shell == \"ZMQInteractiveShell\" : return True # Jupyter notebook or qtconsole elif shell == \"TerminalInteractiveShell\" : return True # Terminal running IPython else : return False # Other type (?) except NameError : return False # Probably standard Python interpreter","title":"isnotebook"},{"location":"utils/#scprint.utils.utils.listToFile","text":"listToFile loads a list with [a,b,..] into an input file a\\n b\\n.. Parameters: l ( list ) \u2013 The list of elements to be written to the file. filename ( str ) \u2013 The name of the file where the list will be written. strconv ( callable , default: lambda x: str ( x ) ) \u2013 A function to convert each element of the list to a string. Defaults to str. Returns: None \u2013 None Source code in scprint/utils/utils.py 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 def listToFile ( li : list , filename : str , strconv : callable = lambda x : str ( x )) -> None : \"\"\" listToFile loads a list with [a,b,..] into an input file a\\\\n b\\\\n.. Args: l (list): The list of elements to be written to the file. filename (str): The name of the file where the list will be written. strconv (callable, optional): A function to convert each element of the list to a string. Defaults to str. Returns: None \"\"\" with open ( filename , \"w\" ) as f : for item in li : f . write ( \" %s \\n \" % strconv ( item ))","title":"listToFile"},{"location":"utils/#scprint.utils.utils.load_genes","text":"load_genes loads the genes for a given organism. Parameters: organisms ( Union [ str , list ] , default: 'NCBITaxon:9606' ) \u2013 A string or list of strings representing the organism(s) to load genes for. Defaults to \"NCBITaxon:9606\". Returns: \u2013 pd.DataFrame: A DataFrame containing gene information for the specified organism(s). Source code in scprint/utils/utils.py 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 def load_genes ( organisms : Union [ str , list ] = \"NCBITaxon:9606\" ): # \"NCBITaxon:10090\", \"\"\" load_genes loads the genes for a given organism. Args: organisms (Union[str, list], optional): A string or list of strings representing the organism(s) to load genes for. Defaults to \"NCBITaxon:9606\". Returns: pd.DataFrame: A DataFrame containing gene information for the specified organism(s). \"\"\" organismdf = [] if type ( organisms ) is str : organisms = [ organisms ] for organism in organisms : genesdf = bt . Gene . filter ( organism_id = bt . Organism . filter ( ontology_id = organism ) . first () . id ) . df () genesdf = genesdf [ ~ genesdf [ \"public_source_id\" ] . isna ()] genesdf = genesdf . drop_duplicates ( subset = \"ensembl_gene_id\" ) genesdf = genesdf . set_index ( \"ensembl_gene_id\" ) . sort_index () # mitochondrial genes genesdf [ \"mt\" ] = genesdf . symbol . astype ( str ) . str . startswith ( \"MT-\" ) # ribosomal genes genesdf [ \"ribo\" ] = genesdf . symbol . astype ( str ) . str . startswith (( \"RPS\" , \"RPL\" )) # hemoglobin genes. genesdf [ \"hb\" ] = genesdf . symbol . astype ( str ) . str . contains (( \"^HB[^(P)]\" )) genesdf [ \"organism\" ] = organism organismdf . append ( genesdf ) organismdf = pd . concat ( organismdf ) organismdf . drop ( columns = [ \"source_id\" , \"stable_id\" , \"run_id\" , \"created_by_id\" , \"updated_at\" ], inplace = True , ) return organismdf","title":"load_genes"},{"location":"utils/#scprint.utils.utils.prepare_device","text":"setup GPU device if available. get gpu device indices which are used for DataParallel Source code in scprint/utils/utils.py 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 def prepare_device ( n_gpu_use ): \"\"\" setup GPU device if available. get gpu device indices which are used for DataParallel \"\"\" n_gpu = torch . cuda . device_count () if n_gpu_use > 0 and n_gpu == 0 : print ( \"Warning: There's no GPU available on this machine,\" \"training will be performed on CPU.\" ) n_gpu_use = 0 if n_gpu_use > n_gpu : print ( f \"Warning: The number of GPU's configured to use is { n_gpu_use } , but only { n_gpu } are \" \"available on this machine.\" ) n_gpu_use = n_gpu device = torch . device ( \"cuda:0\" if n_gpu_use > 0 else \"cpu\" ) list_ids = list ( range ( n_gpu_use )) return device , list_ids","title":"prepare_device"},{"location":"utils/#scprint.utils.utils.run_command","text":"run_command runs a command in the shell and prints the output. Parameters: command ( str ) \u2013 The command to be executed in the shell. Returns: int \u2013 The return code of the command executed. Source code in scprint/utils/utils.py 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def run_command ( command : str , ** kwargs ): \"\"\" run_command runs a command in the shell and prints the output. Args: command (str): The command to be executed in the shell. Returns: int: The return code of the command executed. \"\"\" process = subprocess . Popen ( command , stdout = subprocess . PIPE , ** kwargs ) while True : if process . poll () is not None : break output = process . stdout . readline () if output : print ( output . strip ()) rc = process . poll () return rc","title":"run_command"},{"location":"utils/#scprint.utils.utils.set_seed","text":"set random seed. Source code in scprint/utils/utils.py 77 78 79 80 81 82 83 def set_seed ( seed : int = 42 ): \"\"\"set random seed.\"\"\" random . seed ( seed ) np . random . seed ( seed ) torch . manual_seed ( seed ) torch . backends . cudnn . deterministic = True torch . backends . cudnn . benchmark = False","title":"set_seed"},{"location":"utils/#scprint.utils.get_seq","text":"","title":"get_seq"},{"location":"utils/#scprint.utils.get_seq.load_fasta_species","text":"Downloads and caches FASTA files for a given species from the Ensembl FTP server. Parameters: species ( str , default: 'homo_sapiens' ) \u2013 The species name for which to download FASTA files. Defaults to \"homo_sapiens\". output_path ( str , default: '/tmp/data/fasta/' ) \u2013 The local directory path where the FASTA files will be saved. Defaults to \"/tmp/data/fasta/\". cache ( bool , default: True ) \u2013 If True, use cached files if they exist. If False, re-download the files. Defaults to True. Source code in scprint/utils/get_seq.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 def load_fasta_species ( species : str = \"homo_sapiens\" , output_path : str = \"/tmp/data/fasta/\" , cache : bool = True , ) -> None : \"\"\" Downloads and caches FASTA files for a given species from the Ensembl FTP server. Args: species (str, optional): The species name for which to download FASTA files. Defaults to \"homo_sapiens\". output_path (str, optional): The local directory path where the FASTA files will be saved. Defaults to \"/tmp/data/fasta/\". cache (bool, optional): If True, use cached files if they exist. If False, re-download the files. Defaults to True. \"\"\" ftp = ftplib . FTP ( \"ftp.ensembl.org\" ) ftp . login () ftp . cwd ( \"/pub/release-110/fasta/\" + species + \"/pep/\" ) file = list_files ( ftp , \".all.fa.gz\" )[ 0 ] local_file_path = output_path + file if not os . path . exists ( local_file_path ) or not cache : os . makedirs ( os . path . dirname ( local_file_path ), exist_ok = True ) with open ( local_file_path , \"wb\" ) as local_file : ftp . retrbinary ( \"RETR \" + file , local_file . write ) ftp . cwd ( \"/pub/release-110/fasta/\" + species + \"/ncrna/\" ) file = list_files ( ftp , \".ncrna.fa.gz\" )[ 0 ] local_file_path = output_path + file if not os . path . exists ( local_file_path ) or not cache : with open ( local_file_path , \"wb\" ) as local_file : ftp . retrbinary ( \"RETR \" + file , local_file . write ) ftp . quit ()","title":"load_fasta_species"},{"location":"utils/#scprint.utils.get_seq.seq","text":"Fetch nucleotide or amino acid sequence (FASTA) of a gene (and all its isoforms) or transcript by Ensembl, WormBase, or FlyBase ID. Parameters: ens_ids ( Union [ str , List [ str ]] ) \u2013 One or more Ensembl IDs (passed as string or list of strings). Also supports WormBase and FlyBase IDs. translate ( bool , default: False ) \u2013 Defines whether nucleotide or amino acid sequences are returned. Defaults to False (returns nucleotide sequences). Nucleotide sequences are fetched from the Ensembl REST API server. Amino acid sequences are fetched from the UniProt REST API server. isoforms ( bool , default: False ) \u2013 If True, returns the sequences of all known transcripts. Defaults to False. (Only for gene IDs.) parallel ( bool , default: True ) \u2013 If True, fetches sequences in parallel. Defaults to True. save ( bool , default: False ) \u2013 If True, saves output FASTA to current directory. Defaults to False. transcribe ( bool , default: None ) \u2013 Deprecated. Use 'translate' instead. seqtype ( str , default: None ) \u2013 Deprecated. Use 'translate' instead. verbose ( bool , default: True ) \u2013 If True, prints progress information. Defaults to True. Returns: List [ str ] \u2013 List[str]: A list containing the requested sequences, or a FASTA file if 'save' is True. Raises: ValueError \u2013 If an invalid Ensembl ID is provided. Source code in scprint/utils/get_seq.py 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 def seq ( ens_ids : Union [ str , List [ str ]], translate : bool = False , isoforms : bool = False , parallel : bool = True , save : bool = False , transcribe : Optional [ bool ] = None , seqtype : Optional [ str ] = None , verbose : bool = True , ) -> List [ str ]: \"\"\" Fetch nucleotide or amino acid sequence (FASTA) of a gene (and all its isoforms) or transcript by Ensembl, WormBase, or FlyBase ID. Args: ens_ids (Union[str, List[str]]): One or more Ensembl IDs (passed as string or list of strings). Also supports WormBase and FlyBase IDs. translate (bool, optional): Defines whether nucleotide or amino acid sequences are returned. Defaults to False (returns nucleotide sequences). Nucleotide sequences are fetched from the Ensembl REST API server. Amino acid sequences are fetched from the UniProt REST API server. isoforms (bool, optional): If True, returns the sequences of all known transcripts. Defaults to False. (Only for gene IDs.) parallel (bool, optional): If True, fetches sequences in parallel. Defaults to True. save (bool, optional): If True, saves output FASTA to current directory. Defaults to False. transcribe (bool, optional): Deprecated. Use 'translate' instead. seqtype (str, optional): Deprecated. Use 'translate' instead. verbose (bool, optional): If True, prints progress information. Defaults to True. Returns: List[str]: A list containing the requested sequences, or a FASTA file if 'save' is True. Raises: ValueError: If an invalid Ensembl ID is provided. \"\"\" # Handle deprecated arguments if seqtype : logging . error ( \"'seqtype' argument deprecated! Please use True/False argument 'translate' instead.\" ) return if transcribe : translate = transcribe ## Clean up arguments # Clean up Ensembl IDs # If single Ensembl ID passed as string, convert to list if type ( ens_ids ) is str : ens_ids = [ ens_ids ] # Remove Ensembl ID version if passed ens_ids_clean = [] temp = 0 for ensembl_ID in ens_ids : # But only for Ensembl ID (and not for flybase/wormbase IDs) if ensembl_ID . startswith ( \"ENS\" ): ens_ids_clean . append ( ensembl_ID . split ( \".\" )[ 0 ]) if \".\" in ensembl_ID and temp == 0 : if verbose : logging . info ( \"We noticed that you may have passed a version number with your Ensembl ID. \\n \" \"Please note that gget seq will return information linked to the latest Ensembl ID version.\" ) temp = + 1 else : ens_ids_clean . append ( ensembl_ID ) # Initiate empty 'fasta' fasta = [] ## Fetch nucleotide sequece if translate is False : # Define Ensembl REST API server server = ENSEMBL_REST_API # Define type of returned content from REST content_type = \"application/json\" # Initiate dictionary to save results for all IDs in master_dict = {} # Query REST APIs from https://rest.ensembl.org/ for ensembl_ID in ens_ids_clean : # Create dict to save query results results_dict = { ensembl_ID : {}} # If isoforms False, just fetch sequences of passed Ensembl ID if isoforms is False : # sequence/id/ query: Request sequence by stable identifier query = \"sequence/id/\" + ensembl_ID + \"?\" # Try if query valid try : # Submit query; this will throw RuntimeError if ID not found df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"id\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ({ \"seq\" : df_temp }) if verbose : logging . info ( f \"Requesting nucleotide sequence of { ensembl_ID } from Ensembl.\" ) except RuntimeError : logging . error ( f \"ID { ensembl_ID } not found. Please double-check spelling/arguments and try again.\" ) # If isoforms true, fetch sequences of isoforms instead if isoforms is True : # Get ID type (gene, transcript, ...) using gget info info_df = info ( ensembl_ID , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check if Ensembl ID was found if isinstance ( info_df , type ( None )): logging . warning ( f \"ID ' { ensembl_ID } ' not found. Please double-check spelling/arguments and try again.\" ) continue ens_ID_type = info_df . loc [ ensembl_ID ][ \"object_type\" ] # If the ID is a gene, get the IDs of all its transcripts if ens_ID_type == \"Gene\" : if verbose : logging . info ( f \"Requesting nucleotide sequences of all transcripts of { ensembl_ID } from Ensembl.\" ) for transcipt_id in info_df . loc [ ensembl_ID ][ \"all_transcripts\" ]: # Remove version number for Ensembl IDs (not for flybase/wormbase IDs) if transcipt_id . startswith ( \"ENS\" ): transcipt_id = transcipt_id . split ( \".\" )[ 0 ] # Try if query is valid try : # Define the REST query query = \"sequence/id/\" + transcipt_id + \"?\" # Submit query df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ( { f \" { transcipt_id } \" : df_temp } ) except RuntimeError : logging . error ( f \"ID { transcipt_id } not found. \" \"Please double-check spelling/arguments and try again.\" ) # If isoform true, but ID is not a gene; ignore the isoform parameter else : # Try if query is valid try : # Define the REST query query = \"sequence/id/\" + ensembl_ID + \"?\" # Submit query df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"id\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ({ \"seq\" : df_temp }) logging . info ( f \"Requesting nucleotide sequence of { ensembl_ID } from Ensembl.\" ) logging . warning ( \"The isoform option only applies to gene IDs.\" ) except RuntimeError : logging . error ( f \"ID { ensembl_ID } not found. \" \"Please double-check spelling/arguments and try again.\" ) # Add results to master dict master_dict . update ( results_dict ) # Build FASTA file for ens_ID in master_dict : for key in master_dict [ ens_ID ] . keys (): if key == \"seq\" : fasta . append ( \">\" + ens_ID + \" \" + master_dict [ ens_ID ][ key ][ \"desc\" ]) fasta . append ( master_dict [ ens_ID ][ key ][ \"seq\" ]) else : fasta . append ( \">\" + master_dict [ ens_ID ][ key ][ \"id\" ] + \" \" + master_dict [ ens_ID ][ key ][ \"desc\" ] ) fasta . append ( master_dict [ ens_ID ][ key ][ \"seq\" ]) ## Fetch amino acid sequences from UniProt if translate is True : if isoforms is False : # List to collect transcript IDs trans_ids = [] # Get ID type (gene, transcript, ...) using gget info info_df = info ( ens_ids_clean , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check that Ensembl ID was found missing = set ( ens_ids_clean ) - set ( info_df . index . values ) if len ( missing ) > 0 : logging . warning ( f \" { str ( missing ) } IDs not found. Please double-check spelling/arguments.\" ) ens_ID_type = info_df . loc [ ens_ids_clean [ 0 ]][ \"object_type\" ] # If the ID is a gene, use the ID of its canonical transcript if ens_ID_type == \"Gene\" : # Get ID of canonical transcript for ensembl_ID in info_df . index . values : can_trans = info_df . loc [ ensembl_ID ][ \"canonical_transcript\" ] if ensembl_ID . startswith ( \"ENS\" ): # Remove Ensembl ID version from transcript IDs and append to transcript IDs list temp_trans_id = can_trans . split ( \".\" )[ 0 ] trans_ids . append ( temp_trans_id ) elif ensembl_ID . startswith ( \"WB\" ): # Remove added \".\" at the end of transcript IDs temp_trans_id = \".\" . join ( can_trans . split ( \".\" )[: - 1 ]) # # For WormBase transcript IDs, also remove the version number for submission to UniProt API # temp_trans_id = \".\".join(temp_trans_id1.split(\".\")[:-1]) trans_ids . append ( temp_trans_id ) else : # Remove added \".\" at the end of other transcript IDs temp_trans_id = \".\" . join ( can_trans . split ( \".\" )[: - 1 ]) trans_ids . append ( temp_trans_id ) if verbose : logging . info ( f \"Requesting amino acid sequence of the canonical transcript { temp_trans_id } of gene { ensembl_ID } from UniProt.\" ) # If the ID is a transcript, append the ID directly elif ens_ID_type == \"Transcript\" : # # For WormBase transcript IDs, remove the version number for submission to UniProt API # if ensembl_ID.startswith(\"T\"): # trans_ids.append(\".\".join(ensembl_ID.split(\".\")[:-1])) # else: trans_ids = ens_ids_clean if verbose : logging . info ( f \"Requesting amino acid sequence of { trans_ids } from UniProt.\" ) else : logging . warning ( \"ensembl_IDs not recognized as either a gene or transcript ID. It will not be included in the UniProt query.\" ) # Fetch the amino acid sequences of the transcript Ensembl IDs df_uniprot = get_uniprot_seqs ( UNIPROT_REST_API , trans_ids ) # Add info_df.loc[ensembl_ID] to df_uniprot by joining on \"canonical_transcript\" / \"gene_name\" respectively import pdb pdb . set_trace () info_df . set_index ( \"canonical_transcript\" , inplace = True ) df_uniprot . loc [:, \"gene_id\" ] = info_df . loc [ df_uniprot [ \"query\" ], \"gene_name\" ] . values if isoforms is True : # List to collect transcript IDs trans_ids = [] for ensembl_ID in ens_ids_clean : # Get ID type (gene, transcript, ...) using gget info info_df = info ( ensembl_ID , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check that Ensembl ID was found if isinstance ( info_df , type ( None )): logging . warning ( f \"ID ' { ensembl_ID } ' not found. Please double-check spelling/arguments.\" ) continue ens_ID_type = info_df . loc [ ensembl_ID ][ \"object_type\" ] # If the ID is a gene, get the IDs of all isoforms if ens_ID_type == \"Gene\" : # Get the IDs of all transcripts from the gget info results for transcipt_id in info_df . loc [ ensembl_ID ][ \"all_transcripts\" ]: if ensembl_ID . startswith ( \"ENS\" ): # Append transcript ID (without Ensembl version number) to list of transcripts to fetch trans_ids . append ( transcipt_id . split ( \".\" )[ 0 ]) # elif ensembl_ID.startswith(\"WB\"): # # For WormBase transcript IDs, remove the version number for submission to UniProt API # temp_trans_id = \".\".join(transcipt_id.split(\".\")[:-1]) # trans_ids.append(temp_trans_id) else : # Note: No need to remove the added \".\" at the end of unversioned transcripts here, because \"all_transcripts\" are returned without it trans_ids . append ( transcipt_id ) if verbose : logging . info ( f \"Requesting amino acid sequences of all transcripts of gene { ensembl_ID } from UniProt.\" ) elif ens_ID_type == \"Transcript\" : # # For WormBase transcript IDs, remove the version number for submission to UniProt API # if ensembl_ID.startswith(\"T\"): # trans_ids.append(\".\".join(ensembl_ID.split(\".\")[:-1])) # else: trans_ids . append ( ensembl_ID ) if verbose : logging . info ( f \"Requesting amino acid sequence of { ensembl_ID } from UniProt.\" ) logging . warning ( \"The isoform option only applies to gene IDs.\" ) else : logging . warning ( f \" { ensembl_ID } not recognized as either a gene or transcript ID. It will not be included in the UniProt query.\" ) # Fetch amino acid sequences of all isoforms from the UniProt REST API df_uniprot = get_uniprot_seqs ( UNIPROT_REST_API , trans_ids ) # Check if any results were found if len ( df_uniprot ) < 1 : logging . error ( \"No UniProt amino acid sequences were found for these ID(s).\" ) else : # Build FASTA file from UniProt results for ( uniprot_id , query_ensembl_id , gene_name , organism , sequence_length , uniprot_seq , ) in zip ( df_uniprot [ \"uniprot_id\" ] . values , df_uniprot [ \"query\" ] . values , df_uniprot [ \"gene_name\" ] . values , df_uniprot [ \"gene_id\" ] . values , df_uniprot [ \"organism\" ] . values , df_uniprot [ \"sequence_length\" ] . values , df_uniprot [ \"sequence\" ] . values , ): fasta . append ( \">\" + str ( query_ensembl_id ) + \" uniprot_id: \" + str ( uniprot_id ) + \" ensembl_id: \" + str ( query_ensembl_id ) + \" gene_name: \" + str ( gene_name ) + \" organism: \" + str ( organism ) + \" sequence_length: \" + str ( sequence_length ) ) fasta . append ( str ( uniprot_seq )) # Save if save : file = open ( \"gget_seq_results.fa\" , \"w\" ) for element in fasta : file . write ( element + \" \\n \" ) file . close () # missed samples return ( set ( trans_ids ) - set ( df_uniprot [ \"query\" ] . values )) | set ( missing ) return fasta","title":"seq"},{"location":"utils/#scprint.utils.get_seq.subset_fasta","text":"subset_fasta: creates a new fasta file with only the sequence which names contain one of gene_names Parameters: gene_tosubset ( set ) \u2013 A set of gene names to subset from the original FASTA file. fasta_path ( str ) \u2013 The path to the original FASTA file. subfasta_path ( str , default: './data/fasta/subset.fa' ) \u2013 The path to save the subsetted FASTA file. Defaults to \"./data/fasta/subset.fa\". drop_unknown_seq ( bool , default: True ) \u2013 If True, drop sequences containing unknown amino acids (denoted by '*'). Defaults to True. Returns: set ( set ) \u2013 A set of gene names that were found and included in the subsetted FASTA file. Raises: ValueError \u2013 If a gene name does not start with \"ENS\". Source code in scprint/utils/get_seq.py 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 def subset_fasta ( gene_tosubset : set , fasta_path : str , subfasta_path : str = \"./data/fasta/subset.fa\" , drop_unknown_seq : bool = True , ) -> set : \"\"\" subset_fasta: creates a new fasta file with only the sequence which names contain one of gene_names Args: gene_tosubset (set): A set of gene names to subset from the original FASTA file. fasta_path (str): The path to the original FASTA file. subfasta_path (str, optional): The path to save the subsetted FASTA file. Defaults to \"./data/fasta/subset.fa\". drop_unknown_seq (bool, optional): If True, drop sequences containing unknown amino acids (denoted by '*'). Defaults to True. Returns: set: A set of gene names that were found and included in the subsetted FASTA file. Raises: ValueError: If a gene name does not start with \"ENS\". \"\"\" dup = set () weird = 0 genes_found = set () gene_tosubset = set ( gene_tosubset ) with open ( fasta_path , \"r\" ) as original_fasta , open ( subfasta_path , \"w\" ) as subset_fasta : for record in SeqIO . parse ( original_fasta , \"fasta\" ): gene_name = ( record . description . split ( \" gene:\" )[ 1 ] . split ( \" transcript\" )[ 0 ] . split ( \".\" )[ 0 ] ) if gene_name in gene_tosubset : if drop_unknown_seq : if \"*\" in record . seq : weird += 1 continue if not gene_name . startswith ( \"ENS\" ): raise ValueError ( \"issue\" , gene_name ) if gene_name in genes_found : dup . add ( gene_name ) continue record . description = \"\" record . id = gene_name SeqIO . write ( record , subset_fasta , \"fasta\" ) genes_found . add ( gene_name ) print ( len ( dup ), \" genes had duplicates\" ) print ( \"dropped\" , weird , \"weird sequences\" ) return genes_found","title":"subset_fasta"},{"location":"notebooks/cancer_usecase/","text":"(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.ClipboardCopyElement = factory()); }(this, function () { 'use strict'; function createNode(text) { const node = document.createElement('pre'); node.style.width = '1px'; node.style.height = '1px'; node.style.position = 'fixed'; node.style.top = '5px'; node.textContent = text; return node; } function copyNode(node) { if ('clipboard' in navigator) { // eslint-disable-next-line flowtype/no-flow-fix-me-comments // $FlowFixMe Clipboard is not defined in Flow yet. return navigator.clipboard.writeText(node.textContent); } const selection = getSelection(); if (selection == null) { return Promise.reject(new Error()); } selection.removeAllRanges(); const range = document.createRange(); range.selectNodeContents(node); selection.addRange(range); document.execCommand('copy'); selection.removeAllRanges(); return Promise.resolve(); } function copyText(text) { if ('clipboard' in navigator) { // eslint-disable-next-line flowtype/no-flow-fix-me-comments // $FlowFixMe Clipboard is not defined in Flow yet. return navigator.clipboard.writeText(text); } const body = document.body; if (!body) { return Promise.reject(new Error()); } const node = createNode(text); body.appendChild(node); copyNode(node); body.removeChild(node); return Promise.resolve(); } function copy(button) { const id = button.getAttribute('for'); const text = button.getAttribute('value'); function trigger() { button.dispatchEvent(new CustomEvent('clipboard-copy', { bubbles: true })); } if (text) { copyText(text).then(trigger); } else if (id) { const root = 'getRootNode' in Element.prototype ? button.getRootNode() : button.ownerDocument; if (!(root instanceof Document || 'ShadowRoot' in window && root instanceof ShadowRoot)) return; const node = root.getElementById(id); if (node) copyTarget(node).then(trigger); } } function copyTarget(content) { if (content instanceof HTMLInputElement || content instanceof HTMLTextAreaElement) { return copyText(content.value); } else if (content instanceof HTMLAnchorElement && content.hasAttribute('href')) { return copyText(content.href); } else { return copyNode(content); } } function clicked(event) { const button = event.currentTarget; if (button instanceof HTMLElement) { copy(button); } } function keydown(event) { if (event.key === ' ' || event.key === 'Enter') { const button = event.currentTarget; if (button instanceof HTMLElement) { event.preventDefault(); copy(button); } } } function focused(event) { event.currentTarget.addEventListener('keydown', keydown); } function blurred(event) { event.currentTarget.removeEventListener('keydown', keydown); } class ClipboardCopyElement extends HTMLElement { constructor() { super(); this.addEventListener('click', clicked); this.addEventListener('focus', focused); this.addEventListener('blur', blurred); } connectedCallback() { if (!this.hasAttribute('tabindex')) { this.setAttribute('tabindex', '0'); } if (!this.hasAttribute('role')) { this.setAttribute('role', 'button'); } } get value() { return this.getAttribute('value') || ''; } set value(text) { this.setAttribute('value', text); } } if (!window.customElements.get('clipboard-copy')) { window.ClipboardCopyElement = ClipboardCopyElement; window.customElements.define('clipboard-copy', ClipboardCopyElement); } return ClipboardCopyElement; })); document.addEventListener('clipboard-copy', function(event) { const notice = event.target.querySelector('.notice') notice.hidden = false setTimeout(function() { notice.hidden = true }, 1000) }) pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) } .highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) } .highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */ .highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */ .highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */ .highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */ .highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */ .highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */ .highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */ .highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */ .highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */ .highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */ .highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */ .highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */ .highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */ .highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */ .highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */ .highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */ .highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */ .highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */ .highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */ .highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */ .highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */ .highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */ .highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */ .highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */ .highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */ .highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */ .highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */ .highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */ .highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */ .highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */ .highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */ .highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */ .highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */ .highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */ .highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */ .highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */ .highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */ .highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */ .highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */ .highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */ .highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */ @charset \"UTF-8\";.jupyter-wrapper{--md-red-50: #ffebee;--md-red-100: #ffcdd2;--md-red-200: #ef9a9a;--md-red-300: #e57373;--md-red-400: #ef5350;--md-red-500: #f44336;--md-red-600: #e53935;--md-red-700: #d32f2f;--md-red-800: #c62828;--md-red-900: #b71c1c;--md-red-A100: #ff8a80;--md-red-A200: #ff5252;--md-red-A400: #ff1744;--md-red-A700: #d50000;--md-pink-50: #fce4ec;--md-pink-100: #f8bbd0;--md-pink-200: #f48fb1;--md-pink-300: #f06292;--md-pink-400: #ec407a;--md-pink-500: #e91e63;--md-pink-600: #d81b60;--md-pink-700: #c2185b;--md-pink-800: #ad1457;--md-pink-900: #880e4f;--md-pink-A100: #ff80ab;--md-pink-A200: #ff4081;--md-pink-A400: #f50057;--md-pink-A700: #c51162;--md-purple-50: #f3e5f5;--md-purple-100: #e1bee7;--md-purple-200: #ce93d8;--md-purple-300: #ba68c8;--md-purple-400: #ab47bc;--md-purple-500: #9c27b0;--md-purple-600: #8e24aa;--md-purple-700: #7b1fa2;--md-purple-800: #6a1b9a;--md-purple-900: #4a148c;--md-purple-A100: #ea80fc;--md-purple-A200: #e040fb;--md-purple-A400: #d500f9;--md-purple-A700: #aa00ff;--md-deep-purple-50: #ede7f6;--md-deep-purple-100: #d1c4e9;--md-deep-purple-200: #b39ddb;--md-deep-purple-300: #9575cd;--md-deep-purple-400: #7e57c2;--md-deep-purple-500: #673ab7;--md-deep-purple-600: #5e35b1;--md-deep-purple-700: #512da8;--md-deep-purple-800: #4527a0;--md-deep-purple-900: #311b92;--md-deep-purple-A100: #b388ff;--md-deep-purple-A200: #7c4dff;--md-deep-purple-A400: #651fff;--md-deep-purple-A700: #6200ea;--md-indigo-50: #e8eaf6;--md-indigo-100: #c5cae9;--md-indigo-200: #9fa8da;--md-indigo-300: #7986cb;--md-indigo-400: #5c6bc0;--md-indigo-500: #3f51b5;--md-indigo-600: #3949ab;--md-indigo-700: #303f9f;--md-indigo-800: #283593;--md-indigo-900: #1a237e;--md-indigo-A100: #8c9eff;--md-indigo-A200: #536dfe;--md-indigo-A400: #3d5afe;--md-indigo-A700: #304ffe;--md-blue-50: #e3f2fd;--md-blue-100: #bbdefb;--md-blue-200: #90caf9;--md-blue-300: #64b5f6;--md-blue-400: #42a5f5;--md-blue-500: #2196f3;--md-blue-600: #1e88e5;--md-blue-700: #1976d2;--md-blue-800: #1565c0;--md-blue-900: #0d47a1;--md-blue-A100: #82b1ff;--md-blue-A200: #448aff;--md-blue-A400: #2979ff;--md-blue-A700: #2962ff;--md-light-blue-50: #e1f5fe;--md-light-blue-100: #b3e5fc;--md-light-blue-200: #81d4fa;--md-light-blue-300: #4fc3f7;--md-light-blue-400: #29b6f6;--md-light-blue-500: #03a9f4;--md-light-blue-600: #039be5;--md-light-blue-700: #0288d1;--md-light-blue-800: #0277bd;--md-light-blue-900: #01579b;--md-light-blue-A100: #80d8ff;--md-light-blue-A200: #40c4ff;--md-light-blue-A400: #00b0ff;--md-light-blue-A700: #0091ea;--md-cyan-50: #e0f7fa;--md-cyan-100: #b2ebf2;--md-cyan-200: #80deea;--md-cyan-300: #4dd0e1;--md-cyan-400: #26c6da;--md-cyan-500: #00bcd4;--md-cyan-600: #00acc1;--md-cyan-700: #0097a7;--md-cyan-800: #00838f;--md-cyan-900: #006064;--md-cyan-A100: #84ffff;--md-cyan-A200: #18ffff;--md-cyan-A400: #00e5ff;--md-cyan-A700: #00b8d4;--md-teal-50: #e0f2f1;--md-teal-100: #b2dfdb;--md-teal-200: #80cbc4;--md-teal-300: #4db6ac;--md-teal-400: #26a69a;--md-teal-500: #009688;--md-teal-600: #00897b;--md-teal-700: #00796b;--md-teal-800: #00695c;--md-teal-900: #004d40;--md-teal-A100: #a7ffeb;--md-teal-A200: #64ffda;--md-teal-A400: #1de9b6;--md-teal-A700: #00bfa5;--md-green-50: #e8f5e9;--md-green-100: #c8e6c9;--md-green-200: #a5d6a7;--md-green-300: #81c784;--md-green-400: #66bb6a;--md-green-500: #4caf50;--md-green-600: #43a047;--md-green-700: #388e3c;--md-green-800: #2e7d32;--md-green-900: #1b5e20;--md-green-A100: #b9f6ca;--md-green-A200: #69f0ae;--md-green-A400: #00e676;--md-green-A700: #00c853;--md-light-green-50: #f1f8e9;--md-light-green-100: #dcedc8;--md-light-green-200: #c5e1a5;--md-light-green-300: #aed581;--md-light-green-400: #9ccc65;--md-light-green-500: #8bc34a;--md-light-green-600: #7cb342;--md-light-green-700: #689f38;--md-light-green-800: #558b2f;--md-light-green-900: #33691e;--md-light-green-A100: #ccff90;--md-light-green-A200: #b2ff59;--md-light-green-A400: #76ff03;--md-light-green-A700: #64dd17;--md-lime-50: #f9fbe7;--md-lime-100: #f0f4c3;--md-lime-200: #e6ee9c;--md-lime-300: #dce775;--md-lime-400: #d4e157;--md-lime-500: #cddc39;--md-lime-600: #c0ca33;--md-lime-700: #afb42b;--md-lime-800: #9e9d24;--md-lime-900: #827717;--md-lime-A100: #f4ff81;--md-lime-A200: #eeff41;--md-lime-A400: #c6ff00;--md-lime-A700: #aeea00;--md-yellow-50: #fffde7;--md-yellow-100: #fff9c4;--md-yellow-200: #fff59d;--md-yellow-300: #fff176;--md-yellow-400: #ffee58;--md-yellow-500: #ffeb3b;--md-yellow-600: #fdd835;--md-yellow-700: #fbc02d;--md-yellow-800: #f9a825;--md-yellow-900: #f57f17;--md-yellow-A100: #ffff8d;--md-yellow-A200: #ffff00;--md-yellow-A400: #ffea00;--md-yellow-A700: #ffd600;--md-amber-50: #fff8e1;--md-amber-100: #ffecb3;--md-amber-200: #ffe082;--md-amber-300: #ffd54f;--md-amber-400: #ffca28;--md-amber-500: #ffc107;--md-amber-600: #ffb300;--md-amber-700: #ffa000;--md-amber-800: #ff8f00;--md-amber-900: #ff6f00;--md-amber-A100: #ffe57f;--md-amber-A200: #ffd740;--md-amber-A400: #ffc400;--md-amber-A700: #ffab00;--md-orange-50: #fff3e0;--md-orange-100: #ffe0b2;--md-orange-200: #ffcc80;--md-orange-300: #ffb74d;--md-orange-400: #ffa726;--md-orange-500: #ff9800;--md-orange-600: #fb8c00;--md-orange-700: #f57c00;--md-orange-800: #ef6c00;--md-orange-900: #e65100;--md-orange-A100: #ffd180;--md-orange-A200: #ffab40;--md-orange-A400: #ff9100;--md-orange-A700: #ff6d00;--md-deep-orange-50: #fbe9e7;--md-deep-orange-100: #ffccbc;--md-deep-orange-200: #ffab91;--md-deep-orange-300: #ff8a65;--md-deep-orange-400: #ff7043;--md-deep-orange-500: #ff5722;--md-deep-orange-600: #f4511e;--md-deep-orange-700: #e64a19;--md-deep-orange-800: #d84315;--md-deep-orange-900: #bf360c;--md-deep-orange-A100: #ff9e80;--md-deep-orange-A200: #ff6e40;--md-deep-orange-A400: #ff3d00;--md-deep-orange-A700: #dd2c00;--md-brown-50: #efebe9;--md-brown-100: #d7ccc8;--md-brown-200: #bcaaa4;--md-brown-300: #a1887f;--md-brown-400: #8d6e63;--md-brown-500: #795548;--md-brown-600: #6d4c41;--md-brown-700: #5d4037;--md-brown-800: #4e342e;--md-brown-900: #3e2723;--md-grey-50: #fafafa;--md-grey-100: #f5f5f5;--md-grey-200: #eeeeee;--md-grey-300: #e0e0e0;--md-grey-400: #bdbdbd;--md-grey-500: #9e9e9e;--md-grey-600: #757575;--md-grey-700: #616161;--md-grey-800: #424242;--md-grey-900: #212121;--md-blue-grey-50: #eceff1;--md-blue-grey-100: #cfd8dc;--md-blue-grey-200: #b0bec5;--md-blue-grey-300: #90a4ae;--md-blue-grey-400: #78909c;--md-blue-grey-500: #607d8b;--md-blue-grey-600: #546e7a;--md-blue-grey-700: #455a64;--md-blue-grey-800: #37474f;--md-blue-grey-900: #263238}.jupyter-wrapper{--jp-shadow-base-lightness: 0;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-400);--jp-border-color1: var(--md-grey-400);--jp-border-color2: var(--md-grey-300);--jp-border-color3: var(--md-grey-200);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(0, 0, 0, 1);--jp-ui-font-color1: rgba(0, 0, 0, .87);--jp-ui-font-color2: rgba(0, 0, 0, .54);--jp-ui-font-color3: rgba(0, 0, 0, .38);--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color2: rgba(255, 255, 255, .7);--jp-ui-inverse-font-color3: rgba(255, 255, 255, .5);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(0, 0, 0, 1);--jp-content-font-color1: rgba(0, 0, 0, .87);--jp-content-font-color2: rgba(0, 0, 0, .54);--jp-content-font-color3: rgba(0, 0, 0, .38);--jp-content-link-color: var(--md-blue-700);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: white;--jp-layout-color1: white;--jp-layout-color2: var(--md-grey-200);--jp-layout-color3: var(--md-grey-400);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: #111111;--jp-inverse-layout-color1: var(--md-grey-900);--jp-inverse-layout-color2: var(--md-grey-800);--jp-inverse-layout-color3: var(--md-grey-700);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-900);--jp-brand-color1: var(--md-blue-700);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-900);--jp-accent-color1: var(--md-green-700);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-900);--jp-warn-color1: var(--md-orange-700);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-900);--jp-error-color1: var(--md-red-700);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-900);--jp-success-color1: var(--md-green-700);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-900);--jp-info-color1: var(--md-cyan-700);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--md-grey-100);--jp-cell-editor-border-color: var(--md-grey-300);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: .5;--jp-cell-prompt-not-active-font-color: var(--md-grey-700);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: var(--md-blue-50);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: #fdd;--jp-rendermime-table-row-background: var(--md-grey-100);--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);--jp-dialog-background: rgba(0, 0, 0, .25);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color1);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .24);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--md-grey-300);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color1);--jp-input-hover-background: var(--jp-layout-color1);--jp-input-background: var(--md-grey-100);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: #d9d9d9;--jp-editor-selected-focused-background: #d7d4f0;--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: #008000;--jp-mirror-editor-atom-color: #88f;--jp-mirror-editor-number-color: #080;--jp-mirror-editor-def-color: #00f;--jp-mirror-editor-variable-color: var(--md-grey-900);--jp-mirror-editor-variable-2-color: #05a;--jp-mirror-editor-variable-3-color: #085;--jp-mirror-editor-punctuation-color: #05a;--jp-mirror-editor-property-color: #05a;--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ba2121;--jp-mirror-editor-string-2-color: #708;--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: #008000;--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: #170;--jp-mirror-editor-attribute-color: #00c;--jp-mirror-editor-header-color: blue;--jp-mirror-editor-quote-color: #090;--jp-mirror-editor-link-color: #00c;--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ffad8e;--jp-collaborator-color2: #dac83d;--jp-collaborator-color3: #72dd76;--jp-collaborator-color4: #00e4d0;--jp-collaborator-color5: #45d4ff;--jp-collaborator-color6: #e2b1ff;--jp-collaborator-color7: #ff9de6;--jp-vega-background: white;--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .5;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(245, 200, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-700);--jp-console-icon-background-color: var(--md-blue-700);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-800);--jp-terminal-icon-color: var(--md-grey-200);--jp-text-editor-icon-color: var(--md-grey-700);--jp-inspector-icon-color: var(--md-grey-700);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-900)}[data-md-color-scheme=slate] .jupyter-wrapper{--jp-shadow-base-lightness: 32;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-700);--jp-border-color1: var(--md-grey-700);--jp-border-color2: var(--md-grey-800);--jp-border-color3: var(--md-grey-900);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(255, 255, 255, 1);--jp-ui-font-color1: rgba(255, 255, 255, .87);--jp-ui-font-color2: rgba(255, 255, 255, .54);--jp-ui-font-color3: rgba(255, 255, 255, .38);--jp-ui-inverse-font-color0: rgba(0, 0, 0, 1);--jp-ui-inverse-font-color1: rgba(0, 0, 0, .8);--jp-ui-inverse-font-color2: rgba(0, 0, 0, .5);--jp-ui-inverse-font-color3: rgba(0, 0, 0, .3);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(255, 255, 255, 1);--jp-content-font-color1: rgba(255, 255, 255, 1);--jp-content-font-color2: rgba(255, 255, 255, .7);--jp-content-font-color3: rgba(255, 255, 255, .5);--jp-content-link-color: var(--md-blue-300);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: #111111;--jp-layout-color1: var(--md-grey-900);--jp-layout-color2: var(--md-grey-800);--jp-layout-color3: var(--md-grey-700);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: white;--jp-inverse-layout-color1: white;--jp-inverse-layout-color2: var(--md-grey-200);--jp-inverse-layout-color3: var(--md-grey-400);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-700);--jp-brand-color1: var(--md-blue-500);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-700);--jp-accent-color1: var(--md-green-500);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-700);--jp-warn-color1: var(--md-orange-500);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-700);--jp-error-color1: var(--md-red-500);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-700);--jp-success-color1: var(--md-green-500);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-700);--jp-info-color1: var(--md-cyan-500);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--jp-layout-color1);--jp-cell-editor-border-color: var(--md-grey-700);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: 1;--jp-cell-prompt-not-active-font-color: var(--md-grey-300);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: rgba(33, 150, 243, .24);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: rgba(244, 67, 54, .28);--jp-rendermime-table-row-background: var(--md-grey-900);--jp-rendermime-table-row-hover-background: rgba(3, 169, 244, .2);--jp-dialog-background: rgba(0, 0, 0, .6);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color2);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .8);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--jp-layout-color0);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color0);--jp-input-hover-background: var(--jp-layout-color2);--jp-input-background: var(--md-grey-800);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: var(--jp-layout-color2);--jp-editor-selected-focused-background: rgba(33, 150, 243, .24);--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: var(--md-green-500);--jp-mirror-editor-atom-color: var(--md-blue-300);--jp-mirror-editor-number-color: var(--md-green-400);--jp-mirror-editor-def-color: var(--md-blue-600);--jp-mirror-editor-variable-color: var(--md-grey-300);--jp-mirror-editor-variable-2-color: var(--md-blue-400);--jp-mirror-editor-variable-3-color: var(--md-green-600);--jp-mirror-editor-punctuation-color: var(--md-blue-400);--jp-mirror-editor-property-color: var(--md-blue-400);--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ff7070;--jp-mirror-editor-string-2-color: var(--md-purple-300);--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: var(--md-green-600);--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: var(--md-green-700);--jp-mirror-editor-attribute-color: var(--md-blue-700);--jp-mirror-editor-header-color: var(--md-blue-500);--jp-mirror-editor-quote-color: var(--md-green-300);--jp-mirror-editor-link-color: var(--md-blue-700);--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ad4a00;--jp-collaborator-color2: #7b6a00;--jp-collaborator-color3: #007e00;--jp-collaborator-color4: #008772;--jp-collaborator-color5: #0079b9;--jp-collaborator-color6: #8b45c6;--jp-collaborator-color7: #be208b;--jp-vega-background: var(--md-grey-400);--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .6;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(255, 225, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-scrollbar-background-color: #3f4244;--jp-scrollbar-thumb-color: 88, 96, 97;--jp-scrollbar-endpad: 3px;--jp-scrollbar-thumb-margin: 3.5px;--jp-scrollbar-thumb-radius: 9px;--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-500);--jp-console-icon-background-color: var(--md-blue-500);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-200);--jp-terminal-icon-color: var(--md-grey-800);--jp-text-editor-icon-color: var(--md-grey-200);--jp-inspector-icon-color: var(--md-grey-200);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-700)}.jupyter-wrapper [data-jp-theme-scrollbars=true]{scrollbar-color:rgb(var(--jp-scrollbar-thumb-color)) var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar{scrollbar-color:rgba(var(--jp-scrollbar-thumb-color),.5) transparent}.jupyter-wrapper .jp-scrollbar-tiny{scrollbar-color:rgba(var(--jp-scrollbar-thumb-color),.5) transparent;scrollbar-width:thin}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-corner{background:var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-thumb{background:rgb(var(--jp-scrollbar-thumb-color));border:var(--jp-scrollbar-thumb-margin) solid transparent;background-clip:content-box;border-radius:var(--jp-scrollbar-thumb-radius)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-track:horizontal{border-left:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color);border-right:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-track:vertical{border-top:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color);border-bottom:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-corner,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-corner{background-color:transparent}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-thumb,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-thumb{background:rgba(var(--jp-scrollbar-thumb-color),.5);border:var(--jp-scrollbar-thumb-margin) solid transparent;background-clip:content-box;border-radius:var(--jp-scrollbar-thumb-radius)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-track:horizontal{border-left:var(--jp-scrollbar-endpad) solid transparent;border-right:var(--jp-scrollbar-endpad) solid transparent}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-track:vertical{border-top:var(--jp-scrollbar-endpad) solid transparent;border-bottom:var(--jp-scrollbar-endpad) solid transparent}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar,.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-corner{background-color:transparent;height:4px;width:4px}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-thumb{background:rgba(var(--jp-scrollbar-thumb-color),.5)}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-track:horizontal{border-left:0px solid transparent;border-right:0px solid transparent}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-track:vertical{border-top:0px solid transparent;border-bottom:0px solid transparent}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal]{min-height:16px;max-height:16px;min-width:45px;border-top:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical]{min-width:16px;max-width:16px;min-height:45px;border-left:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar-button{background-color:#f0f0f0;background-position:center center;min-height:15px;max-height:15px;min-width:15px;max-width:15px}.jupyter-wrapper .lm-ScrollBar-button:hover{background-color:#dadada}.jupyter-wrapper .lm-ScrollBar-button.lm-mod-active{background-color:#cdcdcd}.jupyter-wrapper .lm-ScrollBar-track{background:#f0f0f0}.jupyter-wrapper .lm-ScrollBar-thumb{background:#cdcdcd}.jupyter-wrapper .lm-ScrollBar-thumb:hover{background:#bababa}.jupyter-wrapper .lm-ScrollBar-thumb.lm-mod-active{background:#a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-thumb{height:100%;min-width:15px;border-left:1px solid #a0a0a0;border-right:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-thumb{width:100%;min-height:15px;border-top:1px solid #a0a0a0;border-bottom:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-button[data-action=decrement]{background-image:var(--jp-icon-caret-left);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-button[data-action=increment]{background-image:var(--jp-icon-caret-right);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-button[data-action=decrement]{background-image:var(--jp-icon-caret-up);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-button[data-action=increment]{background-image:var(--jp-icon-caret-down);background-size:17px}.jupyter-wrapper .p-Widget,.jupyter-wrapper .lm-Widget{box-sizing:border-box;position:relative;overflow:hidden;cursor:default}.jupyter-wrapper .p-Widget.p-mod-hidden,.jupyter-wrapper .lm-Widget.lm-mod-hidden{display:none!important}.jupyter-wrapper .lm-AccordionPanel[data-orientation=horizontal]>.lm-AccordionPanel-title{display:block;transform-origin:top left;transform:rotate(-90deg) translate(-100%)}.jupyter-wrapper .p-CommandPalette,.jupyter-wrapper .lm-CommandPalette{display:flex;flex-direction:column;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-CommandPalette-search,.jupyter-wrapper .lm-CommandPalette-search{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-content,.jupyter-wrapper .lm-CommandPalette-content{flex:1 1 auto;margin:0;padding:0;min-height:0;overflow:auto;list-style-type:none}.jupyter-wrapper .p-CommandPalette-header,.jupyter-wrapper .lm-CommandPalette-header{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .p-CommandPalette-item,.jupyter-wrapper .lm-CommandPalette-item{display:flex;flex-direction:row}.jupyter-wrapper .p-CommandPalette-itemIcon,.jupyter-wrapper .lm-CommandPalette-itemIcon{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-itemContent,.jupyter-wrapper .lm-CommandPalette-itemContent{flex:1 1 auto;overflow:hidden}.jupyter-wrapper .p-CommandPalette-itemShortcut,.jupyter-wrapper .lm-CommandPalette-itemShortcut{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-itemLabel,.jupyter-wrapper .lm-CommandPalette-itemLabel{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .lm-close-icon{border:1px solid transparent;background-color:transparent;position:absolute;z-index:1;right:3%;top:0;bottom:0;margin:auto;padding:7px 0;display:none;vertical-align:middle;outline:0;cursor:pointer}.jupyter-wrapper .lm-close-icon:after{content:\"X\";display:block;width:15px;height:15px;text-align:center;color:#000;font-weight:400;font-size:12px;cursor:pointer}.jupyter-wrapper .p-DockPanel,.jupyter-wrapper .lm-DockPanel,.jupyter-wrapper .p-DockPanel-widget,.jupyter-wrapper .lm-DockPanel-widget{z-index:0}.jupyter-wrapper .p-DockPanel-tabBar,.jupyter-wrapper .lm-DockPanel-tabBar{z-index:1}.jupyter-wrapper .p-DockPanel-handle,.jupyter-wrapper .lm-DockPanel-handle{z-index:2}.jupyter-wrapper .p-DockPanel-handle.p-mod-hidden,.jupyter-wrapper .lm-DockPanel-handle.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-DockPanel-handle:after,.jupyter-wrapper .lm-DockPanel-handle:after{position:absolute;top:0;left:0;width:100%;height:100%;content:\"\"}.jupyter-wrapper .p-DockPanel-handle[data-orientation=horizontal],.jupyter-wrapper .lm-DockPanel-handle[data-orientation=horizontal]{cursor:ew-resize}.jupyter-wrapper .p-DockPanel-handle[data-orientation=vertical],.jupyter-wrapper .lm-DockPanel-handle[data-orientation=vertical]{cursor:ns-resize}.jupyter-wrapper .p-DockPanel-handle[data-orientation=horizontal]:after,.jupyter-wrapper .lm-DockPanel-handle[data-orientation=horizontal]:after{left:50%;min-width:8px;transform:translate(-50%)}.jupyter-wrapper .p-DockPanel-handle[data-orientation=vertical]:after,.jupyter-wrapper .lm-DockPanel-handle[data-orientation=vertical]:after{top:50%;min-height:8px;transform:translateY(-50%)}.jupyter-wrapper .p-DockPanel-overlay,.jupyter-wrapper .lm-DockPanel-overlay{z-index:3;box-sizing:border-box;pointer-events:none}.jupyter-wrapper .p-DockPanel-overlay.p-mod-hidden,.jupyter-wrapper .lm-DockPanel-overlay.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-Menu,.jupyter-wrapper .lm-Menu{z-index:10000;position:absolute;white-space:nowrap;overflow-x:hidden;overflow-y:auto;outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-Menu-content,.jupyter-wrapper .lm-Menu-content{margin:0;padding:0;display:table;list-style-type:none}.jupyter-wrapper .p-Menu-item,.jupyter-wrapper .lm-Menu-item{display:table-row}.jupyter-wrapper .p-Menu-item.p-mod-hidden,.jupyter-wrapper .p-Menu-item.p-mod-collapsed,.jupyter-wrapper .lm-Menu-item.lm-mod-hidden,.jupyter-wrapper .lm-Menu-item.lm-mod-collapsed{display:none!important}.jupyter-wrapper .p-Menu-itemIcon,.jupyter-wrapper .p-Menu-itemSubmenuIcon,.jupyter-wrapper .lm-Menu-itemIcon,.jupyter-wrapper .lm-Menu-itemSubmenuIcon{display:table-cell;text-align:center}.jupyter-wrapper .p-Menu-itemLabel,.jupyter-wrapper .lm-Menu-itemLabel{display:table-cell;text-align:left}.jupyter-wrapper .p-Menu-itemShortcut,.jupyter-wrapper .lm-Menu-itemShortcut{display:table-cell;text-align:right}.jupyter-wrapper .p-MenuBar,.jupyter-wrapper .lm-MenuBar{outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-MenuBar-content,.jupyter-wrapper .lm-MenuBar-content{margin:0;padding:0;display:flex;flex-direction:row;list-style-type:none}.jupyter-wrapper .p--MenuBar-item,.jupyter-wrapper .lm-MenuBar-item{box-sizing:border-box}.jupyter-wrapper .p-MenuBar-itemIcon,.jupyter-wrapper .p-MenuBar-itemLabel,.jupyter-wrapper .lm-MenuBar-itemIcon,.jupyter-wrapper .lm-MenuBar-itemLabel{display:inline-block}.jupyter-wrapper .p-ScrollBar,.jupyter-wrapper .lm-ScrollBar{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-ScrollBar[data-orientation=horizontal],.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal]{flex-direction:row}.jupyter-wrapper .p-ScrollBar[data-orientation=vertical],.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical]{flex-direction:column}.jupyter-wrapper .p-ScrollBar-button,.jupyter-wrapper .lm-ScrollBar-button{box-sizing:border-box;flex:0 0 auto}.jupyter-wrapper .p-ScrollBar-track,.jupyter-wrapper .lm-ScrollBar-track{box-sizing:border-box;position:relative;overflow:hidden;flex:1 1 auto}.jupyter-wrapper .p-ScrollBar-thumb,.jupyter-wrapper .lm-ScrollBar-thumb{box-sizing:border-box;position:absolute}.jupyter-wrapper .p-SplitPanel-child,.jupyter-wrapper .lm-SplitPanel-child{z-index:0}.jupyter-wrapper .p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel-handle{z-index:1}.jupyter-wrapper .p-SplitPanel-handle.p-mod-hidden,.jupyter-wrapper .lm-SplitPanel-handle.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel-handle:after{position:absolute;top:0;left:0;width:100%;height:100%;content:\"\"}.jupyter-wrapper .p-SplitPanel[data-orientation=horizontal]>.p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel[data-orientation=horizontal]>.lm-SplitPanel-handle{cursor:ew-resize}.jupyter-wrapper .p-SplitPanel[data-orientation=vertical]>.p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel[data-orientation=vertical]>.lm-SplitPanel-handle{cursor:ns-resize}.jupyter-wrapper .p-SplitPanel[data-orientation=horizontal]>.p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel[data-orientation=horizontal]>.lm-SplitPanel-handle:after{left:50%;min-width:8px;transform:translate(-50%)}.jupyter-wrapper .p-SplitPanel[data-orientation=vertical]>.p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel[data-orientation=vertical]>.lm-SplitPanel-handle:after{top:50%;min-height:8px;transform:translateY(-50%)}.jupyter-wrapper .p-TabBar,.jupyter-wrapper .lm-TabBar{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-TabBar[data-orientation=horizontal],.jupyter-wrapper .lm-TabBar[data-orientation=horizontal]{flex-direction:row;align-items:flex-end}.jupyter-wrapper .p-TabBar[data-orientation=vertical],.jupyter-wrapper .lm-TabBar[data-orientation=vertical]{flex-direction:column;align-items:flex-end}.jupyter-wrapper .p-TabBar-content,.jupyter-wrapper .lm-TabBar-content{margin:0;padding:0;display:flex;flex:1 1 auto;list-style-type:none}.jupyter-wrapper .p-TabBar[data-orientation=horizontal]>.p-TabBar-content,.jupyter-wrapper .lm-TabBar[data-orientation=horizontal]>.lm-TabBar-content{flex-direction:row}.jupyter-wrapper .p-TabBar[data-orientation=vertical]>.p-TabBar-content,.jupyter-wrapper .lm-TabBar[data-orientation=vertical]>.lm-TabBar-content{flex-direction:column}.jupyter-wrapper .p-TabBar-tab,.jupyter-wrapper .lm-TabBar-tab{display:flex;flex-direction:row;box-sizing:border-box;overflow:hidden;touch-action:none}.jupyter-wrapper .p-TabBar-tabIcon,.jupyter-wrapper .p-TabBar-tabCloseIcon,.jupyter-wrapper .lm-TabBar-tabIcon,.jupyter-wrapper .lm-TabBar-tabCloseIcon{flex:0 0 auto}.jupyter-wrapper .p-TabBar-tabLabel,.jupyter-wrapper .lm-TabBar-tabLabel{flex:1 1 auto;overflow:hidden;white-space:nowrap}.jupyter-wrapper .lm-TabBar-tabInput{-webkit-user-select:all;user-select:all;width:100%;box-sizing:border-box}.jupyter-wrapper .p-TabBar-tab.p-mod-hidden,.jupyter-wrapper .lm-TabBar-tab.lm-mod-hidden,.jupyter-wrapper .lm-TabBar-addButton.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-TabBar.p-mod-dragging .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging .lm-TabBar-tab{position:relative}.jupyter-wrapper .p-TabBar.p-mod-dragging[data-orientation=horizontal] .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging[data-orientation=horizontal] .lm-TabBar-tab{left:0;transition:left .15s ease}.jupyter-wrapper .p-TabBar.p-mod-dragging[data-orientation=vertical] .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging[data-orientation=vertical] .lm-TabBar-tab{top:0;transition:top .15s ease}.jupyter-wrapper .p-TabBar.p-mod-dragging .p-TabBar-tab.p-mod-dragging,.jupyter-wrapper .lm-TabBar.lm-mod-dragging .lm-TabBar-tab.lm-mod-dragging{transition:none}.jupyter-wrapper .lm-TabBar-tabLabel .lm-TabBar-tabInput{-webkit-user-select:all;user-select:all;width:100%;box-sizing:border-box;background:inherit}.jupyter-wrapper .p-TabPanel-tabBar,.jupyter-wrapper .lm-TabPanel-tabBar{z-index:1}.jupyter-wrapper .p-TabPanel-stackedPanel,.jupyter-wrapper .lm-TabPanel-stackedPanel{z-index:0}.jupyter-wrapper html{-webkit-box-sizing:border-box;box-sizing:border-box}.jupyter-wrapper *,.jupyter-wrapper *:before,.jupyter-wrapper *:after{-webkit-box-sizing:inherit;box-sizing:inherit}.jupyter-wrapper body{font-size:14px;font-weight:400;letter-spacing:0;line-height:1.28581;text-transform:none;color:#182026;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,Icons16,sans-serif}.jupyter-wrapper p{margin-bottom:10px;margin-top:0}.jupyter-wrapper small{font-size:12px}.jupyter-wrapper strong{font-weight:600}.jupyter-wrapper ::-moz-selection{background:rgba(125,188,255,.6)}.jupyter-wrapper ::selection{background:rgba(125,188,255,.6)}.jupyter-wrapper .bp3-heading{color:#182026;font-weight:600;margin:0 0 10px;padding:0}.jupyter-wrapper .bp3-dark .bp3-heading{color:#f5f8fa}.jupyter-wrapper h1.bp3-heading,.jupyter-wrapper .bp3-running-text h1{font-size:36px;line-height:40px}.jupyter-wrapper h2.bp3-heading,.jupyter-wrapper .bp3-running-text h2{font-size:28px;line-height:32px}.jupyter-wrapper h3.bp3-heading,.jupyter-wrapper .bp3-running-text h3{font-size:22px;line-height:25px}.jupyter-wrapper h4.bp3-heading,.jupyter-wrapper .bp3-running-text h4{font-size:18px;line-height:21px}.jupyter-wrapper h5.bp3-heading,.jupyter-wrapper .bp3-running-text h5{font-size:16px;line-height:19px}.jupyter-wrapper h6.bp3-heading,.jupyter-wrapper .bp3-running-text h6{font-size:14px;line-height:16px}.jupyter-wrapper .bp3-ui-text{font-size:14px;font-weight:400;letter-spacing:0;line-height:1.28581;text-transform:none}.jupyter-wrapper .bp3-monospace-text{font-family:monospace;text-transform:none}.jupyter-wrapper .bp3-text-muted{color:#5c7080}.jupyter-wrapper .bp3-dark .bp3-text-muted{color:#a7b6c2}.jupyter-wrapper .bp3-text-disabled{color:#5c708099}.jupyter-wrapper .bp3-dark .bp3-text-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-text-overflow-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal}.jupyter-wrapper .bp3-running-text{font-size:14px;line-height:1.5}.jupyter-wrapper .bp3-running-text h1{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h1{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h2{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h2{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h3{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h3{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h4{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h4{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h5{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h5{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h6{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h6{color:#f5f8fa}.jupyter-wrapper .bp3-running-text hr{border:none;border-bottom:1px solid rgba(16,22,26,.15);margin:20px 0}.jupyter-wrapper .bp3-dark .bp3-running-text hr{border-color:#ffffff26}.jupyter-wrapper .bp3-running-text p{margin:0 0 10px;padding:0}.jupyter-wrapper .bp3-text-large{font-size:16px}.jupyter-wrapper .bp3-text-small{font-size:12px}.jupyter-wrapper a .bp3-icon,.jupyter-wrapper a .bp3-icon-standard,.jupyter-wrapper a .bp3-icon-large,.jupyter-wrapper a code,.jupyter-wrapper .bp3-dark a code{color:inherit}.jupyter-wrapper .bp3-dark a,.jupyter-wrapper .bp3-dark a:hover{color:#48aff0}.jupyter-wrapper .bp3-dark a .bp3-icon,.jupyter-wrapper .bp3-dark a .bp3-icon-standard,.jupyter-wrapper .bp3-dark a .bp3-icon-large,.jupyter-wrapper .bp3-dark a:hover .bp3-icon,.jupyter-wrapper .bp3-dark a:hover .bp3-icon-standard,.jupyter-wrapper .bp3-dark a:hover .bp3-icon-large{color:inherit}.jupyter-wrapper .bp3-running-text code,.jupyter-wrapper .bp3-code{font-family:monospace;text-transform:none;background:rgba(255,255,255,.7);border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33;color:#5c7080;font-size:smaller;padding:2px 5px}.jupyter-wrapper .bp3-dark .bp3-running-text code,.jupyter-wrapper .bp3-running-text .bp3-dark code,.jupyter-wrapper .bp3-dark .bp3-code{background:rgba(16,22,26,.3);-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66;color:#a7b6c2}.jupyter-wrapper .bp3-running-text a>code,.jupyter-wrapper a>.bp3-code{color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-running-text a>code,.jupyter-wrapper .bp3-running-text .bp3-dark a>code,.jupyter-wrapper .bp3-dark a>.bp3-code{color:inherit}.jupyter-wrapper .bp3-running-text pre,.jupyter-wrapper .bp3-code-block{font-family:monospace;text-transform:none;background:rgba(255,255,255,.7);border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26;color:#182026;display:block;font-size:13px;line-height:1.4;margin:10px 0;padding:13px 15px 12px;word-break:break-all;word-wrap:break-word}.jupyter-wrapper .bp3-dark .bp3-running-text pre,.jupyter-wrapper .bp3-running-text .bp3-dark pre,.jupyter-wrapper .bp3-dark .bp3-code-block{background:rgba(16,22,26,.3);-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-running-text pre>code,.jupyter-wrapper .bp3-code-block>code{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit;font-size:inherit;padding:0}.jupyter-wrapper .bp3-running-text kbd,.jupyter-wrapper .bp3-key{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#ffffff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;color:#5c7080;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-family:inherit;font-size:12px;height:24px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:24px;min-width:24px;padding:3px 6px;vertical-align:middle}.jupyter-wrapper .bp3-running-text kbd .bp3-icon,.jupyter-wrapper .bp3-key .bp3-icon,.jupyter-wrapper .bp3-running-text kbd .bp3-icon-standard,.jupyter-wrapper .bp3-key .bp3-icon-standard,.jupyter-wrapper .bp3-running-text kbd .bp3-icon-large,.jupyter-wrapper .bp3-key .bp3-icon-large{margin-right:5px}.jupyter-wrapper .bp3-dark .bp3-running-text kbd,.jupyter-wrapper .bp3-running-text .bp3-dark kbd,.jupyter-wrapper .bp3-dark .bp3-key{background:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66;color:#a7b6c2}.jupyter-wrapper .bp3-running-text blockquote,.jupyter-wrapper .bp3-blockquote{border-left:solid 4px rgba(167,182,194,.5);margin:0 0 10px;padding:0 20px}.jupyter-wrapper .bp3-dark .bp3-running-text blockquote,.jupyter-wrapper .bp3-running-text .bp3-dark blockquote,.jupyter-wrapper .bp3-dark .bp3-blockquote{border-color:#73869480}.jupyter-wrapper .bp3-running-text ul,.jupyter-wrapper .bp3-running-text ol,.jupyter-wrapper .bp3-list{margin:10px 0;padding-left:30px}.jupyter-wrapper .bp3-running-text ul li:not(:last-child),.jupyter-wrapper .bp3-running-text ol li:not(:last-child),.jupyter-wrapper .bp3-list li:not(:last-child){margin-bottom:5px}.jupyter-wrapper .bp3-running-text ul ol,.jupyter-wrapper .bp3-running-text ol ol,.jupyter-wrapper .bp3-list ol,.jupyter-wrapper .bp3-running-text ul ul,.jupyter-wrapper .bp3-running-text ol ul,.jupyter-wrapper .bp3-list ul{margin-top:5px}.jupyter-wrapper .bp3-list-unstyled{list-style:none;margin:0;padding:0}.jupyter-wrapper .bp3-list-unstyled li{padding:0}.jupyter-wrapper .bp3-rtl{text-align:right}.jupyter-wrapper .bp3-dark{color:#f5f8fa}.jupyter-wrapper :focus{outline:rgba(19,124,189,.6) auto 2px;outline-offset:2px;-moz-outline-radius:6px}.jupyter-wrapper .bp3-focus-disabled :focus{outline:none!important}.jupyter-wrapper .bp3-focus-disabled :focus~.bp3-control-indicator{outline:none!important}.jupyter-wrapper .bp3-alert{max-width:400px;padding:20px}.jupyter-wrapper .bp3-alert-body{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-alert-body .bp3-icon{font-size:40px;margin-right:20px;margin-top:0}.jupyter-wrapper .bp3-alert-contents{word-break:break-word}.jupyter-wrapper .bp3-alert-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;margin-top:10px}.jupyter-wrapper .bp3-alert-footer .bp3-button{margin-left:10px}.jupyter-wrapper .bp3-breadcrumbs{-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:default;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;height:30px;list-style:none;margin:0;padding:0}.jupyter-wrapper .bp3-breadcrumbs>li{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-breadcrumbs>li:after{background:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.71 7.29l-4-4a1.003 1.003 0 00-1.42 1.42L8.59 8 5.3 11.29c-.19.18-.3.43-.3.71a1.003 1.003 0 001.71.71l4-4c.18-.18.29-.43.29-.71 0-.28-.11-.53-.29-.71z' fill='%235C7080'/%3e%3c/svg%3e\");content:\"\";display:block;height:16px;margin:0 5px;width:16px}.jupyter-wrapper .bp3-breadcrumbs>li:last-of-type:after{display:none}.jupyter-wrapper .bp3-breadcrumb,.jupyter-wrapper .bp3-breadcrumb-current,.jupyter-wrapper .bp3-breadcrumbs-collapsed{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:16px}.jupyter-wrapper .bp3-breadcrumb,.jupyter-wrapper .bp3-breadcrumbs-collapsed{color:#5c7080}.jupyter-wrapper .bp3-breadcrumb:hover{text-decoration:none}.jupyter-wrapper .bp3-breadcrumb.bp3-disabled{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-breadcrumb .bp3-icon{margin-right:5px}.jupyter-wrapper .bp3-breadcrumb-current{color:inherit;font-weight:600}.jupyter-wrapper .bp3-breadcrumb-current .bp3-input{font-size:inherit;font-weight:inherit;vertical-align:baseline}.jupyter-wrapper .bp3-breadcrumbs-collapsed{background:#ced9e0;border:none;border-radius:3px;cursor:pointer;margin-right:2px;padding:1px 5px;vertical-align:text-bottom}.jupyter-wrapper .bp3-breadcrumbs-collapsed:before{background:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cg fill='%235C7080'%3e%3ccircle cx='2' cy='8.03' r='2'/%3e%3ccircle cx='14' cy='8.03' r='2'/%3e%3ccircle cx='8' cy='8.03' r='2'/%3e%3c/g%3e%3c/svg%3e\") center no-repeat;content:\"\";display:block;height:16px;width:16px}.jupyter-wrapper .bp3-breadcrumbs-collapsed:hover{background:#bfccd6;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-dark .bp3-breadcrumb,.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs>li:after{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-breadcrumb.bp3-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-breadcrumb-current{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed:hover{background:rgba(16,22,26,.6);color:#f5f8fa}.jupyter-wrapper .bp3-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;border-radius:3px;cursor:pointer;font-size:14px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:5px 10px;text-align:left;vertical-align:middle;min-height:30px;min-width:30px}.jupyter-wrapper .bp3-button>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-button>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-button:before,.jupyter-wrapper .bp3-button>*{margin-right:7px}.jupyter-wrapper .bp3-button:empty:before,.jupyter-wrapper .bp3-button>:last-child{margin-right:0}.jupyter-wrapper .bp3-button:empty{padding:0!important}.jupyter-wrapper .bp3-button:disabled,.jupyter-wrapper .bp3-button.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-button.bp3-align-right,.jupyter-wrapper .bp3-align-right .bp3-button{text-align:right}.jupyter-wrapper .bp3-button.bp3-align-left,.jupyter-wrapper .bp3-align-left .bp3-button{text-align:left}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]){background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active:hover,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-button.bp3-intent-primary{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-primary:hover{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-active{background-color:#0e5a8a;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-disabled{background-color:#137cbd80;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-success{background-color:#0f9960;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-success:hover{background-color:#0d8050;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-active{background-color:#0a6640;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-disabled{background-color:#0f996080;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-warning{background-color:#d9822b;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-warning:hover{background-color:#bf7326;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-active{background-color:#a66321;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-disabled{background-color:#d9822b80;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-danger{background-color:#db3737;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-danger:hover{background-color:#c23030;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-active{background-color:#a82a2a;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-disabled{background-color:#db373780;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-button-spinner .bp3-spinner-head{stroke:#fff}.jupyter-wrapper .bp3-button.bp3-large,.jupyter-wrapper .bp3-large .bp3-button{min-height:40px;min-width:40px;font-size:16px;padding:5px 15px}.jupyter-wrapper .bp3-button.bp3-large:before,.jupyter-wrapper .bp3-button.bp3-large>*,.jupyter-wrapper .bp3-large .bp3-button:before,.jupyter-wrapper .bp3-large .bp3-button>*{margin-right:10px}.jupyter-wrapper .bp3-button.bp3-large:empty:before,.jupyter-wrapper .bp3-button.bp3-large>:last-child,.jupyter-wrapper .bp3-large .bp3-button:empty:before,.jupyter-wrapper .bp3-large .bp3-button>:last-child{margin-right:0}.jupyter-wrapper .bp3-button.bp3-small,.jupyter-wrapper .bp3-small .bp3-button{min-height:24px;min-width:24px;padding:0 7px}.jupyter-wrapper .bp3-button.bp3-loading{position:relative}.jupyter-wrapper .bp3-button.bp3-loading[class*=bp3-icon-]:before{visibility:hidden}.jupyter-wrapper .bp3-button.bp3-loading .bp3-button-spinner{margin:0;position:absolute}.jupyter-wrapper .bp3-button.bp3-loading>:not(.bp3-button-spinner){visibility:hidden}.jupyter-wrapper .bp3-button[class*=bp3-icon-]:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#5c7080}.jupyter-wrapper .bp3-button .bp3-icon,.jupyter-wrapper .bp3-button .bp3-icon-standard,.jupyter-wrapper .bp3-button .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-button .bp3-icon.bp3-align-right,.jupyter-wrapper .bp3-button .bp3-icon-standard.bp3-align-right,.jupyter-wrapper .bp3-button .bp3-icon-large.bp3-align-right{margin-left:7px}.jupyter-wrapper .bp3-button .bp3-icon:first-child:last-child,.jupyter-wrapper .bp3-button .bp3-spinner+.bp3-icon:last-child{margin:0 -7px}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]){background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):hover,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):disabled,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-])[class*=bp3-icon-]:before{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon-large{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-],.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:active,.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-].bp3-active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:disabled,.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-].bp3-disabled{background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#ffffff4d}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-] .bp3-button-spinner .bp3-spinner-head{stroke:#8a9ba8}.jupyter-wrapper .bp3-button:disabled:before,.jupyter-wrapper .bp3-button:disabled .bp3-icon,.jupyter-wrapper .bp3-button:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-button:disabled .bp3-icon-large,.jupyter-wrapper .bp3-button.bp3-disabled:before,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon-standard,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon-large,.jupyter-wrapper .bp3-button[class*=bp3-intent-]:before,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon-standard,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon-large{color:inherit!important}.jupyter-wrapper .bp3-button.bp3-minimal{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-button.bp3-minimal:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-button.bp3-minimal:disabled:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-minimal:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined{background:none;-webkit-box-shadow:none;box-shadow:none;border:1px solid rgba(24,32,38,.2);-webkit-box-sizing:border-box;box-sizing:border-box}.jupyter-wrapper .bp3-button.bp3-outlined:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-outlined:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover{border-color:#5c70801a}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined{border-color:#fff6}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover{border-color:#fff3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary{border-color:#106ba399}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{border-color:#106ba333}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary{border-color:#48aff099}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{border-color:#48aff033}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success{border-color:#0d805099}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{border-color:#0d805033}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success{border-color:#3dcc9199}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{border-color:#3dcc9133}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning{border-color:#bf732699}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{border-color:#bf732633}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning{border-color:#ffb36699}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{border-color:#ffb36633}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger{border-color:#c2303099}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{border-color:#c2303033}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger{border-color:#ff737399}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{border-color:#ff737333}.jupyter-wrapper a.bp3-button{text-align:center;text-decoration:none;-webkit-transition:none;transition:none}.jupyter-wrapper a.bp3-button,.jupyter-wrapper a.bp3-button:hover,.jupyter-wrapper a.bp3-button:active{color:#182026}.jupyter-wrapper a.bp3-button.bp3-disabled{color:#5c708099}.jupyter-wrapper .bp3-button-text{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.jupyter-wrapper .bp3-button.bp3-align-left .bp3-button-text,.jupyter-wrapper .bp3-button.bp3-align-right .bp3-button-text,.jupyter-wrapper .bp3-button-group.bp3-align-left .bp3-button-text,.jupyter-wrapper .bp3-button-group.bp3-align-right .bp3-button-text{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.jupyter-wrapper .bp3-button-group .bp3-button{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;position:relative;z-index:4}.jupyter-wrapper .bp3-button-group .bp3-button:focus{z-index:5}.jupyter-wrapper .bp3-button-group .bp3-button:hover{z-index:6}.jupyter-wrapper .bp3-button-group .bp3-button:active,.jupyter-wrapper .bp3-button-group .bp3-button.bp3-active{z-index:7}.jupyter-wrapper .bp3-button-group .bp3-button:disabled,.jupyter-wrapper .bp3-button-group .bp3-button.bp3-disabled{z-index:3}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]{z-index:9}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:focus{z-index:10}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:hover{z-index:11}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:active,.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-].bp3-active{z-index:12}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:disabled,.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-].bp3-disabled{z-index:8}.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:first-child) .bp3-button,.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:hover,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button-group .bp3-popover-wrapper,.jupyter-wrapper .bp3-button-group .bp3-popover-target{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-button-group .bp3-button.bp3-fill,.jupyter-wrapper .bp3-button-group.bp3-fill .bp3-button:not(.bp3-fixed){-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group.bp3-vertical{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;vertical-align:top}.jupyter-wrapper .bp3-button-group.bp3-vertical.bp3-fill{height:100%;width:unset}.jupyter-wrapper .bp3-button-group.bp3-vertical .bp3-button{margin-right:0!important;width:100%}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:first-child .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:first-child{border-radius:3px 3px 0 0}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:last-child .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:last-child{border-radius:0 0 3px 3px}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:not(:last-child){margin-bottom:-1px}.jupyter-wrapper .bp3-button-group.bp3-align-left .bp3-button{text-align:left}.jupyter-wrapper .bp3-dark .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-dark .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:last-child){margin-right:1px}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-vertical>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-vertical>.bp3-button:not(:last-child){margin-bottom:1px}.jupyter-wrapper .bp3-callout{font-size:14px;line-height:1.5;background-color:#8a9ba826;border-radius:3px;padding:10px 12px 9px;position:relative;width:100%}.jupyter-wrapper .bp3-callout[class*=bp3-icon-]{padding-left:40px}.jupyter-wrapper .bp3-callout[class*=bp3-icon-]:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#5c7080;left:10px;position:absolute;top:10px}.jupyter-wrapper .bp3-callout.bp3-callout-icon{padding-left:40px}.jupyter-wrapper .bp3-callout.bp3-callout-icon>.bp3-icon:first-child{color:#5c7080;left:10px;position:absolute;top:10px}.jupyter-wrapper .bp3-callout .bp3-heading{line-height:20px;margin-bottom:5px;margin-top:0}.jupyter-wrapper .bp3-callout .bp3-heading:last-child{margin-bottom:0}.jupyter-wrapper .bp3-dark .bp3-callout{background-color:#8a9ba833}.jupyter-wrapper .bp3-dark .bp3-callout[class*=bp3-icon-]:before{color:#a7b6c2}.jupyter-wrapper .bp3-callout.bp3-intent-primary{background-color:#137cbd26}.jupyter-wrapper .bp3-callout.bp3-intent-primary[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-primary>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-primary .bp3-heading{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary{background-color:#137cbd40}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary .bp3-heading{color:#48aff0}.jupyter-wrapper .bp3-callout.bp3-intent-success{background-color:#0f996026}.jupyter-wrapper .bp3-callout.bp3-intent-success[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-success>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-success .bp3-heading{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success{background-color:#0f996040}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success .bp3-heading{color:#3dcc91}.jupyter-wrapper .bp3-callout.bp3-intent-warning{background-color:#d9822b26}.jupyter-wrapper .bp3-callout.bp3-intent-warning[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-warning>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-warning .bp3-heading{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning{background-color:#d9822b40}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning .bp3-heading{color:#ffb366}.jupyter-wrapper .bp3-callout.bp3-intent-danger{background-color:#db373726}.jupyter-wrapper .bp3-callout.bp3-intent-danger[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-danger>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-danger .bp3-heading{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger{background-color:#db373740}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger .bp3-heading{color:#ff7373}.jupyter-wrapper .bp3-running-text .bp3-callout{margin:20px 0}.jupyter-wrapper .bp3-card{background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.15),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a26,0 0 #10161a00,0 0 #10161a00;padding:20px;-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),box-shadow .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-card.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a66,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-0{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.15),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a26,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-0.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-0{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a66,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-1{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33}.jupyter-wrapper .bp3-elevation-1.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-1{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-elevation-2{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 1px 1px rgba(16,22,26,.2),0 2px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 1px 1px #10161a33,0 2px 6px #10161a33}.jupyter-wrapper .bp3-elevation-2.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-2{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.4),0 2px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a66,0 2px 6px #10161a66}.jupyter-wrapper .bp3-elevation-3{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33}.jupyter-wrapper .bp3-elevation-3.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-3{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-elevation-4{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33}.jupyter-wrapper .bp3-elevation-4.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-4{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66}.jupyter-wrapper .bp3-card.bp3-interactive:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;cursor:pointer}.jupyter-wrapper .bp3-card.bp3-interactive:hover.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card.bp3-interactive:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-card.bp3-interactive:active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;opacity:.9;-webkit-transition-duration:0;transition-duration:0}.jupyter-wrapper .bp3-card.bp3-interactive:active.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card.bp3-interactive:active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-collapse{height:0;overflow-y:hidden;-webkit-transition:height .2s cubic-bezier(.4,1,.75,.9);transition:height .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-collapse .bp3-collapse-body{-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-collapse .bp3-collapse-body[aria-hidden=true]{display:none}.jupyter-wrapper .bp3-context-menu .bp3-popover-target{display:block}.jupyter-wrapper .bp3-context-menu-popover-target{position:fixed}.jupyter-wrapper .bp3-dialog-container{opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;min-height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-enter>.bp3-dialog,.jupyter-wrapper .bp3-dialog-container.bp3-overlay-appear>.bp3-dialog{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-enter-active>.bp3-dialog,.jupyter-wrapper .bp3-dialog-container.bp3-overlay-appear-active>.bp3-dialog{opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-exit>.bp3-dialog{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-exit-active>.bp3-dialog{opacity:0;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-dialog{background:#ebf1f5;border-radius:6px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:30px 0;padding-bottom:20px;pointer-events:all;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;width:500px}.jupyter-wrapper .bp3-dialog:focus{outline:0}.jupyter-wrapper .bp3-dialog.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-dialog{background:#293742;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dialog-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#ffffff;border-radius:6px 6px 0 0;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;min-height:40px;padding-left:20px;padding-right:5px;z-index:30}.jupyter-wrapper .bp3-dialog-header .bp3-icon-large,.jupyter-wrapper .bp3-dialog-header .bp3-icon{color:#5c7080;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-right:10px}.jupyter-wrapper .bp3-dialog-header .bp3-heading{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:inherit;margin:0}.jupyter-wrapper .bp3-dialog-header .bp3-heading:last-child{margin-right:20px}.jupyter-wrapper .bp3-dark .bp3-dialog-header{background:#30404d;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.4);box-shadow:0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-dialog-header .bp3-icon-large,.jupyter-wrapper .bp3-dark .bp3-dialog-header .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dialog-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:18px;margin:20px}.jupyter-wrapper .bp3-dialog-footer{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin:0 20px}.jupyter-wrapper .bp3-dialog-footer-actions{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.jupyter-wrapper .bp3-dialog-footer-actions .bp3-button{margin-left:10px}.jupyter-wrapper .bp3-multistep-dialog-panels{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-multistep-dialog-left-panel{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-left-panel{background:#202b33}.jupyter-wrapper .bp3-multistep-dialog-right-panel{background-color:#f5f8fa;border-left:1px solid rgba(16,22,26,.15);border-radius:0 0 6px;-webkit-box-flex:3;-ms-flex:3;flex:3;min-width:0}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-right-panel{background-color:#293742;border-left:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-multistep-dialog-footer{background-color:#fff;border-radius:0 0 6px;border-top:1px solid rgba(16,22,26,.15);padding:10px}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-footer{background:#30404d;border-top:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dialog-step-container{background-color:#f5f8fa;border-bottom:1px solid rgba(16,22,26,.15)}.jupyter-wrapper .bp3-dark .bp3-dialog-step-container{background:#293742;border-bottom:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dialog-step-container.bp3-dialog-step-viewed{background-color:#fff}.jupyter-wrapper .bp3-dark .bp3-dialog-step-container.bp3-dialog-step-viewed{background:#30404d}.jupyter-wrapper .bp3-dialog-step{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#f5f8fa;border-radius:6px;cursor:not-allowed;display:-webkit-box;display:-ms-flexbox;display:flex;margin:4px;padding:6px 14px}.jupyter-wrapper .bp3-dark .bp3-dialog-step{background:#293742}.jupyter-wrapper .bp3-dialog-step-viewed .bp3-dialog-step{background-color:#fff;cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-dialog-step-viewed .bp3-dialog-step{background:#30404d}.jupyter-wrapper .bp3-dialog-step:hover{background-color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-dialog-step:hover{background:#293742}.jupyter-wrapper .bp3-dialog-step-icon{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#5c708099;border-radius:50%;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;height:25px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:25px}.jupyter-wrapper .bp3-dark .bp3-dialog-step-icon{background-color:#a7b6c299}.jupyter-wrapper .bp3-active.bp3-dialog-step-viewed .bp3-dialog-step-icon{background-color:#2b95d6}.jupyter-wrapper .bp3-dialog-step-viewed .bp3-dialog-step-icon{background-color:#8a9ba8}.jupyter-wrapper .bp3-dialog-step-title{color:#5c708099;-webkit-box-flex:1;-ms-flex:1;flex:1;padding-left:10px}.jupyter-wrapper .bp3-dark .bp3-dialog-step-title{color:#a7b6c299}.jupyter-wrapper .bp3-active.bp3-dialog-step-viewed .bp3-dialog-step-title{color:#2b95d6}.jupyter-wrapper .bp3-dialog-step-viewed:not(.bp3-active) .bp3-dialog-step-title{color:#182026}.jupyter-wrapper .bp3-dark .bp3-dialog-step-viewed:not(.bp3-active) .bp3-dialog-step-title{color:#f5f8fa}.jupyter-wrapper .bp3-drawer{background:#ffffff;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0;padding:0}.jupyter-wrapper .bp3-drawer:focus{outline:0}.jupyter-wrapper .bp3-drawer.bp3-position-top{height:50%;left:0;right:0;top:0}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-appear{-webkit-transform:translateY(-100%);transform:translateY(-100%)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-exit-active{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom{bottom:0;height:50%;left:0;right:0}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-appear{-webkit-transform:translateY(100%);transform:translateY(100%)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-exit-active{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-left{bottom:0;left:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-appear{-webkit-transform:translateX(-100%);transform:translate(-100%)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-exit-active{-webkit-transform:translateX(-100%);transform:translate(-100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-right{bottom:0;right:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-appear{-webkit-transform:translateX(100%);transform:translate(100%)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical){bottom:0;right:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-enter,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-appear{-webkit-transform:translateX(100%);transform:translate(100%)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical{bottom:0;height:50%;left:0;right:0}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-appear{-webkit-transform:translateY(100%);transform:translateY(100%)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-exit-active{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-drawer{background:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-drawer-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:0;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;min-height:40px;padding:5px 5px 5px 20px;position:relative}.jupyter-wrapper .bp3-drawer-header .bp3-icon-large,.jupyter-wrapper .bp3-drawer-header .bp3-icon{color:#5c7080;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-right:10px}.jupyter-wrapper .bp3-drawer-header .bp3-heading{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:inherit;margin:0}.jupyter-wrapper .bp3-drawer-header .bp3-heading:last-child{margin-right:20px}.jupyter-wrapper .bp3-dark .bp3-drawer-header{-webkit-box-shadow:0 1px 0 rgba(16,22,26,.4);box-shadow:0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-drawer-header .bp3-icon-large,.jupyter-wrapper .bp3-dark .bp3-drawer-header .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-drawer-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:18px;overflow:auto}.jupyter-wrapper .bp3-drawer-footer{-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;padding:10px 20px;position:relative}.jupyter-wrapper .bp3-dark .bp3-drawer-footer{-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.4);box-shadow:inset 0 1px #10161a66}.jupyter-wrapper .bp3-editable-text{cursor:text;display:inline-block;max-width:100%;position:relative;vertical-align:top;white-space:nowrap}.jupyter-wrapper .bp3-editable-text:before{bottom:-3px;left:-3px;position:absolute;right:-3px;top:-3px;border-radius:3px;content:\"\";-webkit-transition:background-color .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-editable-text:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-editable-text.bp3-editable-text-editing:before{background-color:#fff;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-disabled:before{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-primary .bp3-editable-text-content{color:#137cbd}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(19,124,189,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd66}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-success .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-success .bp3-editable-text-content{color:#0f9960}.jupyter-wrapper .bp3-editable-text.bp3-intent-success:hover:before{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px rgba(15,153,96,.4);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f996066}.jupyter-wrapper .bp3-editable-text.bp3-intent-success.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-warning .bp3-editable-text-content{color:#d9822b}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning:hover:before{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px rgba(217,130,43,.4);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b66}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-danger .bp3-editable-text-content{color:#db3737}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger:hover:before{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px rgba(219,55,55,.4);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db373766}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-dark .bp3-editable-text:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(255,255,255,.15);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #ffffff26}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-editable-text-editing:before{background-color:#10161a4d;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-disabled:before{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary .bp3-editable-text-content{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary:hover:before{-webkit-box-shadow:0 0 0 0 rgba(72,175,240,0),0 0 0 0 rgba(72,175,240,0),inset 0 0 0 1px rgba(72,175,240,.4);box-shadow:0 0 #48aff000,0 0 #48aff000,inset 0 0 0 1px #48aff066}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #48aff0,0 0 0 3px rgba(72,175,240,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #48aff0,0 0 0 3px #48aff04d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success .bp3-editable-text-content{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success:hover:before{-webkit-box-shadow:0 0 0 0 rgba(61,204,145,0),0 0 0 0 rgba(61,204,145,0),inset 0 0 0 1px rgba(61,204,145,.4);box-shadow:0 0 #3dcc9100,0 0 #3dcc9100,inset 0 0 0 1px #3dcc9166}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #3dcc91,0 0 0 3px rgba(61,204,145,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #3dcc91,0 0 0 3px #3dcc914d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning .bp3-editable-text-content{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning:hover:before{-webkit-box-shadow:0 0 0 0 rgba(255,179,102,0),0 0 0 0 rgba(255,179,102,0),inset 0 0 0 1px rgba(255,179,102,.4);box-shadow:0 0 #ffb36600,0 0 #ffb36600,inset 0 0 0 1px #ffb36666}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #ffb366,0 0 0 3px rgba(255,179,102,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #ffb366,0 0 0 3px #ffb3664d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger .bp3-editable-text-content{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger:hover:before{-webkit-box-shadow:0 0 0 0 rgba(255,115,115,0),0 0 0 0 rgba(255,115,115,0),inset 0 0 0 1px rgba(255,115,115,.4);box-shadow:0 0 #ff737300,0 0 #ff737300,inset 0 0 0 1px #ff737366}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #ff7373,0 0 0 3px rgba(255,115,115,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #ff7373,0 0 0 3px #ff73734d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text-content{color:inherit;display:inherit;font:inherit;letter-spacing:inherit;max-width:inherit;min-width:inherit;position:relative;resize:none;text-transform:inherit;vertical-align:top}.jupyter-wrapper .bp3-editable-text-input{background:none;border:none;-webkit-box-shadow:none;box-shadow:none;padding:0;white-space:pre-wrap;width:100%}.jupyter-wrapper .bp3-editable-text-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input:focus{outline:none}.jupyter-wrapper .bp3-editable-text-input::-ms-clear{display:none}.jupyter-wrapper .bp3-editable-text-content{overflow:hidden;padding-right:2px;text-overflow:ellipsis;white-space:pre}.jupyter-wrapper .bp3-editable-text-editing>.bp3-editable-text-content{left:0;position:absolute;visibility:hidden}.jupyter-wrapper .bp3-editable-text-placeholder>.bp3-editable-text-content{color:#5c708099}.jupyter-wrapper .bp3-dark .bp3-editable-text-placeholder>.bp3-editable-text-content{color:#a7b6c299}.jupyter-wrapper .bp3-editable-text.bp3-multiline{display:block}.jupyter-wrapper .bp3-editable-text.bp3-multiline .bp3-editable-text-content{overflow:auto;white-space:pre-wrap;word-wrap:break-word}.jupyter-wrapper .bp3-divider{border-bottom:1px solid rgba(16,22,26,.15);border-right:1px solid rgba(16,22,26,.15);margin:5px}.jupyter-wrapper .bp3-dark .bp3-divider{border-color:#10161a66}.jupyter-wrapper .bp3-control-group{-webkit-transform:translateZ(0);transform:translateZ(0);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.jupyter-wrapper .bp3-control-group>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-control-group>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-control-group .bp3-button,.jupyter-wrapper .bp3-control-group .bp3-html-select,.jupyter-wrapper .bp3-control-group .bp3-input,.jupyter-wrapper .bp3-control-group .bp3-select{position:relative}.jupyter-wrapper .bp3-control-group .bp3-input{border-radius:inherit;z-index:2}.jupyter-wrapper .bp3-control-group .bp3-input:focus{border-radius:3px;z-index:14}.jupyter-wrapper .bp3-control-group .bp3-input[class*=bp3-intent]{z-index:13}.jupyter-wrapper .bp3-control-group .bp3-input[class*=bp3-intent]:focus{z-index:15}.jupyter-wrapper .bp3-control-group .bp3-input[readonly],.jupyter-wrapper .bp3-control-group .bp3-input:disabled,.jupyter-wrapper .bp3-control-group .bp3-input.bp3-disabled{z-index:1}.jupyter-wrapper .bp3-control-group .bp3-input-group[class*=bp3-intent] .bp3-input{z-index:13}.jupyter-wrapper .bp3-control-group .bp3-input-group[class*=bp3-intent] .bp3-input:focus{z-index:15}.jupyter-wrapper .bp3-control-group .bp3-button,.jupyter-wrapper .bp3-control-group .bp3-html-select select,.jupyter-wrapper .bp3-control-group .bp3-select select{-webkit-transform:translateZ(0);transform:translateZ(0);border-radius:inherit;z-index:4}.jupyter-wrapper .bp3-control-group .bp3-button:focus,.jupyter-wrapper .bp3-control-group .bp3-html-select select:focus,.jupyter-wrapper .bp3-control-group .bp3-select select:focus{z-index:5}.jupyter-wrapper .bp3-control-group .bp3-button:hover,.jupyter-wrapper .bp3-control-group .bp3-html-select select:hover,.jupyter-wrapper .bp3-control-group .bp3-select select:hover{z-index:6}.jupyter-wrapper .bp3-control-group .bp3-button:active,.jupyter-wrapper .bp3-control-group .bp3-html-select select:active,.jupyter-wrapper .bp3-control-group .bp3-select select:active{z-index:7}.jupyter-wrapper .bp3-control-group .bp3-button[readonly],.jupyter-wrapper .bp3-control-group .bp3-button:disabled,.jupyter-wrapper .bp3-control-group .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[readonly],.jupyter-wrapper .bp3-control-group .bp3-html-select select:disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[readonly],.jupyter-wrapper .bp3-control-group .bp3-select select:disabled,.jupyter-wrapper .bp3-control-group .bp3-select select.bp3-disabled{z-index:3}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent],.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent],.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]{z-index:9}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:focus,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:focus,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:focus{z-index:10}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:hover,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:hover,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:hover{z-index:11}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:active,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:active,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:active{z-index:12}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent].bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent].bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent].bp3-disabled{z-index:8}.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-icon,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-button,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-input-action{z-index:16}.jupyter-wrapper .bp3-control-group .bp3-select:after,.jupyter-wrapper .bp3-control-group .bp3-html-select:after,.jupyter-wrapper .bp3-control-group .bp3-select>.bp3-icon,.jupyter-wrapper .bp3-control-group .bp3-html-select>.bp3-icon{z-index:17}.jupyter-wrapper .bp3-control-group .bp3-select:focus-within{z-index:5}.jupyter-wrapper .bp3-control-group:not(.bp3-vertical)>*:not(.bp3-divider){margin-right:-1px}.jupyter-wrapper .bp3-control-group:not(.bp3-vertical)>.bp3-divider:not(:first-child){margin-left:6px}.jupyter-wrapper .bp3-dark .bp3-control-group:not(.bp3-vertical)>*:not(.bp3-divider){margin-right:0}.jupyter-wrapper .bp3-dark .bp3-control-group:not(.bp3-vertical)>.bp3-button+.bp3-button{margin-left:1px}.jupyter-wrapper .bp3-control-group .bp3-popover-wrapper,.jupyter-wrapper .bp3-control-group .bp3-popover-target{border-radius:inherit}.jupyter-wrapper .bp3-control-group>:first-child{border-radius:3px 0 0 3px}.jupyter-wrapper .bp3-control-group>:last-child{border-radius:0 3px 3px 0;margin-right:0}.jupyter-wrapper .bp3-control-group>:only-child{border-radius:3px;margin-right:0}.jupyter-wrapper .bp3-control-group .bp3-input-group .bp3-button{border-radius:3px}.jupyter-wrapper .bp3-control-group .bp3-numeric-input:not(:first-child) .bp3-input-group{border-bottom-left-radius:0;border-top-left-radius:0}.jupyter-wrapper .bp3-control-group.bp3-fill{width:100%}.jupyter-wrapper .bp3-control-group>.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-control-group.bp3-fill>*:not(.bp3-fixed){-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-control-group.bp3-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-control-group.bp3-vertical>*{margin-top:-1px}.jupyter-wrapper .bp3-control-group.bp3-vertical>:first-child{border-radius:3px 3px 0 0;margin-top:0}.jupyter-wrapper .bp3-control-group.bp3-vertical>:last-child{border-radius:0 0 3px 3px}.jupyter-wrapper .bp3-control{cursor:pointer;display:block;margin-bottom:10px;position:relative;text-transform:none}.jupyter-wrapper .bp3-control input:checked~.bp3-control-indicator{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-control:hover input:checked~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-control input:not(:disabled):active:checked~.bp3-control-indicator{background:#0e5a8a;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control input:disabled:checked~.bp3-control-indicator{background:rgba(19,124,189,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-control input:checked~.bp3-control-indicator{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control:hover input:checked~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control input:not(:disabled):active:checked~.bp3-control-indicator{background-color:#0e5a8a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control input:disabled:checked~.bp3-control-indicator{background:rgba(14,90,138,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-control:not(.bp3-align-right){padding-left:26px}.jupyter-wrapper .bp3-control:not(.bp3-align-right) .bp3-control-indicator{margin-left:-26px}.jupyter-wrapper .bp3-control.bp3-align-right{padding-right:26px}.jupyter-wrapper .bp3-control.bp3-align-right .bp3-control-indicator{margin-right:-26px}.jupyter-wrapper .bp3-control.bp3-disabled{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-control.bp3-inline{display:inline-block;margin-right:20px}.jupyter-wrapper .bp3-control input{left:0;opacity:0;position:absolute;top:0;z-index:-1}.jupyter-wrapper .bp3-control .bp3-control-indicator{background-clip:padding-box;background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));border:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;cursor:pointer;display:inline-block;font-size:16px;height:1em;margin-right:10px;margin-top:-3px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;width:1em}.jupyter-wrapper .bp3-control .bp3-control-indicator:before{content:\"\";display:block;height:1em;width:1em}.jupyter-wrapper .bp3-control:hover .bp3-control-indicator{background-color:#ebf1f5}.jupyter-wrapper .bp3-control input:not(:disabled):active~.bp3-control-indicator{background:#d8e1e8;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control input:disabled~.bp3-control-indicator{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;cursor:not-allowed}.jupyter-wrapper .bp3-control input:focus~.bp3-control-indicator{outline:rgba(19,124,189,.6) auto 2px;outline-offset:2px;-moz-outline-radius:6px}.jupyter-wrapper .bp3-control.bp3-align-right .bp3-control-indicator{float:right;margin-left:10px;margin-top:1px}.jupyter-wrapper .bp3-control.bp3-large{font-size:16px}.jupyter-wrapper .bp3-control.bp3-large:not(.bp3-align-right){padding-left:30px}.jupyter-wrapper .bp3-control.bp3-large:not(.bp3-align-right) .bp3-control-indicator{margin-left:-30px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right{padding-right:30px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right .bp3-control-indicator{margin-right:-30px}.jupyter-wrapper .bp3-control.bp3-large .bp3-control-indicator{font-size:20px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right .bp3-control-indicator{margin-top:0}.jupyter-wrapper .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-control.bp3-checkbox:hover input:indeterminate~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-control.bp3-checkbox input:not(:disabled):active:indeterminate~.bp3-control-indicator{background:#0e5a8a;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{background:rgba(19,124,189,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox:hover input:indeterminate~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:not(:disabled):active:indeterminate~.bp3-control-indicator{background-color:#0e5a8a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{background:rgba(14,90,138,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-control.bp3-checkbox .bp3-control-indicator{border-radius:3px}.jupyter-wrapper .bp3-control.bp3-checkbox input:checked~.bp3-control-indicator:before{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='white'/%3e%3c/svg%3e\")}.jupyter-wrapper .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator:before{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 7H5c-.55 0-1 .45-1 1s.45 1 1 1h6c.55 0 1-.45 1-1s-.45-1-1-1z' fill='white'/%3e%3c/svg%3e\")}.jupyter-wrapper .bp3-control.bp3-radio .bp3-control-indicator{border-radius:50%}.jupyter-wrapper .bp3-control.bp3-radio input:checked~.bp3-control-indicator:before{background-image:radial-gradient(#ffffff,#ffffff 28%,transparent 32%)}.jupyter-wrapper .bp3-control.bp3-radio input:checked:disabled~.bp3-control-indicator:before{opacity:.5}.jupyter-wrapper .bp3-control.bp3-radio input:focus~.bp3-control-indicator{-moz-outline-radius:16px}.jupyter-wrapper .bp3-control.bp3-switch input~.bp3-control-indicator{background:rgba(167,182,194,.5)}.jupyter-wrapper .bp3-control.bp3-switch:hover input~.bp3-control-indicator{background:rgba(115,134,148,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:not(:disabled):active~.bp3-control-indicator{background:rgba(92,112,128,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:disabled~.bp3-control-indicator{background:rgba(206,217,224,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:disabled~.bp3-control-indicator:before{background:rgba(255,255,255,.8)}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator{background:#137cbd}.jupyter-wrapper .bp3-control.bp3-switch:hover input:checked~.bp3-control-indicator{background:#106ba3}.jupyter-wrapper .bp3-control.bp3-switch input:checked:not(:disabled):active~.bp3-control-indicator{background:#0e5a8a}.jupyter-wrapper .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator{background:rgba(19,124,189,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator:before{background:rgba(255,255,255,.8)}.jupyter-wrapper .bp3-control.bp3-switch:not(.bp3-align-right){padding-left:38px}.jupyter-wrapper .bp3-control.bp3-switch:not(.bp3-align-right) .bp3-control-indicator{margin-left:-38px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-align-right{padding-right:38px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-align-right .bp3-control-indicator{margin-right:-38px}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator{border:none;border-radius:1.75em;-webkit-box-shadow:none!important;box-shadow:none!important;min-width:1.75em;-webkit-transition:background-color .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9);width:auto}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator:before{background:#ffffff;border-radius:50%;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;height:calc(1em - 4px);left:0;margin:2px;position:absolute;-webkit-transition:left .1s cubic-bezier(.4,1,.75,.9);transition:left .1s cubic-bezier(.4,1,.75,.9);width:calc(1em - 4px)}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator:before{left:calc(100% - 1em)}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large:not(.bp3-align-right){padding-left:45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large:not(.bp3-align-right) .bp3-control-indicator{margin-left:-45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large.bp3-align-right{padding-right:45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large.bp3-align-right .bp3-control-indicator{margin-right:-45px}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input~.bp3-control-indicator{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch:hover input~.bp3-control-indicator{background:rgba(16,22,26,.7)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:not(:disabled):active~.bp3-control-indicator{background:rgba(16,22,26,.9)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:disabled~.bp3-control-indicator{background:rgba(57,75,89,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:disabled~.bp3-control-indicator:before{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked~.bp3-control-indicator{background:#137cbd}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch:hover input:checked~.bp3-control-indicator{background:#106ba3}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:not(:disabled):active~.bp3-control-indicator{background:#0e5a8a}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator{background:rgba(14,90,138,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator:before{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch .bp3-control-indicator:before{background:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked~.bp3-control-indicator:before{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-control.bp3-switch .bp3-switch-inner-text{font-size:.7em;text-align:center}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator-child:first-child{line-height:0;margin-left:.5em;margin-right:1.2em;visibility:hidden}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator-child:last-child{line-height:1em;margin-left:1.2em;margin-right:.5em;visibility:visible}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator .bp3-control-indicator-child:first-child{line-height:1em;visibility:visible}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator .bp3-control-indicator-child:last-child{line-height:0;visibility:hidden}.jupyter-wrapper .bp3-dark .bp3-control{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-control.bp3-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-control .bp3-control-indicator{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control:hover .bp3-control-indicator{background-color:#30404d}.jupyter-wrapper .bp3-dark .bp3-control input:not(:disabled):active~.bp3-control-indicator{background:#202b33;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control input:disabled~.bp3-control-indicator{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:checked~.bp3-control-indicator,.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{color:#a7b6c299}.jupyter-wrapper .bp3-file-input{cursor:pointer;display:inline-block;height:30px;position:relative}.jupyter-wrapper .bp3-file-input input{margin:0;min-width:200px;opacity:0}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active:hover,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input:after,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-file-input.bp3-file-input-has-selection .bp3-file-upload-input{color:#182026}.jupyter-wrapper .bp3-dark .bp3-file-input.bp3-file-input-has-selection .bp3-file-upload-input{color:#f5f8fa}.jupyter-wrapper .bp3-file-input.bp3-fill{width:100%}.jupyter-wrapper .bp3-file-input.bp3-large,.jupyter-wrapper .bp3-large .bp3-file-input{height:40px}.jupyter-wrapper .bp3-file-input .bp3-file-upload-input-custom-text:after{content:attr(bp3-button-text)}.jupyter-wrapper .bp3-file-upload-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff;border:none;border-radius:3px;-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33;color:#182026;font-size:14px;font-weight:400;height:30px;line-height:30px;outline:none;padding:0 80px 0 10px;-webkit-transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;color:#5c708099;left:0;position:absolute;right:0;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-file-upload-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input:focus,.jupyter-wrapper .bp3-file-upload-input.bp3-active{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-file-upload-input[type=search],.jupyter-wrapper .bp3-file-upload-input.bp3-round{border-radius:30px;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:10px}.jupyter-wrapper .bp3-file-upload-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-file-upload-input:disabled,.jupyter-wrapper .bp3-file-upload-input.bp3-disabled{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-file-upload-input:after{background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;min-height:24px;min-width:24px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;border-radius:3px;content:\"Browse\";line-height:24px;margin:3px;position:absolute;right:0;text-align:center;top:0;width:70px}.jupyter-wrapper .bp3-file-upload-input:after:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-file-upload-input:after .bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-file-upload-input:after:disabled,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-file-upload-input:after:disabled .bp3-active,.jupyter-wrapper .bp3-file-upload-input:after:disabled .bp3-active:hover,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled.bp3-active,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-file-upload-input:hover:after{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-file-upload-input:active:after{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-large .bp3-file-upload-input{font-size:16px;height:40px;line-height:40px;padding-right:95px}.jupyter-wrapper .bp3-large .bp3-file-upload-input[type=search],.jupyter-wrapper .bp3-large .bp3-file-upload-input.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-large .bp3-file-upload-input:after{min-height:30px;min-width:30px;line-height:30px;margin:5px;width:85px}.jupyter-wrapper .bp3-dark .bp3-file-upload-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:disabled,.jupyter-wrapper .bp3-dark .bp3-file-upload-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:hover,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:disabled,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:disabled .bp3-active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:hover:after{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:active:after{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-file-upload-input:after{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 0 15px}.jupyter-wrapper .bp3-form-group label.bp3-label{margin-bottom:5px}.jupyter-wrapper .bp3-form-group .bp3-control{margin-top:7px}.jupyter-wrapper .bp3-form-group .bp3-form-helper-text{color:#5c7080;font-size:12px;margin-top:5px}.jupyter-wrapper .bp3-form-group.bp3-intent-primary .bp3-form-helper-text{color:#106ba3}.jupyter-wrapper .bp3-form-group.bp3-intent-success .bp3-form-helper-text{color:#0d8050}.jupyter-wrapper .bp3-form-group.bp3-intent-warning .bp3-form-helper-text{color:#bf7326}.jupyter-wrapper .bp3-form-group.bp3-intent-danger .bp3-form-helper-text{color:#c23030}.jupyter-wrapper .bp3-form-group.bp3-inline{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.jupyter-wrapper .bp3-form-group.bp3-inline.bp3-large label.bp3-label{line-height:40px;margin:0 10px 0 0}.jupyter-wrapper .bp3-form-group.bp3-inline label.bp3-label{line-height:30px;margin:0 10px 0 0}.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-label,.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-text-muted,.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-form-helper-text{color:#5c708099!important}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-primary .bp3-form-helper-text{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-success .bp3-form-helper-text{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-warning .bp3-form-helper-text{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-danger .bp3-form-helper-text{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-form-group .bp3-form-helper-text{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-label,.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-text-muted,.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-form-helper-text{color:#a7b6c299!important}.jupyter-wrapper .bp3-input-group{display:block;position:relative}.jupyter-wrapper .bp3-input-group .bp3-input{position:relative;width:100%}.jupyter-wrapper .bp3-input-group .bp3-input:not(:first-child){padding-left:30px}.jupyter-wrapper .bp3-input-group .bp3-input:not(:last-child){padding-right:30px}.jupyter-wrapper .bp3-input-group .bp3-input-action,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-input-group>.bp3-button,.jupyter-wrapper .bp3-input-group>.bp3-icon{position:absolute;top:0}.jupyter-wrapper .bp3-input-group .bp3-input-action:first-child,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container:first-child,.jupyter-wrapper .bp3-input-group>.bp3-button:first-child,.jupyter-wrapper .bp3-input-group>.bp3-icon:first-child{left:0}.jupyter-wrapper .bp3-input-group .bp3-input-action:last-child,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container:last-child,.jupyter-wrapper .bp3-input-group>.bp3-button:last-child,.jupyter-wrapper .bp3-input-group>.bp3-icon:last-child{right:0}.jupyter-wrapper .bp3-input-group .bp3-button{min-height:24px;min-width:24px;margin:3px;padding:0 7px}.jupyter-wrapper .bp3-input-group .bp3-button:empty{padding:0}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-input-group>.bp3-icon{z-index:1}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group>.bp3-icon{color:#5c7080}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon:empty,.jupyter-wrapper .bp3-input-group>.bp3-icon:empty{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group>.bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input-action>.bp3-spinner{margin:7px}.jupyter-wrapper .bp3-input-group .bp3-tag{margin:5px}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus),.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus){color:#5c7080}.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus),.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus){color:#a7b6c2}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-large,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled{color:#5c708099!important}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon-large,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon-large{color:#5c708099!important}.jupyter-wrapper .bp3-input-group.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-input-group.bp3-disabled .bp3-icon{color:#5c708099}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-button{min-height:30px;min-width:30px;margin:5px}.jupyter-wrapper .bp3-input-group.bp3-large>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-large>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input-action>.bp3-spinner{margin:12px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input{font-size:16px;height:40px;line-height:40px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input[type=search],.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input:not(:first-child){padding-left:40px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input:not(:last-child){padding-right:40px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-button,.jupyter-wrapper .bp3-input-group.bp3-small .bp3-tag{min-height:20px;min-width:20px;margin:2px}.jupyter-wrapper .bp3-input-group.bp3-small>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-small>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input-action>.bp3-spinner{margin:4px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input{font-size:12px;height:24px;line-height:24px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input[type=search],.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input.bp3-round{padding:0 12px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input:not(:first-child){padding-left:24px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input:not(:last-child){padding-right:24px}.jupyter-wrapper .bp3-input-group.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:100%}.jupyter-wrapper .bp3-input-group.bp3-round .bp3-button,.jupyter-wrapper .bp3-input-group.bp3-round .bp3-input,.jupyter-wrapper .bp3-input-group.bp3-round .bp3-tag{border-radius:30px}.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-disabled .bp3-icon{color:#a7b6c299}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-primary>.bp3-icon{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-primary>.bp3-icon{color:#48aff0}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-success>.bp3-icon{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-success>.bp3-icon{color:#3dcc91}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-warning>.bp3-icon{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-warning>.bp3-icon{color:#ffb366}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-danger>.bp3-icon{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-danger>.bp3-icon{color:#ff7373}.jupyter-wrapper .bp3-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff;border:none;border-radius:3px;-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33;color:#182026;font-size:14px;font-weight:400;height:30px;line-height:30px;outline:none;padding:0 10px;-webkit-transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);vertical-align:middle}.jupyter-wrapper .bp3-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input:focus,.jupyter-wrapper .bp3-input.bp3-active{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input[type=search],.jupyter-wrapper .bp3-input.bp3-round{border-radius:30px;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:10px}.jupyter-wrapper .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-input:disabled,.jupyter-wrapper .bp3-input.bp3-disabled{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-input.bp3-large{font-size:16px;height:40px;line-height:40px}.jupyter-wrapper .bp3-input.bp3-large[type=search],.jupyter-wrapper .bp3-input.bp3-large.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-input.bp3-small{font-size:12px;height:24px;line-height:24px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-input.bp3-small[type=search],.jupyter-wrapper .bp3-input.bp3-small.bp3-round{padding:0 12px}.jupyter-wrapper .bp3-input.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:100%}.jupyter-wrapper .bp3-dark .bp3-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-input.bp3-intent-primary{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-primary:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-primary[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-input.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-input.bp3-intent-primary.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-success{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-success:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-success[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-input.bp3-intent-success:disabled,.jupyter-wrapper .bp3-input.bp3-intent-success.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #0f996000,0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #0f9960,0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-warning{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-warning:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-warning[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-input.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-input.bp3-intent-warning.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #d9822b00,0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #d9822b,0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-danger{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-danger:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-danger[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-input.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-input.bp3-intent-danger.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #db373700,0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #db3737,0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input::-ms-clear{display:none}.jupyter-wrapper textarea.bp3-input{max-width:100%;padding:10px}.jupyter-wrapper textarea.bp3-input,.jupyter-wrapper textarea.bp3-input.bp3-large,.jupyter-wrapper textarea.bp3-input.bp3-small{height:auto;line-height:inherit}.jupyter-wrapper textarea.bp3-input.bp3-small{padding:8px}.jupyter-wrapper .bp3-dark textarea.bp3-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark textarea.bp3-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark textarea.bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark textarea.bp3-input:disabled,.jupyter-wrapper .bp3-dark textarea.bp3-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper label.bp3-label{display:block;margin-bottom:15px;margin-top:0}.jupyter-wrapper label.bp3-label .bp3-html-select,.jupyter-wrapper label.bp3-label .bp3-input,.jupyter-wrapper label.bp3-label .bp3-select,.jupyter-wrapper label.bp3-label .bp3-slider,.jupyter-wrapper label.bp3-label .bp3-popover-wrapper{display:block;margin-top:5px;text-transform:none}.jupyter-wrapper label.bp3-label .bp3-button-group{margin-top:5px}.jupyter-wrapper label.bp3-label .bp3-select select,.jupyter-wrapper label.bp3-label .bp3-html-select select{font-weight:400;vertical-align:top;width:100%}.jupyter-wrapper label.bp3-label.bp3-disabled,.jupyter-wrapper label.bp3-label.bp3-disabled .bp3-text-muted{color:#5c708099}.jupyter-wrapper label.bp3-label.bp3-inline{line-height:30px}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-html-select,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input-group,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-select,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-popover-wrapper{display:inline-block;margin:0 0 0 5px;vertical-align:top}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-button-group{margin:0 0 0 5px}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input-group .bp3-input{margin-left:0}.jupyter-wrapper label.bp3-label.bp3-inline.bp3-large{line-height:40px}.jupyter-wrapper label.bp3-label:not(.bp3-inline) .bp3-popover-target{display:block}.jupyter-wrapper .bp3-dark label.bp3-label{color:#f5f8fa}.jupyter-wrapper .bp3-dark label.bp3-label.bp3-disabled,.jupyter-wrapper .bp3-dark label.bp3-label.bp3-disabled .bp3-text-muted{color:#a7b6c299}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button{-webkit-box-flex:1;-ms-flex:1 1 14px;flex:1 1 14px;min-height:0;padding:0;width:30px}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button:first-child{border-radius:0 3px 0 0}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button:last-child{border-radius:0 0 3px}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical:first-child>.bp3-button:first-child{border-radius:3px 0 0}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical:first-child>.bp3-button:last-child{border-radius:0 0 0 3px}.jupyter-wrapper .bp3-numeric-input.bp3-large .bp3-button-group.bp3-vertical>.bp3-button{width:40px}.jupyter-wrapper form{display:block}.jupyter-wrapper .bp3-html-select select,.jupyter-wrapper .bp3-select select{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;cursor:pointer;font-size:14px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:left;vertical-align:middle;background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;-moz-appearance:none;-webkit-appearance:none;border-radius:3px;height:30px;padding:0 25px 0 10px;width:100%}.jupyter-wrapper .bp3-html-select select>*,.jupyter-wrapper .bp3-select select>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-html-select select>.bp3-fill,.jupyter-wrapper .bp3-select select>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-html-select select:before,.jupyter-wrapper .bp3-select select:before,.jupyter-wrapper .bp3-html-select select>*,.jupyter-wrapper .bp3-select select>*{margin-right:7px}.jupyter-wrapper .bp3-html-select select:empty:before,.jupyter-wrapper .bp3-select select:empty:before,.jupyter-wrapper .bp3-html-select select>:last-child,.jupyter-wrapper .bp3-select select>:last-child{margin-right:0}.jupyter-wrapper .bp3-html-select select:hover,.jupyter-wrapper .bp3-select select:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-html-select select:active,.jupyter-wrapper .bp3-select select:active,.jupyter-wrapper .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-select select.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-html-select select:disabled,.jupyter-wrapper .bp3-select select:disabled,.jupyter-wrapper .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-select select.bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-html-select select:disabled.bp3-active,.jupyter-wrapper .bp3-select select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select select:disabled.bp3-active:hover,.jupyter-wrapper .bp3-select select:disabled.bp3-active:hover,.jupyter-wrapper .bp3-html-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select select.bp3-disabled.bp3-active:hover,.jupyter-wrapper .bp3-select select.bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-html-select.bp3-minimal select,.jupyter-wrapper .bp3-select.bp3-minimal select{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal select:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-html-select.bp3-large select,.jupyter-wrapper .bp3-select.bp3-large select{font-size:16px;height:40px;padding-right:35px}.jupyter-wrapper .bp3-dark .bp3-html-select select,.jupyter-wrapper .bp3-dark .bp3-select select{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select select:hover,.jupyter-wrapper .bp3-dark .bp3-select select:hover,.jupyter-wrapper .bp3-dark .bp3-html-select select:active,.jupyter-wrapper .bp3-dark .bp3-select select:active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select select:hover,.jupyter-wrapper .bp3-dark .bp3-select select:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-html-select select:active,.jupyter-wrapper .bp3-dark .bp3-select select:active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-html-select select:disabled,.jupyter-wrapper .bp3-dark .bp3-select select:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-html-select select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-html-select select .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-dark .bp3-select select .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-html-select select:disabled,.jupyter-wrapper .bp3-select select:disabled{background-color:#ced9e080;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-select .bp3-icon,.jupyter-wrapper .bp3-select:after{color:#5c7080;pointer-events:none;position:absolute;right:7px;top:7px}.jupyter-wrapper .bp3-html-select .bp3-disabled.bp3-icon,.jupyter-wrapper .bp3-select .bp3-disabled.bp3-icon,.jupyter-wrapper .bp3-disabled.bp3-select:after{color:#5c708099}.jupyter-wrapper .bp3-html-select,.jupyter-wrapper .bp3-select{display:inline-block;letter-spacing:normal;position:relative;vertical-align:middle}.jupyter-wrapper .bp3-html-select select::-ms-expand,.jupyter-wrapper .bp3-select select::-ms-expand{display:none}.jupyter-wrapper .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-select .bp3-icon{color:#5c7080}.jupyter-wrapper .bp3-html-select .bp3-icon:hover,.jupyter-wrapper .bp3-select .bp3-icon:hover{color:#182026}.jupyter-wrapper .bp3-dark .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-select .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-html-select .bp3-icon:hover,.jupyter-wrapper .bp3-dark .bp3-select .bp3-icon:hover{color:#f5f8fa}.jupyter-wrapper .bp3-html-select.bp3-large:after,.jupyter-wrapper .bp3-html-select.bp3-large .bp3-icon,.jupyter-wrapper .bp3-select.bp3-large:after,.jupyter-wrapper .bp3-select.bp3-large .bp3-icon{right:12px;top:12px}.jupyter-wrapper .bp3-html-select.bp3-fill,.jupyter-wrapper .bp3-html-select.bp3-fill select,.jupyter-wrapper .bp3-select.bp3-fill,.jupyter-wrapper .bp3-select.bp3-fill select{width:100%}.jupyter-wrapper .bp3-dark .bp3-html-select option,.jupyter-wrapper .bp3-dark .bp3-select option{background-color:#30404d;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select option:disabled,.jupyter-wrapper .bp3-dark .bp3-select option:disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-html-select:after,.jupyter-wrapper .bp3-dark .bp3-select:after{color:#a7b6c2}.jupyter-wrapper .bp3-select:after{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;content:\"\ue6c6\"}.jupyter-wrapper .bp3-running-text table,.jupyter-wrapper table.bp3-html-table{border-spacing:0;font-size:14px}.jupyter-wrapper .bp3-running-text table th,.jupyter-wrapper table.bp3-html-table th,.jupyter-wrapper .bp3-running-text table td,.jupyter-wrapper table.bp3-html-table td{padding:11px;text-align:left;vertical-align:top}.jupyter-wrapper .bp3-running-text table th,.jupyter-wrapper table.bp3-html-table th{color:#182026;font-weight:600}.jupyter-wrapper .bp3-running-text table td,.jupyter-wrapper table.bp3-html-table td{color:#182026}.jupyter-wrapper .bp3-running-text table tbody tr:first-child th,.jupyter-wrapper table.bp3-html-table tbody tr:first-child th,.jupyter-wrapper .bp3-running-text table tbody tr:first-child td,.jupyter-wrapper table.bp3-html-table tbody tr:first-child td,.jupyter-wrapper .bp3-running-text table tfoot tr:first-child th,.jupyter-wrapper table.bp3-html-table tfoot tr:first-child th,.jupyter-wrapper .bp3-running-text table tfoot tr:first-child td,.jupyter-wrapper table.bp3-html-table tfoot tr:first-child td{-webkit-box-shadow:inset 0 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26}.jupyter-wrapper .bp3-dark .bp3-running-text table th,.jupyter-wrapper .bp3-running-text .bp3-dark table th,.jupyter-wrapper .bp3-dark table.bp3-html-table th,.jupyter-wrapper .bp3-dark .bp3-running-text table td,.jupyter-wrapper .bp3-running-text .bp3-dark table td,.jupyter-wrapper .bp3-dark table.bp3-html-table td{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-running-text table tbody tr:first-child th,.jupyter-wrapper .bp3-running-text .bp3-dark table tbody tr:first-child th,.jupyter-wrapper .bp3-dark table.bp3-html-table tbody tr:first-child th,.jupyter-wrapper .bp3-dark .bp3-running-text table tbody tr:first-child td,.jupyter-wrapper .bp3-running-text .bp3-dark table tbody tr:first-child td,.jupyter-wrapper .bp3-dark table.bp3-html-table tbody tr:first-child td,.jupyter-wrapper .bp3-dark .bp3-running-text table tfoot tr:first-child th,.jupyter-wrapper .bp3-running-text .bp3-dark table tfoot tr:first-child th,.jupyter-wrapper .bp3-dark table.bp3-html-table tfoot tr:first-child th,.jupyter-wrapper .bp3-dark .bp3-running-text table tfoot tr:first-child td,.jupyter-wrapper .bp3-running-text .bp3-dark table tfoot tr:first-child td,.jupyter-wrapper .bp3-dark table.bp3-html-table tfoot tr:first-child td{-webkit-box-shadow:inset 0 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 0 1px #ffffff26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-condensed th,.jupyter-wrapper table.bp3-html-table.bp3-html-table-condensed td,.jupyter-wrapper table.bp3-html-table.bp3-small th,.jupyter-wrapper table.bp3-html-table.bp3-small td{padding-bottom:6px;padding-top:6px}.jupyter-wrapper table.bp3-html-table.bp3-html-table-striped tbody tr:nth-child(odd) td{background:rgba(191,204,214,.15)}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered th:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 0 #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tbody tr td,.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tfoot tr td{-webkit-box-shadow:inset 0 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tbody tr td:not(:first-child),.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tfoot tr td:not(:first-child){-webkit-box-shadow:inset 1px 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 1px #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 0 #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-interactive tbody tr:hover td{background-color:#bfccd64d;cursor:pointer}.jupyter-wrapper table.bp3-html-table.bp3-interactive tbody tr:active td{background-color:#bfccd666}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-striped tbody tr:nth-child(odd) td{background:rgba(92,112,128,.15)}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered th:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 0 #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tbody tr td,.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tfoot tr td{-webkit-box-shadow:inset 0 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 0 1px #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tbody tr td:not(:first-child),.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tfoot tr td:not(:first-child){-webkit-box-shadow:inset 1px 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 1px #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td{-webkit-box-shadow:inset 1px 0 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 0 #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td:first-child{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-interactive tbody tr:hover td{background-color:#5c70804d;cursor:pointer}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-interactive tbody tr:active td{background-color:#5c708066}.jupyter-wrapper .bp3-key-combo{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.jupyter-wrapper .bp3-key-combo>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-key-combo>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-key-combo:before,.jupyter-wrapper .bp3-key-combo>*{margin-right:5px}.jupyter-wrapper .bp3-key-combo:empty:before,.jupyter-wrapper .bp3-key-combo>:last-child{margin-right:0}.jupyter-wrapper .bp3-hotkey-dialog{padding-bottom:0;top:40px}.jupyter-wrapper .bp3-hotkey-dialog .bp3-dialog-body{margin:0;padding:0}.jupyter-wrapper .bp3-hotkey-dialog .bp3-hotkey-label{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.jupyter-wrapper .bp3-hotkey-column{margin:auto;max-height:80vh;overflow-y:auto;padding:30px}.jupyter-wrapper .bp3-hotkey-column .bp3-heading{margin-bottom:20px}.jupyter-wrapper .bp3-hotkey-column .bp3-heading:not(:first-child){margin-top:40px}.jupyter-wrapper .bp3-hotkey{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin-left:0;margin-right:0}.jupyter-wrapper .bp3-hotkey:not(:last-child){margin-bottom:10px}.jupyter-wrapper .bp3-icon{display:inline-block;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;vertical-align:text-bottom}.jupyter-wrapper .bp3-icon:not(:empty):before{content:\"\"!important;content:unset!important}.jupyter-wrapper .bp3-icon>svg{display:block}.jupyter-wrapper .bp3-icon>svg:not([fill]){fill:currentColor}.jupyter-wrapper .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-icon-large.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-icon-large.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-icon-large.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-icon-large.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-danger{color:#ff7373}.jupyter-wrapper span.bp3-icon-standard{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block}.jupyter-wrapper span.bp3-icon-large{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block}.jupyter-wrapper span.bp3-icon:empty{font-family:Icons20;font-size:inherit;font-style:normal;font-weight:400;line-height:1}.jupyter-wrapper span.bp3-icon:empty:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.jupyter-wrapper .bp3-icon-add:before{content:\"\ue63e\"}.jupyter-wrapper .bp3-icon-add-column-left:before{content:\"\ue6f9\"}.jupyter-wrapper .bp3-icon-add-column-right:before{content:\"\ue6fa\"}.jupyter-wrapper .bp3-icon-add-row-bottom:before{content:\"\ue6f8\"}.jupyter-wrapper .bp3-icon-add-row-top:before{content:\"\ue6f7\"}.jupyter-wrapper .bp3-icon-add-to-artifact:before{content:\"\ue67c\"}.jupyter-wrapper .bp3-icon-add-to-folder:before{content:\"\ue6d2\"}.jupyter-wrapper .bp3-icon-airplane:before{content:\"\ue74b\"}.jupyter-wrapper .bp3-icon-align-center:before{content:\"\ue603\"}.jupyter-wrapper .bp3-icon-align-justify:before{content:\"\ue605\"}.jupyter-wrapper .bp3-icon-align-left:before{content:\"\ue602\"}.jupyter-wrapper .bp3-icon-align-right:before{content:\"\ue604\"}.jupyter-wrapper .bp3-icon-alignment-bottom:before{content:\"\ue727\"}.jupyter-wrapper .bp3-icon-alignment-horizontal-center:before{content:\"\ue726\"}.jupyter-wrapper .bp3-icon-alignment-left:before{content:\"\ue722\"}.jupyter-wrapper .bp3-icon-alignment-right:before{content:\"\ue724\"}.jupyter-wrapper .bp3-icon-alignment-top:before{content:\"\ue725\"}.jupyter-wrapper .bp3-icon-alignment-vertical-center:before{content:\"\ue723\"}.jupyter-wrapper .bp3-icon-annotation:before{content:\"\ue6f0\"}.jupyter-wrapper .bp3-icon-application:before{content:\"\ue735\"}.jupyter-wrapper .bp3-icon-applications:before{content:\"\ue621\"}.jupyter-wrapper .bp3-icon-archive:before{content:\"\ue907\"}.jupyter-wrapper .bp3-icon-arrow-bottom-left:before{content:\"\u2199\"}.jupyter-wrapper .bp3-icon-arrow-bottom-right:before{content:\"\u2198\"}.jupyter-wrapper .bp3-icon-arrow-down:before{content:\"\u2193\"}.jupyter-wrapper .bp3-icon-arrow-left:before{content:\"\u2190\"}.jupyter-wrapper .bp3-icon-arrow-right:before{content:\"\u2192\"}.jupyter-wrapper .bp3-icon-arrow-top-left:before{content:\"\u2196\"}.jupyter-wrapper .bp3-icon-arrow-top-right:before{content:\"\u2197\"}.jupyter-wrapper .bp3-icon-arrow-up:before{content:\"\u2191\"}.jupyter-wrapper .bp3-icon-arrows-horizontal:before{content:\"\u2194\"}.jupyter-wrapper .bp3-icon-arrows-vertical:before{content:\"\u2195\"}.jupyter-wrapper .bp3-icon-asterisk:before{content:\"*\"}.jupyter-wrapper .bp3-icon-automatic-updates:before{content:\"\ue65f\"}.jupyter-wrapper .bp3-icon-badge:before{content:\"\ue6e3\"}.jupyter-wrapper .bp3-icon-ban-circle:before{content:\"\ue69d\"}.jupyter-wrapper .bp3-icon-bank-account:before{content:\"\ue76f\"}.jupyter-wrapper .bp3-icon-barcode:before{content:\"\ue676\"}.jupyter-wrapper .bp3-icon-blank:before{content:\"\ue900\"}.jupyter-wrapper .bp3-icon-blocked-person:before{content:\"\ue768\"}.jupyter-wrapper .bp3-icon-bold:before{content:\"\ue606\"}.jupyter-wrapper .bp3-icon-book:before{content:\"\ue6b8\"}.jupyter-wrapper .bp3-icon-bookmark:before{content:\"\ue61a\"}.jupyter-wrapper .bp3-icon-box:before{content:\"\ue6bf\"}.jupyter-wrapper .bp3-icon-briefcase:before{content:\"\ue674\"}.jupyter-wrapper .bp3-icon-bring-data:before{content:\"\ue90a\"}.jupyter-wrapper .bp3-icon-build:before{content:\"\ue72d\"}.jupyter-wrapper .bp3-icon-calculator:before{content:\"\ue70b\"}.jupyter-wrapper .bp3-icon-calendar:before{content:\"\ue62b\"}.jupyter-wrapper .bp3-icon-camera:before{content:\"\ue69e\"}.jupyter-wrapper .bp3-icon-caret-down:before{content:\"\u2304\"}.jupyter-wrapper .bp3-icon-caret-left:before{content:\"\u2329\"}.jupyter-wrapper .bp3-icon-caret-right:before{content:\"\u232a\"}.jupyter-wrapper .bp3-icon-caret-up:before{content:\"\u2303\"}.jupyter-wrapper .bp3-icon-cell-tower:before{content:\"\ue770\"}.jupyter-wrapper .bp3-icon-MKDOCS_changes:before{content:\"\ue623\"}.jupyter-wrapper .bp3-icon-chart:before{content:\"\ue67e\"}.jupyter-wrapper .bp3-icon-chat:before{content:\"\ue689\"}.jupyter-wrapper .bp3-icon-chevron-backward:before{content:\"\ue6df\"}.jupyter-wrapper .bp3-icon-chevron-down:before{content:\"\ue697\"}.jupyter-wrapper .bp3-icon-chevron-forward:before{content:\"\ue6e0\"}.jupyter-wrapper .bp3-icon-chevron-left:before{content:\"\ue694\"}.jupyter-wrapper .bp3-icon-chevron-right:before{content:\"\ue695\"}.jupyter-wrapper .bp3-icon-chevron-up:before{content:\"\ue696\"}.jupyter-wrapper .bp3-icon-circle:before{content:\"\ue66a\"}.jupyter-wrapper .bp3-icon-circle-arrow-down:before{content:\"\ue68e\"}.jupyter-wrapper .bp3-icon-circle-arrow-left:before{content:\"\ue68c\"}.jupyter-wrapper .bp3-icon-circle-arrow-right:before{content:\"\ue68b\"}.jupyter-wrapper .bp3-icon-circle-arrow-up:before{content:\"\ue68d\"}.jupyter-wrapper .bp3-icon-citation:before{content:\"\ue61b\"}.jupyter-wrapper .bp3-icon-clean:before{content:\"\ue7c5\"}.jupyter-wrapper .bp3-icon-clipboard:before{content:\"\ue61d\"}.jupyter-wrapper .bp3-icon-cloud:before{content:\"\u2601\"}.jupyter-wrapper .bp3-icon-cloud-download:before{content:\"\ue690\"}.jupyter-wrapper .bp3-icon-cloud-upload:before{content:\"\ue691\"}.jupyter-wrapper .bp3-icon-code:before{content:\"\ue661\"}.jupyter-wrapper .bp3-icon-code-block:before{content:\"\ue6c5\"}.jupyter-wrapper .bp3-icon-cog:before{content:\"\ue645\"}.jupyter-wrapper .bp3-icon-collapse-all:before{content:\"\ue763\"}.jupyter-wrapper .bp3-icon-column-layout:before{content:\"\ue6da\"}.jupyter-wrapper .bp3-icon-comment:before{content:\"\ue68a\"}.jupyter-wrapper .bp3-icon-comparison:before{content:\"\ue637\"}.jupyter-wrapper .bp3-icon-compass:before{content:\"\ue79c\"}.jupyter-wrapper .bp3-icon-compressed:before{content:\"\ue6c0\"}.jupyter-wrapper .bp3-icon-confirm:before{content:\"\ue639\"}.jupyter-wrapper .bp3-icon-console:before{content:\"\ue79b\"}.jupyter-wrapper .bp3-icon-contrast:before{content:\"\ue6cb\"}.jupyter-wrapper .bp3-icon-control:before{content:\"\ue67f\"}.jupyter-wrapper .bp3-icon-credit-card:before{content:\"\ue649\"}.jupyter-wrapper .bp3-icon-cross:before{content:\"\u2717\"}.jupyter-wrapper .bp3-icon-crown:before{content:\"\ue7b4\"}.jupyter-wrapper .bp3-icon-cube:before{content:\"\ue7c8\"}.jupyter-wrapper .bp3-icon-cube-add:before{content:\"\ue7c9\"}.jupyter-wrapper .bp3-icon-cube-remove:before{content:\"\ue7d0\"}.jupyter-wrapper .bp3-icon-curved-range-chart:before{content:\"\ue71b\"}.jupyter-wrapper .bp3-icon-cut:before{content:\"\ue6ef\"}.jupyter-wrapper .bp3-icon-dashboard:before{content:\"\ue751\"}.jupyter-wrapper .bp3-icon-data-lineage:before{content:\"\ue908\"}.jupyter-wrapper .bp3-icon-database:before{content:\"\ue683\"}.jupyter-wrapper .bp3-icon-delete:before{content:\"\ue644\"}.jupyter-wrapper .bp3-icon-delta:before{content:\"\u0394\"}.jupyter-wrapper .bp3-icon-derive-column:before{content:\"\ue739\"}.jupyter-wrapper .bp3-icon-desktop:before{content:\"\ue6af\"}.jupyter-wrapper .bp3-icon-diagnosis:before{content:\"\ue90d\"}.jupyter-wrapper .bp3-icon-diagram-tree:before{content:\"\ue7b3\"}.jupyter-wrapper .bp3-icon-direction-left:before{content:\"\ue681\"}.jupyter-wrapper .bp3-icon-direction-right:before{content:\"\ue682\"}.jupyter-wrapper .bp3-icon-disable:before{content:\"\ue600\"}.jupyter-wrapper .bp3-icon-document:before{content:\"\ue630\"}.jupyter-wrapper .bp3-icon-document-open:before{content:\"\ue71e\"}.jupyter-wrapper .bp3-icon-document-share:before{content:\"\ue71f\"}.jupyter-wrapper .bp3-icon-dollar:before{content:\"$\"}.jupyter-wrapper .bp3-icon-dot:before{content:\"\u2022\"}.jupyter-wrapper .bp3-icon-double-caret-horizontal:before{content:\"\ue6c7\"}.jupyter-wrapper .bp3-icon-double-caret-vertical:before{content:\"\ue6c6\"}.jupyter-wrapper .bp3-icon-double-chevron-down:before{content:\"\ue703\"}.jupyter-wrapper .bp3-icon-double-chevron-left:before{content:\"\ue6ff\"}.jupyter-wrapper .bp3-icon-double-chevron-right:before{content:\"\ue701\"}.jupyter-wrapper .bp3-icon-double-chevron-up:before{content:\"\ue702\"}.jupyter-wrapper .bp3-icon-doughnut-chart:before{content:\"\ue6ce\"}.jupyter-wrapper .bp3-icon-download:before{content:\"\ue62f\"}.jupyter-wrapper .bp3-icon-drag-handle-horizontal:before{content:\"\ue716\"}.jupyter-wrapper .bp3-icon-drag-handle-vertical:before{content:\"\ue715\"}.jupyter-wrapper .bp3-icon-draw:before{content:\"\ue66b\"}.jupyter-wrapper .bp3-icon-drive-time:before{content:\"\ue615\"}.jupyter-wrapper .bp3-icon-duplicate:before{content:\"\ue69c\"}.jupyter-wrapper .bp3-icon-edit:before{content:\"\u270e\"}.jupyter-wrapper .bp3-icon-eject:before{content:\"\u23cf\"}.jupyter-wrapper .bp3-icon-endorsed:before{content:\"\ue75f\"}.jupyter-wrapper .bp3-icon-envelope:before{content:\"\u2709\"}.jupyter-wrapper .bp3-icon-equals:before{content:\"\ue7d9\"}.jupyter-wrapper .bp3-icon-eraser:before{content:\"\ue773\"}.jupyter-wrapper .bp3-icon-error:before{content:\"\ue648\"}.jupyter-wrapper .bp3-icon-euro:before{content:\"\u20ac\"}.jupyter-wrapper .bp3-icon-MKDOCS_exchange:before{content:\"\ue636\"}.jupyter-wrapper .bp3-icon-exclude-row:before{content:\"\ue6ea\"}.jupyter-wrapper .bp3-icon-expand-all:before{content:\"\ue764\"}.jupyter-wrapper .bp3-icon-export:before{content:\"\ue633\"}.jupyter-wrapper .bp3-icon-eye-off:before{content:\"\ue6cc\"}.jupyter-wrapper .bp3-icon-eye-on:before{content:\"\ue75a\"}.jupyter-wrapper .bp3-icon-eye-open:before{content:\"\ue66f\"}.jupyter-wrapper .bp3-icon-fast-backward:before{content:\"\ue6a8\"}.jupyter-wrapper .bp3-icon-fast-forward:before{content:\"\ue6ac\"}.jupyter-wrapper .bp3-icon-feed:before{content:\"\ue656\"}.jupyter-wrapper .bp3-icon-feed-subscribed:before{content:\"\ue78f\"}.jupyter-wrapper .bp3-icon-film:before{content:\"\ue6a1\"}.jupyter-wrapper .bp3-icon-filter:before{content:\"\ue638\"}.jupyter-wrapper .bp3-icon-filter-keep:before{content:\"\ue78c\"}.jupyter-wrapper .bp3-icon-filter-list:before{content:\"\ue6ee\"}.jupyter-wrapper .bp3-icon-filter-open:before{content:\"\ue7d7\"}.jupyter-wrapper .bp3-icon-filter-remove:before{content:\"\ue78d\"}.jupyter-wrapper .bp3-icon-flag:before{content:\"\u2691\"}.jupyter-wrapper .bp3-icon-flame:before{content:\"\ue7a9\"}.jupyter-wrapper .bp3-icon-flash:before{content:\"\ue6b3\"}.jupyter-wrapper .bp3-icon-floppy-disk:before{content:\"\ue6b7\"}.jupyter-wrapper .bp3-icon-flow-branch:before{content:\"\ue7c1\"}.jupyter-wrapper .bp3-icon-flow-end:before{content:\"\ue7c4\"}.jupyter-wrapper .bp3-icon-flow-linear:before{content:\"\ue7c0\"}.jupyter-wrapper .bp3-icon-flow-review:before{content:\"\ue7c2\"}.jupyter-wrapper .bp3-icon-flow-review-branch:before{content:\"\ue7c3\"}.jupyter-wrapper .bp3-icon-flows:before{content:\"\ue659\"}.jupyter-wrapper .bp3-icon-folder-close:before{content:\"\ue652\"}.jupyter-wrapper .bp3-icon-folder-new:before{content:\"\ue7b0\"}.jupyter-wrapper .bp3-icon-folder-open:before{content:\"\ue651\"}.jupyter-wrapper .bp3-icon-folder-shared:before{content:\"\ue653\"}.jupyter-wrapper .bp3-icon-folder-shared-open:before{content:\"\ue670\"}.jupyter-wrapper .bp3-icon-follower:before{content:\"\ue760\"}.jupyter-wrapper .bp3-icon-following:before{content:\"\ue761\"}.jupyter-wrapper .bp3-icon-font:before{content:\"\ue6b4\"}.jupyter-wrapper .bp3-icon-fork:before{content:\"\ue63a\"}.jupyter-wrapper .bp3-icon-form:before{content:\"\ue795\"}.jupyter-wrapper .bp3-icon-full-circle:before{content:\"\ue685\"}.jupyter-wrapper .bp3-icon-full-stacked-chart:before{content:\"\ue75e\"}.jupyter-wrapper .bp3-icon-fullscreen:before{content:\"\ue699\"}.jupyter-wrapper .bp3-icon-function:before{content:\"\ue6e5\"}.jupyter-wrapper .bp3-icon-gantt-chart:before{content:\"\ue6f4\"}.jupyter-wrapper .bp3-icon-geolocation:before{content:\"\ue640\"}.jupyter-wrapper .bp3-icon-geosearch:before{content:\"\ue613\"}.jupyter-wrapper .bp3-icon-git-branch:before{content:\"\ue72a\"}.jupyter-wrapper .bp3-icon-git-commit:before{content:\"\ue72b\"}.jupyter-wrapper .bp3-icon-git-merge:before{content:\"\ue729\"}.jupyter-wrapper .bp3-icon-git-new-branch:before{content:\"\ue749\"}.jupyter-wrapper .bp3-icon-git-pull:before{content:\"\ue728\"}.jupyter-wrapper .bp3-icon-git-push:before{content:\"\ue72c\"}.jupyter-wrapper .bp3-icon-git-repo:before{content:\"\ue748\"}.jupyter-wrapper .bp3-icon-glass:before{content:\"\ue6b1\"}.jupyter-wrapper .bp3-icon-globe:before{content:\"\ue666\"}.jupyter-wrapper .bp3-icon-globe-network:before{content:\"\ue7b5\"}.jupyter-wrapper .bp3-icon-graph:before{content:\"\ue673\"}.jupyter-wrapper .bp3-icon-graph-remove:before{content:\"\ue609\"}.jupyter-wrapper .bp3-icon-greater-than:before{content:\"\ue7e1\"}.jupyter-wrapper .bp3-icon-greater-than-or-equal-to:before{content:\"\ue7e2\"}.jupyter-wrapper .bp3-icon-grid:before{content:\"\ue6d0\"}.jupyter-wrapper .bp3-icon-grid-view:before{content:\"\ue6e4\"}.jupyter-wrapper .bp3-icon-group-objects:before{content:\"\ue60a\"}.jupyter-wrapper .bp3-icon-grouped-bar-chart:before{content:\"\ue75d\"}.jupyter-wrapper .bp3-icon-hand:before{content:\"\ue6de\"}.jupyter-wrapper .bp3-icon-hand-down:before{content:\"\ue6bb\"}.jupyter-wrapper .bp3-icon-hand-left:before{content:\"\ue6bc\"}.jupyter-wrapper .bp3-icon-hand-right:before{content:\"\ue6b9\"}.jupyter-wrapper .bp3-icon-hand-up:before{content:\"\ue6ba\"}.jupyter-wrapper .bp3-icon-header:before{content:\"\ue6b5\"}.jupyter-wrapper .bp3-icon-header-one:before{content:\"\ue793\"}.jupyter-wrapper .bp3-icon-header-two:before{content:\"\ue794\"}.jupyter-wrapper .bp3-icon-headset:before{content:\"\ue6dc\"}.jupyter-wrapper .bp3-icon-heart:before{content:\"\u2665\"}.jupyter-wrapper .bp3-icon-heart-broken:before{content:\"\ue7a2\"}.jupyter-wrapper .bp3-icon-heat-grid:before{content:\"\ue6f3\"}.jupyter-wrapper .bp3-icon-heatmap:before{content:\"\ue614\"}.jupyter-wrapper .bp3-icon-help:before{content:\"?\"}.jupyter-wrapper .bp3-icon-helper-management:before{content:\"\ue66d\"}.jupyter-wrapper .bp3-icon-highlight:before{content:\"\ue6ed\"}.jupyter-wrapper .bp3-icon-history:before{content:\"\ue64a\"}.jupyter-wrapper .bp3-icon-home:before{content:\"\u2302\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart:before{content:\"\ue70c\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart-asc:before{content:\"\ue75c\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart-desc:before{content:\"\ue71d\"}.jupyter-wrapper .bp3-icon-horizontal-distribution:before{content:\"\ue720\"}.jupyter-wrapper .bp3-icon-id-number:before{content:\"\ue771\"}.jupyter-wrapper .bp3-icon-image-rotate-left:before{content:\"\ue73a\"}.jupyter-wrapper .bp3-icon-image-rotate-right:before{content:\"\ue73b\"}.jupyter-wrapper .bp3-icon-import:before{content:\"\ue632\"}.jupyter-wrapper .bp3-icon-inbox:before{content:\"\ue629\"}.jupyter-wrapper .bp3-icon-inbox-filtered:before{content:\"\ue7d1\"}.jupyter-wrapper .bp3-icon-inbox-geo:before{content:\"\ue7d2\"}.jupyter-wrapper .bp3-icon-inbox-search:before{content:\"\ue7d3\"}.jupyter-wrapper .bp3-icon-inbox-update:before{content:\"\ue7d4\"}.jupyter-wrapper .bp3-icon-info-sign:before{content:\"\u2139\"}.jupyter-wrapper .bp3-icon-inheritance:before{content:\"\ue7d5\"}.jupyter-wrapper .bp3-icon-inner-join:before{content:\"\ue7a3\"}.jupyter-wrapper .bp3-icon-insert:before{content:\"\ue66c\"}.jupyter-wrapper .bp3-icon-intersection:before{content:\"\ue765\"}.jupyter-wrapper .bp3-icon-ip-address:before{content:\"\ue772\"}.jupyter-wrapper .bp3-icon-issue:before{content:\"\ue774\"}.jupyter-wrapper .bp3-icon-issue-closed:before{content:\"\ue776\"}.jupyter-wrapper .bp3-icon-issue-new:before{content:\"\ue775\"}.jupyter-wrapper .bp3-icon-italic:before{content:\"\ue607\"}.jupyter-wrapper .bp3-icon-join-table:before{content:\"\ue738\"}.jupyter-wrapper .bp3-icon-key:before{content:\"\ue78e\"}.jupyter-wrapper .bp3-icon-key-backspace:before{content:\"\ue707\"}.jupyter-wrapper .bp3-icon-key-command:before{content:\"\ue705\"}.jupyter-wrapper .bp3-icon-key-control:before{content:\"\ue704\"}.jupyter-wrapper .bp3-icon-key-delete:before{content:\"\ue708\"}.jupyter-wrapper .bp3-icon-key-enter:before{content:\"\ue70a\"}.jupyter-wrapper .bp3-icon-key-escape:before{content:\"\ue709\"}.jupyter-wrapper .bp3-icon-key-option:before{content:\"\ue742\"}.jupyter-wrapper .bp3-icon-key-shift:before{content:\"\ue706\"}.jupyter-wrapper .bp3-icon-key-tab:before{content:\"\ue757\"}.jupyter-wrapper .bp3-icon-known-vehicle:before{content:\"\ue73c\"}.jupyter-wrapper .bp3-icon-lab-test:before{content:\"\ue90e\"}.jupyter-wrapper .bp3-icon-label:before{content:\"\ue665\"}.jupyter-wrapper .bp3-icon-layer:before{content:\"\ue6cf\"}.jupyter-wrapper .bp3-icon-layers:before{content:\"\ue618\"}.jupyter-wrapper .bp3-icon-layout:before{content:\"\ue60c\"}.jupyter-wrapper .bp3-icon-layout-auto:before{content:\"\ue60d\"}.jupyter-wrapper .bp3-icon-layout-balloon:before{content:\"\ue6d3\"}.jupyter-wrapper .bp3-icon-layout-circle:before{content:\"\ue60e\"}.jupyter-wrapper .bp3-icon-layout-grid:before{content:\"\ue610\"}.jupyter-wrapper .bp3-icon-layout-group-by:before{content:\"\ue611\"}.jupyter-wrapper .bp3-icon-layout-hierarchy:before{content:\"\ue60f\"}.jupyter-wrapper .bp3-icon-layout-linear:before{content:\"\ue6c3\"}.jupyter-wrapper .bp3-icon-layout-skew-grid:before{content:\"\ue612\"}.jupyter-wrapper .bp3-icon-layout-sorted-clusters:before{content:\"\ue6d4\"}.jupyter-wrapper .bp3-icon-learning:before{content:\"\ue904\"}.jupyter-wrapper .bp3-icon-left-join:before{content:\"\ue7a4\"}.jupyter-wrapper .bp3-icon-less-than:before{content:\"\ue7e3\"}.jupyter-wrapper .bp3-icon-less-than-or-equal-to:before{content:\"\ue7e4\"}.jupyter-wrapper .bp3-icon-lifesaver:before{content:\"\ue7c7\"}.jupyter-wrapper .bp3-icon-lightbulb:before{content:\"\ue6b0\"}.jupyter-wrapper .bp3-icon-link:before{content:\"\ue62d\"}.jupyter-wrapper .bp3-icon-list:before{content:\"\u2630\"}.jupyter-wrapper .bp3-icon-list-columns:before{content:\"\ue7b9\"}.jupyter-wrapper .bp3-icon-list-detail-view:before{content:\"\ue743\"}.jupyter-wrapper .bp3-icon-locate:before{content:\"\ue619\"}.jupyter-wrapper .bp3-icon-lock:before{content:\"\ue625\"}.jupyter-wrapper .bp3-icon-log-in:before{content:\"\ue69a\"}.jupyter-wrapper .bp3-icon-log-out:before{content:\"\ue64c\"}.jupyter-wrapper .bp3-icon-manual:before{content:\"\ue6f6\"}.jupyter-wrapper .bp3-icon-manually-entered-data:before{content:\"\ue74a\"}.jupyter-wrapper .bp3-icon-map:before{content:\"\ue662\"}.jupyter-wrapper .bp3-icon-map-create:before{content:\"\ue741\"}.jupyter-wrapper .bp3-icon-map-marker:before{content:\"\ue67d\"}.jupyter-wrapper .bp3-icon-maximize:before{content:\"\ue635\"}.jupyter-wrapper .bp3-icon-media:before{content:\"\ue62c\"}.jupyter-wrapper .bp3-icon-menu:before{content:\"\ue762\"}.jupyter-wrapper .bp3-icon-menu-closed:before{content:\"\ue655\"}.jupyter-wrapper .bp3-icon-menu-open:before{content:\"\ue654\"}.jupyter-wrapper .bp3-icon-merge-columns:before{content:\"\ue74f\"}.jupyter-wrapper .bp3-icon-merge-links:before{content:\"\ue60b\"}.jupyter-wrapper .bp3-icon-minimize:before{content:\"\ue634\"}.jupyter-wrapper .bp3-icon-minus:before{content:\"\u2212\"}.jupyter-wrapper .bp3-icon-mobile-phone:before{content:\"\ue717\"}.jupyter-wrapper .bp3-icon-mobile-video:before{content:\"\ue69f\"}.jupyter-wrapper .bp3-icon-moon:before{content:\"\ue754\"}.jupyter-wrapper .bp3-icon-more:before{content:\"\ue62a\"}.jupyter-wrapper .bp3-icon-mountain:before{content:\"\ue7b1\"}.jupyter-wrapper .bp3-icon-move:before{content:\"\ue693\"}.jupyter-wrapper .bp3-icon-mugshot:before{content:\"\ue6db\"}.jupyter-wrapper .bp3-icon-multi-select:before{content:\"\ue680\"}.jupyter-wrapper .bp3-icon-music:before{content:\"\ue6a6\"}.jupyter-wrapper .bp3-icon-new-drawing:before{content:\"\ue905\"}.jupyter-wrapper .bp3-icon-new-grid-item:before{content:\"\ue747\"}.jupyter-wrapper .bp3-icon-new-layer:before{content:\"\ue902\"}.jupyter-wrapper .bp3-icon-new-layers:before{content:\"\ue903\"}.jupyter-wrapper .bp3-icon-new-link:before{content:\"\ue65c\"}.jupyter-wrapper .bp3-icon-new-object:before{content:\"\ue65d\"}.jupyter-wrapper .bp3-icon-new-person:before{content:\"\ue6e9\"}.jupyter-wrapper .bp3-icon-new-prescription:before{content:\"\ue78b\"}.jupyter-wrapper .bp3-icon-new-text-box:before{content:\"\ue65b\"}.jupyter-wrapper .bp3-icon-ninja:before{content:\"\ue675\"}.jupyter-wrapper .bp3-icon-not-equal-to:before{content:\"\ue7e0\"}.jupyter-wrapper .bp3-icon-notifications:before{content:\"\ue624\"}.jupyter-wrapper .bp3-icon-notifications-updated:before{content:\"\ue7b8\"}.jupyter-wrapper .bp3-icon-numbered-list:before{content:\"\ue746\"}.jupyter-wrapper .bp3-icon-numerical:before{content:\"\ue756\"}.jupyter-wrapper .bp3-icon-office:before{content:\"\ue69b\"}.jupyter-wrapper .bp3-icon-offline:before{content:\"\ue67a\"}.jupyter-wrapper .bp3-icon-oil-field:before{content:\"\ue73f\"}.jupyter-wrapper .bp3-icon-one-column:before{content:\"\ue658\"}.jupyter-wrapper .bp3-icon-outdated:before{content:\"\ue7a8\"}.jupyter-wrapper .bp3-icon-page-layout:before{content:\"\ue660\"}.jupyter-wrapper .bp3-icon-panel-stats:before{content:\"\ue777\"}.jupyter-wrapper .bp3-icon-panel-table:before{content:\"\ue778\"}.jupyter-wrapper .bp3-icon-paperclip:before{content:\"\ue664\"}.jupyter-wrapper .bp3-icon-paragraph:before{content:\"\ue76c\"}.jupyter-wrapper .bp3-icon-path:before{content:\"\ue753\"}.jupyter-wrapper .bp3-icon-path-search:before{content:\"\ue65e\"}.jupyter-wrapper .bp3-icon-pause:before{content:\"\ue6a9\"}.jupyter-wrapper .bp3-icon-people:before{content:\"\ue63d\"}.jupyter-wrapper .bp3-icon-percentage:before{content:\"\ue76a\"}.jupyter-wrapper .bp3-icon-person:before{content:\"\ue63c\"}.jupyter-wrapper .bp3-icon-phone:before{content:\"\u260e\"}.jupyter-wrapper .bp3-icon-pie-chart:before{content:\"\ue684\"}.jupyter-wrapper .bp3-icon-pin:before{content:\"\ue646\"}.jupyter-wrapper .bp3-icon-pivot:before{content:\"\ue6f1\"}.jupyter-wrapper .bp3-icon-pivot-table:before{content:\"\ue6eb\"}.jupyter-wrapper .bp3-icon-play:before{content:\"\ue6ab\"}.jupyter-wrapper .bp3-icon-plus:before{content:\"+\"}.jupyter-wrapper .bp3-icon-polygon-filter:before{content:\"\ue6d1\"}.jupyter-wrapper .bp3-icon-power:before{content:\"\ue6d9\"}.jupyter-wrapper .bp3-icon-predictive-analysis:before{content:\"\ue617\"}.jupyter-wrapper .bp3-icon-prescription:before{content:\"\ue78a\"}.jupyter-wrapper .bp3-icon-presentation:before{content:\"\ue687\"}.jupyter-wrapper .bp3-icon-print:before{content:\"\u2399\"}.jupyter-wrapper .bp3-icon-projects:before{content:\"\ue622\"}.jupyter-wrapper .bp3-icon-properties:before{content:\"\ue631\"}.jupyter-wrapper .bp3-icon-property:before{content:\"\ue65a\"}.jupyter-wrapper .bp3-icon-publish-function:before{content:\"\ue752\"}.jupyter-wrapper .bp3-icon-pulse:before{content:\"\ue6e8\"}.jupyter-wrapper .bp3-icon-random:before{content:\"\ue698\"}.jupyter-wrapper .bp3-icon-record:before{content:\"\ue6ae\"}.jupyter-wrapper .bp3-icon-redo:before{content:\"\ue6c4\"}.jupyter-wrapper .bp3-icon-refresh:before{content:\"\ue643\"}.jupyter-wrapper .bp3-icon-regression-chart:before{content:\"\ue758\"}.jupyter-wrapper .bp3-icon-remove:before{content:\"\ue63f\"}.jupyter-wrapper .bp3-icon-remove-column:before{content:\"\ue755\"}.jupyter-wrapper .bp3-icon-remove-column-left:before{content:\"\ue6fd\"}.jupyter-wrapper .bp3-icon-remove-column-right:before{content:\"\ue6fe\"}.jupyter-wrapper .bp3-icon-remove-row-bottom:before{content:\"\ue6fc\"}.jupyter-wrapper .bp3-icon-remove-row-top:before{content:\"\ue6fb\"}.jupyter-wrapper .bp3-icon-repeat:before{content:\"\ue692\"}.jupyter-wrapper .bp3-icon-reset:before{content:\"\ue7d6\"}.jupyter-wrapper .bp3-icon-resolve:before{content:\"\ue672\"}.jupyter-wrapper .bp3-icon-rig:before{content:\"\ue740\"}.jupyter-wrapper .bp3-icon-right-join:before{content:\"\ue7a5\"}.jupyter-wrapper .bp3-icon-ring:before{content:\"\ue6f2\"}.jupyter-wrapper .bp3-icon-rotate-document:before{content:\"\ue6e1\"}.jupyter-wrapper .bp3-icon-rotate-page:before{content:\"\ue6e2\"}.jupyter-wrapper .bp3-icon-satellite:before{content:\"\ue76b\"}.jupyter-wrapper .bp3-icon-saved:before{content:\"\ue6b6\"}.jupyter-wrapper .bp3-icon-scatter-plot:before{content:\"\ue73e\"}.jupyter-wrapper .bp3-icon-search:before{content:\"\ue64b\"}.jupyter-wrapper .bp3-icon-search-around:before{content:\"\ue608\"}.jupyter-wrapper .bp3-icon-search-template:before{content:\"\ue628\"}.jupyter-wrapper .bp3-icon-search-text:before{content:\"\ue663\"}.jupyter-wrapper .bp3-icon-segmented-control:before{content:\"\ue6ec\"}.jupyter-wrapper .bp3-icon-select:before{content:\"\ue616\"}.jupyter-wrapper .bp3-icon-selection:before{content:\"\u29bf\"}.jupyter-wrapper .bp3-icon-send-to:before{content:\"\ue66e\"}.jupyter-wrapper .bp3-icon-send-to-graph:before{content:\"\ue736\"}.jupyter-wrapper .bp3-icon-send-to-map:before{content:\"\ue737\"}.jupyter-wrapper .bp3-icon-series-add:before{content:\"\ue796\"}.jupyter-wrapper .bp3-icon-series-configuration:before{content:\"\ue79a\"}.jupyter-wrapper .bp3-icon-series-derived:before{content:\"\ue799\"}.jupyter-wrapper .bp3-icon-series-filtered:before{content:\"\ue798\"}.jupyter-wrapper .bp3-icon-series-search:before{content:\"\ue797\"}.jupyter-wrapper .bp3-icon-settings:before{content:\"\ue6a2\"}.jupyter-wrapper .bp3-icon-share:before{content:\"\ue62e\"}.jupyter-wrapper .bp3-icon-shield:before{content:\"\ue7b2\"}.jupyter-wrapper .bp3-icon-shop:before{content:\"\ue6c2\"}.jupyter-wrapper .bp3-icon-shopping-cart:before{content:\"\ue6c1\"}.jupyter-wrapper .bp3-icon-signal-search:before{content:\"\ue909\"}.jupyter-wrapper .bp3-icon-sim-card:before{content:\"\ue718\"}.jupyter-wrapper .bp3-icon-slash:before{content:\"\ue769\"}.jupyter-wrapper .bp3-icon-small-cross:before{content:\"\ue6d7\"}.jupyter-wrapper .bp3-icon-small-minus:before{content:\"\ue70e\"}.jupyter-wrapper .bp3-icon-small-plus:before{content:\"\ue70d\"}.jupyter-wrapper .bp3-icon-small-tick:before{content:\"\ue6d8\"}.jupyter-wrapper .bp3-icon-snowflake:before{content:\"\ue7b6\"}.jupyter-wrapper .bp3-icon-social-media:before{content:\"\ue671\"}.jupyter-wrapper .bp3-icon-sort:before{content:\"\ue64f\"}.jupyter-wrapper .bp3-icon-sort-alphabetical:before{content:\"\ue64d\"}.jupyter-wrapper .bp3-icon-sort-alphabetical-desc:before{content:\"\ue6c8\"}.jupyter-wrapper .bp3-icon-sort-asc:before{content:\"\ue6d5\"}.jupyter-wrapper .bp3-icon-sort-desc:before{content:\"\ue6d6\"}.jupyter-wrapper .bp3-icon-sort-numerical:before{content:\"\ue64e\"}.jupyter-wrapper .bp3-icon-sort-numerical-desc:before{content:\"\ue6c9\"}.jupyter-wrapper .bp3-icon-split-columns:before{content:\"\ue750\"}.jupyter-wrapper .bp3-icon-square:before{content:\"\ue686\"}.jupyter-wrapper .bp3-icon-stacked-chart:before{content:\"\ue6e7\"}.jupyter-wrapper .bp3-icon-star:before{content:\"\u2605\"}.jupyter-wrapper .bp3-icon-star-empty:before{content:\"\u2606\"}.jupyter-wrapper .bp3-icon-step-backward:before{content:\"\ue6a7\"}.jupyter-wrapper .bp3-icon-step-chart:before{content:\"\ue70f\"}.jupyter-wrapper .bp3-icon-step-forward:before{content:\"\ue6ad\"}.jupyter-wrapper .bp3-icon-stop:before{content:\"\ue6aa\"}.jupyter-wrapper .bp3-icon-stopwatch:before{content:\"\ue901\"}.jupyter-wrapper .bp3-icon-strikethrough:before{content:\"\ue7a6\"}.jupyter-wrapper .bp3-icon-style:before{content:\"\ue601\"}.jupyter-wrapper .bp3-icon-swap-horizontal:before{content:\"\ue745\"}.jupyter-wrapper .bp3-icon-swap-vertical:before{content:\"\ue744\"}.jupyter-wrapper .bp3-icon-symbol-circle:before{content:\"\ue72e\"}.jupyter-wrapper .bp3-icon-symbol-cross:before{content:\"\ue731\"}.jupyter-wrapper .bp3-icon-symbol-diamond:before{content:\"\ue730\"}.jupyter-wrapper .bp3-icon-symbol-square:before{content:\"\ue72f\"}.jupyter-wrapper .bp3-icon-symbol-triangle-down:before{content:\"\ue733\"}.jupyter-wrapper .bp3-icon-symbol-triangle-up:before{content:\"\ue732\"}.jupyter-wrapper .bp3-icon-tag:before{content:\"\ue61c\"}.jupyter-wrapper .bp3-icon-take-action:before{content:\"\ue6ca\"}.jupyter-wrapper .bp3-icon-taxi:before{content:\"\ue79e\"}.jupyter-wrapper .bp3-icon-text-highlight:before{content:\"\ue6dd\"}.jupyter-wrapper .bp3-icon-th:before{content:\"\ue667\"}.jupyter-wrapper .bp3-icon-th-derived:before{content:\"\ue669\"}.jupyter-wrapper .bp3-icon-th-disconnect:before{content:\"\ue7d8\"}.jupyter-wrapper .bp3-icon-th-filtered:before{content:\"\ue7c6\"}.jupyter-wrapper .bp3-icon-th-list:before{content:\"\ue668\"}.jupyter-wrapper .bp3-icon-thumbs-down:before{content:\"\ue6be\"}.jupyter-wrapper .bp3-icon-thumbs-up:before{content:\"\ue6bd\"}.jupyter-wrapper .bp3-icon-tick:before{content:\"\u2713\"}.jupyter-wrapper .bp3-icon-tick-circle:before{content:\"\ue779\"}.jupyter-wrapper .bp3-icon-time:before{content:\"\u23f2\"}.jupyter-wrapper .bp3-icon-timeline-area-chart:before{content:\"\ue6cd\"}.jupyter-wrapper .bp3-icon-timeline-bar-chart:before{content:\"\ue620\"}.jupyter-wrapper .bp3-icon-timeline-events:before{content:\"\ue61e\"}.jupyter-wrapper .bp3-icon-timeline-line-chart:before{content:\"\ue61f\"}.jupyter-wrapper .bp3-icon-tint:before{content:\"\ue6b2\"}.jupyter-wrapper .bp3-icon-torch:before{content:\"\ue677\"}.jupyter-wrapper .bp3-icon-tractor:before{content:\"\ue90c\"}.jupyter-wrapper .bp3-icon-train:before{content:\"\ue79f\"}.jupyter-wrapper .bp3-icon-translate:before{content:\"\ue759\"}.jupyter-wrapper .bp3-icon-trash:before{content:\"\ue63b\"}.jupyter-wrapper .bp3-icon-tree:before{content:\"\ue7b7\"}.jupyter-wrapper .bp3-icon-trending-down:before{content:\"\ue71a\"}.jupyter-wrapper .bp3-icon-trending-up:before{content:\"\ue719\"}.jupyter-wrapper .bp3-icon-truck:before{content:\"\ue90b\"}.jupyter-wrapper .bp3-icon-two-columns:before{content:\"\ue657\"}.jupyter-wrapper .bp3-icon-unarchive:before{content:\"\ue906\"}.jupyter-wrapper .bp3-icon-underline:before{content:\"\u2381\"}.jupyter-wrapper .bp3-icon-undo:before{content:\"\u238c\"}.jupyter-wrapper .bp3-icon-ungroup-objects:before{content:\"\ue688\"}.jupyter-wrapper .bp3-icon-unknown-vehicle:before{content:\"\ue73d\"}.jupyter-wrapper .bp3-icon-unlock:before{content:\"\ue626\"}.jupyter-wrapper .bp3-icon-unpin:before{content:\"\ue650\"}.jupyter-wrapper .bp3-icon-unresolve:before{content:\"\ue679\"}.jupyter-wrapper .bp3-icon-updated:before{content:\"\ue7a7\"}.jupyter-wrapper .bp3-icon-upload:before{content:\"\ue68f\"}.jupyter-wrapper .bp3-icon-user:before{content:\"\ue627\"}.jupyter-wrapper .bp3-icon-variable:before{content:\"\ue6f5\"}.jupyter-wrapper .bp3-icon-vertical-bar-chart-asc:before{content:\"\ue75b\"}.jupyter-wrapper .bp3-icon-vertical-bar-chart-desc:before{content:\"\ue71c\"}.jupyter-wrapper .bp3-icon-vertical-distribution:before{content:\"\ue721\"}.jupyter-wrapper .bp3-icon-video:before{content:\"\ue6a0\"}.jupyter-wrapper .bp3-icon-volume-down:before{content:\"\ue6a4\"}.jupyter-wrapper .bp3-icon-volume-off:before{content:\"\ue6a3\"}.jupyter-wrapper .bp3-icon-volume-up:before{content:\"\ue6a5\"}.jupyter-wrapper .bp3-icon-walk:before{content:\"\ue79d\"}.jupyter-wrapper .bp3-icon-warning-sign:before{content:\"\ue647\"}.jupyter-wrapper .bp3-icon-waterfall-chart:before{content:\"\ue6e6\"}.jupyter-wrapper .bp3-icon-widget:before{content:\"\ue678\"}.jupyter-wrapper .bp3-icon-widget-button:before{content:\"\ue790\"}.jupyter-wrapper .bp3-icon-widget-footer:before{content:\"\ue792\"}.jupyter-wrapper .bp3-icon-widget-header:before{content:\"\ue791\"}.jupyter-wrapper .bp3-icon-wrench:before{content:\"\ue734\"}.jupyter-wrapper .bp3-icon-zoom-in:before{content:\"\ue641\"}.jupyter-wrapper .bp3-icon-zoom-out:before{content:\"\ue642\"}.jupyter-wrapper .bp3-icon-zoom-to-fit:before{content:\"\ue67b\"}.jupyter-wrapper .bp3-submenu>.bp3-popover-wrapper{display:block}.jupyter-wrapper .bp3-submenu .bp3-popover-target{display:block}.jupyter-wrapper .bp3-submenu.bp3-popover{-webkit-box-shadow:none;box-shadow:none;padding:0 5px}.jupyter-wrapper .bp3-submenu.bp3-popover>.bp3-popover-content{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33}.jupyter-wrapper .bp3-dark .bp3-submenu.bp3-popover,.jupyter-wrapper .bp3-submenu.bp3-popover.bp3-dark{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-submenu.bp3-popover>.bp3-popover-content,.jupyter-wrapper .bp3-submenu.bp3-popover.bp3-dark>.bp3-popover-content{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-menu{background:#ffffff;border-radius:3px;color:#182026;list-style:none;margin:0;min-width:180px;padding:5px;text-align:left}.jupyter-wrapper .bp3-menu-divider{border-top:1px solid rgba(16,22,26,.15);display:block;margin:5px}.jupyter-wrapper .bp3-dark .bp3-menu-divider{border-top-color:#ffffff26}.jupyter-wrapper .bp3-menu-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;border-radius:2px;color:inherit;line-height:20px;padding:5px 7px;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-menu-item>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-menu-item>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item>*{margin-right:7px}.jupyter-wrapper .bp3-menu-item:empty:before,.jupyter-wrapper .bp3-menu-item>:last-child{margin-right:0}.jupyter-wrapper .bp3-menu-item>.bp3-fill{word-break:break-word}.jupyter-wrapper .bp3-menu-item:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item{background-color:#a7b6c24d;cursor:pointer;text-decoration:none}.jupyter-wrapper .bp3-menu-item.bp3-disabled{background-color:inherit;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-menu-item{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-menu-item{background-color:#8a9ba826;color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled{background-color:inherit;color:#a7b6c299}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary .bp3-menu-item-label{color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active{background-color:#137cbd}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active{background-color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success .bp3-menu-item-label{color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active{background-color:#0f9960}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active{background-color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning .bp3-menu-item-label{color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active{background-color:#d9822b}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active{background-color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger .bp3-menu-item-label{color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active{background-color:#db3737}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active{background-color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-right:7px}.jupyter-wrapper .bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item>.bp3-icon{color:#5c7080;margin-top:2px}.jupyter-wrapper .bp3-menu-item .bp3-menu-item-label{color:#5c7080}.jupyter-wrapper .bp3-menu-item:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-active,.jupyter-wrapper .bp3-menu-item:active{background-color:#7386944d}.jupyter-wrapper .bp3-menu-item.bp3-disabled{background-color:inherit!important;color:#5c708099!important;cursor:not-allowed!important;outline:none!important}.jupyter-wrapper .bp3-menu-item.bp3-disabled:before,.jupyter-wrapper .bp3-menu-item.bp3-disabled>.bp3-icon,.jupyter-wrapper .bp3-menu-item.bp3-disabled .bp3-menu-item-label{color:#5c708099!important}.jupyter-wrapper .bp3-large .bp3-menu-item{font-size:16px;line-height:22px;padding:9px 7px}.jupyter-wrapper .bp3-large .bp3-menu-item .bp3-icon{margin-top:3px}.jupyter-wrapper .bp3-large .bp3-menu-item:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-right:10px;margin-top:1px}.jupyter-wrapper button.bp3-menu-item{background:none;border:none;text-align:left;width:100%}.jupyter-wrapper .bp3-menu-header{border-top:1px solid rgba(16,22,26,.15);display:block;margin:5px;cursor:default;padding-left:2px}.jupyter-wrapper .bp3-dark .bp3-menu-header{border-top-color:#ffffff26}.jupyter-wrapper .bp3-menu-header:first-of-type{border-top:none}.jupyter-wrapper .bp3-menu-header>h6{color:#182026;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;line-height:17px;margin:0;padding:10px 7px 0 1px}.jupyter-wrapper .bp3-menu-header:first-of-type>h6{padding-top:0}.jupyter-wrapper .bp3-large .bp3-menu-header>h6{font-size:18px;padding-bottom:5px;padding-top:15px}.jupyter-wrapper .bp3-large .bp3-menu-header:first-of-type>h6{padding-top:0}.jupyter-wrapper .bp3-dark .bp3-menu{background:#30404d;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary .bp3-menu-item-label{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active{background-color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active{background-color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success .bp3-menu-item-label{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active{background-color:#0f9960}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active{background-color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning .bp3-menu-item-label{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active{background-color:#d9822b}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active{background-color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger .bp3-menu-item-label{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active{background-color:#db3737}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active{background-color:#c23030}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item>.bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-menu-item .bp3-menu-item-label{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item:active{background-color:#8a9ba84d}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled{color:#a7b6c299!important}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled .bp3-menu-item-label{color:#a7b6c299!important}.jupyter-wrapper .bp3-dark .bp3-menu-divider,.jupyter-wrapper .bp3-dark .bp3-menu-header{border-color:#ffffff26}.jupyter-wrapper .bp3-dark .bp3-menu-header>h6{color:#f5f8fa}.jupyter-wrapper .bp3-label .bp3-menu{margin-top:5px}.jupyter-wrapper .bp3-navbar{background-color:#fff;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;height:50px;padding:0 15px;position:relative;width:100%;z-index:10}.jupyter-wrapper .bp3-navbar.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-navbar{background-color:#394b59}.jupyter-wrapper .bp3-navbar.bp3-dark{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-navbar{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-navbar.bp3-fixed-top{left:0;position:fixed;right:0;top:0}.jupyter-wrapper .bp3-navbar-heading{font-size:16px;margin-right:15px}.jupyter-wrapper .bp3-navbar-group{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:50px}.jupyter-wrapper .bp3-navbar-group.bp3-align-left{float:left}.jupyter-wrapper .bp3-navbar-group.bp3-align-right{float:right}.jupyter-wrapper .bp3-navbar-divider{border-left:1px solid rgba(16,22,26,.15);height:20px;margin:0 10px}.jupyter-wrapper .bp3-dark .bp3-navbar-divider{border-left-color:#ffffff26}.jupyter-wrapper .bp3-non-ideal-state{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%}.jupyter-wrapper .bp3-non-ideal-state>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-non-ideal-state>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-non-ideal-state:before,.jupyter-wrapper .bp3-non-ideal-state>*{margin-bottom:20px}.jupyter-wrapper .bp3-non-ideal-state:empty:before,.jupyter-wrapper .bp3-non-ideal-state>:last-child{margin-bottom:0}.jupyter-wrapper .bp3-non-ideal-state>*{max-width:400px}.jupyter-wrapper .bp3-non-ideal-state-visual{color:#5c708099;font-size:60px}.jupyter-wrapper .bp3-dark .bp3-non-ideal-state-visual{color:#a7b6c299}.jupyter-wrapper .bp3-overflow-list{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;min-width:0}.jupyter-wrapper .bp3-overflow-list-spacer{-ms-flex-negative:1;flex-shrink:1;width:1px}.jupyter-wrapper body.bp3-overlay-open{overflow:hidden}.jupyter-wrapper .bp3-overlay{bottom:0;left:0;position:static;right:0;top:0;z-index:20}.jupyter-wrapper .bp3-overlay:not(.bp3-overlay-open){pointer-events:none}.jupyter-wrapper .bp3-overlay.bp3-overlay-container{overflow:hidden;position:fixed}.jupyter-wrapper .bp3-overlay.bp3-overlay-container.bp3-overlay-inline{position:absolute}.jupyter-wrapper .bp3-overlay.bp3-overlay-scroll-container{overflow:auto;position:fixed}.jupyter-wrapper .bp3-overlay.bp3-overlay-scroll-container.bp3-overlay-inline{position:absolute}.jupyter-wrapper .bp3-overlay.bp3-overlay-inline{display:inline;overflow:visible}.jupyter-wrapper .bp3-overlay-content{position:fixed;z-index:20}.jupyter-wrapper .bp3-overlay-inline .bp3-overlay-content,.jupyter-wrapper .bp3-overlay-scroll-container .bp3-overlay-content{position:absolute}.jupyter-wrapper .bp3-overlay-backdrop{bottom:0;left:0;position:fixed;right:0;top:0;opacity:1;background-color:#10161ab3;overflow:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:20}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-enter,.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-appear{opacity:0}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-enter-active,.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-appear-active{opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-exit{opacity:1}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-exit-active{opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-overlay-backdrop:focus{outline:none}.jupyter-wrapper .bp3-overlay-inline .bp3-overlay-backdrop{position:absolute}.jupyter-wrapper .bp3-panel-stack{overflow:hidden;position:relative}.jupyter-wrapper .bp3-panel-stack-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-shadow:0 1px rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;height:30px;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack-header{-webkit-box-shadow:0 1px rgba(255,255,255,.15);box-shadow:0 1px #ffffff26}.jupyter-wrapper .bp3-panel-stack-header>span{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1}.jupyter-wrapper .bp3-panel-stack-header .bp3-heading{margin:0 5px}.jupyter-wrapper .bp3-button.bp3-panel-stack-header-back{margin-left:5px;padding-left:0;white-space:nowrap}.jupyter-wrapper .bp3-button.bp3-panel-stack-header-back .bp3-icon{margin:0 2px}.jupyter-wrapper .bp3-panel-stack-view{bottom:0;left:0;position:absolute;right:0;top:0;background-color:#fff;border-right:1px solid rgba(16,22,26,.15);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:-1px;overflow-y:auto;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack-view{background-color:#30404d}.jupyter-wrapper .bp3-panel-stack-view:nth-last-child(n+4){display:none}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-enter,.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-appear{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-enter-active,.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-exit-active{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-enter,.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-appear{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-enter-active,.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2{overflow:hidden;position:relative}.jupyter-wrapper .bp3-panel-stack2-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-shadow:0 1px rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;height:30px;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack2-header{-webkit-box-shadow:0 1px rgba(255,255,255,.15);box-shadow:0 1px #ffffff26}.jupyter-wrapper .bp3-panel-stack2-header>span{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1}.jupyter-wrapper .bp3-panel-stack2-header .bp3-heading{margin:0 5px}.jupyter-wrapper .bp3-button.bp3-panel-stack2-header-back{margin-left:5px;padding-left:0;white-space:nowrap}.jupyter-wrapper .bp3-button.bp3-panel-stack2-header-back .bp3-icon{margin:0 2px}.jupyter-wrapper .bp3-panel-stack2-view{bottom:0;left:0;position:absolute;right:0;top:0;background-color:#fff;border-right:1px solid rgba(16,22,26,.15);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:-1px;overflow-y:auto;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack2-view{background-color:#30404d}.jupyter-wrapper .bp3-panel-stack2-view:nth-last-child(n+4){display:none}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-enter,.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-appear{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-enter-active,.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-exit-active{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-enter,.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-appear{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-enter-active,.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-popover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;-webkit-transform:scale(1);transform:scale(1);border-radius:3px;display:inline-block;z-index:20}.jupyter-wrapper .bp3-popover .bp3-popover-arrow{height:30px;position:absolute;width:30px}.jupyter-wrapper .bp3-popover .bp3-popover-arrow:before{height:20px;margin:5px;width:20px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover{margin-bottom:17px;margin-top:-17px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow{bottom:-11px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover{margin-left:17px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow{left:-11px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(0);transform:rotate(0)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover{margin-top:17px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow{top:-11px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover{margin-left:-17px;margin-right:17px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow{right:-11px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.jupyter-wrapper .bp3-tether-element-attached-middle>.bp3-popover>.bp3-popover-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.jupyter-wrapper .bp3-tether-element-attached-center>.bp3-popover>.bp3-popover-arrow{right:50%;-webkit-transform:translateX(50%);transform:translate(50%)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow{top:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow{right:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow{left:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow{bottom:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:top left;transform-origin:top left}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:top center;transform-origin:top center}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:top right;transform-origin:top right}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:center left;transform-origin:center left}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:center center;transform-origin:center center}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:center right;transform-origin:center right}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:bottom left;transform-origin:bottom left}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:bottom center;transform-origin:bottom center}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:bottom right;transform-origin:bottom right}.jupyter-wrapper .bp3-popover .bp3-popover-content{background:#ffffff;color:inherit}.jupyter-wrapper .bp3-popover .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.2);box-shadow:1px 1px 6px #10161a33}.jupyter-wrapper .bp3-popover .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.1}.jupyter-wrapper .bp3-popover .bp3-popover-arrow-fill{fill:#fff}.jupyter-wrapper .bp3-popover-enter>.bp3-popover,.jupyter-wrapper .bp3-popover-appear>.bp3-popover{-webkit-transform:scale(.3);transform:scale(.3)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-popover,.jupyter-wrapper .bp3-popover-appear-active>.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-popover-exit>.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-popover{-webkit-transform:scale(.3);transform:scale(.3);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-popover .bp3-popover-content{border-radius:3px;position:relative}.jupyter-wrapper .bp3-popover.bp3-popover-content-sizing .bp3-popover-content{max-width:350px;padding:20px}.jupyter-wrapper .bp3-popover-target+.bp3-overlay .bp3-popover.bp3-popover-content-sizing{width:350px}.jupyter-wrapper .bp3-popover.bp3-minimal{margin:0!important}.jupyter-wrapper .bp3-popover.bp3-minimal .bp3-popover-arrow{display:none}.jupyter-wrapper .bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-enter>.bp3-popover.bp3-minimal.bp3-popover,.jupyter-wrapper .bp3-popover-appear>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-popover.bp3-minimal.bp3-popover,.jupyter-wrapper .bp3-popover-appear-active>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover-exit>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-popover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-content,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-content{background:#30404d;color:inherit}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow:before,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.4);box-shadow:1px 1px 6px #10161a66}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow-border,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.2}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow-fill,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow-fill{fill:#30404d}.jupyter-wrapper .bp3-popover-arrow:before{border-radius:2px;content:\"\";display:block;position:absolute;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.jupyter-wrapper .bp3-tether-pinned .bp3-popover-arrow{display:none}.jupyter-wrapper .bp3-popover-backdrop{background:rgba(255,255,255,0)}.jupyter-wrapper .bp3-transition-container{opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;z-index:20}.jupyter-wrapper .bp3-transition-container.bp3-popover-enter,.jupyter-wrapper .bp3-transition-container.bp3-popover-appear{opacity:0}.jupyter-wrapper .bp3-transition-container.bp3-popover-enter-active,.jupyter-wrapper .bp3-transition-container.bp3-popover-appear-active{opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-transition-container.bp3-popover-exit{opacity:1}.jupyter-wrapper .bp3-transition-container.bp3-popover-exit-active{opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-transition-container:focus{outline:none}.jupyter-wrapper .bp3-transition-container.bp3-popover-leave .bp3-popover-content{pointer-events:none}.jupyter-wrapper .bp3-transition-container[data-x-out-of-boundaries]{display:none}.jupyter-wrapper span.bp3-popover-target{display:inline-block}.jupyter-wrapper .bp3-popover-wrapper.bp3-fill{width:100%}.jupyter-wrapper .bp3-portal{left:0;position:absolute;right:0;top:0}@-webkit-keyframes linear-progress-bar-stripes{0%{background-position:0 0}to{background-position:30px 0}}@keyframes linear-progress-bar-stripes{0%{background-position:0 0}to{background-position:30px 0}}.jupyter-wrapper .bp3-progress-bar{background:rgba(92,112,128,.2);border-radius:40px;display:block;height:8px;overflow:hidden;position:relative;width:100%}.jupyter-wrapper .bp3-progress-bar .bp3-progress-meter{background:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%);background-color:#5c7080cc;background-size:30px 30px;border-radius:40px;height:100%;position:absolute;-webkit-transition:width .2s cubic-bezier(.4,1,.75,.9);transition:width .2s cubic-bezier(.4,1,.75,.9);width:100%}.jupyter-wrapper .bp3-progress-bar:not(.bp3-no-animation):not(.bp3-no-stripes) .bp3-progress-meter{animation:linear-progress-bar-stripes .3s linear infinite reverse}.jupyter-wrapper .bp3-progress-bar.bp3-no-stripes .bp3-progress-meter{background-image:none}.jupyter-wrapper .bp3-dark .bp3-progress-bar{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-dark .bp3-progress-bar .bp3-progress-meter{background-color:#8a9ba8}.jupyter-wrapper .bp3-progress-bar.bp3-intent-primary .bp3-progress-meter{background-color:#137cbd}.jupyter-wrapper .bp3-progress-bar.bp3-intent-success .bp3-progress-meter{background-color:#0f9960}.jupyter-wrapper .bp3-progress-bar.bp3-intent-warning .bp3-progress-meter{background-color:#d9822b}.jupyter-wrapper .bp3-progress-bar.bp3-intent-danger .bp3-progress-meter{background-color:#db3737}@-webkit-keyframes skeleton-glow{0%{background:rgba(206,217,224,.2);border-color:#ced9e033}to{background:rgba(92,112,128,.2);border-color:#5c708033}}@keyframes skeleton-glow{0%{background:rgba(206,217,224,.2);border-color:#ced9e033}to{background:rgba(92,112,128,.2);border-color:#5c708033}}.jupyter-wrapper .bp3-skeleton{-webkit-animation:1s linear infinite alternate skeleton-glow;animation:1s linear infinite alternate skeleton-glow;background:rgba(206,217,224,.2);background-clip:padding-box!important;border-color:#ced9e033!important;border-radius:2px;-webkit-box-shadow:none!important;box-shadow:none!important;color:transparent!important;cursor:default;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-skeleton:before,.jupyter-wrapper .bp3-skeleton:after,.jupyter-wrapper .bp3-skeleton *{visibility:hidden!important}.jupyter-wrapper .bp3-slider{height:40px;min-width:150px;width:100%;cursor:default;outline:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-slider:hover{cursor:pointer}.jupyter-wrapper .bp3-slider:active{cursor:-webkit-grabbing;cursor:grabbing}.jupyter-wrapper .bp3-slider.bp3-disabled{cursor:not-allowed;opacity:.5}.jupyter-wrapper .bp3-slider.bp3-slider-unlabeled{height:16px}.jupyter-wrapper .bp3-slider-track,.jupyter-wrapper .bp3-slider-progress{height:6px;left:0;right:0;top:5px;position:absolute}.jupyter-wrapper .bp3-slider-track{border-radius:3px;overflow:hidden}.jupyter-wrapper .bp3-slider-progress{background:rgba(92,112,128,.2)}.jupyter-wrapper .bp3-dark .bp3-slider-progress{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-slider-progress.bp3-intent-primary{background-color:#137cbd}.jupyter-wrapper .bp3-slider-progress.bp3-intent-success{background-color:#0f9960}.jupyter-wrapper .bp3-slider-progress.bp3-intent-warning{background-color:#d9822b}.jupyter-wrapper .bp3-slider-progress.bp3-intent-danger{background-color:#db3737}.jupyter-wrapper .bp3-slider-handle{background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;cursor:pointer;height:16px;left:0;position:absolute;top:0;width:16px}.jupyter-wrapper .bp3-slider-handle:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-slider-handle:active,.jupyter-wrapper .bp3-slider-handle.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-slider-handle:disabled,.jupyter-wrapper .bp3-slider-handle.bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-slider-handle:disabled.bp3-active,.jupyter-wrapper .bp3-slider-handle:disabled.bp3-active:hover,.jupyter-wrapper .bp3-slider-handle.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-slider-handle.bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-slider-handle:focus{z-index:1}.jupyter-wrapper .bp3-slider-handle:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;cursor:-webkit-grab;cursor:grab;z-index:2}.jupyter-wrapper .bp3-slider-handle.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),inset 0 1px 1px rgba(16,22,26,.1);box-shadow:0 0 0 1px #10161a33,inset 0 1px 1px #10161a1a;cursor:-webkit-grabbing;cursor:grabbing}.jupyter-wrapper .bp3-disabled .bp3-slider-handle{background:#bfccd6;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.jupyter-wrapper .bp3-dark .bp3-slider-handle{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover,.jupyter-wrapper .bp3-dark .bp3-slider-handle:active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-slider-handle:active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-slider-handle:disabled,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-slider-handle:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-slider-handle .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-slider-handle,.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover{background-color:#394b59}.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{background-color:#293742}.jupyter-wrapper .bp3-dark .bp3-disabled .bp3-slider-handle{background:#5c7080;border-color:#5c7080;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-slider-handle .bp3-slider-label{background:#394b59;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;color:#f5f8fa;margin-left:8px}.jupyter-wrapper .bp3-dark .bp3-slider-handle .bp3-slider-label{background:#e1e8ed;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66;color:#394b59}.jupyter-wrapper .bp3-disabled .bp3-slider-handle .bp3-slider-label{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-slider-handle.bp3-start,.jupyter-wrapper .bp3-slider-handle.bp3-end{width:8px}.jupyter-wrapper .bp3-slider-handle.bp3-start{border-bottom-right-radius:0;border-top-right-radius:0}.jupyter-wrapper .bp3-slider-handle.bp3-end{border-bottom-left-radius:0;border-top-left-radius:0;margin-left:8px}.jupyter-wrapper .bp3-slider-handle.bp3-end .bp3-slider-label{margin-left:0}.jupyter-wrapper .bp3-slider-label{-webkit-transform:translate(-50%,20px);transform:translate(-50%,20px);display:inline-block;font-size:12px;line-height:1;padding:2px 5px;position:absolute;vertical-align:top}.jupyter-wrapper .bp3-slider.bp3-vertical{height:150px;min-width:40px;width:40px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-track,.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-progress{bottom:0;height:auto;left:5px;top:0;width:6px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-progress{top:auto}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-label{-webkit-transform:translate(20px,50%);transform:translate(20px,50%)}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle{top:auto}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle .bp3-slider-label{margin-left:0;margin-top:-8px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-end,.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start{height:8px;margin-left:0;width:16px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start{border-bottom-right-radius:3px;border-top-left-radius:0}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start .bp3-slider-label{-webkit-transform:translate(20px);transform:translate(20px)}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-end{border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:3px;margin-bottom:8px}@-webkit-keyframes pt-spinner-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes pt-spinner-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.jupyter-wrapper .bp3-spinner{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:visible;vertical-align:middle}.jupyter-wrapper .bp3-spinner svg{display:block}.jupyter-wrapper .bp3-spinner path{fill-opacity:0}.jupyter-wrapper .bp3-spinner .bp3-spinner-head{stroke:#5c7080cc;stroke-linecap:round;-webkit-transform-origin:center;transform-origin:center;-webkit-transition:stroke-dashoffset .2s cubic-bezier(.4,1,.75,.9);transition:stroke-dashoffset .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-spinner .bp3-spinner-track{stroke:#5c708033}.jupyter-wrapper .bp3-spinner-animation{-webkit-animation:pt-spinner-animation .5s linear infinite;animation:pt-spinner-animation .5s linear infinite}.jupyter-wrapper .bp3-no-spin>.bp3-spinner-animation{-webkit-animation:none;animation:none}.jupyter-wrapper .bp3-dark .bp3-spinner .bp3-spinner-head{stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-spinner .bp3-spinner-track{stroke:#10161a80}.jupyter-wrapper .bp3-spinner.bp3-intent-primary .bp3-spinner-head{stroke:#137cbd}.jupyter-wrapper .bp3-spinner.bp3-intent-success .bp3-spinner-head{stroke:#0f9960}.jupyter-wrapper .bp3-spinner.bp3-intent-warning .bp3-spinner-head{stroke:#d9822b}.jupyter-wrapper .bp3-spinner.bp3-intent-danger .bp3-spinner-head{stroke:#db3737}.jupyter-wrapper .bp3-tabs.bp3-vertical{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab{border-radius:3px;padding:0 10px;width:100%}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab[aria-selected=true]{background-color:#137cbd33;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab-indicator-wrapper .bp3-tab-indicator{background-color:#137cbd33;border-radius:3px;bottom:0;height:auto;left:0;right:0;top:0}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-panel{margin-top:0;padding-left:20px}.jupyter-wrapper .bp3-tab-list{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;border:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;list-style:none;margin:0;padding:0;position:relative}.jupyter-wrapper .bp3-tab-list>*:not(:last-child){margin-right:20px}.jupyter-wrapper .bp3-tab{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;color:#182026;cursor:pointer;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;font-size:14px;line-height:30px;max-width:100%;position:relative;vertical-align:top}.jupyter-wrapper .bp3-tab a{color:inherit;display:block;text-decoration:none}.jupyter-wrapper .bp3-tab-indicator-wrapper~.bp3-tab{background-color:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}.jupyter-wrapper .bp3-tab[aria-disabled=true]{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tab[aria-selected=true]{border-radius:0;-webkit-box-shadow:inset 0 -3px 0 #106ba3;box-shadow:inset 0 -3px #106ba3}.jupyter-wrapper .bp3-tab[aria-selected=true],.jupyter-wrapper .bp3-tab:not([aria-disabled=true]):hover{color:#106ba3}.jupyter-wrapper .bp3-tab:focus{-moz-outline-radius:0}.jupyter-wrapper .bp3-large>.bp3-tab{font-size:16px;line-height:40px}.jupyter-wrapper .bp3-tab-panel{margin-top:20px}.jupyter-wrapper .bp3-tab-panel[aria-hidden=true]{display:none}.jupyter-wrapper .bp3-tab-indicator-wrapper{left:0;pointer-events:none;position:absolute;top:0;-webkit-transform:translateX(0),translateY(0);transform:translate(0),translateY(0);-webkit-transition:height,width,-webkit-transform;transition:height,width,-webkit-transform;transition:height,transform,width;transition:height,transform,width,-webkit-transform;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tab-indicator-wrapper .bp3-tab-indicator{background-color:#106ba3;bottom:0;height:3px;left:0;position:absolute;right:0}.jupyter-wrapper .bp3-tab-indicator-wrapper.bp3-no-animation{-webkit-transition:none;transition:none}.jupyter-wrapper .bp3-dark .bp3-tab{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tab[aria-disabled=true]{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tab[aria-selected=true]{-webkit-box-shadow:inset 0 -3px 0 #48aff0;box-shadow:inset 0 -3px #48aff0}.jupyter-wrapper .bp3-dark .bp3-tab[aria-selected=true],.jupyter-wrapper .bp3-dark .bp3-tab:not([aria-disabled=true]):hover{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-tab-indicator{background-color:#48aff0}.jupyter-wrapper .bp3-flex-expander{-webkit-box-flex:1;-ms-flex:1 1;flex:1 1}.jupyter-wrapper .bp3-tag{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#5c7080;border:none;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;color:#f5f8fa;font-size:12px;line-height:16px;max-width:100%;min-height:20px;min-width:20px;padding:2px 6px;position:relative}.jupyter-wrapper .bp3-tag.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-interactive:hover{background-color:#5c7080d9}.jupyter-wrapper .bp3-tag.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-interactive:active{background-color:#5c7080b3}.jupyter-wrapper .bp3-tag>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag:before,.jupyter-wrapper .bp3-tag>*{margin-right:4px}.jupyter-wrapper .bp3-tag:empty:before,.jupyter-wrapper .bp3-tag>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag:focus{outline:rgba(19,124,189,.6) auto 2px;outline-offset:0;-moz-outline-radius:6px}.jupyter-wrapper .bp3-tag.bp3-round{border-radius:30px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-dark .bp3-tag{background-color:#bfccd6;color:#182026}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive:hover{background-color:#bfccd6d9}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive:active{background-color:#bfccd6b3}.jupyter-wrapper .bp3-dark .bp3-tag>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tag .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tag .bp3-icon-large{fill:currentColor}.jupyter-wrapper .bp3-tag>.bp3-icon,.jupyter-wrapper .bp3-tag .bp3-icon-standard,.jupyter-wrapper .bp3-tag .bp3-icon-large{fill:#fff}.jupyter-wrapper .bp3-tag.bp3-large,.jupyter-wrapper .bp3-large .bp3-tag{font-size:14px;line-height:20px;min-height:30px;min-width:30px;padding:5px 10px}.jupyter-wrapper .bp3-tag.bp3-large:before,.jupyter-wrapper .bp3-tag.bp3-large>*,.jupyter-wrapper .bp3-large .bp3-tag:before,.jupyter-wrapper .bp3-large .bp3-tag>*{margin-right:7px}.jupyter-wrapper .bp3-tag.bp3-large:empty:before,.jupyter-wrapper .bp3-tag.bp3-large>:last-child,.jupyter-wrapper .bp3-large .bp3-tag:empty:before,.jupyter-wrapper .bp3-large .bp3-tag>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag.bp3-large.bp3-round,.jupyter-wrapper .bp3-large .bp3-tag.bp3-round{padding-left:12px;padding-right:12px}.jupyter-wrapper .bp3-tag.bp3-intent-primary{background:#137cbd;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbdd9}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive:active{background-color:#137cbdb3}.jupyter-wrapper .bp3-tag.bp3-intent-success{background:#0f9960;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive:hover{background-color:#0f9960d9}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive:active{background-color:#0f9960b3}.jupyter-wrapper .bp3-tag.bp3-intent-warning{background:#d9822b;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822bd9}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive:active{background-color:#d9822bb3}.jupyter-wrapper .bp3-tag.bp3-intent-danger{background:#db3737;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive:hover{background-color:#db3737d9}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive:active{background-color:#db3737b3}.jupyter-wrapper .bp3-tag.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-tag.bp3-minimal>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal .bp3-icon-large{fill:#5c7080}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]){background-color:#8a9ba833;color:#182026}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:hover{background-color:#5c70804d}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:active{background-color:#5c708066}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]){color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:hover{background-color:#bfccd64d}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:active{background-color:#bfccd666}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-])>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]) .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]) .bp3-icon-large{fill:#a7b6c2}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary{background-color:#137cbd26;color:#106ba3}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbd40}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:active{background-color:#137cbd59}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary .bp3-icon-large{fill:#137cbd}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary{background-color:#137cbd40;color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbd59}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:active{background-color:#137cbd73}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success{background-color:#0f996026;color:#0d8050}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:hover{background-color:#0f996040}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:active{background-color:#0f996059}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success .bp3-icon-large{fill:#0f9960}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success{background-color:#0f996040;color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:hover{background-color:#0f996059}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:active{background-color:#0f996073}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning{background-color:#d9822b26;color:#bf7326}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822b40}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:active{background-color:#d9822b59}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning .bp3-icon-large{fill:#d9822b}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning{background-color:#d9822b40;color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822b59}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:active{background-color:#d9822b73}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger{background-color:#db373726;color:#c23030}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:hover{background-color:#db373740}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:active{background-color:#db373759}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger .bp3-icon-large{fill:#db3737}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger{background-color:#db373740;color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:hover{background-color:#db373759}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:active{background-color:#db373773}.jupyter-wrapper .bp3-tag-remove{background:none;border:none;color:inherit;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:-2px;margin-right:-6px!important;margin-top:-2px;opacity:.5;padding:2px 2px 2px 0}.jupyter-wrapper .bp3-tag-remove:hover{background:none;opacity:.8;text-decoration:none}.jupyter-wrapper .bp3-tag-remove:active{opacity:1}.jupyter-wrapper .bp3-tag-remove:empty:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;content:\"\ue6d7\"}.jupyter-wrapper .bp3-large .bp3-tag-remove{margin-right:-10px!important;padding:0 5px 0 0}.jupyter-wrapper .bp3-large .bp3-tag-remove:empty:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1}.jupyter-wrapper .bp3-tag-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;cursor:text;height:auto;line-height:inherit;min-height:30px;padding-left:5px;padding-right:0}.jupyter-wrapper .bp3-tag-input>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag-input>.bp3-tag-input-values{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-icon{color:#5c7080;margin-left:2px;margin-right:7px;margin-top:7px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-item-align:stretch;align-self:stretch;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:7px;margin-top:5px;min-width:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:before,.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{margin-right:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:empty:before,.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:first-child .bp3-input-ghost:first-child{padding-left:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{margin-bottom:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag{overflow-wrap:break-word}.jupyter-wrapper .bp3-tag-input .bp3-tag.bp3-active{outline:rgba(19,124,189,.6) auto 2px;outline-offset:0;-moz-outline-radius:6px}.jupyter-wrapper .bp3-tag-input .bp3-input-ghost{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:20px;width:80px}.jupyter-wrapper .bp3-tag-input .bp3-input-ghost:disabled,.jupyter-wrapper .bp3-tag-input .bp3-input-ghost.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-tag-input .bp3-button,.jupyter-wrapper .bp3-tag-input .bp3-spinner{margin:3px 3px 3px 0}.jupyter-wrapper .bp3-tag-input .bp3-button{min-height:24px;min-width:24px;padding:0 7px}.jupyter-wrapper .bp3-tag-input.bp3-large{height:auto;min-height:40px}.jupyter-wrapper .bp3-tag-input.bp3-large:before,.jupyter-wrapper .bp3-tag-input.bp3-large>*{margin-right:10px}.jupyter-wrapper .bp3-tag-input.bp3-large:empty:before,.jupyter-wrapper .bp3-tag-input.bp3-large>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-tag-input-icon{margin-left:5px;margin-top:10px}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-input-ghost{line-height:30px}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-button{min-height:30px;min-width:30px;padding:5px 10px;margin:5px 5px 5px 0}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-spinner{margin:8px 8px 8px 0}.jupyter-wrapper .bp3-tag-input.bp3-active{background-color:#fff;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-primary{-webkit-box-shadow:0 0 0 1px #106ba3,0 0 0 3px rgba(16,107,163,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #106ba3,0 0 0 3px #106ba34d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-success{-webkit-box-shadow:0 0 0 1px #0d8050,0 0 0 3px rgba(13,128,80,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0d8050,0 0 0 3px #0d80504d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-warning{-webkit-box-shadow:0 0 0 1px #bf7326,0 0 0 3px rgba(191,115,38,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #bf7326,0 0 0 3px #bf73264d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-danger{-webkit-box-shadow:0 0 0 1px #c23030,0 0 0 3px rgba(194,48,48,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #c23030,0 0 0 3px #c230304d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-tag-input-icon,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-tag-input-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-webkit-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-moz-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost:-ms-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-ms-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active{background-color:#10161a4d;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-primary,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-primary{-webkit-box-shadow:0 0 0 1px #106ba3,0 0 0 3px rgba(16,107,163,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #106ba3,0 0 0 3px #106ba34d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-success,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-success{-webkit-box-shadow:0 0 0 1px #0d8050,0 0 0 3px rgba(13,128,80,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #0d8050,0 0 0 3px #0d80504d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-warning,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-warning{-webkit-box-shadow:0 0 0 1px #bf7326,0 0 0 3px rgba(191,115,38,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #bf7326,0 0 0 3px #bf73264d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-danger,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-danger{-webkit-box-shadow:0 0 0 1px #c23030,0 0 0 3px rgba(194,48,48,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #c23030,0 0 0 3px #c230304d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-input-ghost{background:none;border:none;-webkit-box-shadow:none;box-shadow:none;padding:0}.jupyter-wrapper .bp3-input-ghost::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost:focus{outline:none!important}.jupyter-wrapper .bp3-toast{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;margin:20px 0 0;max-width:500px;min-width:300px;pointer-events:all;position:relative!important}.jupyter-wrapper .bp3-toast.bp3-toast-enter,.jupyter-wrapper .bp3-toast.bp3-toast-appear{-webkit-transform:translateY(-40px);transform:translateY(-40px)}.jupyter-wrapper .bp3-toast.bp3-toast-enter-active,.jupyter-wrapper .bp3-toast.bp3-toast-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-toast.bp3-toast-enter~.bp3-toast,.jupyter-wrapper .bp3-toast.bp3-toast-appear~.bp3-toast{-webkit-transform:translateY(-40px);transform:translateY(-40px)}.jupyter-wrapper .bp3-toast.bp3-toast-enter-active~.bp3-toast,.jupyter-wrapper .bp3-toast.bp3-toast-appear-active~.bp3-toast{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-toast.bp3-toast-exit{opacity:1;-webkit-filter:blur(0);filter:blur(0)}.jupyter-wrapper .bp3-toast.bp3-toast-exit-active{opacity:0;-webkit-filter:blur(10px);filter:blur(10px);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:opacity,filter;transition-property:opacity,filter,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-toast.bp3-toast-exit~.bp3-toast{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-toast.bp3-toast-exit-active~.bp3-toast{-webkit-transform:translateY(-40px);transform:translateY(-40px);-webkit-transition-delay:50ms;transition-delay:50ms;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-toast .bp3-button-group{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;padding:5px 5px 5px 0}.jupyter-wrapper .bp3-toast>.bp3-icon{color:#5c7080;margin:12px 0 12px 12px}.jupyter-wrapper .bp3-toast.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-toast{background-color:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-toast.bp3-dark>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-toast>.bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] a{color:#ffffffb3}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] a:hover{color:#fff}.jupyter-wrapper .bp3-toast[class*=bp3-intent-]>.bp3-icon{color:#fff}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:before,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button .bp3-icon,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:active{color:#ffffffb3!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:focus{outline-color:#ffffff80}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:hover{background-color:#ffffff26!important;color:#fff!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:active{background-color:#ffffff4d!important;color:#fff!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:after{background:rgba(255,255,255,.3)!important}.jupyter-wrapper .bp3-toast.bp3-intent-primary{background-color:#137cbd;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-success{background-color:#0f9960;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-warning{background-color:#d9822b;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-danger{background-color:#db3737;color:#fff}.jupyter-wrapper .bp3-toast-message{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:11px;word-break:break-word}.jupyter-wrapper .bp3-toast-container{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;left:0;overflow:hidden;padding:0 20px 20px;pointer-events:none;right:0;z-index:40}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-in-portal{position:fixed}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-inline{position:absolute}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-top{top:0}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-bottom{bottom:0;-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;top:auto}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-left{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-right{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-enter:not(.bp3-toast-enter-active),.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-enter:not(.bp3-toast-enter-active)~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-appear:not(.bp3-toast-appear-active),.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-appear:not(.bp3-toast-appear-active)~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-exit-active~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-leave-active~.bp3-toast{-webkit-transform:translateY(60px);transform:translateY(60px)}.jupyter-wrapper .bp3-tooltip{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow{height:22px;position:absolute;width:22px}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow:before{height:14px;margin:4px;width:14px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip{margin-bottom:11px;margin-top:-11px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow{bottom:-8px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip{margin-left:11px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow{left:-8px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(0);transform:rotate(0)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip{margin-top:11px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow{top:-8px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip{margin-left:-11px;margin-right:11px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow{right:-8px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.jupyter-wrapper .bp3-tether-element-attached-middle>.bp3-tooltip>.bp3-popover-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.jupyter-wrapper .bp3-tether-element-attached-center>.bp3-tooltip>.bp3-popover-arrow{right:50%;-webkit-transform:translateX(50%);transform:translate(50%)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow{top:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow{right:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow{left:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow{bottom:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:top left;transform-origin:top left}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:top center;transform-origin:top center}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:top right;transform-origin:top right}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:center left;transform-origin:center left}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:center center;transform-origin:center center}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:center right;transform-origin:center right}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:bottom left;transform-origin:bottom left}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:bottom center;transform-origin:bottom center}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:bottom right;transform-origin:bottom right}.jupyter-wrapper .bp3-tooltip .bp3-popover-content{background:#394b59;color:#f5f8fa}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.2);box-shadow:1px 1px 6px #10161a33}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.1}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow-fill{fill:#394b59}.jupyter-wrapper .bp3-popover-enter>.bp3-tooltip,.jupyter-wrapper .bp3-popover-appear>.bp3-tooltip{-webkit-transform:scale(.8);transform:scale(.8)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-tooltip,.jupyter-wrapper .bp3-popover-appear-active>.bp3-tooltip{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover-exit>.bp3-tooltip{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-tooltip{-webkit-transform:scale(.8);transform:scale(.8);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tooltip .bp3-popover-content{padding:10px 12px}.jupyter-wrapper .bp3-tooltip.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-tooltip{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-content,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-content{background:#e1e8ed;color:#394b59}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow:before,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.4);box-shadow:1px 1px 6px #10161a66}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow-border,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.2}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow-fill,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow-fill{fill:#e1e8ed}.jupyter-wrapper .bp3-tooltip.bp3-intent-primary .bp3-popover-content{background:#137cbd;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-primary .bp3-popover-arrow-fill{fill:#137cbd}.jupyter-wrapper .bp3-tooltip.bp3-intent-success .bp3-popover-content{background:#0f9960;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-success .bp3-popover-arrow-fill{fill:#0f9960}.jupyter-wrapper .bp3-tooltip.bp3-intent-warning .bp3-popover-content{background:#d9822b;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-warning .bp3-popover-arrow-fill{fill:#d9822b}.jupyter-wrapper .bp3-tooltip.bp3-intent-danger .bp3-popover-content{background:#db3737;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-danger .bp3-popover-arrow-fill{fill:#db3737}.jupyter-wrapper .bp3-tooltip-indicator{border-bottom:dotted 1px;cursor:help}.jupyter-wrapper .bp3-tree .bp3-icon,.jupyter-wrapper .bp3-tree .bp3-icon-standard,.jupyter-wrapper .bp3-tree .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-primary{color:#137cbd}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-success{color:#0f9960}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-warning{color:#d9822b}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-danger{color:#db3737}.jupyter-wrapper .bp3-tree-node-list{list-style:none;margin:0;padding-left:0}.jupyter-wrapper .bp3-tree-root{background-color:transparent;cursor:default;padding-left:0;position:relative}.jupyter-wrapper .bp3-tree-node-content-0{padding-left:0}.jupyter-wrapper .bp3-tree-node-content-1{padding-left:23px}.jupyter-wrapper .bp3-tree-node-content-2{padding-left:46px}.jupyter-wrapper .bp3-tree-node-content-3{padding-left:69px}.jupyter-wrapper .bp3-tree-node-content-4{padding-left:92px}.jupyter-wrapper .bp3-tree-node-content-5{padding-left:115px}.jupyter-wrapper .bp3-tree-node-content-6{padding-left:138px}.jupyter-wrapper .bp3-tree-node-content-7{padding-left:161px}.jupyter-wrapper .bp3-tree-node-content-8{padding-left:184px}.jupyter-wrapper .bp3-tree-node-content-9{padding-left:207px}.jupyter-wrapper .bp3-tree-node-content-10{padding-left:230px}.jupyter-wrapper .bp3-tree-node-content-11{padding-left:253px}.jupyter-wrapper .bp3-tree-node-content-12{padding-left:276px}.jupyter-wrapper .bp3-tree-node-content-13{padding-left:299px}.jupyter-wrapper .bp3-tree-node-content-14{padding-left:322px}.jupyter-wrapper .bp3-tree-node-content-15{padding-left:345px}.jupyter-wrapper .bp3-tree-node-content-16{padding-left:368px}.jupyter-wrapper .bp3-tree-node-content-17{padding-left:391px}.jupyter-wrapper .bp3-tree-node-content-18{padding-left:414px}.jupyter-wrapper .bp3-tree-node-content-19{padding-left:437px}.jupyter-wrapper .bp3-tree-node-content-20{padding-left:460px}.jupyter-wrapper .bp3-tree-node-content{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:30px;padding-right:5px;width:100%}.jupyter-wrapper .bp3-tree-node-content:hover{background-color:#bfccd666}.jupyter-wrapper .bp3-tree-node-caret,.jupyter-wrapper .bp3-tree-node-caret-none{min-width:30px}.jupyter-wrapper .bp3-tree-node-caret{color:#5c7080;cursor:pointer;padding:7px;-webkit-transform:rotate(0deg);transform:rotate(0);-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tree-node-caret:hover{color:#182026}.jupyter-wrapper .bp3-dark .bp3-tree-node-caret{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tree-node-caret:hover{color:#f5f8fa}.jupyter-wrapper .bp3-tree-node-caret.bp3-tree-node-caret-open{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tree-node-caret.bp3-icon-standard:before{content:\"\ue695\"}.jupyter-wrapper .bp3-tree-node-icon{margin-right:7px;position:relative}.jupyter-wrapper .bp3-tree-node-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-tree-node-label span{display:inline}.jupyter-wrapper .bp3-tree-node-secondary-label{padding:0 5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-tree-node-secondary-label .bp3-popover-wrapper,.jupyter-wrapper .bp3-tree-node-secondary-label .bp3-popover-target{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-content{background-color:inherit;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-caret,.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-icon{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content{background-color:#137cbd}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon-standard,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon-large{color:#fff}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-tree-node-caret:before{color:#ffffffb3}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-tree-node-caret:hover:before{color:#fff}.jupyter-wrapper .bp3-dark .bp3-tree-node-content:hover{background-color:#5c70804d}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-primary{color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-success{color:#0f9960}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-warning{color:#d9822b}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-danger{color:#db3737}.jupyter-wrapper .bp3-dark .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content{background-color:#137cbd}.jupyter-wrapper .bp3-omnibar{-webkit-filter:blur(0);filter:blur(0);opacity:1;background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;left:calc(50% - 250px);top:20vh;width:500px;z-index:21}.jupyter-wrapper .bp3-omnibar.bp3-overlay-enter,.jupyter-wrapper .bp3-omnibar.bp3-overlay-appear{-webkit-filter:blur(20px);filter:blur(20px);opacity:.2}.jupyter-wrapper .bp3-omnibar.bp3-overlay-enter-active,.jupyter-wrapper .bp3-omnibar.bp3-overlay-appear-active{-webkit-filter:blur(0);filter:blur(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:filter,opacity;transition-property:filter,opacity,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-omnibar.bp3-overlay-exit{-webkit-filter:blur(0);filter:blur(0);opacity:1}.jupyter-wrapper .bp3-omnibar.bp3-overlay-exit-active{-webkit-filter:blur(20px);filter:blur(20px);opacity:.2;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:filter,opacity;transition-property:filter,opacity,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-omnibar .bp3-input{background-color:transparent;border-radius:0}.jupyter-wrapper .bp3-omnibar .bp3-input,.jupyter-wrapper .bp3-omnibar .bp3-input:focus{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-omnibar .bp3-menu{background-color:transparent;border-radius:0;-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26;max-height:calc(60vh - 40px);overflow:auto}.jupyter-wrapper .bp3-omnibar .bp3-menu:empty{display:none}.jupyter-wrapper .bp3-dark .bp3-omnibar,.jupyter-wrapper .bp3-omnibar.bp3-dark{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66}.jupyter-wrapper .bp3-omnibar-overlay .bp3-overlay-backdrop{background-color:#10161a33}.jupyter-wrapper .bp3-multi-select{min-width:150px}.jupyter-wrapper .bp3-multi-select-popover .bp3-menu{max-height:300px;max-width:400px;overflow:auto}.jupyter-wrapper .bp3-select-popover .bp3-popover-content{padding:5px}.jupyter-wrapper .bp3-select-popover .bp3-input-group{margin-bottom:0}.jupyter-wrapper .bp3-select-popover .bp3-menu{max-height:300px;max-width:400px;overflow:auto;padding:0}.jupyter-wrapper .bp3-select-popover .bp3-menu:not(:first-child){padding-top:5px}.jupyter-wrapper :root{--jp-icon-add-above: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5MikiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik00Ljc1IDQuOTMwNjZINi42MjVWNi44MDU2NkM2LjYyNSA3LjAxMTkxIDYuNzkzNzUgNy4xODA2NiA3IDcuMTgwNjZDNy4yMDYyNSA3LjE4MDY2IDcuMzc1IDcuMDExOTEgNy4zNzUgNi44MDU2NlY0LjkzMDY2SDkuMjVDOS40NTYyNSA0LjkzMDY2IDkuNjI1IDQuNzYxOTEgOS42MjUgNC41NTU2NkM5LjYyNSA0LjM0OTQxIDkuNDU2MjUgNC4xODA2NiA5LjI1IDQuMTgwNjZINy4zNzVWMi4zMDU2NkM3LjM3NSAyLjA5OTQxIDcuMjA2MjUgMS45MzA2NiA3IDEuOTMwNjZDNi43OTM3NSAxLjkzMDY2IDYuNjI1IDIuMDk5NDEgNi42MjUgMi4zMDU2NlY0LjE4MDY2SDQuNzVDNC41NDM3NSA0LjE4MDY2IDQuMzc1IDQuMzQ5NDEgNC4zNzUgNC41NTU2NkM0LjM3NSA0Ljc2MTkxIDQuNTQzNzUgNC45MzA2NiA0Ljc1IDQuOTMwNjZaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC43Ii8+CjwvZz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTExLjUgOS41VjExLjVMMi41IDExLjVWOS41TDExLjUgOS41Wk0xMiA4QzEyLjU1MjMgOCAxMyA4LjQ0NzcyIDEzIDlWMTJDMTMgMTIuNTUyMyAxMi41NTIzIDEzIDEyIDEzTDIgMTNDMS40NDc3MiAxMyAxIDEyLjU1MjMgMSAxMlY5QzEgOC40NDc3MiAxLjQ0NzcxIDggMiA4TDEyIDhaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5MiI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KC0xIDAgMCAxIDEwIDEuNTU1NjYpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==);--jp-icon-add-below: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5OCkiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik05LjI1IDEwLjA2OTNMNy4zNzUgMTAuMDY5M0w3LjM3NSA4LjE5NDM0QzcuMzc1IDcuOTg4MDkgNy4yMDYyNSA3LjgxOTM0IDcgNy44MTkzNEM2Ljc5Mzc1IDcuODE5MzQgNi42MjUgNy45ODgwOSA2LjYyNSA4LjE5NDM0TDYuNjI1IDEwLjA2OTNMNC43NSAxMC4wNjkzQzQuNTQzNzUgMTAuMDY5MyA0LjM3NSAxMC4yMzgxIDQuMzc1IDEwLjQ0NDNDNC4zNzUgMTAuNjUwNiA0LjU0Mzc1IDEwLjgxOTMgNC43NSAxMC44MTkzTDYuNjI1IDEwLjgxOTNMNi42MjUgMTIuNjk0M0M2LjYyNSAxMi45MDA2IDYuNzkzNzUgMTMuMDY5MyA3IDEzLjA2OTNDNy4yMDYyNSAxMy4wNjkzIDcuMzc1IDEyLjkwMDYgNy4zNzUgMTIuNjk0M0w3LjM3NSAxMC44MTkzTDkuMjUgMTAuODE5M0M5LjQ1NjI1IDEwLjgxOTMgOS42MjUgMTAuNjUwNiA5LjYyNSAxMC40NDQzQzkuNjI1IDEwLjIzODEgOS40NTYyNSAxMC4wNjkzIDkuMjUgMTAuMDY5M1oiIGZpbGw9IiM2MTYxNjEiIHN0cm9rZT0iIzYxNjE2MSIgc3Ryb2tlLXdpZHRoPSIwLjciLz4KPC9nPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMi41IDUuNUwyLjUgMy41TDExLjUgMy41TDExLjUgNS41TDIuNSA1LjVaTTIgN0MxLjQ0NzcyIDcgMSA2LjU1MjI4IDEgNkwxIDNDMSAyLjQ0NzcyIDEuNDQ3NzIgMiAyIDJMMTIgMkMxMi41NTIzIDIgMTMgMi40NDc3MiAxMyAzTDEzIDZDMTMgNi41NTIyOSAxMi41NTIzIDcgMTIgN0wyIDdaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5OCI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KDEgMS43NDg0NmUtMDcgMS43NDg0NmUtMDcgLTEgNCAxMy40NDQzKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=);--jp-icon-add: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDEzaC02djZoLTJ2LTZINXYtMmg2VjVoMnY2aDZ2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-bell: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiB2ZXJzaW9uPSIxLjEiPgogICA8cGF0aCBjbGFzcz0ianAtaWNvbjIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzMzMzMzIgogICAgICBkPSJtOCAwLjI5Yy0xLjQgMC0yLjcgMC43My0zLjYgMS44LTEuMiAxLjUtMS40IDMuNC0xLjUgNS4yLTAuMTggMi4yLTAuNDQgNC0yLjMgNS4zbDAuMjggMS4zaDVjMC4wMjYgMC42NiAwLjMyIDEuMSAwLjcxIDEuNSAwLjg0IDAuNjEgMiAwLjYxIDIuOCAwIDAuNTItMC40IDAuNi0xIDAuNzEtMS41aDVsMC4yOC0xLjNjLTEuOS0wLjk3LTIuMi0zLjMtMi4zLTUuMy0wLjEzLTEuOC0wLjI2LTMuNy0xLjUtNS4yLTAuODUtMS0yLjItMS44LTMuNi0xLjh6bTAgMS40YzAuODggMCAxLjkgMC41NSAyLjUgMS4zIDAuODggMS4xIDEuMSAyLjcgMS4yIDQuNCAwLjEzIDEuNyAwLjIzIDMuNiAxLjMgNS4yaC0xMGMxLjEtMS42IDEuMi0zLjQgMS4zLTUuMiAwLjEzLTEuNyAwLjMtMy4zIDEuMi00LjQgMC41OS0wLjcyIDEuNi0xLjMgMi41LTEuM3ptLTAuNzQgMTJoMS41Yy0wLjAwMTUgMC4yOCAwLjAxNSAwLjc5LTAuNzQgMC43OS0wLjczIDAuMDAxNi0wLjcyLTAuNTMtMC43NC0wLjc5eiIgLz4KPC9zdmc+Cg==);--jp-icon-bug-dot: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiPgogICAgICAgIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTcuMTkgOEgyMFYxMEgxNy45MUMxNy45NiAxMC4zMyAxOCAxMC42NiAxOCAxMVYxMkgyMFYxNEgxOC41SDE4VjE0LjAyNzVDMTUuNzUgMTQuMjc2MiAxNCAxNi4xODM3IDE0IDE4LjVDMTQgMTkuMjA4IDE0LjE2MzUgMTkuODc3OSAxNC40NTQ5IDIwLjQ3MzlDMTMuNzA2MyAyMC44MTE3IDEyLjg3NTcgMjEgMTIgMjFDOS43OCAyMSA3Ljg1IDE5Ljc5IDYuODEgMThINFYxNkg2LjA5QzYuMDQgMTUuNjcgNiAxNS4zNCA2IDE1VjE0SDRWMTJINlYxMUM2IDEwLjY2IDYuMDQgMTAuMzMgNi4wOSAxMEg0VjhINi44MUM3LjI2IDcuMjIgNy44OCA2LjU1IDguNjIgNi4wNEw3IDQuNDFMOC40MSAzTDEwLjU5IDUuMTdDMTEuMDQgNS4wNiAxMS41MSA1IDEyIDVDMTIuNDkgNSAxMi45NiA1LjA2IDEzLjQyIDUuMTdMMTUuNTkgM0wxNyA0LjQxTDE1LjM3IDYuMDRDMTYuMTIgNi41NSAxNi43NCA3LjIyIDE3LjE5IDhaTTEwIDE2SDE0VjE0SDEwVjE2Wk0xMCAxMkgxNFYxMEgxMFYxMloiIGZpbGw9IiM2MTYxNjEiLz4KICAgICAgICA8cGF0aCBkPSJNMjIgMTguNUMyMiAyMC40MzMgMjAuNDMzIDIyIDE4LjUgMjJDMTYuNTY3IDIyIDE1IDIwLjQzMyAxNSAxOC41QzE1IDE2LjU2NyAxNi41NjcgMTUgMTguNSAxNUMyMC40MzMgMTUgMjIgMTYuNTY3IDIyIDE4LjVaIiBmaWxsPSIjNjE2MTYxIi8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-bug: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yMCA4aC0yLjgxYy0uNDUtLjc4LTEuMDctMS40NS0xLjgyLTEuOTZMMTcgNC40MSAxNS41OSAzbC0yLjE3IDIuMTdDMTIuOTYgNS4wNiAxMi40OSA1IDEyIDVjLS40OSAwLS45Ni4wNi0xLjQxLjE3TDguNDEgMyA3IDQuNDFsMS42MiAxLjYzQzcuODggNi41NSA3LjI2IDcuMjIgNi44MSA4SDR2MmgyLjA5Yy0uMDUuMzMtLjA5LjY2LS4wOSAxdjFINHYyaDJ2MWMwIC4zNC4wNC42Ny4wOSAxSDR2MmgyLjgxYzEuMDQgMS43OSAyLjk3IDMgNS4xOSAzczQuMTUtMS4yMSA1LjE5LTNIMjB2LTJoLTIuMDljLjA1LS4zMy4wOS0uNjYuMDktMXYtMWgydi0yaC0ydi0xYzAtLjM0LS4wNC0uNjctLjA5LTFIMjBWOHptLTYgOGgtNHYtMmg0djJ6bTAtNGgtNHYtMmg0djJ6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-build: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE0LjkgMTcuNDVDMTYuMjUgMTcuNDUgMTcuMzUgMTYuMzUgMTcuMzUgMTVDMTcuMzUgMTMuNjUgMTYuMjUgMTIuNTUgMTQuOSAxMi41NUMxMy41NCAxMi41NSAxMi40NSAxMy42NSAxMi40NSAxNUMxMi40NSAxNi4zNSAxMy41NCAxNy40NSAxNC45IDE3LjQ1Wk0yMC4xIDE1LjY4TDIxLjU4IDE2Ljg0QzIxLjcxIDE2Ljk1IDIxLjc1IDE3LjEzIDIxLjY2IDE3LjI5TDIwLjI2IDE5LjcxQzIwLjE3IDE5Ljg2IDIwIDE5LjkyIDE5LjgzIDE5Ljg2TDE4LjA5IDE5LjE2QzE3LjczIDE5LjQ0IDE3LjMzIDE5LjY3IDE2LjkxIDE5Ljg1TDE2LjY0IDIxLjdDMTYuNjIgMjEuODcgMTYuNDcgMjIgMTYuMyAyMkgxMy41QzEzLjMyIDIyIDEzLjE4IDIxLjg3IDEzLjE1IDIxLjdMMTIuODkgMTkuODVDMTIuNDYgMTkuNjcgMTIuMDcgMTkuNDQgMTEuNzEgMTkuMTZMOS45NjAwMiAxOS44NkM5LjgxMDAyIDE5LjkyIDkuNjIwMDIgMTkuODYgOS41NDAwMiAxOS43MUw4LjE0MDAyIDE3LjI5QzguMDUwMDIgMTcuMTMgOC4wOTAwMiAxNi45NSA4LjIyMDAyIDE2Ljg0TDkuNzAwMDIgMTUuNjhMOS42NTAwMSAxNUw5LjcwMDAyIDE0LjMxTDguMjIwMDIgMTMuMTZDOC4wOTAwMiAxMy4wNSA4LjA1MDAyIDEyLjg2IDguMTQwMDIgMTIuNzFMOS41NDAwMiAxMC4yOUM5LjYyMDAyIDEwLjEzIDkuODEwMDIgMTAuMDcgOS45NjAwMiAxMC4xM0wxMS43MSAxMC44NEMxMi4wNyAxMC41NiAxMi40NiAxMC4zMiAxMi44OSAxMC4xNUwxMy4xNSA4LjI4OTk4QzEzLjE4IDguMTI5OTggMTMuMzIgNy45OTk5OCAxMy41IDcuOTk5OThIMTYuM0MxNi40NyA3Ljk5OTk4IDE2LjYyIDguMTI5OTggMTYuNjQgOC4yODk5OEwxNi45MSAxMC4xNUMxNy4zMyAxMC4zMiAxNy43MyAxMC41NiAxOC4wOSAxMC44NEwxOS44MyAxMC4xM0MyMCAxMC4wNyAyMC4xNyAxMC4xMyAyMC4yNiAxMC4yOUwyMS42NiAxMi43MUMyMS43NSAxMi44NiAyMS43MSAxMy4wNSAyMS41OCAxMy4xNkwyMC4xIDE0LjMxTDIwLjE1IDE1TDIwLjEgMTUuNjhaIi8+CiAgICA8cGF0aCBkPSJNNy4zMjk2NiA3LjQ0NDU0QzguMDgzMSA3LjAwOTU0IDguMzM5MzIgNi4wNTMzMiA3LjkwNDMyIDUuMjk5ODhDNy40NjkzMiA0LjU0NjQzIDYuNTA4MSA0LjI4MTU2IDUuNzU0NjYgNC43MTY1NkM1LjM5MTc2IDQuOTI2MDggNS4xMjY5NSA1LjI3MTE4IDUuMDE4NDkgNS42NzU5NEM0LjkxMDA0IDYuMDgwNzEgNC45NjY4MiA2LjUxMTk4IDUuMTc2MzQgNi44NzQ4OEM1LjYxMTM0IDcuNjI4MzIgNi41NzYyMiA3Ljg3OTU0IDcuMzI5NjYgNy40NDQ1NFpNOS42NTcxOCA0Ljc5NTkzTDEwLjg2NzIgNC45NTE3OUMxMC45NjI4IDQuOTc3NDEgMTEuMDQwMiA1LjA3MTMzIDExLjAzODIgNS4xODc5M0wxMS4wMzg4IDYuOTg4OTNDMTEuMDQ1NSA3LjEwMDU0IDEwLjk2MTYgNy4xOTUxOCAxMC44NTUgNy4yMTA1NEw5LjY2MDAxIDcuMzgwODNMOS4yMzkxNSA4LjEzMTg4TDkuNjY5NjEgOS4yNTc0NUM5LjcwNzI5IDkuMzYyNzEgOS42NjkzNCA5LjQ3Njk5IDkuNTc0MDggOS41MzE5OUw4LjAxNTIzIDEwLjQzMkM3LjkxMTMxIDEwLjQ5MiA3Ljc5MzM3IDEwLjQ2NzcgNy43MjEwNSAxMC4zODI0TDYuOTg3NDggOS40MzE4OEw2LjEwOTMxIDkuNDMwODNMNS4zNDcwNCAxMC4zOTA1QzUuMjg5MDkgMTAuNDcwMiA1LjE3MzgzIDEwLjQ5MDUgNS4wNzE4NyAxMC40MzM5TDMuNTEyNDUgOS41MzI5M0MzLjQxMDQ5IDkuNDc2MzMgMy4zNzY0NyA5LjM1NzQxIDMuNDEwNzUgOS4yNTY3OUwzLjg2MzQ3IDguMTQwOTNMMy42MTc0OSA3Ljc3NDg4TDMuNDIzNDcgNy4zNzg4M0wyLjIzMDc1IDcuMjEyOTdDMi4xMjY0NyA3LjE5MjM1IDIuMDQwNDkgNy4xMDM0MiAyLjA0MjQ1IDYuOTg2ODJMMi4wNDE4NyA1LjE4NTgyQzIuMDQzODMgNS4wNjkyMiAyLjExOTA5IDQuOTc5NTggMi4yMTcwNCA0Ljk2OTIyTDMuNDIwNjUgNC43OTM5M0wzLjg2NzQ5IDQuMDI3ODhMMy40MTEwNSAyLjkxNzMxQzMuMzczMzcgMi44MTIwNCAzLjQxMTMxIDIuNjk3NzYgMy41MTUyMyAyLjYzNzc2TDUuMDc0MDggMS43Mzc3NkM1LjE2OTM0IDEuNjgyNzYgNS4yODcyOSAxLjcwNzA0IDUuMzU5NjEgMS43OTIzMUw2LjExOTE1IDIuNzI3ODhMNi45ODAwMSAyLjczODkzTDcuNzI0OTYgMS43ODkyMkM3Ljc5MTU2IDEuNzA0NTggNy45MTU0OCAxLjY3OTIyIDguMDA4NzkgMS43NDA4Mkw5LjU2ODIxIDIuNjQxODJDOS42NzAxNyAyLjY5ODQyIDkuNzEyODUgMi44MTIzNCA5LjY4NzIzIDIuOTA3OTdMOS4yMTcxOCA0LjAzMzgzTDkuNDYzMTYgNC4zOTk4OEw5LjY1NzE4IDQuNzk1OTNaIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-caret-down-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iOS45LDEzLjYgMy42LDcuNCA0LjQsNi42IDkuOSwxMi4yIDE1LjQsNi43IDE2LjEsNy40ICIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-caret-down-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNS45TDksOS43bDMuOC0zLjhsMS4yLDEuMmwtNC45LDVsLTQuOS01TDUuMiw1Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-caret-down: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNy41TDksMTEuMmwzLjgtMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-caret-left: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik0xMC44LDEyLjhMNy4xLDlsMy44LTMuOGwwLDcuNkgxMC44eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-caret-right: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik03LjIsNS4yTDEwLjksOWwtMy44LDMuOFY1LjJINy4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-caret-up-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iMTUuNCwxMy4zIDkuOSw3LjcgNC40LDEzLjIgMy42LDEyLjUgOS45LDYuMyAxNi4xLDEyLjYgIi8+Cgk8L2c+Cjwvc3ZnPgo=);--jp-icon-caret-up: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik01LjIsMTAuNUw5LDYuOGwzLjgsMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-case-sensitive: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgogIDxnIGNsYXNzPSJqcC1pY29uLWFjY2VudDIiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTcuNiw4aDAuOWwzLjUsOGgtMS4xTDEwLDE0SDZsLTAuOSwySDRMNy42LDh6IE04LDkuMUw2LjQsMTNoMy4yTDgsOS4xeiIvPgogICAgPHBhdGggZD0iTTE2LjYsOS44Yy0wLjIsMC4xLTAuNCwwLjEtMC43LDAuMWMtMC4yLDAtMC40LTAuMS0wLjYtMC4yYy0wLjEtMC4xLTAuMi0wLjQtMC4yLTAuNyBjLTAuMywwLjMtMC42LDAuNS0wLjksMC43Yy0wLjMsMC4xLTAuNywwLjItMS4xLDAuMmMtMC4zLDAtMC41LDAtMC43LTAuMWMtMC4yLTAuMS0wLjQtMC4yLTAuNi0wLjNjLTAuMi0wLjEtMC4zLTAuMy0wLjQtMC41IGMtMC4xLTAuMi0wLjEtMC40LTAuMS0wLjdjMC0wLjMsMC4xLTAuNiwwLjItMC44YzAuMS0wLjIsMC4zLTAuNCwwLjQtMC41QzEyLDcsMTIuMiw2LjksMTIuNSw2LjhjMC4yLTAuMSwwLjUtMC4xLDAuNy0wLjIgYzAuMy0wLjEsMC41LTAuMSwwLjctMC4xYzAuMiwwLDAuNC0wLjEsMC42LTAuMWMwLjIsMCwwLjMtMC4xLDAuNC0wLjJjMC4xLTAuMSwwLjItMC4yLDAuMi0wLjRjMC0xLTEuMS0xLTEuMy0xIGMtMC40LDAtMS40LDAtMS40LDEuMmgtMC45YzAtMC40LDAuMS0wLjcsMC4yLTFjMC4xLTAuMiwwLjMtMC40LDAuNS0wLjZjMC4yLTAuMiwwLjUtMC4zLDAuOC0wLjNDMTMuMyw0LDEzLjYsNCwxMy45LDQgYzAuMywwLDAuNSwwLDAuOCwwLjFjMC4zLDAsMC41LDAuMSwwLjcsMC4yYzAuMiwwLjEsMC40LDAuMywwLjUsMC41QzE2LDUsMTYsNS4yLDE2LDUuNnYyLjljMCwwLjIsMCwwLjQsMCwwLjUgYzAsMC4xLDAuMSwwLjIsMC4zLDAuMmMwLjEsMCwwLjIsMCwwLjMsMFY5Ljh6IE0xNS4yLDYuOWMtMS4yLDAuNi0zLjEsMC4yLTMuMSwxLjRjMCwxLjQsMy4xLDEsMy4xLTAuNVY2Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-check: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-circle-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDJDNi40NyAyIDIgNi40NyAyIDEyczQuNDcgMTAgMTAgMTAgMTAtNC40NyAxMC0xMFMxNy41MyAyIDEyIDJ6bTAgMThjLTQuNDEgMC04LTMuNTktOC04czMuNTktOCA4LTggOCAzLjU5IDggOC0zLjU5IDgtOCA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-circle: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iOSIgY3k9IjkiIHI9IjgiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-clear: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8bWFzayBpZD0iZG9udXRIb2xlIj4KICAgIDxyZWN0IHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0id2hpdGUiIC8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSI4IiBmaWxsPSJibGFjayIvPgogIDwvbWFzaz4KCiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxyZWN0IGhlaWdodD0iMTgiIHdpZHRoPSIyIiB4PSIxMSIgeT0iMyIgdHJhbnNmb3JtPSJyb3RhdGUoMzE1LCAxMiwgMTIpIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIgbWFzaz0idXJsKCNkb251dEhvbGUpIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-close: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1ub25lIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIGpwLWljb24zLWhvdmVyIiBmaWxsPSJub25lIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjExIi8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIGpwLWljb24tYWNjZW50Mi1ob3ZlciIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPgogIDwvZz4KCiAgPGcgY2xhc3M9ImpwLWljb24tbm9uZSBqcC1pY29uLWJ1c3kiIGZpbGw9Im5vbmUiPgogICAgPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iNyIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-code: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTExLjQgMTguNkw2LjggMTRMMTEuNCA5LjRMMTAgOEw0IDE0TDEwIDIwTDExLjQgMTguNlpNMTYuNiAxOC42TDIxLjIgMTRMMTYuNiA5LjRMMTggOEwyNCAxNEwxOCAyMEwxNi42IDE4LjZWMTguNloiLz4KCTwvZz4KPC9zdmc+Cg==);--jp-icon-console: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwMCAyMDAiPgogIDxnIGNsYXNzPSJqcC1jb25zb2xlLWljb24tYmFja2dyb3VuZC1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMjg4RDEiPgogICAgPHBhdGggZD0iTTIwIDE5LjhoMTYwdjE1OS45SDIweiIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtY29uc29sZS1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIj4KICAgIDxwYXRoIGQ9Ik0xMDUgMTI3LjNoNDB2MTIuOGgtNDB6TTUxLjEgNzdMNzQgOTkuOWwtMjMuMyAyMy4zIDEwLjUgMTAuNSAyMy4zLTIzLjNMOTUgOTkuOSA4NC41IDg5LjQgNjEuNiA2Ni41eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-copy: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTExLjksMUgzLjJDMi40LDEsMS43LDEuNywxLjcsMi41djEwLjJoMS41VjIuNWg4LjdWMXogTTE0LjEsMy45aC04Yy0wLjgsMC0xLjUsMC43LTEuNSwxLjV2MTAuMmMwLDAuOCwwLjcsMS41LDEuNSwxLjVoOCBjMC44LDAsMS41LTAuNywxLjUtMS41VjUuNEMxNS41LDQuNiwxNC45LDMuOSwxNC4xLDMuOXogTTE0LjEsMTUuNWgtOFY1LjRoOFYxNS41eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-copyright: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCI+CiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0xMS44OCw5LjE0YzEuMjgsMC4wNiwxLjYxLDEuMTUsMS42MywxLjY2aDEuNzljLTAuMDgtMS45OC0xLjQ5LTMuMTktMy40NS0zLjE5QzkuNjQsNy42MSw4LDksOCwxMi4xNCBjMCwxLjk0LDAuOTMsNC4yNCwzLjg0LDQuMjRjMi4yMiwwLDMuNDEtMS42NSwzLjQ0LTIuOTVoLTEuNzljLTAuMDMsMC41OS0wLjQ1LDEuMzgtMS42MywxLjQ0QzEwLjU1LDE0LjgzLDEwLDEzLjgxLDEwLDEyLjE0IEMxMCw5LjI1LDExLjI4LDkuMTYsMTEuODgsOS4xNHogTTEyLDJDNi40OCwyLDIsNi40OCwyLDEyczQuNDgsMTAsMTAsMTBzMTAtNC40OCwxMC0xMFMxNy41MiwyLDEyLDJ6IE0xMiwyMGMtNC40MSwwLTgtMy41OS04LTggczMuNTktOCw4LThzOCwzLjU5LDgsOFMxNi40MSwyMCwxMiwyMHoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-cut: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkuNjQgNy42NGMuMjMtLjUuMzYtMS4wNS4zNi0xLjY0IDAtMi4yMS0xLjc5LTQtNC00UzIgMy43OSAyIDZzMS43OSA0IDQgNGMuNTkgMCAxLjE0LS4xMyAxLjY0LS4zNkwxMCAxMmwtMi4zNiAyLjM2QzcuMTQgMTQuMTMgNi41OSAxNCA2IDE0Yy0yLjIxIDAtNCAxLjc5LTQgNHMxLjc5IDQgNCA0IDQtMS43OSA0LTRjMC0uNTktLjEzLTEuMTQtLjM2LTEuNjRMMTIgMTRsNyA3aDN2LTFMOS42NCA3LjY0ek02IDhjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTAgMTJjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTYtNy41Yy0uMjggMC0uNS0uMjItLjUtLjVzLjIyLS41LjUtLjUuNS4yMi41LjUtLjIyLjUtLjUuNXpNMTkgM2wtNiA2IDIgMiA3LTdWM3oiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-delete: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCI+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjI2MjYyIiBkPSJNNiAxOWMwIDEuMS45IDIgMiAyaDhjMS4xIDAgMi0uOSAyLTJWN0g2djEyek0xOSA0aC0zLjVsLTEtMWgtNWwtMSAxSDV2MmgxNFY0eiIgLz4KPC9zdmc+Cg==);--jp-icon-download: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDloLTRWM0g5djZINWw3IDcgNy03ek01IDE4djJoMTR2LTJINXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-duplicate: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIuNzk5OTggMC44NzVIOC44OTU4MkM5LjIwMDYxIDAuODc1IDkuNDQ5OTggMS4xMzkxNCA5LjQ0OTk4IDEuNDYxOThDOS40NDk5OCAxLjc4NDgyIDkuMjAwNjEgMi4wNDg5NiA4Ljg5NTgyIDIuMDQ4OTZIMy4zNTQxNUMzLjA0OTM2IDIuMDQ4OTYgMi43OTk5OCAyLjMxMzEgMi43OTk5OCAyLjYzNTk0VjkuNjc5NjlDMi43OTk5OCAxMC4wMDI1IDIuNTUwNjEgMTAuMjY2NyAyLjI0NTgyIDEwLjI2NjdDMS45NDEwMyAxMC4yNjY3IDEuNjkxNjUgMTAuMDAyNSAxLjY5MTY1IDkuNjc5NjlWMi4wNDg5NkMxLjY5MTY1IDEuNDAzMjggMi4xOTA0IDAuODc1IDIuNzk5OTggMC44NzVaTTUuMzY2NjUgMTEuOVY0LjU1SDExLjA4MzNWMTEuOUg1LjM2NjY1Wk00LjE0MTY1IDQuMTQxNjdDNC4xNDE2NSAzLjY5MDYzIDQuNTA3MjggMy4zMjUgNC45NTgzMiAzLjMyNUgxMS40OTE3QzExLjk0MjcgMy4zMjUgMTIuMzA4MyAzLjY5MDYzIDEyLjMwODMgNC4xNDE2N1YxMi4zMDgzQzEyLjMwODMgMTIuNzU5NCAxMS45NDI3IDEzLjEyNSAxMS40OTE3IDEzLjEyNUg0Ljk1ODMyQzQuNTA3MjggMTMuMTI1IDQuMTQxNjUgMTIuNzU5NCA0LjE0MTY1IDEyLjMwODNWNC4xNDE2N1oiIGZpbGw9IiM2MTYxNjEiLz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNOS40MzU3NCA4LjI2NTA3SDguMzY0MzFWOS4zMzY1QzguMzY0MzEgOS40NTQzNSA4LjI2Nzg4IDkuNTUwNzggOC4xNTAwMiA5LjU1MDc4QzguMDMyMTcgOS41NTA3OCA3LjkzNTc0IDkuNDU0MzUgNy45MzU3NCA5LjMzNjVWOC4yNjUwN0g2Ljg2NDMxQzYuNzQ2NDUgOC4yNjUwNyA2LjY1MDAyIDguMTY4NjQgNi42NTAwMiA4LjA1MDc4QzYuNjUwMDIgNy45MzI5MiA2Ljc0NjQ1IDcuODM2NSA2Ljg2NDMxIDcuODM2NUg3LjkzNTc0VjYuNzY1MDdDNy45MzU3NCA2LjY0NzIxIDguMDMyMTcgNi41NTA3OCA4LjE1MDAyIDYuNTUwNzhDOC4yNjc4OCA2LjU1MDc4IDguMzY0MzEgNi42NDcyMSA4LjM2NDMxIDYuNzY1MDdWNy44MzY1SDkuNDM1NzRDOS41NTM2IDcuODM2NSA5LjY1MDAyIDcuOTMyOTIgOS42NTAwMiA4LjA1MDc4QzkuNjUwMDIgOC4xNjg2NCA5LjU1MzYgOC4yNjUwNyA5LjQzNTc0IDguMjY1MDdaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC41Ii8+Cjwvc3ZnPgo=);--jp-icon-edit: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMgMTcuMjVWMjFoMy43NUwxNy44MSA5Ljk0bC0zLjc1LTMuNzVMMyAxNy4yNXpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-ellipses: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iNSIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxOSIgY3k9IjEyIiByPSIyIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-extension: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwLjUgMTFIMTlWN2MwLTEuMS0uOS0yLTItMmgtNFYzLjVDMTMgMi4xMiAxMS44OCAxIDEwLjUgMVM4IDIuMTIgOCAzLjVWNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAydjMuOEgzLjVjMS40OSAwIDIuNyAxLjIxIDIuNyAyLjdzLTEuMjEgMi43LTIuNyAyLjdIMlYyMGMwIDEuMS45IDIgMiAyaDMuOHYtMS41YzAtMS40OSAxLjIxLTIuNyAyLjctMi43IDEuNDkgMCAyLjcgMS4yMSAyLjcgMi43VjIySDE3YzEuMSAwIDItLjkgMi0ydi00aDEuNWMxLjM4IDAgMi41LTEuMTIgMi41LTIuNVMyMS44OCAxMSAyMC41IDExeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-fast-forward: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTQgMThsOC41LTZMNCA2djEyem05LTEydjEybDguNS02TDEzIDZ6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-file-upload: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkgMTZoNnYtNmg0bC03LTctNyA3aDR6bS00IDJoMTR2Mkg1eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-file: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuMyA4LjJsLTUuNS01LjVjLS4zLS4zLS43LS41LTEuMi0uNUgzLjljLS44LjEtMS42LjktMS42IDEuOHYxNC4xYzAgLjkuNyAxLjYgMS42IDEuNmgxNC4yYy45IDAgMS42LS43IDEuNi0xLjZWOS40Yy4xLS41LS4xLS45LS40LTEuMnptLTUuOC0zLjNsMy40IDMuNmgtMy40VjQuOXptMy45IDEyLjdINC43Yy0uMSAwLS4yIDAtLjItLjJWNC43YzAtLjIuMS0uMy4yLS4zaDcuMnY0LjRzMCAuOC4zIDEuMWMuMy4zIDEuMS4zIDEuMS4zaDQuM3Y3LjJzLS4xLjItLjIuMnoiLz4KPC9zdmc+Cg==);--jp-icon-filter-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEwIDE4aDR2LTJoLTR2MnpNMyA2djJoMThWNkgzem0zIDdoMTJ2LTJINnYyeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-folder-favorite: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggY2xhc3M9ImpwLWljb24zIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxNjE2MSIgZD0iTTIwIDZoLThsLTItMkg0Yy0xLjEgMC0yIC45LTIgMnYxMmMwIDEuMS45IDIgMiAyaDE2YzEuMSAwIDItLjkgMi0yVjhjMC0xLjEtLjktMi0yLTJ6bS0yLjA2IDExTDE1IDE1LjI4IDEyLjA2IDE3bC43OC0zLjMzLTIuNTktMi4yNCAzLjQxLS4yOUwxNSA4bDEuMzQgMy4xNCAzLjQxLjI5LTIuNTkgMi4yNC43OCAzLjMzeiIvPgo8L3N2Zz4K);--jp-icon-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY4YzAtMS4xLS45LTItMi0yaC04bC0yLTJ6Ii8+Cjwvc3ZnPgo=);--jp-icon-home: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xMCAyMHYtNmg0djZoNXYtOGgzTDEyIDMgMiAxMmgzdjh6Ii8+Cjwvc3ZnPgo=);--jp-icon-html5: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uMCBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMDAiIGQ9Ik0xMDguNCAwaDIzdjIyLjhoMjEuMlYwaDIzdjY5aC0yM1Y0NmgtMjF2MjNoLTIzLjJNMjA2IDIzaC0yMC4zVjBoNjMuN3YyM0gyMjl2NDZoLTIzbTUzLjUtNjloMjQuMWwxNC44IDI0LjNMMzEzLjIgMGgyNC4xdjY5aC0yM1YzNC44bC0xNi4xIDI0LjgtMTYuMS0yNC44VjY5aC0yMi42bTg5LjItNjloMjN2NDYuMmgzMi42VjY5aC01NS42Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2U0NGQyNiIgZD0iTTEwNy42IDQ3MWwtMzMtMzcwLjRoMzYyLjhsLTMzIDM3MC4yTDI1NS43IDUxMiIvPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNmMTY1MjkiIGQ9Ik0yNTYgNDgwLjVWMTMxaDE0OC4zTDM3NiA0NDciLz4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNlYmViZWIiIGQ9Ik0xNDIgMTc2LjNoMTE0djQ1LjRoLTY0LjJsNC4yIDQ2LjVoNjB2NDUuM0gxNTQuNG0yIDIyLjhIMjAybDMuMiAzNi4zIDUwLjggMTMuNnY0Ny40bC05My4yLTI2Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIiBkPSJNMzY5LjYgMTc2LjNIMjU1Ljh2NDUuNGgxMDkuNm0tNC4xIDQ2LjVIMjU1Ljh2NDUuNGg1NmwtNS4zIDU5LTUwLjcgMTMuNnY0Ny4ybDkzLTI1LjgiLz4KPC9zdmc+Cg==);--jp-icon-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1icmFuZDQganAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNGRkYiIGQ9Ik0yLjIgMi4yaDE3LjV2MTcuNUgyLjJ6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzNGNTFCNSIgZD0iTTIuMiAyLjJ2MTcuNWgxNy41bC4xLTE3LjVIMi4yem0xMi4xIDIuMmMxLjIgMCAyLjIgMSAyLjIgMi4ycy0xIDIuMi0yLjIgMi4yLTIuMi0xLTIuMi0yLjIgMS0yLjIgMi4yLTIuMnpNNC40IDE3LjZsMy4zLTguOCAzLjMgNi42IDIuMi0zLjIgNC40IDUuNEg0LjR6Ii8+Cjwvc3ZnPgo=);--jp-icon-inspector: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaW5zcGVjdG9yLWljb24tY29sb3IganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yem0tNSAxNEg0di00aDExdjR6bTAtNUg0VjloMTF2NHptNSA1aC00VjloNHY5eiIvPgo8L3N2Zz4K);--jp-icon-json: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtanNvbi1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0Y5QTgyNSI+CiAgICA8cGF0aCBkPSJNMjAuMiAxMS44Yy0xLjYgMC0xLjcuNS0xLjcgMSAwIC40LjEuOS4xIDEuMy4xLjUuMS45LjEgMS4zIDAgMS43LTEuNCAyLjMtMy41IDIuM2gtLjl2LTEuOWguNWMxLjEgMCAxLjQgMCAxLjQtLjggMC0uMyAwLS42LS4xLTEgMC0uNC0uMS0uOC0uMS0xLjIgMC0xLjMgMC0xLjggMS4zLTItMS4zLS4yLTEuMy0uNy0xLjMtMiAwLS40LjEtLjguMS0xLjIuMS0uNC4xLS43LjEtMSAwLS44LS40LS43LTEuNC0uOGgtLjVWNC4xaC45YzIuMiAwIDMuNS43IDMuNSAyLjMgMCAuNC0uMS45LS4xIDEuMy0uMS41LS4xLjktLjEgMS4zIDAgLjUuMiAxIDEuNyAxdjEuOHpNMS44IDEwLjFjMS42IDAgMS43LS41IDEuNy0xIDAtLjQtLjEtLjktLjEtMS4zLS4xLS41LS4xLS45LS4xLTEuMyAwLTEuNiAxLjQtMi4zIDMuNS0yLjNoLjl2MS45aC0uNWMtMSAwLTEuNCAwLTEuNC44IDAgLjMgMCAuNi4xIDEgMCAuMi4xLjYuMSAxIDAgMS4zIDAgMS44LTEuMyAyQzYgMTEuMiA2IDExLjcgNiAxM2MwIC40LS4xLjgtLjEgMS4yLS4xLjMtLjEuNy0uMSAxIDAgLjguMy44IDEuNC44aC41djEuOWgtLjljLTIuMSAwLTMuNS0uNi0zLjUtMi4zIDAtLjQuMS0uOS4xLTEuMy4xLS41LjEtLjkuMS0xLjMgMC0uNS0uMi0xLTEuNy0xdi0xLjl6Ii8+CiAgICA8Y2lyY2xlIGN4PSIxMSIgY3k9IjEzLjgiIHI9IjIuMSIvPgogICAgPGNpcmNsZSBjeD0iMTEiIGN5PSI4LjIiIHI9IjIuMSIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-julia: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDMyNSAzMDAiPgogIDxnIGNsYXNzPSJqcC1icmFuZDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjY2IzYzMzIj4KICAgIDxwYXRoIGQ9Ik0gMTUwLjg5ODQzOCAyMjUgQyAxNTAuODk4NDM4IDI2Ni40MjE4NzUgMTE3LjMyMDMxMiAzMDAgNzUuODk4NDM4IDMwMCBDIDM0LjQ3NjU2MiAzMDAgMC44OTg0MzggMjY2LjQyMTg3NSAwLjg5ODQzOCAyMjUgQyAwLjg5ODQzOCAxODMuNTc4MTI1IDM0LjQ3NjU2MiAxNTAgNzUuODk4NDM4IDE1MCBDIDExNy4zMjAzMTIgMTUwIDE1MC44OTg0MzggMTgzLjU3ODEyNSAxNTAuODk4NDM4IDIyNSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzM4OTgyNiI+CiAgICA8cGF0aCBkPSJNIDIzNy41IDc1IEMgMjM3LjUgMTE2LjQyMTg3NSAyMDMuOTIxODc1IDE1MCAxNjIuNSAxNTAgQyAxMjEuMDc4MTI1IDE1MCA4Ny41IDExNi40MjE4NzUgODcuNSA3NSBDIDg3LjUgMzMuNTc4MTI1IDEyMS4wNzgxMjUgMCAxNjIuNSAwIEMgMjAzLjkyMTg3NSAwIDIzNy41IDMzLjU3ODEyNSAyMzcuNSA3NSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzk1NThiMiI+CiAgICA8cGF0aCBkPSJNIDMyNC4xMDE1NjIgMjI1IEMgMzI0LjEwMTU2MiAyNjYuNDIxODc1IDI5MC41MjM0MzggMzAwIDI0OS4xMDE1NjIgMzAwIEMgMjA3LjY3OTY4OCAzMDAgMTc0LjEwMTU2MiAyNjYuNDIxODc1IDE3NC4xMDE1NjIgMjI1IEMgMTc0LjEwMTU2MiAxODMuNTc4MTI1IDIwNy42Nzk2ODggMTUwIDI0OS4xMDE1NjIgMTUwIEMgMjkwLjUyMzQzOCAxNTAgMzI0LjEwMTU2MiAxODMuNTc4MTI1IDMyNC4xMDE1NjIgMjI1Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-jupyter-favicon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUyIiBoZWlnaHQ9IjE2NSIgdmlld0JveD0iMCAwIDE1MiAxNjUiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgPGcgY2xhc3M9ImpwLWp1cHl0ZXItaWNvbi1jb2xvciIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA3ODk0NywgMTEwLjU4MjkyNykiIGQ9Ik03NS45NDIyODQyLDI5LjU4MDQ1NjEgQzQzLjMwMjM5NDcsMjkuNTgwNDU2MSAxNC43OTY3ODMyLDE3LjY1MzQ2MzQgMCwwIEM1LjUxMDgzMjExLDE1Ljg0MDY4MjkgMTUuNzgxNTM4OSwyOS41NjY3NzMyIDI5LjM5MDQ5NDcsMzkuMjc4NDE3MSBDNDIuOTk5Nyw0OC45ODk4NTM3IDU5LjI3MzcsNTQuMjA2NzgwNSA3NS45NjA1Nzg5LDU0LjIwNjc4MDUgQzkyLjY0NzQ1NzksNTQuMjA2NzgwNSAxMDguOTIxNDU4LDQ4Ljk4OTg1MzcgMTIyLjUzMDY2MywzOS4yNzg0MTcxIEMxMzYuMTM5NDUzLDI5LjU2Njc3MzIgMTQ2LjQxMDI4NCwxNS44NDA2ODI5IDE1MS45MjExNTgsMCBDMTM3LjA4Nzg2OCwxNy42NTM0NjM0IDEwOC41ODI1ODksMjkuNTgwNDU2MSA3NS45NDIyODQyLDI5LjU4MDQ1NjEgTDc1Ljk0MjI4NDIsMjkuNTgwNDU2MSBaIiAvPgogICAgPHBhdGggdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMzczNjgsIDAuNzA0ODc4KSIgZD0iTTc1Ljk3ODQ1NzksMjQuNjI2NDA3MyBDMTA4LjYxODc2MywyNC42MjY0MDczIDEzNy4xMjQ0NTgsMzYuNTUzNDQxNSAxNTEuOTIxMTU4LDU0LjIwNjc4MDUgQzE0Ni40MTAyODQsMzguMzY2MjIyIDEzNi4xMzk0NTMsMjQuNjQwMTMxNyAxMjIuNTMwNjYzLDE0LjkyODQ4NzggQzEwOC45MjE0NTgsNS4yMTY4NDM5IDkyLjY0NzQ1NzksMCA3NS45NjA1Nzg5LDAgQzU5LjI3MzcsMCA0Mi45OTk3LDUuMjE2ODQzOSAyOS4zOTA0OTQ3LDE0LjkyODQ4NzggQzE1Ljc4MTUzODksMjQuNjQwMTMxNyA1LjUxMDgzMjExLDM4LjM2NjIyMiAwLDU0LjIwNjc4MDUgQzE0LjgzMzA4MTYsMzYuNTg5OTI5MyA0My4zMzg1Njg0LDI0LjYyNjQwNzMgNzUuOTc4NDU3OSwyNC42MjY0MDczIEw3NS45Nzg0NTc5LDI0LjYyNjQwNzMgWiIgLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-jupyter: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzkiIGhlaWdodD0iNTEiIHZpZXdCb3g9IjAgMCAzOSA1MSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTYzOCAtMjI4MSkiPgogICAgIDxnIGNsYXNzPSJqcC1qdXB5dGVyLWljb24tY29sb3IiIGZpbGw9IiNGMzc3MjYiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5Ljc0IDIzMTEuOTgpIiBkPSJNIDE4LjI2NDYgNy4xMzQxMUMgMTAuNDE0NSA3LjEzNDExIDMuNTU4NzIgNC4yNTc2IDAgMEMgMS4zMjUzOSAzLjgyMDQgMy43OTU1NiA3LjEzMDgxIDcuMDY4NiA5LjQ3MzAzQyAxMC4zNDE3IDExLjgxNTIgMTQuMjU1NyAxMy4wNzM0IDE4LjI2OSAxMy4wNzM0QyAyMi4yODIzIDEzLjA3MzQgMjYuMTk2MyAxMS44MTUyIDI5LjQ2OTQgOS40NzMwM0MgMzIuNzQyNCA3LjEzMDgxIDM1LjIxMjYgMy44MjA0IDM2LjUzOCAwQyAzMi45NzA1IDQuMjU3NiAyNi4xMTQ4IDcuMTM0MTEgMTguMjY0NiA3LjEzNDExWiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5LjczIDIyODUuNDgpIiBkPSJNIDE4LjI3MzMgNS45MzkzMUMgMjYuMTIzNSA1LjkzOTMxIDMyLjk3OTMgOC44MTU4MyAzNi41MzggMTMuMDczNEMgMzUuMjEyNiA5LjI1MzAzIDMyLjc0MjQgNS45NDI2MiAyOS40Njk0IDMuNjAwNEMgMjYuMTk2MyAxLjI1ODE4IDIyLjI4MjMgMCAxOC4yNjkgMEMgMTQuMjU1NyAwIDEwLjM0MTcgMS4yNTgxOCA3LjA2ODYgMy42MDA0QyAzLjc5NTU2IDUuOTQyNjIgMS4zMjUzOSA5LjI1MzAzIDAgMTMuMDczNEMgMy41Njc0NSA4LjgyNDYzIDEwLjQyMzIgNS45MzkzMSAxOC4yNzMzIDUuOTM5MzFaIi8+CiAgICA8L2c+CiAgICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjY5LjMgMjI4MS4zMSkiIGQ9Ik0gNS44OTM1MyAyLjg0NEMgNS45MTg4OSAzLjQzMTY1IDUuNzcwODUgNC4wMTM2NyA1LjQ2ODE1IDQuNTE2NDVDIDUuMTY1NDUgNS4wMTkyMiA0LjcyMTY4IDUuNDIwMTUgNC4xOTI5OSA1LjY2ODUxQyAzLjY2NDMgNS45MTY4OCAzLjA3NDQ0IDYuMDAxNTEgMi40OTgwNSA1LjkxMTcxQyAxLjkyMTY2IDUuODIxOSAxLjM4NDYzIDUuNTYxNyAwLjk1NDg5OCA1LjE2NDAxQyAwLjUyNTE3IDQuNzY2MzMgMC4yMjIwNTYgNC4yNDkwMyAwLjA4MzkwMzcgMy42Nzc1N0MgLTAuMDU0MjQ4MyAzLjEwNjExIC0wLjAyMTIzIDIuNTA2MTcgMC4xNzg3ODEgMS45NTM2NEMgMC4zNzg3OTMgMS40MDExIDAuNzM2ODA5IDAuOTIwODE3IDEuMjA3NTQgMC41NzM1MzhDIDEuNjc4MjYgMC4yMjYyNTkgMi4yNDA1NSAwLjAyNzU5MTkgMi44MjMyNiAwLjAwMjY3MjI5QyAzLjYwMzg5IC0wLjAzMDcxMTUgNC4zNjU3MyAwLjI0OTc4OSA0Ljk0MTQyIDAuNzgyNTUxQyA1LjUxNzExIDEuMzE1MzEgNS44NTk1NiAyLjA1Njc2IDUuODkzNTMgMi44NDRaIi8+CiAgICAgIDxwYXRoIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2MzkuOCAyMzIzLjgxKSIgZD0iTSA3LjQyNzg5IDMuNTgzMzhDIDcuNDYwMDggNC4zMjQzIDcuMjczNTUgNS4wNTgxOSA2Ljg5MTkzIDUuNjkyMTNDIDYuNTEwMzEgNi4zMjYwNyA1Ljk1MDc1IDYuODMxNTYgNS4yODQxMSA3LjE0NDZDIDQuNjE3NDcgNy40NTc2MyAzLjg3MzcxIDcuNTY0MTQgMy4xNDcwMiA3LjQ1MDYzQyAyLjQyMDMyIDcuMzM3MTIgMS43NDMzNiA3LjAwODcgMS4yMDE4NCA2LjUwNjk1QyAwLjY2MDMyOCA2LjAwNTIgMC4yNzg2MSA1LjM1MjY4IDAuMTA1MDE3IDQuNjMyMDJDIC0wLjA2ODU3NTcgMy45MTEzNSAtMC4wMjYyMzYxIDMuMTU0OTQgMC4yMjY2NzUgMi40NTg1NkMgMC40Nzk1ODcgMS43NjIxNyAwLjkzMTY5NyAxLjE1NzEzIDEuNTI1NzYgMC43MjAwMzNDIDIuMTE5ODMgMC4yODI5MzUgMi44MjkxNCAwLjAzMzQzOTUgMy41NjM4OSAwLjAwMzEzMzQ0QyA0LjU0NjY3IC0wLjAzNzQwMzMgNS41MDUyOSAwLjMxNjcwNiA2LjIyOTYxIDAuOTg3ODM1QyA2Ljk1MzkzIDEuNjU4OTYgNy4zODQ4NCAyLjU5MjM1IDcuNDI3ODkgMy41ODMzOEwgNy40Mjc4OSAzLjU4MzM4WiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM4LjM2IDIyODYuMDYpIiBkPSJNIDIuMjc0NzEgNC4zOTYyOUMgMS44NDM2MyA0LjQxNTA4IDEuNDE2NzEgNC4zMDQ0NSAxLjA0Nzk5IDQuMDc4NDNDIDAuNjc5MjY4IDMuODUyNCAwLjM4NTMyOCAzLjUyMTE0IDAuMjAzMzcxIDMuMTI2NTZDIDAuMDIxNDEzNiAyLjczMTk4IC0wLjA0MDM3OTggMi4yOTE4MyAwLjAyNTgxMTYgMS44NjE4MUMgMC4wOTIwMDMxIDEuNDMxOCAwLjI4MzIwNCAxLjAzMTI2IDAuNTc1MjEzIDAuNzEwODgzQyAwLjg2NzIyMiAwLjM5MDUxIDEuMjQ2OTEgMC4xNjQ3MDggMS42NjYyMiAwLjA2MjA1OTJDIDIuMDg1NTMgLTAuMDQwNTg5NyAyLjUyNTYxIC0wLjAxNTQ3MTQgMi45MzA3NiAwLjEzNDIzNUMgMy4zMzU5MSAwLjI4Mzk0MSAzLjY4NzkyIDAuNTUxNTA1IDMuOTQyMjIgMC45MDMwNkMgNC4xOTY1MiAxLjI1NDYyIDQuMzQxNjkgMS42NzQzNiA0LjM1OTM1IDIuMTA5MTZDIDQuMzgyOTkgMi42OTEwNyA0LjE3Njc4IDMuMjU4NjkgMy43ODU5NyAzLjY4NzQ2QyAzLjM5NTE2IDQuMTE2MjQgMi44NTE2NiA0LjM3MTE2IDIuMjc0NzEgNC4zOTYyOUwgMi4yNzQ3MSA0LjM5NjI5WiIvPgogICAgPC9nPgogIDwvZz4+Cjwvc3ZnPgo=);--jp-icon-jupyterlab-wordmark: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIHZpZXdCb3g9IjAgMCAxODYwLjggNDc1Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0RTRFNEUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ4MC4xMzY0MDEsIDY0LjI3MTQ5MykiPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDU4Ljg3NTU2NikiPgogICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA4NzYwMywgMC4xNDAyOTQpIj4KICAgICAgICA8cGF0aCBkPSJNLTQyNi45LDE2OS44YzAsNDguNy0zLjcsNjQuNy0xMy42LDc2LjRjLTEwLjgsMTAtMjUsMTUuNS0zOS43LDE1LjVsMy43LDI5IGMyMi44LDAuMyw0NC44LTcuOSw2MS45LTIzLjFjMTcuOC0xOC41LDI0LTQ0LjEsMjQtODMuM1YwSC00Mjd2MTcwLjFMLTQyNi45LDE2OS44TC00MjYuOSwxNjkuOHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTU1LjA0NTI5NiwgNTYuODM3MTA0KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuNTYyNDUzLCAxLjc5OTg0MikiPgogICAgICAgIDxwYXRoIGQ9Ik0tMzEyLDE0OGMwLDIxLDAsMzkuNSwxLjcsNTUuNGgtMzEuOGwtMi4xLTMzLjNoLTAuOGMtNi43LDExLjYtMTYuNCwyMS4zLTI4LDI3LjkgYy0xMS42LDYuNi0yNC44LDEwLTM4LjIsOS44Yy0zMS40LDAtNjktMTcuNy02OS04OVYwaDM2LjR2MTEyLjdjMCwzOC43LDExLjYsNjQuNyw0NC42LDY0LjdjMTAuMy0wLjIsMjAuNC0zLjUsMjguOS05LjQgYzguNS01LjksMTUuMS0xNC4zLDE4LjktMjMuOWMyLjItNi4xLDMuMy0xMi41LDMuMy0xOC45VjAuMmgzNi40VjE0OEgtMzEyTC0zMTIsMTQ4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTAuMDEzMzIyLCA1My40Nzk2MzgpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS43MDY0NTgsIDAuMjMxNDI1KSI+CiAgICAgICAgPHBhdGggZD0iTS00NzguNiw3MS40YzAtMjYtMC44LTQ3LTEuNy02Ni43aDMyLjdsMS43LDM0LjhoMC44YzcuMS0xMi41LDE3LjUtMjIuOCwzMC4xLTI5LjcgYzEyLjUtNywyNi43LTEwLjMsNDEtOS44YzQ4LjMsMCw4NC43LDQxLjcsODQuNywxMDMuM2MwLDczLjEtNDMuNywxMDkuMi05MSwxMDkuMmMtMTIuMSwwLjUtMjQuMi0yLjItMzUtNy44IGMtMTAuOC01LjYtMTkuOS0xMy45LTI2LjYtMjQuMmgtMC44VjI5MWgtMzZ2LTIyMEwtNDc4LjYsNzEuNEwtNDc4LjYsNzEuNHogTS00NDIuNiwxMjUuNmMwLjEsNS4xLDAuNiwxMC4xLDEuNywxNS4xIGMzLDEyLjMsOS45LDIzLjMsMTkuOCwzMS4xYzkuOSw3LjgsMjIuMSwxMi4xLDM0LjcsMTIuMWMzOC41LDAsNjAuNy0zMS45LDYwLjctNzguNWMwLTQwLjctMjEuMS03NS42LTU5LjUtNzUuNiBjLTEyLjksMC40LTI1LjMsNS4xLTM1LjMsMTMuNGMtOS45LDguMy0xNi45LDE5LjctMTkuNiwzMi40Yy0xLjUsNC45LTIuMywxMC0yLjUsMTUuMVYxMjUuNkwtNDQyLjYsMTI1LjZMLTQ0Mi42LDEyNS42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2MDYuNzQwNzI2LCA1Ni44MzcxMDQpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC43NTEyMjYsIDEuOTg5Mjk5KSI+CiAgICAgICAgPHBhdGggZD0iTS00NDAuOCwwbDQzLjcsMTIwLjFjNC41LDEzLjQsOS41LDI5LjQsMTIuOCw0MS43aDAuOGMzLjctMTIuMiw3LjktMjcuNywxMi44LTQyLjQgbDM5LjctMTE5LjJoMzguNUwtMzQ2LjksMTQ1Yy0yNiw2OS43LTQzLjcsMTA1LjQtNjguNiwxMjcuMmMtMTIuNSwxMS43LTI3LjksMjAtNDQuNiwyMy45bC05LjEtMzEuMSBjMTEuNy0zLjksMjIuNS0xMC4xLDMxLjgtMTguMWMxMy4yLTExLjEsMjMuNy0yNS4yLDMwLjYtNDEuMmMxLjUtMi44LDIuNS01LjcsMi45LTguOGMtMC4zLTMuMy0xLjItNi42LTIuNS05LjdMLTQ4MC4yLDAuMSBoMzkuN0wtNDQwLjgsMEwtNDQwLjgsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODIyLjc0ODEwNCwgMC4wMDAwMDApIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS40NjQwNTAsIDAuMzc4OTE0KSI+CiAgICAgICAgPHBhdGggZD0iTS00MTMuNywwdjU4LjNoNTJ2MjguMmgtNTJWMTk2YzAsMjUsNywzOS41LDI3LjMsMzkuNWM3LjEsMC4xLDE0LjItMC43LDIxLjEtMi41IGwxLjcsMjcuN2MtMTAuMywzLjctMjEuMyw1LjQtMzIuMiw1Yy03LjMsMC40LTE0LjYtMC43LTIxLjMtMy40Yy02LjgtMi43LTEyLjktNi44LTE3LjktMTIuMWMtMTAuMy0xMC45LTE0LjEtMjktMTQuMS01Mi45IFY4Ni41aC0zMVY1OC4zaDMxVjkuNkwtNDEzLjcsMEwtNDEzLjcsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTc0LjQzMzI4NiwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAuOTkwMDM0LCAwLjYxMDMzOSkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDQ1LjgsMTEzYzAuOCw1MCwzMi4yLDcwLjYsNjguNiw3MC42YzE5LDAuNiwzNy45LTMsNTUuMy0xMC41bDYuMiwyNi40IGMtMjAuOSw4LjktNDMuNSwxMy4xLTY2LjIsMTIuNmMtNjEuNSwwLTk4LjMtNDEuMi05OC4zLTEwMi41Qy00ODAuMiw0OC4yLTQ0NC43LDAtMzg2LjUsMGM2NS4yLDAsODIuNyw1OC4zLDgyLjcsOTUuNyBjLTAuMSw1LjgtMC41LDExLjUtMS4yLDE3LjJoLTE0MC42SC00NDUuOEwtNDQ1LjgsMTEzeiBNLTMzOS4yLDg2LjZjMC40LTIzLjUtOS41LTYwLjEtNTAuNC02MC4xIGMtMzYuOCwwLTUyLjgsMzQuNC01NS43LDYwLjFILTMzOS4yTC0zMzkuMiw4Ni42TC0zMzkuMiw4Ni42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjAxLjk2MTA1OCwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuMTc5NjQwLCAwLjcwNTA2OCkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDc4LjYsNjhjMC0yMy45LTAuNC00NC41LTEuNy02My40aDMxLjhsMS4yLDM5LjloMS43YzkuMS0yNy4zLDMxLTQ0LjUsNTUuMy00NC41IGMzLjUtMC4xLDcsMC40LDEwLjMsMS4ydjM0LjhjLTQuMS0wLjktOC4yLTEuMy0xMi40LTEuMmMtMjUuNiwwLTQzLjcsMTkuNy00OC43LDQ3LjRjLTEsNS43LTEuNiwxMS41LTEuNywxNy4ydjEwOC4zaC0zNlY2OCBMLTQ3OC42LDY4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi13YXJuMCIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCBkPSJNMTM1Mi4zLDMyNi4yaDM3VjI4aC0zN1YzMjYuMnogTTE2MDQuOCwzMjYuMmMtMi41LTEzLjktMy40LTMxLjEtMy40LTQ4Ljd2LTc2IGMwLTQwLjctMTUuMS04My4xLTc3LjMtODMuMWMtMjUuNiwwLTUwLDcuMS02Ni44LDE4LjFsOC40LDI0LjRjMTQuMy05LjIsMzQtMTUuMSw1My0xNS4xYzQxLjYsMCw0Ni4yLDMwLjIsNDYuMiw0N3Y0LjIgYy03OC42LTAuNC0xMjIuMywyNi41LTEyMi4zLDc1LjZjMCwyOS40LDIxLDU4LjQsNjIuMiw1OC40YzI5LDAsNTAuOS0xNC4zLDYyLjItMzAuMmgxLjNsMi45LDI1LjZIMTYwNC44eiBNMTU2NS43LDI1Ny43IGMwLDMuOC0wLjgsOC0yLjEsMTEuOGMtNS45LDE3LjItMjIuNywzNC00OS4yLDM0Yy0xOC45LDAtMzQuOS0xMS4zLTM0LjktMzUuM2MwLTM5LjUsNDUuOC00Ni42LDg2LjItNDUuOFYyNTcuN3ogTTE2OTguNSwzMjYuMiBsMS43LTMzLjZoMS4zYzE1LjEsMjYuOSwzOC43LDM4LjIsNjguMSwzOC4yYzQ1LjQsMCw5MS4yLTM2LjEsOTEuMi0xMDguOGMwLjQtNjEuNy0zNS4zLTEwMy43LTg1LjctMTAzLjcgYy0zMi44LDAtNTYuMywxNC43LTY5LjMsMzcuNGgtMC44VjI4aC0zNi42djI0NS43YzAsMTguMS0wLjgsMzguNi0xLjcsNTIuNUgxNjk4LjV6IE0xNzA0LjgsMjA4LjJjMC01LjksMS4zLTEwLjksMi4xLTE1LjEgYzcuNi0yOC4xLDMxLjEtNDUuNCw1Ni4zLTQ1LjRjMzkuNSwwLDYwLjUsMzQuOSw2MC41LDc1LjZjMCw0Ni42LTIzLjEsNzguMS02MS44LDc4LjFjLTI2LjksMC00OC4zLTE3LjYtNTUuNS00My4zIGMtMC44LTQuMi0xLjctOC44LTEuNy0xMy40VjIwOC4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgZmlsbD0iIzYxNjE2MSIgZD0iTTE1IDlIOXY2aDZWOXptLTIgNGgtMnYtMmgydjJ6bTgtMlY5aC0yVjdjMC0xLjEtLjktMi0yLTJoLTJWM2gtMnYyaC0yVjNIOXYySDdjLTEuMSAwLTIgLjktMiAydjJIM3YyaDJ2MkgzdjJoMnYyYzAgMS4xLjkgMiAyIDJoMnYyaDJ2LTJoMnYyaDJ2LTJoMmMxLjEgMCAyLS45IDItMnYtMmgydi0yaC0ydi0yaDJ6bS00IDZIN1Y3aDEwdjEweiIvPgo8L3N2Zz4K);--jp-icon-keyboard: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMTdjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY3YzAtMS4xLS45LTItMi0yem0tOSAzaDJ2MmgtMlY4em0wIDNoMnYyaC0ydi0yek04IDhoMnYySDhWOHptMCAzaDJ2Mkg4di0yem0tMSAySDV2LTJoMnYyem0wLTNINVY4aDJ2MnptOSA3SDh2LTJoOHYyem0wLTRoLTJ2LTJoMnYyem0wLTNoLTJWOGgydjJ6bTMgM2gtMnYtMmgydjJ6bTAtM2gtMlY4aDJ2MnoiLz4KPC9zdmc+Cg==);--jp-icon-launch: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzIgMzIiIHdpZHRoPSIzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yNiwyOEg2YTIuMDAyNywyLjAwMjcsMCwwLDEtMi0yVjZBMi4wMDI3LDIuMDAyNywwLDAsMSw2LDRIMTZWNkg2VjI2SDI2VjE2aDJWMjZBMi4wMDI3LDIuMDAyNywwLDAsMSwyNiwyOFoiLz4KICAgIDxwb2x5Z29uIHBvaW50cz0iMjAgMiAyMCA0IDI2LjU4NiA0IDE4IDEyLjU4NiAxOS40MTQgMTQgMjggNS40MTQgMjggMTIgMzAgMTIgMzAgMiAyMCAyIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-launcher: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkgMTlINVY1aDdWM0g1YTIgMiAwIDAwLTIgMnYxNGEyIDIgMCAwMDIgMmgxNGMxLjEgMCAyLS45IDItMnYtN2gtMnY3ek0xNCAzdjJoMy41OWwtOS44MyA5LjgzIDEuNDEgMS40MUwxOSA2LjQxVjEwaDJWM2gtN3oiLz4KPC9zdmc+Cg==);--jp-icon-line-form: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGZpbGw9IndoaXRlIiBkPSJNNS44OCA0LjEyTDEzLjc2IDEybC03Ljg4IDcuODhMOCAyMmwxMC0xMEw4IDJ6Ii8+Cjwvc3ZnPgo=);--jp-icon-link: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMuOSAxMmMwLTEuNzEgMS4zOS0zLjEgMy4xLTMuMWg0VjdIN2MtMi43NiAwLTUgMi4yNC01IDVzMi4yNCA1IDUgNWg0di0xLjlIN2MtMS43MSAwLTMuMS0xLjM5LTMuMS0zLjF6TTggMTNoOHYtMkg4djJ6bTktNmgtNHYxLjloNGMxLjcxIDAgMy4xIDEuMzkgMy4xIDMuMXMtMS4zOSAzLjEtMy4xIDMuMWgtNFYxN2g0YzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xOSA1djE0SDVWNWgxNG0xLjEtMkgzLjljLS41IDAtLjkuNC0uOS45djE2LjJjMCAuNC40LjkuOS45aDE2LjJjLjQgMCAuOS0uNS45LS45VjMuOWMwLS41LS41LS45LS45LS45ek0xMSA3aDZ2MmgtNlY3em0wIDRoNnYyaC02di0yem0wIDRoNnYyaC02ek03IDdoMnYySDd6bTAgNGgydjJIN3ptMCA0aDJ2Mkg3eiIvPgo8L3N2Zz4=);--jp-icon-listings-info: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MC45NzggNTAuOTc4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MC45NzggNTAuOTc4OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+Cgk8Zz4KCQk8cGF0aCBzdHlsZT0iZmlsbDojMDEwMDAyOyIgZD0iTTQzLjUyLDcuNDU4QzM4LjcxMSwyLjY0OCwzMi4zMDcsMCwyNS40ODksMEMxOC42NywwLDEyLjI2NiwyLjY0OCw3LjQ1OCw3LjQ1OAoJCQljLTkuOTQzLDkuOTQxLTkuOTQzLDI2LjExOSwwLDM2LjA2MmM0LjgwOSw0LjgwOSwxMS4yMTIsNy40NTYsMTguMDMxLDcuNDU4YzAsMCwwLjAwMSwwLDAuMDAyLDAKCQkJYzYuODE2LDAsMTMuMjIxLTIuNjQ4LDE4LjAyOS03LjQ1OGM0LjgwOS00LjgwOSw3LjQ1Ny0xMS4yMTIsNy40NTctMTguMDNDNTAuOTc3LDE4LjY3LDQ4LjMyOCwxMi4yNjYsNDMuNTIsNy40NTh6CgkJCSBNNDIuMTA2LDQyLjEwNWMtNC40MzIsNC40MzEtMTAuMzMyLDYuODcyLTE2LjYxNSw2Ljg3MmgtMC4wMDJjLTYuMjg1LTAuMDAxLTEyLjE4Ny0yLjQ0MS0xNi42MTctNi44NzIKCQkJYy05LjE2Mi05LjE2My05LjE2Mi0yNC4wNzEsMC0zMy4yMzNDMTMuMzAzLDQuNDQsMTkuMjA0LDIsMjUuNDg5LDJjNi4yODQsMCwxMi4xODYsMi40NCwxNi42MTcsNi44NzIKCQkJYzQuNDMxLDQuNDMxLDYuODcxLDEwLjMzMiw2Ljg3MSwxNi42MTdDNDguOTc3LDMxLjc3Miw0Ni41MzYsMzcuNjc1LDQyLjEwNiw0Mi4xMDV6Ii8+CgkJPHBhdGggc3R5bGU9ImZpbGw6IzAxMDAwMjsiIGQ9Ik0yMy41NzgsMzIuMjE4Yy0wLjAyMy0xLjczNCwwLjE0My0zLjA1OSwwLjQ5Ni0zLjk3MmMwLjM1My0wLjkxMywxLjExLTEuOTk3LDIuMjcyLTMuMjUzCgkJCWMwLjQ2OC0wLjUzNiwwLjkyMy0xLjA2MiwxLjM2Ny0xLjU3NWMwLjYyNi0wLjc1MywxLjEwNC0xLjQ3OCwxLjQzNi0yLjE3NWMwLjMzMS0wLjcwNywwLjQ5NS0xLjU0MSwwLjQ5NS0yLjUKCQkJYzAtMS4wOTYtMC4yNi0yLjA4OC0wLjc3OS0yLjk3OWMtMC41NjUtMC44NzktMS41MDEtMS4zMzYtMi44MDYtMS4zNjljLTEuODAyLDAuMDU3LTIuOTg1LDAuNjY3LTMuNTUsMS44MzIKCQkJYy0wLjMwMSwwLjUzNS0wLjUwMywxLjE0MS0wLjYwNywxLjgxNGMtMC4xMzksMC43MDctMC4yMDcsMS40MzItMC4yMDcsMi4xNzRoLTIuOTM3Yy0wLjA5MS0yLjIwOCwwLjQwNy00LjExNCwxLjQ5My01LjcxOQoJCQljMS4wNjItMS42NCwyLjg1NS0yLjQ4MSw1LjM3OC0yLjUyN2MyLjE2LDAuMDIzLDMuODc0LDAuNjA4LDUuMTQxLDEuNzU4YzEuMjc4LDEuMTYsMS45MjksMi43NjQsMS45NSw0LjgxMQoJCQljMCwxLjE0Mi0wLjEzNywyLjExMS0wLjQxLDIuOTExYy0wLjMwOSwwLjg0NS0wLjczMSwxLjU5My0xLjI2OCwyLjI0M2MtMC40OTIsMC42NS0xLjA2OCwxLjMxOC0xLjczLDIuMDAyCgkJCWMtMC42NSwwLjY5Ny0xLjMxMywxLjQ3OS0xLjk4NywyLjM0NmMtMC4yMzksMC4zNzctMC40MjksMC43NzctMC41NjUsMS4xOTljLTAuMTYsMC45NTktMC4yMTcsMS45NTEtMC4xNzEsMi45NzkKCQkJQzI2LjU4OSwzMi4yMTgsMjMuNTc4LDMyLjIxOCwyMy41NzgsMzIuMjE4eiBNMjMuNTc4LDM4LjIydi0zLjQ4NGgzLjA3NnYzLjQ4NEgyMy41Nzh6Ii8+Cgk8L2c+Cjwvc3ZnPgo=);--jp-icon-markdown: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjN0IxRkEyIiBkPSJNNSAxNC45aDEybC02LjEgNnptOS40LTYuOGMwLTEuMy0uMS0yLjktLjEtNC41LS40IDEuNC0uOSAyLjktMS4zIDQuM2wtMS4zIDQuM2gtMkw4LjUgNy45Yy0uNC0xLjMtLjctMi45LTEtNC4zLS4xIDEuNi0uMSAzLjItLjIgNC42TDcgMTIuNEg0LjhsLjctMTFoMy4zTDEwIDVjLjQgMS4yLjcgMi43IDEgMy45LjMtMS4yLjctMi42IDEtMy45bDEuMi0zLjdoMy4zbC42IDExaC0yLjRsLS4zLTQuMnoiLz4KPC9zdmc+Cg==);--jp-icon-move-down: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMTIuNDcxIDcuNTI4OTlDMTIuNzYzMiA3LjIzNjg0IDEyLjc2MzIgNi43NjMxNiAxMi40NzEgNi40NzEwMVY2LjQ3MTAxQzEyLjE3OSA2LjE3OTA1IDExLjcwNTcgNi4xNzg4NCAxMS40MTM1IDYuNDcwNTRMNy43NSAxMC4xMjc1VjEuNzVDNy43NSAxLjMzNTc5IDcuNDE0MjEgMSA3IDFWMUM2LjU4NTc5IDEgNi4yNSAxLjMzNTc5IDYuMjUgMS43NVYxMC4xMjc1TDIuNTk3MjYgNi40NjgyMkMyLjMwMzM4IDYuMTczODEgMS44MjY0MSA2LjE3MzU5IDEuNTMyMjYgNi40Njc3NFY2LjQ2Nzc0QzEuMjM4MyA2Ljc2MTcgMS4yMzgzIDcuMjM4MyAxLjUzMjI2IDcuNTMyMjZMNi4yOTI4OSAxMi4yOTI5QzYuNjgzNDIgMTIuNjgzNCA3LjMxNjU4IDEyLjY4MzQgNy43MDcxMSAxMi4yOTI5TDEyLjQ3MSA3LjUyODk5WiIgZmlsbD0iIzYxNjE2MSIvPgo8L3N2Zz4K);--jp-icon-move-up: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMS41Mjg5OSA2LjQ3MTAxQzEuMjM2ODQgNi43NjMxNiAxLjIzNjg0IDcuMjM2ODQgMS41Mjg5OSA3LjUyODk5VjcuNTI4OTlDMS44MjA5NSA3LjgyMDk1IDIuMjk0MjYgNy44MjExNiAyLjU4NjQ5IDcuNTI5NDZMNi4yNSAzLjg3MjVWMTIuMjVDNi4yNSAxMi42NjQyIDYuNTg1NzkgMTMgNyAxM1YxM0M3LjQxNDIxIDEzIDcuNzUgMTIuNjY0MiA3Ljc1IDEyLjI1VjMuODcyNUwxMS40MDI3IDcuNTMxNzhDMTEuNjk2NiA3LjgyNjE5IDEyLjE3MzYgNy44MjY0MSAxMi40Njc3IDcuNTMyMjZWNy41MzIyNkMxMi43NjE3IDcuMjM4MyAxMi43NjE3IDYuNzYxNyAxMi40Njc3IDYuNDY3NzRMNy43MDcxMSAxLjcwNzExQzcuMzE2NTggMS4zMTY1OCA2LjY4MzQyIDEuMzE2NTggNi4yOTI4OSAxLjcwNzExTDEuNTI4OTkgNi40NzEwMVoiIGZpbGw9IiM2MTYxNjEiLz4KPC9zdmc+Cg==);--jp-icon-new-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwIDZoLThsLTItMkg0Yy0xLjExIDAtMS45OS44OS0xLjk5IDJMMiAxOGMwIDEuMTEuODkgMiAyIDJoMTZjMS4xMSAwIDItLjg5IDItMlY4YzAtMS4xMS0uODktMi0yLTJ6bS0xIDhoLTN2M2gtMnYtM2gtM3YtMmgzVjloMnYzaDN2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-not-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI1IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMTkgMTcuMTg0NCAyLjk2OTY4IDE0LjMwMzIgMS44NjA5NCAxMS40NDA5WiIvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24yIiBzdHJva2U9IiMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4zMTU5MiA5LjMyMDMxKSIgZD0iTTcuMzY4NDIgMEwwIDcuMzY0NzkiLz4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMzE1OTIgMTYuNjgzNikgc2NhbGUoMSAtMSkiIGQ9Ik03LjM2ODQyIDBMMCA3LjM2NDc5Ii8+Cjwvc3ZnPgo=);--jp-icon-notebook: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtbm90ZWJvb2staWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNFRjZDMDAiPgogICAgPHBhdGggZD0iTTE4LjcgMy4zdjE1LjRIMy4zVjMuM2gxNS40bTEuNS0xLjVIMS44djE4LjNoMTguM2wuMS0xOC4zeiIvPgogICAgPHBhdGggZD0iTTE2LjUgMTYuNWwtNS40LTQuMy01LjYgNC4zdi0xMWgxMXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-numbering: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTQgMTlINlYxOS41SDVWMjAuNUg2VjIxSDRWMjJIN1YxOEg0VjE5Wk01IDEwSDZWNkg0VjdINVYxMFpNNCAxM0g1LjhMNCAxNS4xVjE2SDdWMTVINS4yTDcgMTIuOVYxMkg0VjEzWk05IDdWOUgyM1Y3SDlaTTkgMjFIMjNWMTlIOVYyMVpNOSAxNUgyM1YxM0g5VjE1WiIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-offline-bolt: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDIuMDJjLTUuNTEgMC05Ljk4IDQuNDctOS45OCA5Ljk4czQuNDcgOS45OCA5Ljk4IDkuOTggOS45OC00LjQ3IDkuOTgtOS45OFMxNy41MSAyLjAyIDEyIDIuMDJ6TTExLjQ4IDIwdi02LjI2SDhMMTMgNHY2LjI2aDMuMzVMMTEuNDggMjB6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-palette: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE4IDEzVjIwSDRWNkg5LjAyQzkuMDcgNS4yOSA5LjI0IDQuNjIgOS41IDRINEMyLjkgNCAyIDQuOSAyIDZWMjBDMiAyMS4xIDIuOSAyMiA0IDIySDE4QzE5LjEgMjIgMjAgMjEuMSAyMCAyMFYxNUwxOCAxM1pNMTkuMyA4Ljg5QzE5Ljc0IDguMTkgMjAgNy4zOCAyMCA2LjVDMjAgNC4wMSAxNy45OSAyIDE1LjUgMkMxMy4wMSAyIDExIDQuMDEgMTEgNi41QzExIDguOTkgMTMuMDEgMTEgMTUuNDkgMTFDMTYuMzcgMTEgMTcuMTkgMTAuNzQgMTcuODggMTAuM0wyMSAxMy40MkwyMi40MiAxMkwxOS4zIDguODlaTTE1LjUgOUMxNC4xMiA5IDEzIDcuODggMTMgNi41QzEzIDUuMTIgMTQuMTIgNCAxNS41IDRDMTYuODggNCAxOCA1LjEyIDE4IDYuNUMxOCA3Ljg4IDE2Ljg4IDkgMTUuNSA5WiIvPgogICAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDZIOS4wMTg5NEM5LjAwNjM5IDYuMTY1MDIgOSA2LjMzMTc2IDkgNi41QzkgOC44MTU3NyAxMC4yMTEgMTAuODQ4NyAxMi4wMzQzIDEySDlWMTRIMTZWMTIuOTgxMUMxNi41NzAzIDEyLjkzNzcgMTcuMTIgMTIuODIwNyAxNy42Mzk2IDEyLjYzOTZMMTggMTNWMjBINFY2Wk04IDhINlYxMEg4VjhaTTYgMTJIOFYxNEg2VjEyWk04IDE2SDZWMThIOFYxNlpNOSAxNkgxNlYxOEg5VjE2WiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-paste: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE5IDJoLTQuMThDMTQuNC44NCAxMy4zIDAgMTIgMGMtMS4zIDAtMi40Ljg0LTIuODIgMkg1Yy0xLjEgMC0yIC45LTIgMnYxNmMwIDEuMS45IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6bS03IDBjLjU1IDAgMSAuNDUgMSAxcy0uNDUgMS0xIDEtMS0uNDUtMS0xIC40NS0xIDEtMXptNyAxOEg1VjRoMnYzaDEwVjRoMnYxNnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);--jp-icon-pdf: url(data:image/svg+xml;base64,PHN2ZwogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMiAyMiIgd2lkdGg9IjE2Ij4KICAgIDxwYXRoIHRyYW5zZm9ybT0icm90YXRlKDQ1KSIgY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0ZGMkEyQSIKICAgICAgIGQ9Im0gMjIuMzQ0MzY5LC0zLjAxNjM2NDIgaCA1LjYzODYwNCB2IDEuNTc5MjQzMyBoIC0zLjU0OTIyNyB2IDEuNTA4NjkyOTkgaCAzLjMzNzU3NiBWIDEuNjUwODE1NCBoIC0zLjMzNzU3NiB2IDMuNDM1MjYxMyBoIC0yLjA4OTM3NyB6IG0gLTcuMTM2NDQ0LDEuNTc5MjQzMyB2IDQuOTQzOTU0MyBoIDAuNzQ4OTIgcSAxLjI4MDc2MSwwIDEuOTUzNzAzLC0wLjYzNDk1MzUgMC42NzgzNjksLTAuNjM0OTUzNSAwLjY3ODM2OSwtMS44NDUxNjQxIDAsLTEuMjA0NzgzNTUgLTAuNjcyOTQyLC0xLjgzNDMxMDExIC0wLjY3Mjk0MiwtMC42Mjk1MjY1OSAtMS45NTkxMywtMC42Mjk1MjY1OSB6IG0gLTIuMDg5Mzc3LC0xLjU3OTI0MzMgaCAyLjIwMzM0MyBxIDEuODQ1MTY0LDAgMi43NDYwMzksMC4yNjU5MjA3IDAuOTA2MzAxLDAuMjYwNDkzNyAxLjU1MjEwOCwwLjg5MDAyMDMgMC41Njk4MywwLjU0ODEyMjMgMC44NDY2MDUsMS4yNjQ0ODAwNiAwLjI3Njc3NCwwLjcxNjM1NzgxIDAuMjc2Nzc0LDEuNjIyNjU4OTQgMCwwLjkxNzE1NTEgLTAuMjc2Nzc0LDEuNjM4OTM5OSAtMC4yNzY3NzUsMC43MTYzNTc4IC0wLjg0NjYwNSwxLjI2NDQ4IC0wLjY1MTIzNCwwLjYyOTUyNjYgLTEuNTYyOTYyLDAuODk1NDQ3MyAtMC45MTE3MjgsMC4yNjA0OTM3IC0yLjczNTE4NSwwLjI2MDQ5MzcgaCAtMi4yMDMzNDMgeiBtIC04LjE0NTg1NjUsMCBoIDMuNDY3ODIzIHEgMS41NDY2ODE2LDAgMi4zNzE1Nzg1LDAuNjg5MjIzIDAuODMwMzI0LDAuNjgzNzk2MSAwLjgzMDMyNCwxLjk1MzcwMzE0IDAsMS4yNzUzMzM5NyAtMC44MzAzMjQsMS45NjQ1NTcwNiBRIDkuOTg3MTk2MSwyLjI3NDkxNSA4LjQ0MDUxNDUsMi4yNzQ5MTUgSCA3LjA2MjA2ODQgViA1LjA4NjA3NjcgSCA0Ljk3MjY5MTUgWiBtIDIuMDg5Mzc2OSwxLjUxNDExOTkgdiAyLjI2MzAzOTQzIGggMS4xNTU5NDEgcSAwLjYwNzgxODgsMCAwLjkzODg2MjksLTAuMjkzMDU1NDcgMC4zMzEwNDQxLC0wLjI5ODQ4MjQxIDAuMzMxMDQ0MSwtMC44NDExNzc3MiAwLC0wLjU0MjY5NTMxIC0wLjMzMTA0NDEsLTAuODM1NzUwNzQgLTAuMzMxMDQ0MSwtMC4yOTMwNTU1IC0wLjkzODg2MjksLTAuMjkzMDU1NSB6IgovPgo8L3N2Zz4K);--jp-icon-python: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iLTEwIC0xMCAxMzEuMTYxMzYxNjk0MzM1OTQgMTMyLjM4ODk5OTkzODk2NDg0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzA2OTk4IiBkPSJNIDU0LjkxODc4NSw5LjE5Mjc0MjFlLTQgQyA1MC4zMzUxMzIsMC4wMjIyMTcyNyA0NS45NTc4NDYsMC40MTMxMzY5NyA0Mi4xMDYyODUsMS4wOTQ2NjkzIDMwLjc2MDA2OSwzLjA5OTE3MzEgMjguNzAwMDM2LDcuMjk0NzcxNCAyOC43MDAwMzUsMTUuMDMyMTY5IHYgMTAuMjE4NzUgaCAyNi44MTI1IHYgMy40MDYyNSBoIC0yNi44MTI1IC0xMC4wNjI1IGMgLTcuNzkyNDU5LDAgLTE0LjYxNTc1ODgsNC42ODM3MTcgLTE2Ljc0OTk5OTgsMTMuNTkzNzUgLTIuNDYxODE5OTgsMTAuMjEyOTY2IC0yLjU3MTAxNTA4LDE2LjU4NjAyMyAwLDI3LjI1IDEuOTA1OTI4Myw3LjkzNzg1MiA2LjQ1NzU0MzIsMTMuNTkzNzQ4IDE0LjI0OTk5OTgsMTMuNTkzNzUgaCA5LjIxODc1IHYgLTEyLjI1IGMgMCwtOC44NDk5MDIgNy42NTcxNDQsLTE2LjY1NjI0OCAxNi43NSwtMTYuNjU2MjUgaCAyNi43ODEyNSBjIDcuNDU0OTUxLDAgMTMuNDA2MjUzLC02LjEzODE2NCAxMy40MDYyNSwtMTMuNjI1IHYgLTI1LjUzMTI1IGMgMCwtNy4yNjYzMzg2IC02LjEyOTk4LC0xMi43MjQ3NzcxIC0xMy40MDYyNSwtMTMuOTM3NDk5NyBDIDY0LjI4MTU0OCwwLjMyNzk0Mzk3IDU5LjUwMjQzOCwtMC4wMjAzNzkwMyA1NC45MTg3ODUsOS4xOTI3NDIxZS00IFogbSAtMTQuNSw4LjIxODc1MDEyNTc5IGMgMi43Njk1NDcsMCA1LjAzMTI1LDIuMjk4NjQ1NiA1LjAzMTI1LDUuMTI0OTk5NiAtMmUtNiwyLjgxNjMzNiAtMi4yNjE3MDMsNS4wOTM3NSAtNS4wMzEyNSw1LjA5Mzc1IC0yLjc3OTQ3NiwtMWUtNiAtNS4wMzEyNSwtMi4yNzc0MTUgLTUuMDMxMjUsLTUuMDkzNzUgLTEwZS03LC0yLjgyNjM1MyAyLjI1MTc3NCwtNS4xMjQ5OTk2IDUuMDMxMjUsLTUuMTI0OTk5NiB6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2ZmZDQzYiIgZD0ibSA4NS42Mzc1MzUsMjguNjU3MTY5IHYgMTEuOTA2MjUgYyAwLDkuMjMwNzU1IC03LjgyNTg5NSwxNi45OTk5OTkgLTE2Ljc1LDE3IGggLTI2Ljc4MTI1IGMgLTcuMzM1ODMzLDAgLTEzLjQwNjI0OSw2LjI3ODQ4MyAtMTMuNDA2MjUsMTMuNjI1IHYgMjUuNTMxMjQ3IGMgMCw3LjI2NjM0NCA2LjMxODU4OCwxMS41NDAzMjQgMTMuNDA2MjUsMTMuNjI1MDA0IDguNDg3MzMxLDIuNDk1NjEgMTYuNjI2MjM3LDIuOTQ2NjMgMjYuNzgxMjUsMCA2Ljc1MDE1NSwtMS45NTQzOSAxMy40MDYyNTMsLTUuODg3NjEgMTMuNDA2MjUsLTEzLjYyNTAwNCBWIDg2LjUwMDkxOSBoIC0yNi43ODEyNSB2IC0zLjQwNjI1IGggMjYuNzgxMjUgMTMuNDA2MjU0IGMgNy43OTI0NjEsMCAxMC42OTYyNTEsLTUuNDM1NDA4IDEzLjQwNjI0MSwtMTMuNTkzNzUgMi43OTkzMywtOC4zOTg4ODYgMi42ODAyMiwtMTYuNDc1Nzc2IDAsLTI3LjI1IC0xLjkyNTc4LC03Ljc1NzQ0MSAtNS42MDM4NywtMTMuNTkzNzUgLTEzLjQwNjI0MSwtMTMuNTkzNzUgeiBtIC0xNS4wNjI1LDY0LjY1NjI1IGMgMi43Nzk0NzgsM2UtNiA1LjAzMTI1LDIuMjc3NDE3IDUuMDMxMjUsNS4wOTM3NDcgLTJlLTYsMi44MjYzNTQgLTIuMjUxNzc1LDUuMTI1MDA0IC01LjAzMTI1LDUuMTI1MDA0IC0yLjc2OTU1LDAgLTUuMDMxMjUsLTIuMjk4NjUgLTUuMDMxMjUsLTUuMTI1MDA0IDJlLTYsLTIuODE2MzMgMi4yNjE2OTcsLTUuMDkzNzQ3IDUuMDMxMjUsLTUuMDkzNzQ3IHoiLz4KPC9zdmc+Cg==);--jp-icon-r-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjE5NkYzIiBkPSJNNC40IDIuNWMxLjItLjEgMi45LS4zIDQuOS0uMyAyLjUgMCA0LjEuNCA1LjIgMS4zIDEgLjcgMS41IDEuOSAxLjUgMy41IDAgMi0xLjQgMy41LTIuOSA0LjEgMS4yLjQgMS43IDEuNiAyLjIgMyAuNiAxLjkgMSAzLjkgMS4zIDQuNmgtMy44Yy0uMy0uNC0uOC0xLjctMS4yLTMuN3MtMS4yLTIuNi0yLjYtMi42aC0uOXY2LjRINC40VjIuNXptMy43IDYuOWgxLjRjMS45IDAgMi45LS45IDIuOS0yLjNzLTEtMi4zLTIuOC0yLjNjLS43IDAtMS4zIDAtMS42LjJ2NC41aC4xdi0uMXoiLz4KPC9zdmc+Cg==);--jp-icon-react: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMTUwIDE1MCA1NDEuOSAyOTUuMyI+CiAgPGcgY2xhc3M9ImpwLWljb24tYnJhbmQyIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxREFGQiI+CiAgICA8cGF0aCBkPSJNNjY2LjMgMjk2LjVjMC0zMi41LTQwLjctNjMuMy0xMDMuMS04Mi40IDE0LjQtNjMuNiA4LTExNC4yLTIwLjItMTMwLjQtNi41LTMuOC0xNC4xLTUuNi0yMi40LTUuNnYyMi4zYzQuNiAwIDguMy45IDExLjQgMi42IDEzLjYgNy44IDE5LjUgMzcuNSAxNC45IDc1LjctMS4xIDkuNC0yLjkgMTkuMy01LjEgMjkuNC0xOS42LTQuOC00MS04LjUtNjMuNS0xMC45LTEzLjUtMTguNS0yNy41LTM1LjMtNDEuNi01MCAzMi42LTMwLjMgNjMuMi00Ni45IDg0LTQ2LjlWNzhjLTI3LjUgMC02My41IDE5LjYtOTkuOSA1My42LTM2LjQtMzMuOC03Mi40LTUzLjItOTkuOS01My4ydjIyLjNjMjAuNyAwIDUxLjQgMTYuNSA4NCA0Ni42LTE0IDE0LjctMjggMzEuNC00MS4zIDQ5LjktMjIuNiAyLjQtNDQgNi4xLTYzLjYgMTEtMi4zLTEwLTQtMTkuNy01LjItMjktNC43LTM4LjIgMS4xLTY3LjkgMTQuNi03NS44IDMtMS44IDYuOS0yLjYgMTEuNS0yLjZWNzguNWMtOC40IDAtMTYgMS44LTIyLjYgNS42LTI4LjEgMTYuMi0zNC40IDY2LjctMTkuOSAxMzAuMS02Mi4yIDE5LjItMTAyLjcgNDkuOS0xMDIuNyA4Mi4zIDAgMzIuNSA0MC43IDYzLjMgMTAzLjEgODIuNC0xNC40IDYzLjYtOCAxMTQuMiAyMC4yIDEzMC40IDYuNSAzLjggMTQuMSA1LjYgMjIuNSA1LjYgMjcuNSAwIDYzLjUtMTkuNiA5OS45LTUzLjYgMzYuNCAzMy44IDcyLjQgNTMuMiA5OS45IDUzLjIgOC40IDAgMTYtMS44IDIyLjYtNS42IDI4LjEtMTYuMiAzNC40LTY2LjcgMTkuOS0xMzAuMSA2Mi0xOS4xIDEwMi41LTQ5LjkgMTAyLjUtODIuM3ptLTEzMC4yLTY2LjdjLTMuNyAxMi45LTguMyAyNi4yLTEzLjUgMzkuNS00LjEtOC04LjQtMTYtMTMuMS0yNC00LjYtOC05LjUtMTUuOC0xNC40LTIzLjQgMTQuMiAyLjEgMjcuOSA0LjcgNDEgNy45em0tNDUuOCAxMDYuNWMtNy44IDEzLjUtMTUuOCAyNi4zLTI0LjEgMzguMi0xNC45IDEuMy0zMCAyLTQ1LjIgMi0xNS4xIDAtMzAuMi0uNy00NS0xLjktOC4zLTExLjktMTYuNC0yNC42LTI0LjItMzgtNy42LTEzLjEtMTQuNS0yNi40LTIwLjgtMzkuOCA2LjItMTMuNCAxMy4yLTI2LjggMjAuNy0zOS45IDcuOC0xMy41IDE1LjgtMjYuMyAyNC4xLTM4LjIgMTQuOS0xLjMgMzAtMiA0NS4yLTIgMTUuMSAwIDMwLjIuNyA0NSAxLjkgOC4zIDExLjkgMTYuNCAyNC42IDI0LjIgMzggNy42IDEzLjEgMTQuNSAyNi40IDIwLjggMzkuOC02LjMgMTMuNC0xMy4yIDI2LjgtMjAuNyAzOS45em0zMi4zLTEzYzUuNCAxMy40IDEwIDI2LjggMTMuOCAzOS44LTEzLjEgMy4yLTI2LjkgNS45LTQxLjIgOCA0LjktNy43IDkuOC0xNS42IDE0LjQtMjMuNyA0LjYtOCA4LjktMTYuMSAxMy0yNC4xek00MjEuMiA0MzBjLTkuMy05LjYtMTguNi0yMC4zLTI3LjgtMzIgOSAuNCAxOC4yLjcgMjcuNS43IDkuNCAwIDE4LjctLjIgMjcuOC0uNy05IDExLjctMTguMyAyMi40LTI3LjUgMzJ6bS03NC40LTU4LjljLTE0LjItMi4xLTI3LjktNC43LTQxLTcuOSAzLjctMTIuOSA4LjMtMjYuMiAxMy41LTM5LjUgNC4xIDggOC40IDE2IDEzLjEgMjQgNC43IDggOS41IDE1LjggMTQuNCAyMy40ek00MjAuNyAxNjNjOS4zIDkuNiAxOC42IDIwLjMgMjcuOCAzMi05LS40LTE4LjItLjctMjcuNS0uNy05LjQgMC0xOC43LjItMjcuOC43IDktMTEuNyAxOC4zLTIyLjQgMjcuNS0zMnptLTc0IDU4LjljLTQuOSA3LjctOS44IDE1LjYtMTQuNCAyMy43LTQuNiA4LTguOSAxNi0xMyAyNC01LjQtMTMuNC0xMC0yNi44LTEzLjgtMzkuOCAxMy4xLTMuMSAyNi45LTUuOCA0MS4yLTcuOXptLTkwLjUgMTI1LjJjLTM1LjQtMTUuMS01OC4zLTM0LjktNTguMy01MC42IDAtMTUuNyAyMi45LTM1LjYgNTguMy01MC42IDguNi0zLjcgMTgtNyAyNy43LTEwLjEgNS43IDE5LjYgMTMuMiA0MCAyMi41IDYwLjktOS4yIDIwLjgtMTYuNiA0MS4xLTIyLjIgNjAuNi05LjktMy4xLTE5LjMtNi41LTI4LTEwLjJ6TTMxMCA0OTBjLTEzLjYtNy44LTE5LjUtMzcuNS0xNC45LTc1LjcgMS4xLTkuNCAyLjktMTkuMyA1LjEtMjkuNCAxOS42IDQuOCA0MSA4LjUgNjMuNSAxMC45IDEzLjUgMTguNSAyNy41IDM1LjMgNDEuNiA1MC0zMi42IDMwLjMtNjMuMiA0Ni45LTg0IDQ2LjktNC41LS4xLTguMy0xLTExLjMtMi43em0yMzcuMi03Ni4yYzQuNyAzOC4yLTEuMSA2Ny45LTE0LjYgNzUuOC0zIDEuOC02LjkgMi42LTExLjUgMi42LTIwLjcgMC01MS40LTE2LjUtODQtNDYuNiAxNC0xNC43IDI4LTMxLjQgNDEuMy00OS45IDIyLjYtMi40IDQ0LTYuMSA2My42LTExIDIuMyAxMC4xIDQuMSAxOS44IDUuMiAyOS4xem0zOC41LTY2LjdjLTguNiAzLjctMTggNy0yNy43IDEwLjEtNS43LTE5LjYtMTMuMi00MC0yMi41LTYwLjkgOS4yLTIwLjggMTYuNi00MS4xIDIyLjItNjAuNiA5LjkgMy4xIDE5LjMgNi41IDI4LjEgMTAuMiAzNS40IDE1LjEgNTguMyAzNC45IDU4LjMgNTAuNi0uMSAxNS43LTIzIDM1LjYtNTguNCA1MC42ek0zMjAuOCA3OC40eiIvPgogICAgPGNpcmNsZSBjeD0iNDIwLjkiIGN5PSIyOTYuNSIgcj0iNDUuNyIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-redo: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTE4LjQgMTAuNkMxNi41NSA4Ljk5IDE0LjE1IDggMTEuNSA4Yy00LjY1IDAtOC41OCAzLjAzLTkuOTYgNy4yMkwzLjkgMTZjMS4wNS0zLjE5IDQuMDUtNS41IDcuNi01LjUgMS45NSAwIDMuNzMuNzIgNS4xMiAxLjg4TDEzIDE2aDlWN2wtMy42IDMuNnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-refresh: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTkgMTMuNWMtMi40OSAwLTQuNS0yLjAxLTQuNS00LjVTNi41MSA0LjUgOSA0LjVjMS4yNCAwIDIuMzYuNTIgMy4xNyAxLjMzTDEwIDhoNVYzbC0xLjc2IDEuNzZDMTIuMTUgMy42OCAxMC42NiAzIDkgMyA1LjY5IDMgMy4wMSA1LjY5IDMuMDEgOVM1LjY5IDE1IDkgMTVjMi45NyAwIDUuNDMtMi4xNiA1LjktNWgtMS41MmMtLjQ2IDItMi4yNCAzLjUtNC4zOCAzLjV6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-regex: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi1hY2NlbnQyIiBmaWxsPSIjRkZGIj4KICAgIDxjaXJjbGUgY2xhc3M9InN0MiIgY3g9IjUuNSIgY3k9IjE0LjUiIHI9IjEuNSIvPgogICAgPHJlY3QgeD0iMTIiIHk9IjQiIGNsYXNzPSJzdDIiIHdpZHRoPSIxIiBoZWlnaHQ9IjgiLz4KICAgIDxyZWN0IHg9IjguNSIgeT0iNy41IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjg2NiAtMC41IDAuNSAwLjg2NiAtMi4zMjU1IDcuMzIxOSkiIGNsYXNzPSJzdDIiIHdpZHRoPSI4IiBoZWlnaHQ9IjEiLz4KICAgIDxyZWN0IHg9IjEyIiB5PSI0IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjUgLTAuODY2IDAuODY2IDAuNSAtMC42Nzc5IDE0LjgyNTIpIiBjbGFzcz0ic3QyIiB3aWR0aD0iMSIgaGVpZ2h0PSI4Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-run: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTggNXYxNGwxMS03eiIvPgogICAgPC9nPgo8L3N2Zz4K);--jp-icon-running: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMjU2IDhDMTE5IDggOCAxMTkgOCAyNTZzMTExIDI0OCAyNDggMjQ4IDI0OC0xMTEgMjQ4LTI0OFMzOTMgOCAyNTYgOHptOTYgMzI4YzAgOC44LTcuMiAxNi0xNiAxNkgxNzZjLTguOCAwLTE2LTcuMi0xNi0xNlYxNzZjMC04LjggNy4yLTE2IDE2LTE2aDE2MGM4LjggMCAxNiA3LjIgMTYgMTZ2MTYweiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-save: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE3IDNINWMtMS4xMSAwLTIgLjktMiAydjE0YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjdsLTQtNHptLTUgMTZjLTEuNjYgMC0zLTEuMzQtMy0zczEuMzQtMyAzLTMgMyAxLjM0IDMgMy0xLjM0IDMtMyAzem0zLTEwSDVWNWgxMHY0eiIvPgogICAgPC9nPgo8L3N2Zz4K);--jp-icon-search: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjEsMTAuOWgtMC43bC0wLjItMC4yYzAuOC0wLjksMS4zLTIuMiwxLjMtMy41YzAtMy0yLjQtNS40LTUuNC01LjRTMS44LDQuMiwxLjgsNy4xczIuNCw1LjQsNS40LDUuNCBjMS4zLDAsMi41LTAuNSwzLjUtMS4zbDAuMiwwLjJ2MC43bDQuMSw0LjFsMS4yLTEuMkwxMi4xLDEwLjl6IE03LjEsMTAuOWMtMi4xLDAtMy43LTEuNy0zLjctMy43czEuNy0zLjcsMy43LTMuN3MzLjcsMS43LDMuNywzLjcgUzkuMiwxMC45LDcuMSwxMC45eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-settings: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuNDMgMTIuOThjLjA0LS4zMi4wNy0uNjQuMDctLjk4cy0uMDMtLjY2LS4wNy0uOThsMi4xMS0xLjY1Yy4xOS0uMTUuMjQtLjQyLjEyLS42NGwtMi0zLjQ2Yy0uMTItLjIyLS4zOS0uMy0uNjEtLjIybC0yLjQ5IDFjLS41Mi0uNC0xLjA4LS43My0xLjY5LS45OGwtLjM4LTIuNjVBLjQ4OC40ODggMCAwMDE0IDJoLTRjLS4yNSAwLS40Ni4xOC0uNDkuNDJsLS4zOCAyLjY1Yy0uNjEuMjUtMS4xNy41OS0xLjY5Ljk4bC0yLjQ5LTFjLS4yMy0uMDktLjQ5IDAtLjYxLjIybC0yIDMuNDZjLS4xMy4yMi0uMDcuNDkuMTIuNjRsMi4xMSAxLjY1Yy0uMDQuMzItLjA3LjY1LS4wNy45OHMuMDMuNjYuMDcuOThsLTIuMTEgMS42NWMtLjE5LjE1LS4yNC40Mi0uMTIuNjRsMiAzLjQ2Yy4xMi4yMi4zOS4zLjYxLjIybDIuNDktMWMuNTIuNCAxLjA4LjczIDEuNjkuOThsLjM4IDIuNjVjLjAzLjI0LjI0LjQyLjQ5LjQyaDRjLjI1IDAgLjQ2LS4xOC40OS0uNDJsLjM4LTIuNjVjLjYxLS4yNSAxLjE3LS41OSAxLjY5LS45OGwyLjQ5IDFjLjIzLjA5LjQ5IDAgLjYxLS4yMmwyLTMuNDZjLjEyLS4yMi4wNy0uNDktLjEyLS42NGwtMi4xMS0xLjY1ek0xMiAxNS41Yy0xLjkzIDAtMy41LTEuNTctMy41LTMuNXMxLjU3LTMuNSAzLjUtMy41IDMuNSAxLjU3IDMuNSAzLjUtMS41NyAzLjUtMy41IDMuNXoiLz4KPC9zdmc+Cg==);--jp-icon-share: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTSAxOCAyIEMgMTYuMzU0OTkgMiAxNSAzLjM1NDk5MDQgMTUgNSBDIDE1IDUuMTkwOTUyOSAxNS4wMjE3OTEgNS4zNzcxMjI0IDE1LjA1NjY0MSA1LjU1ODU5MzggTCA3LjkyMTg3NSA5LjcyMDcwMzEgQyA3LjM5ODUzOTkgOS4yNzc4NTM5IDYuNzMyMDc3MSA5IDYgOSBDIDQuMzU0OTkwNCA5IDMgMTAuMzU0OTkgMyAxMiBDIDMgMTMuNjQ1MDEgNC4zNTQ5OTA0IDE1IDYgMTUgQyA2LjczMjA3NzEgMTUgNy4zOTg1Mzk5IDE0LjcyMjE0NiA3LjkyMTg3NSAxNC4yNzkyOTcgTCAxNS4wNTY2NDEgMTguNDM5NDUzIEMgMTUuMDIxNTU1IDE4LjYyMTUxNCAxNSAxOC44MDgzODYgMTUgMTkgQyAxNSAyMC42NDUwMSAxNi4zNTQ5OSAyMiAxOCAyMiBDIDE5LjY0NTAxIDIyIDIxIDIwLjY0NTAxIDIxIDE5IEMgMjEgMTcuMzU0OTkgMTkuNjQ1MDEgMTYgMTggMTYgQyAxNy4yNjc0OCAxNiAxNi42MDE1OTMgMTYuMjc5MzI4IDE2LjA3ODEyNSAxNi43MjI2NTYgTCA4Ljk0MzM1OTQgMTIuNTU4NTk0IEMgOC45NzgyMDk1IDEyLjM3NzEyMiA5IDEyLjE5MDk1MyA5IDEyIEMgOSAxMS44MDkwNDcgOC45NzgyMDk1IDExLjYyMjg3OCA4Ljk0MzM1OTQgMTEuNDQxNDA2IEwgMTYuMDc4MTI1IDcuMjc5Mjk2OSBDIDE2LjYwMTQ2IDcuNzIyMTQ2MSAxNy4yNjc5MjMgOCAxOCA4IEMgMTkuNjQ1MDEgOCAyMSA2LjY0NTAwOTYgMjEgNSBDIDIxIDMuMzU0OTkwNCAxOS42NDUwMSAyIDE4IDIgeiBNIDE4IDQgQyAxOC41NjQxMjkgNCAxOSA0LjQzNTg3MDYgMTkgNSBDIDE5IDUuNTY0MTI5NCAxOC41NjQxMjkgNiAxOCA2IEMgMTcuNDM1ODcxIDYgMTcgNS41NjQxMjk0IDE3IDUgQyAxNyA0LjQzNTg3MDYgMTcuNDM1ODcxIDQgMTggNCB6IE0gNiAxMSBDIDYuNTY0MTI5NCAxMSA3IDExLjQzNTg3MSA3IDEyIEMgNyAxMi41NjQxMjkgNi41NjQxMjk0IDEzIDYgMTMgQyA1LjQzNTg3MDYgMTMgNSAxMi41NjQxMjkgNSAxMiBDIDUgMTEuNDM1ODcxIDUuNDM1ODcwNiAxMSA2IDExIHogTSAxOCAxOCBDIDE4LjU2NDEyOSAxOCAxOSAxOC40MzU4NzEgMTkgMTkgQyAxOSAxOS41NjQxMjkgMTguNTY0MTI5IDIwIDE4IDIwIEMgMTcuNDM1ODcxIDIwIDE3IDE5LjU2NDEyOSAxNyAxOSBDIDE3IDE4LjQzNTg3MSAxNy40MzU4NzEgMTggMTggMTggeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-spreadsheet: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNENBRjUwIiBkPSJNMi4yIDIuMnYxNy42aDE3LjZWMi4ySDIuMnptMTUuNCA3LjdoLTUuNVY0LjRoNS41djUuNXpNOS45IDQuNHY1LjVINC40VjQuNGg1LjV6bS01LjUgNy43aDUuNXY1LjVINC40di01LjV6bTcuNyA1LjV2LTUuNWg1LjV2NS41aC01LjV6Ii8+Cjwvc3ZnPgo=);--jp-icon-stop: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik02IDZoMTJ2MTJINnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);--jp-icon-tab: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIxIDNIM2MtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxOGMxLjEgMCAyLS45IDItMlY1YzAtMS4xLS45LTItMi0yem0wIDE2SDNWNWgxMHY0aDh2MTB6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-table-rows: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMSw4SDNWNGgxOFY4eiBNMjEsMTBIM3Y0aDE4VjEweiBNMjEsMTZIM3Y0aDE4VjE2eiIvPgogICAgPC9nPgo8L3N2Zz4=);--jp-icon-tag: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCA0MyAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTI4LjgzMzIgMTIuMzM0TDMyLjk5OTggMTYuNTAwN0wzNy4xNjY1IDEyLjMzNEgyOC44MzMyWiIvPgoJCTxwYXRoIGQ9Ik0xNi4yMDk1IDIxLjYxMDRDMTUuNjg3MyAyMi4xMjk5IDE0Ljg0NDMgMjIuMTI5OSAxNC4zMjQ4IDIxLjYxMDRMNi45ODI5IDE0LjcyNDVDNi41NzI0IDE0LjMzOTQgNi4wODMxMyAxMy42MDk4IDYuMDQ3ODYgMTMuMDQ4MkM1Ljk1MzQ3IDExLjUyODggNi4wMjAwMiA4LjYxOTQ0IDYuMDY2MjEgNy4wNzY5NUM2LjA4MjgxIDYuNTE0NzcgNi41NTU0OCA2LjA0MzQ3IDcuMTE4MDQgNi4wMzA1NUM5LjA4ODYzIDUuOTg0NzMgMTMuMjYzOCA1LjkzNTc5IDEzLjY1MTggNi4zMjQyNUwyMS43MzY5IDEzLjYzOUMyMi4yNTYgMTQuMTU4NSAyMS43ODUxIDE1LjQ3MjQgMjEuMjYyIDE1Ljk5NDZMMTYuMjA5NSAyMS42MTA0Wk05Ljc3NTg1IDguMjY1QzkuMzM1NTEgNy44MjU2NiA4LjYyMzUxIDcuODI1NjYgOC4xODI4IDguMjY1QzcuNzQzNDYgOC43MDU3MSA3Ljc0MzQ2IDkuNDE3MzMgOC4xODI4IDkuODU2NjdDOC42MjM4MiAxMC4yOTY0IDkuMzM1ODIgMTAuMjk2NCA5Ljc3NTg1IDkuODU2NjdDMTAuMjE1NiA5LjQxNzMzIDEwLjIxNTYgOC43MDUzMyA5Ljc3NTg1IDguMjY1WiIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-terminal: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiA+CiAgICA8cmVjdCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1iYWNrZ3JvdW5kLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyIDIpIiBmaWxsPSIjMzMzMzMzIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUtaW52ZXJzZSIgZD0iTTUuMDU2NjQgOC43NjE3MkM1LjA1NjY0IDguNTk3NjYgNS4wMzEyNSA4LjQ1MzEyIDQuOTgwNDcgOC4zMjgxMkM0LjkzMzU5IDguMTk5MjIgNC44NTU0NyA4LjA4MjAzIDQuNzQ2MDkgNy45NzY1NkM0LjY0MDYyIDcuODcxMDkgNC41IDcuNzc1MzkgNC4zMjQyMiA3LjY4OTQ1QzQuMTUyMzQgNy41OTk2MSAzLjk0MzM2IDcuNTExNzIgMy42OTcyNyA3LjQyNTc4QzMuMzAyNzMgNy4yODUxNiAyLjk0MzM2IDcuMTM2NzIgMi42MTkxNCA2Ljk4MDQ3QzIuMjk0OTIgNi44MjQyMiAyLjAxNzU4IDYuNjQyNTggMS43ODcxMSA2LjQzNTU1QzEuNTYwNTUgNi4yMjg1MiAxLjM4NDc3IDUuOTg4MjggMS4yNTk3NyA1LjcxNDg0QzEuMTM0NzcgNS40Mzc1IDEuMDcyMjcgNS4xMDkzOCAxLjA3MjI3IDQuNzMwNDdDMS4wNzIyNyA0LjM5ODQ0IDEuMTI4OTEgNC4wOTU3IDEuMjQyMTkgMy44MjIyN0MxLjM1NTQ3IDMuNTQ0OTIgMS41MTU2MiAzLjMwNDY5IDEuNzIyNjYgMy4xMDE1NkMxLjkyOTY5IDIuODk4NDQgMi4xNzk2OSAyLjczNDM3IDIuNDcyNjYgMi42MDkzOEMyLjc2NTYyIDIuNDg0MzggMy4wOTE4IDIuNDA0MyAzLjQ1MTE3IDIuMzY5MTRWMS4xMDkzOEg0LjM4ODY3VjIuMzgwODZDNC43NDAyMyAyLjQyNzczIDUuMDU2NjQgMi41MjM0NCA1LjMzNzg5IDIuNjY3OTdDNS42MTkxNCAyLjgxMjUgNS44NTc0MiAzLjAwMTk1IDYuMDUyNzMgMy4yMzYzM0M2LjI1MTk1IDMuNDY2OCA2LjQwNDMgMy43NDAyMyA2LjUwOTc3IDQuMDU2NjRDNi42MTkxNCA0LjM2OTE0IDYuNjczODMgNC43MjA3IDYuNjczODMgNS4xMTEzM0g1LjA0NDkyQzUuMDQ0OTIgNC42Mzg2NyA0LjkzNzUgNC4yODEyNSA0LjcyMjY2IDQuMDM5MDZDNC41MDc4MSAzLjc5Mjk3IDQuMjE2OCAzLjY2OTkyIDMuODQ5NjEgMy42Njk5MkMzLjY1MDM5IDMuNjY5OTIgMy40NzY1NiAzLjY5NzI3IDMuMzI4MTIgMy43NTE5NUMzLjE4MzU5IDMuODAyNzMgMy4wNjQ0NSAzLjg3Njk1IDIuOTcwNyAzLjk3NDYxQzIuODc2OTUgNC4wNjgzNiAyLjgwNjY0IDQuMTc5NjkgMi43NTk3NyA0LjMwODU5QzIuNzE2OCA0LjQzNzUgMi42OTUzMSA0LjU3ODEyIDIuNjk1MzEgNC43MzA0N0MyLjY5NTMxIDQuODgyODEgMi43MTY4IDUuMDE5NTMgMi43NTk3NyA1LjE0MDYyQzIuODA2NjQgNS4yNTc4MSAyLjg4MjgxIDUuMzY3MTkgMi45ODgyOCA1LjQ2ODc1QzMuMDk3NjYgNS41NzAzMSAzLjI0MDIzIDUuNjY3OTcgMy40MTYwMiA1Ljc2MTcyQzMuNTkxOCA1Ljg1MTU2IDMuODEwNTUgNS45NDMzNiA0LjA3MjI3IDYuMDM3MTFDNC40NjY4IDYuMTg1NTUgNC44MjQyMiA2LjMzOTg0IDUuMTQ0NTMgNi41QzUuNDY0ODQgNi42NTYyNSA1LjczODI4IDYuODM5ODQgNS45NjQ4NCA3LjA1MDc4QzYuMTk1MzEgNy4yNTc4MSA2LjM3MTA5IDcuNSA2LjQ5MjE5IDcuNzc3MzRDNi42MTcxOSA4LjA1MDc4IDYuNjc5NjkgOC4zNzUgNi42Nzk2OSA4Ljc1QzYuNjc5NjkgOS4wOTM3NSA2LjYyMzA1IDkuNDA0MyA2LjUwOTc3IDkuNjgxNjRDNi4zOTY0OCA5Ljk1NTA4IDYuMjM0MzggMTAuMTkxNCA2LjAyMzQ0IDEwLjM5MDZDNS44MTI1IDEwLjU4OTggNS41NTg1OSAxMC43NSA1LjI2MTcyIDEwLjg3MTFDNC45NjQ4NCAxMC45ODgzIDQuNjMyODEgMTEuMDY0NSA0LjI2NTYyIDExLjA5OTZWMTIuMjQ4SDMuMzMzOThWMTEuMDk5NkMzLjAwMTk1IDExLjA2ODQgMi42Nzk2OSAxMC45OTYxIDIuMzY3MTkgMTAuODgyOEMyLjA1NDY5IDEwLjc2NTYgMS43NzczNCAxMC41OTc3IDEuNTM1MTYgMTAuMzc4OUMxLjI5Njg4IDEwLjE2MDIgMS4xMDU0NyA5Ljg4NDc3IDAuOTYwOTM4IDkuNTUyNzNDMC44MTY0MDYgOS4yMTY4IDAuNzQ0MTQxIDguODE0NDUgMC43NDQxNDEgOC4zNDU3SDIuMzc4OTFDMi4zNzg5MSA4LjYyNjk1IDIuNDE5OTIgOC44NjMyOCAyLjUwMTk1IDkuMDU0NjlDMi41ODM5OCA5LjI0MjE5IDIuNjg5NDUgOS4zOTI1OCAyLjgxODM2IDkuNTA1ODZDMi45NTExNyA5LjYxNTIzIDMuMTAxNTYgOS42OTMzNiAzLjI2OTUzIDkuNzQwMjNDMy40Mzc1IDkuNzg3MTEgMy42MDkzOCA5LjgxMDU1IDMuNzg1MTYgOS44MTA1NUM0LjIwMzEyIDkuODEwNTUgNC41MTk1MyA5LjcxMjg5IDQuNzM0MzggOS41MTc1OEM0Ljk0OTIyIDkuMzIyMjcgNS4wNTY2NCA5LjA3MDMxIDUuMDU2NjQgOC43NjE3MlpNMTMuNDE4IDEyLjI3MTVIOC4wNzQyMlYxMUgxMy40MThWMTIuMjcxNVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMuOTUyNjQgNikiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=);--jp-icon-text-editor: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtdGV4dC1lZGl0b3ItaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xNSAxNUgzdjJoMTJ2LTJ6bTAtOEgzdjJoMTJWN3pNMyAxM2gxOHYtMkgzdjJ6bTAgOGgxOHYtMkgzdjJ6TTMgM3YyaDE4VjNIM3oiLz4KPC9zdmc+Cg==);--jp-icon-toc: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik03LDVIMjFWN0g3VjVNNywxM1YxMUgyMVYxM0g3TTQsNC41QTEuNSwxLjUgMCAwLDEgNS41LDZBMS41LDEuNSAwIDAsMSA0LDcuNUExLjUsMS41IDAgMCwxIDIuNSw2QTEuNSwxLjUgMCAwLDEgNCw0LjVNNCwxMC41QTEuNSwxLjUgMCAwLDEgNS41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMy41QTEuNSwxLjUgMCAwLDEgMi41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMC41TTcsMTlWMTdIMjFWMTlIN000LDE2LjVBMS41LDEuNSAwIDAsMSA1LjUsMThBMS41LDEuNSAwIDAsMSA0LDE5LjVBMS41LDEuNSAwIDAsMSAyLjUsMThBMS41LDEuNSAwIDAsMSA0LDE2LjVaIiAvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-tree-view: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMiAxMVYzaC03djNIOVYzSDJ2OGg3VjhoMnYxMGg0djNoN3YtOGgtN3YzaC0yVjhoMnYzeiIvPgogICAgPC9nPgo8L3N2Zz4=);--jp-icon-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMiAxNy4xODQ0IDIuOTY5NjggMTQuMzAzMiAxLjg2MDk0IDExLjQ0MDlaIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiMzMzMzMzMiIHN0cm9rZT0iIzMzMzMzMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOCA5Ljg2NzE5KSIgZD0iTTIuODYwMTUgNC44NjUzNUwwLjcyNjU0OSAyLjk5OTU5TDAgMy42MzA0NUwyLjg2MDE1IDYuMTMxNTdMOCAwLjYzMDg3Mkw3LjI3ODU3IDBMMi44NjAxNSA0Ljg2NTM1WiIvPgo8L3N2Zz4K);--jp-icon-undo: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjUgOGMtMi42NSAwLTUuMDUuOTktNi45IDIuNkwyIDd2OWg5bC0zLjYyLTMuNjJjMS4zOS0xLjE2IDMuMTYtMS44OCA1LjEyLTEuODggMy41NCAwIDYuNTUgMi4zMSA3LjYgNS41bDIuMzctLjc4QzIxLjA4IDExLjAzIDE3LjE1IDggMTIuNSA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-user: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE2IDdhNCA0IDAgMTEtOCAwIDQgNCAwIDAxOCAwek0xMiAxNGE3IDcgMCAwMC03IDdoMTRhNyA3IDAgMDAtNy03eiIvPgogIDwvZz4KPC9zdmc+);--jp-icon-users: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDM2IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogPGcgY2xhc3M9ImpwLWljb24zIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjczMjcgMCAwIDEuNzMyNyAtMy42MjgyIC4wOTk1NzcpIiBmaWxsPSIjNjE2MTYxIj4KICA8cGF0aCB0cmFuc2Zvcm09Im1hdHJpeCgxLjUsMCwwLDEuNSwwLC02KSIgZD0ibTEyLjE4NiA3LjUwOThjLTEuMDUzNSAwLTEuOTc1NyAwLjU2NjUtMi40Nzg1IDEuNDEwMiAwLjc1MDYxIDAuMzEyNzcgMS4zOTc0IDAuODI2NDggMS44NzMgMS40NzI3aDMuNDg2M2MwLTEuNTkyLTEuMjg4OS0yLjg4MjgtMi44ODA5LTIuODgyOHoiLz4KICA8cGF0aCBkPSJtMjAuNDY1IDIuMzg5NWEyLjE4ODUgMi4xODg1IDAgMCAxLTIuMTg4NCAyLjE4ODUgMi4xODg1IDIuMTg4NSAwIDAgMS0yLjE4ODUtMi4xODg1IDIuMTg4NSAyLjE4ODUgMCAwIDEgMi4xODg1LTIuMTg4NSAyLjE4ODUgMi4xODg1IDAgMCAxIDIuMTg4NCAyLjE4ODV6Ii8+CiAgPHBhdGggdHJhbnNmb3JtPSJtYXRyaXgoMS41LDAsMCwxLjUsMCwtNikiIGQ9Im0zLjU4OTggOC40MjE5Yy0xLjExMjYgMC0yLjAxMzcgMC45MDExMS0yLjAxMzcgMi4wMTM3aDIuODE0NWMwLjI2Nzk3LTAuMzczMDkgMC41OTA3LTAuNzA0MzUgMC45NTg5OC0wLjk3ODUyLTAuMzQ0MzMtMC42MTY4OC0xLjAwMzEtMS4wMzUyLTEuNzU5OC0xLjAzNTJ6Ii8+CiAgPHBhdGggZD0ibTYuOTE1NCA0LjYyM2ExLjUyOTQgMS41Mjk0IDAgMCAxLTEuNTI5NCAxLjUyOTQgMS41Mjk0IDEuNTI5NCAwIDAgMS0xLjUyOTQtMS41Mjk0IDEuNTI5NCAxLjUyOTQgMCAwIDEgMS41Mjk0LTEuNTI5NCAxLjUyOTQgMS41Mjk0IDAgMCAxIDEuNTI5NCAxLjUyOTR6Ii8+CiAgPHBhdGggZD0ibTYuMTM1IDEzLjUzNWMwLTMuMjM5MiAyLjYyNTktNS44NjUgNS44NjUtNS44NjUgMy4yMzkyIDAgNS44NjUgMi42MjU5IDUuODY1IDUuODY1eiIvPgogIDxjaXJjbGUgY3g9IjEyIiBjeT0iMy43Njg1IiByPSIyLjk2ODUiLz4KIDwvZz4KPC9zdmc+Cg==);--jp-icon-vega: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbjEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjEyMTIxIj4KICAgIDxwYXRoIGQ9Ik0xMC42IDUuNGwyLjItMy4ySDIuMnY3LjNsNC02LjZ6Ii8+CiAgICA8cGF0aCBkPSJNMTUuOCAyLjJsLTQuNCA2LjZMNyA2LjNsLTQuOCA4djUuNWgxNy42VjIuMmgtNHptLTcgMTUuNEg1LjV2LTQuNGgzLjN2NC40em00LjQgMEg5LjhWOS44aDMuNHY3Ljh6bTQuNCAwaC0zLjRWNi41aDMuNHYxMS4xeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-yaml: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1jb250cmFzdDIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjRDgxQjYwIj4KICAgIDxwYXRoIGQ9Ik03LjIgMTguNnYtNS40TDMgNS42aDMuM2wxLjQgMy4xYy4zLjkuNiAxLjYgMSAyLjUuMy0uOC42LTEuNiAxLTIuNWwxLjQtMy4xaDMuNGwtNC40IDcuNnY1LjVsLTIuOS0uMXoiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxNi41IiByPSIyLjEiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxMSIgcj0iMi4xIi8+CiAgPC9nPgo8L3N2Zz4K)}.jupyter-wrapper .jp-AddAboveIcon{background-image:var(--jp-icon-add-above)}.jupyter-wrapper .jp-AddBelowIcon{background-image:var(--jp-icon-add-below)}.jupyter-wrapper .jp-AddIcon{background-image:var(--jp-icon-add)}.jupyter-wrapper .jp-BellIcon{background-image:var(--jp-icon-bell)}.jupyter-wrapper .jp-BugDotIcon{background-image:var(--jp-icon-bug-dot)}.jupyter-wrapper .jp-BugIcon{background-image:var(--jp-icon-bug)}.jupyter-wrapper .jp-BuildIcon{background-image:var(--jp-icon-build)}.jupyter-wrapper .jp-CaretDownEmptyIcon{background-image:var(--jp-icon-caret-down-empty)}.jupyter-wrapper .jp-CaretDownEmptyThinIcon{background-image:var(--jp-icon-caret-down-empty-thin)}.jupyter-wrapper .jp-CaretDownIcon{background-image:var(--jp-icon-caret-down)}.jupyter-wrapper .jp-CaretLeftIcon{background-image:var(--jp-icon-caret-left)}.jupyter-wrapper .jp-CaretRightIcon{background-image:var(--jp-icon-caret-right)}.jupyter-wrapper .jp-CaretUpEmptyThinIcon{background-image:var(--jp-icon-caret-up-empty-thin)}.jupyter-wrapper .jp-CaretUpIcon{background-image:var(--jp-icon-caret-up)}.jupyter-wrapper .jp-CaseSensitiveIcon{background-image:var(--jp-icon-case-sensitive)}.jupyter-wrapper .jp-CheckIcon{background-image:var(--jp-icon-check)}.jupyter-wrapper .jp-CircleEmptyIcon{background-image:var(--jp-icon-circle-empty)}.jupyter-wrapper .jp-CircleIcon{background-image:var(--jp-icon-circle)}.jupyter-wrapper .jp-ClearIcon{background-image:var(--jp-icon-clear)}.jupyter-wrapper .jp-CloseIcon{background-image:var(--jp-icon-close)}.jupyter-wrapper .jp-CodeIcon{background-image:var(--jp-icon-code)}.jupyter-wrapper .jp-ConsoleIcon{background-image:var(--jp-icon-console)}.jupyter-wrapper .jp-CopyIcon{background-image:var(--jp-icon-copy)}.jupyter-wrapper .jp-CopyrightIcon{background-image:var(--jp-icon-copyright)}.jupyter-wrapper .jp-CutIcon{background-image:var(--jp-icon-cut)}.jupyter-wrapper .jp-DeleteIcon{background-image:var(--jp-icon-delete)}.jupyter-wrapper .jp-DownloadIcon{background-image:var(--jp-icon-download)}.jupyter-wrapper .jp-DuplicateIcon{background-image:var(--jp-icon-duplicate)}.jupyter-wrapper .jp-EditIcon{background-image:var(--jp-icon-edit)}.jupyter-wrapper .jp-EllipsesIcon{background-image:var(--jp-icon-ellipses)}.jupyter-wrapper .jp-ExtensionIcon{background-image:var(--jp-icon-extension)}.jupyter-wrapper .jp-FastForwardIcon{background-image:var(--jp-icon-fast-forward)}.jupyter-wrapper .jp-FileIcon{background-image:var(--jp-icon-file)}.jupyter-wrapper .jp-FileUploadIcon{background-image:var(--jp-icon-file-upload)}.jupyter-wrapper .jp-FilterListIcon{background-image:var(--jp-icon-filter-list)}.jupyter-wrapper .jp-FolderFavoriteIcon{background-image:var(--jp-icon-folder-favorite)}.jupyter-wrapper .jp-FolderIcon{background-image:var(--jp-icon-folder)}.jupyter-wrapper .jp-HomeIcon{background-image:var(--jp-icon-home)}.jupyter-wrapper .jp-Html5Icon{background-image:var(--jp-icon-html5)}.jupyter-wrapper .jp-ImageIcon{background-image:var(--jp-icon-image)}.jupyter-wrapper .jp-InspectorIcon{background-image:var(--jp-icon-inspector)}.jupyter-wrapper .jp-JsonIcon{background-image:var(--jp-icon-json)}.jupyter-wrapper .jp-JuliaIcon{background-image:var(--jp-icon-julia)}.jupyter-wrapper .jp-JupyterFaviconIcon{background-image:var(--jp-icon-jupyter-favicon)}.jupyter-wrapper .jp-JupyterIcon{background-image:var(--jp-icon-jupyter)}.jupyter-wrapper .jp-JupyterlabWordmarkIcon{background-image:var(--jp-icon-jupyterlab-wordmark)}.jupyter-wrapper .jp-KernelIcon{background-image:var(--jp-icon-kernel)}.jupyter-wrapper .jp-KeyboardIcon{background-image:var(--jp-icon-keyboard)}.jupyter-wrapper .jp-LaunchIcon{background-image:var(--jp-icon-launch)}.jupyter-wrapper .jp-LauncherIcon{background-image:var(--jp-icon-launcher)}.jupyter-wrapper .jp-LineFormIcon{background-image:var(--jp-icon-line-form)}.jupyter-wrapper .jp-LinkIcon{background-image:var(--jp-icon-link)}.jupyter-wrapper .jp-ListIcon{background-image:var(--jp-icon-list)}.jupyter-wrapper .jp-ListingsInfoIcon{background-image:var(--jp-icon-listings-info)}.jupyter-wrapper .jp-MarkdownIcon{background-image:var(--jp-icon-markdown)}.jupyter-wrapper .jp-MoveDownIcon{background-image:var(--jp-icon-move-down)}.jupyter-wrapper .jp-MoveUpIcon{background-image:var(--jp-icon-move-up)}.jupyter-wrapper .jp-NewFolderIcon{background-image:var(--jp-icon-new-folder)}.jupyter-wrapper .jp-NotTrustedIcon{background-image:var(--jp-icon-not-trusted)}.jupyter-wrapper .jp-NotebookIcon{background-image:var(--jp-icon-notebook)}.jupyter-wrapper .jp-NumberingIcon{background-image:var(--jp-icon-numbering)}.jupyter-wrapper .jp-OfflineBoltIcon{background-image:var(--jp-icon-offline-bolt)}.jupyter-wrapper .jp-PaletteIcon{background-image:var(--jp-icon-palette)}.jupyter-wrapper .jp-PasteIcon{background-image:var(--jp-icon-paste)}.jupyter-wrapper .jp-PdfIcon{background-image:var(--jp-icon-pdf)}.jupyter-wrapper .jp-PythonIcon{background-image:var(--jp-icon-python)}.jupyter-wrapper .jp-RKernelIcon{background-image:var(--jp-icon-r-kernel)}.jupyter-wrapper .jp-ReactIcon{background-image:var(--jp-icon-react)}.jupyter-wrapper .jp-RedoIcon{background-image:var(--jp-icon-redo)}.jupyter-wrapper .jp-RefreshIcon{background-image:var(--jp-icon-refresh)}.jupyter-wrapper .jp-RegexIcon{background-image:var(--jp-icon-regex)}.jupyter-wrapper .jp-RunIcon{background-image:var(--jp-icon-run)}.jupyter-wrapper .jp-RunningIcon{background-image:var(--jp-icon-running)}.jupyter-wrapper .jp-SaveIcon{background-image:var(--jp-icon-save)}.jupyter-wrapper .jp-SearchIcon{background-image:var(--jp-icon-search)}.jupyter-wrapper .jp-SettingsIcon{background-image:var(--jp-icon-settings)}.jupyter-wrapper .jp-ShareIcon{background-image:var(--jp-icon-share)}.jupyter-wrapper .jp-SpreadsheetIcon{background-image:var(--jp-icon-spreadsheet)}.jupyter-wrapper .jp-StopIcon{background-image:var(--jp-icon-stop)}.jupyter-wrapper .jp-TabIcon{background-image:var(--jp-icon-tab)}.jupyter-wrapper .jp-TableRowsIcon{background-image:var(--jp-icon-table-rows)}.jupyter-wrapper .jp-TagIcon{background-image:var(--jp-icon-tag)}.jupyter-wrapper .jp-TerminalIcon{background-image:var(--jp-icon-terminal)}.jupyter-wrapper .jp-TextEditorIcon{background-image:var(--jp-icon-text-editor)}.jupyter-wrapper .jp-TocIcon{background-image:var(--jp-icon-toc)}.jupyter-wrapper .jp-TreeViewIcon{background-image:var(--jp-icon-tree-view)}.jupyter-wrapper .jp-TrustedIcon{background-image:var(--jp-icon-trusted)}.jupyter-wrapper .jp-UndoIcon{background-image:var(--jp-icon-undo)}.jupyter-wrapper .jp-UserIcon{background-image:var(--jp-icon-user)}.jupyter-wrapper .jp-UsersIcon{background-image:var(--jp-icon-users)}.jupyter-wrapper .jp-VegaIcon{background-image:var(--jp-icon-vega)}.jupyter-wrapper .jp-YamlIcon{background-image:var(--jp-icon-yaml)}.jupyter-wrapper .jp-Icon,.jupyter-wrapper .jp-MaterialIcon{background-position:center;background-repeat:no-repeat;background-size:16px;min-width:16px;min-height:16px}.jupyter-wrapper .jp-Icon-cover{background-position:center;background-repeat:no-repeat;background-size:cover}.jupyter-wrapper .jp-Icon-16{background-size:16px;min-width:16px;min-height:16px}.jupyter-wrapper .jp-Icon-18{background-size:18px;min-width:18px;min-height:18px}.jupyter-wrapper .jp-Icon-20{background-size:20px;min-width:20px;min-height:20px}.jupyter-wrapper .lm-TabBar .lm-TabBar-addButton{align-items:center;display:flex;padding:4px 4px 5px;margin-right:1px;background-color:var(--jp-layout-color2)}.jupyter-wrapper .lm-TabBar .lm-TabBar-addButton:hover{background-color:var(--jp-layout-color1)}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab{width:var(--jp-private-horizontal-tab-width)}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-content{flex:unset}.jupyter-wrapper .lm-DockPanel-tabBar[data-orientation=horizontal]{flex:1 1 auto}.jupyter-wrapper .jp-icon0[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon1[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon2[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon3[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon4[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon0[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon1[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon2[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon3[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon4[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-accent0[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-accent1[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-accent2[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-accent3[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-accent4[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-accent0[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-accent1[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-accent2[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-accent3[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-accent4[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-none[fill]{fill:none}.jupyter-wrapper .jp-icon-none[stroke]{stroke:none}.jupyter-wrapper .jp-icon-brand0[fill]{fill:var(--jp-brand-color0)}.jupyter-wrapper .jp-icon-brand1[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper .jp-icon-brand2[fill]{fill:var(--jp-brand-color2)}.jupyter-wrapper .jp-icon-brand3[fill]{fill:var(--jp-brand-color3)}.jupyter-wrapper .jp-icon-brand4[fill]{fill:var(--jp-brand-color4)}.jupyter-wrapper .jp-icon-brand0[stroke]{stroke:var(--jp-brand-color0)}.jupyter-wrapper .jp-icon-brand1[stroke]{stroke:var(--jp-brand-color1)}.jupyter-wrapper .jp-icon-brand2[stroke]{stroke:var(--jp-brand-color2)}.jupyter-wrapper .jp-icon-brand3[stroke]{stroke:var(--jp-brand-color3)}.jupyter-wrapper .jp-icon-brand4[stroke]{stroke:var(--jp-brand-color4)}.jupyter-wrapper .jp-icon-warn0[fill]{fill:var(--jp-warn-color0)}.jupyter-wrapper .jp-icon-warn1[fill]{fill:var(--jp-warn-color1)}.jupyter-wrapper .jp-icon-warn2[fill]{fill:var(--jp-warn-color2)}.jupyter-wrapper .jp-icon-warn3[fill]{fill:var(--jp-warn-color3)}.jupyter-wrapper .jp-icon-warn0[stroke]{stroke:var(--jp-warn-color0)}.jupyter-wrapper .jp-icon-warn1[stroke]{stroke:var(--jp-warn-color1)}.jupyter-wrapper .jp-icon-warn2[stroke]{stroke:var(--jp-warn-color2)}.jupyter-wrapper .jp-icon-warn3[stroke]{stroke:var(--jp-warn-color3)}.jupyter-wrapper .jp-icon-contrast0[fill]{fill:var(--jp-icon-contrast-color0)}.jupyter-wrapper .jp-icon-contrast1[fill]{fill:var(--jp-icon-contrast-color1)}.jupyter-wrapper .jp-icon-contrast2[fill]{fill:var(--jp-icon-contrast-color2)}.jupyter-wrapper .jp-icon-contrast3[fill]{fill:var(--jp-icon-contrast-color3)}.jupyter-wrapper .jp-icon-contrast0[stroke]{stroke:var(--jp-icon-contrast-color0)}.jupyter-wrapper .jp-icon-contrast1[stroke]{stroke:var(--jp-icon-contrast-color1)}.jupyter-wrapper .jp-icon-contrast2[stroke]{stroke:var(--jp-icon-contrast-color2)}.jupyter-wrapper .jp-icon-contrast3[stroke]{stroke:var(--jp-icon-contrast-color3)}.jupyter-wrapper .jp-jupyter-icon-color[fill]{fill:var(--jp-jupyter-icon-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-notebook-icon-color[fill]{fill:var(--jp-notebook-icon-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-json-icon-color[fill]{fill:var(--jp-json-icon-color, var(--jp-warn-color1))}.jupyter-wrapper .jp-console-icon-color[fill]{fill:var(--jp-console-icon-color, white)}.jupyter-wrapper .jp-console-icon-background-color[fill]{fill:var(--jp-console-icon-background-color, var(--jp-brand-color1))}.jupyter-wrapper .jp-terminal-icon-color[fill]{fill:var(--jp-terminal-icon-color, var(--jp-layout-color2))}.jupyter-wrapper .jp-terminal-icon-background-color[fill]{fill:var(--jp-terminal-icon-background-color, var(--jp-inverse-layout2))}.jupyter-wrapper .jp-text-editor-icon-color[fill]{fill:var(--jp-text-editor-icon-color, var(--jp-inverse-layout3))}.jupyter-wrapper .jp-inspector-icon-color[fill]{fill:var(--jp-inspector-icon-color, var(--jp-inverse-layout3))}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected .jp-icon-selectable-inverse[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-selectable-inverse[fill],.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-hover :hover .jp-icon-selectable[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-hover :hover .jp-icon-selectable-inverse[fill]{fill:#fff}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon3[fill]{fill:none}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty.jp-mod-active>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:#fff}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon3[fill]{fill:none}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper #jp-main-statusbar .jp-mod-selected .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper #jp-main-statusbar .jp-mod-selected .jp-icon-selectable-inverse[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper :root{--jp-warn-color0: var(--md-orange-700)}.jupyter-wrapper .jp-DragIcon{margin-right:4px}.jupyter-wrapper .jp-icon-alt .jp-icon0[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon1[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon2[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon3[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon4[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon0[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon1[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon2[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon3[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon4[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent0[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent1[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent2[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent3[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent4[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent0[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent1[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent2[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent3[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent4[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hoverShow:not(:hover) .jp-icon-hoverShow-content{display:none!important}.jupyter-wrapper .jp-icon-hover :hover .jp-icon0-hover[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon1-hover[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon2-hover[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon3-hover[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon4-hover[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon0-hover[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon1-hover[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon2-hover[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon3-hover[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon4-hover[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent0-hover[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent1-hover[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent2-hover[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent3-hover[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent4-hover[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent0-hover[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent1-hover[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent2-hover[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent3-hover[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent4-hover[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-none-hover[fill]{fill:none}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-none-hover[stroke]{stroke:none}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-switch{display:flex;align-items:center;padding-left:4px;padding-right:4px;font-size:var(--jp-ui-font-size1);background-color:transparent;color:var(--jp-ui-font-color1);border:none;height:20px}.jupyter-wrapper .jp-switch:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-switch-label{margin-right:5px}.jupyter-wrapper .jp-switch-track{cursor:pointer;background-color:var(--jp-switch-color, var(--jp-border-color1));-webkit-transition:.4s;transition:.4s;border-radius:34px;height:16px;width:35px;position:relative}.jupyter-wrapper .jp-switch-track:before{content:\"\";position:absolute;height:10px;width:10px;margin:3px;left:0;background-color:var(--jp-ui-inverse-font-color1);-webkit-transition:.4s;transition:.4s;border-radius:50%}.jupyter-wrapper .jp-switch[aria-checked=true] .jp-switch-track{background-color:var(--jp-switch-true-position-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-switch[aria-checked=true] .jp-switch-track:before{left:19px}.jupyter-wrapper html{box-sizing:unset}.jupyter-wrapper *,.jupyter-wrapper *:before,.jupyter-wrapper *:after{box-sizing:unset}.jupyter-wrapper body{color:unset;font-family:var(--jp-ui-font-family)}.jupyter-wrapper :focus{outline:unset;outline-offset:unset;-moz-outline-radius:unset}.jupyter-wrapper .jp-Button{border-radius:var(--jp-border-radius);padding:0 12px;font-size:var(--jp-ui-font-size1)}.jupyter-wrapper button.jp-Button.bp3-button.bp3-minimal:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-Button.minimal{color:unset!important}.jupyter-wrapper .jp-Button.jp-ToolbarButtonComponent{text-transform:none}.jupyter-wrapper .jp-InputGroup input{box-sizing:border-box;border-radius:0;background-color:transparent;color:var(--jp-ui-font-color0);box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color)}.jupyter-wrapper .jp-InputGroup input:focus{box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-active-box-shadow-color),inset 0 0 0 3px var(--jp-input-active-box-shadow-color)}.jupyter-wrapper .jp-InputGroup input::placeholder,.jupyter-wrapper input::placeholder{color:var(--jp-ui-font-color3)}.jupyter-wrapper .jp-BPIcon{display:inline-block;vertical-align:middle;margin:auto}.jupyter-wrapper .bp3-icon.jp-BPIcon>svg:not([fill]){fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-InputGroupAction{padding:6px}.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select{background-color:initial;border:none;border-radius:0;box-shadow:none;color:var(--jp-ui-font-color0);display:block;font-size:var(--jp-ui-font-size1);height:24px;line-height:14px;padding:0 25px 0 10px;text-align:left;-moz-appearance:none;-webkit-appearance:none}.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select:hover,.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select>option{background-color:var(--jp-layout-color2);color:var(--jp-ui-font-color0)}.jupyter-wrapper select{box-sizing:border-box}.jupyter-wrapper .jp-Collapse{display:flex;flex-direction:column;align-items:stretch;border-top:1px solid var(--jp-border-color2);border-bottom:1px solid var(--jp-border-color2)}.jupyter-wrapper .jp-Collapse-header{padding:1px 12px;color:var(--jp-ui-font-color1);background-color:var(--jp-layout-color1);font-size:var(--jp-ui-font-size2)}.jupyter-wrapper .jp-Collapse-header:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-Collapse-contents{padding:0 12px;background-color:var(--jp-layout-color1);color:var(--jp-ui-font-color1);overflow:auto}.jupyter-wrapper :root{--jp-private-commandpalette-search-height: 28px}.jupyter-wrapper .lm-CommandPalette{padding-bottom:0;color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .jp-ModalCommandPalette{position:absolute;z-index:10000;top:38px;left:30%;margin:0;padding:4px;width:40%;box-shadow:var(--jp-elevation-z4);border-radius:4px;background:var(--jp-layout-color0)}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette{max-height:40vh}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-close-icon:after{display:none}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-header{display:none}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item{margin-left:4px;margin-right:4px}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item.lm-mod-disabled{display:none}.jupyter-wrapper .lm-CommandPalette-search{padding:4px;background-color:var(--jp-layout-color1);z-index:2}.jupyter-wrapper .lm-CommandPalette-wrapper{overflow:overlay;padding:0 9px;background-color:var(--jp-input-active-background);height:30px;box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color)}.jupyter-wrapper .lm-CommandPalette.lm-mod-focused .lm-CommandPalette-wrapper{box-shadow:inset 0 0 0 1px var(--jp-input-active-box-shadow-color),inset 0 0 0 3px var(--jp-input-active-box-shadow-color)}.jupyter-wrapper .jp-SearchIconGroup{color:#fff;background-color:var(--jp-brand-color1);position:absolute;top:4px;right:4px;padding:5px 5px 1px}.jupyter-wrapper .jp-SearchIconGroup svg{height:20px;width:20px}.jupyter-wrapper .jp-SearchIconGroup .jp-icon3[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .lm-CommandPalette-input{background:transparent;width:calc(100% - 18px);float:left;border:none;outline:none;font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);line-height:var(--jp-private-commandpalette-search-height)}.jupyter-wrapper .lm-CommandPalette-input::-webkit-input-placeholder,.jupyter-wrapper .lm-CommandPalette-input::-moz-placeholder,.jupyter-wrapper .lm-CommandPalette-input:-ms-input-placeholder{color:var(--jp-ui-font-color2);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .lm-CommandPalette-header:first-child{margin-top:0}.jupyter-wrapper .lm-CommandPalette-header{border-bottom:solid var(--jp-border-width) var(--jp-border-color2);color:var(--jp-ui-font-color1);cursor:pointer;display:flex;font-size:var(--jp-ui-font-size0);font-weight:600;letter-spacing:1px;margin-top:8px;padding:8px 0 8px 12px;text-transform:uppercase}.jupyter-wrapper .lm-CommandPalette-header.lm-mod-active{background:var(--jp-layout-color2)}.jupyter-wrapper .lm-CommandPalette-header>mark{background-color:transparent;font-weight:700;color:var(--jp-ui-font-color1)}.jupyter-wrapper .lm-CommandPalette-item{padding:4px 12px 4px 4px;color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);font-weight:400;display:flex}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled{color:var(--jp-ui-font-color2)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active{color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active .jp-icon-selectable[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active .lm-CommandPalette-itemLabel>mark{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active:hover:not(.lm-mod-disabled){color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .lm-CommandPalette-item:hover:not(.lm-mod-active):not(.lm-mod-disabled){background:var(--jp-layout-color2)}.jupyter-wrapper .lm-CommandPalette-itemContent{overflow:hidden}.jupyter-wrapper .lm-CommandPalette-itemLabel>mark{color:var(--jp-ui-font-color0);background-color:transparent;font-weight:700}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled mark{color:var(--jp-ui-font-color2)}.jupyter-wrapper .lm-CommandPalette-item .lm-CommandPalette-itemIcon{margin:0 4px 0 0;position:relative;width:16px;top:2px;flex:0 0 auto}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled .lm-CommandPalette-itemIcon{opacity:.6}.jupyter-wrapper .lm-CommandPalette-item .lm-CommandPalette-itemShortcut{flex:0 0 auto}.jupyter-wrapper .lm-CommandPalette-itemCaption{display:none}.jupyter-wrapper .lm-CommandPalette-content{background-color:var(--jp-layout-color1)}.jupyter-wrapper .lm-CommandPalette-content:empty:after{content:\"No results\";margin:20px auto auto;width:100px;display:block;font-size:var(--jp-ui-font-size2);font-family:var(--jp-ui-font-family);font-weight:lighter}.jupyter-wrapper .lm-CommandPalette-emptyMessage{text-align:center;margin-top:24px;line-height:1.32;padding:0 8px;color:var(--jp-content-font-color3)}.jupyter-wrapper .jp-Dialog{position:absolute;z-index:10000;display:flex;flex-direction:column;align-items:center;justify-content:center;top:0;left:0;margin:0;padding:0;width:100%;height:100%;background:var(--jp-dialog-background)}.jupyter-wrapper .jp-Dialog-content{display:flex;flex-direction:column;margin-left:auto;margin-right:auto;background:var(--jp-layout-color1);padding:24px 24px 12px;min-width:300px;min-height:150px;max-width:1000px;max-height:500px;box-sizing:border-box;box-shadow:var(--jp-elevation-z20);word-wrap:break-word;border-radius:var(--jp-border-radius);font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color1);resize:both}.jupyter-wrapper .jp-Dialog-content.jp-Dialog-content-small{max-width:500px}.jupyter-wrapper .jp-Dialog-button{overflow:visible}.jupyter-wrapper button.jp-Dialog-button:focus{outline:1px solid var(--jp-brand-color1);outline-offset:4px;-moz-outline-radius:0px}.jupyter-wrapper button.jp-Dialog-button:focus::-moz-focus-inner{border:0}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus,.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus,.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus{outline-offset:4px;-moz-outline-radius:0px}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus{outline:1px solid var(--md-blue-700)}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus{outline:1px solid var(--md-red-600)}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus{outline:1px solid var(--md-grey-700)}.jupyter-wrapper button.jp-Dialog-close-button{padding:0;height:100%;min-width:unset;min-height:unset}.jupyter-wrapper .jp-Dialog-header{display:flex;justify-content:space-between;flex:0 0 auto;padding-bottom:12px;font-size:var(--jp-ui-font-size3);font-weight:400;color:var(--jp-ui-font-color0)}.jupyter-wrapper .jp-Dialog-body{display:flex;flex-direction:column;flex:1 1 auto;font-size:var(--jp-ui-font-size1);background:var(--jp-layout-color1);overflow:auto}.jupyter-wrapper .jp-Dialog-footer{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;flex:0 0 auto;margin-left:-12px;margin-right:-12px;padding:12px}.jupyter-wrapper .jp-Dialog-checkbox{padding-right:5px}.jupyter-wrapper .jp-Dialog-checkbox>input:focus-visible{outline:1px solid var(--jp-input-active-border-color);outline-offset:1px}.jupyter-wrapper .jp-Dialog-spacer{flex:1 1 auto}.jupyter-wrapper .jp-Dialog-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .jp-Dialog-body>.jp-select-wrapper{width:100%}.jupyter-wrapper .jp-Dialog-body>button{padding:0 16px}.jupyter-wrapper .jp-Dialog-body>label{line-height:1.4;color:var(--jp-ui-font-color0)}.jupyter-wrapper .jp-Dialog-button.jp-mod-styled:not(:last-child){margin-right:12px}.jupyter-wrapper .jp-HoverBox{position:fixed}.jupyter-wrapper .jp-HoverBox.jp-mod-outofview{display:none}.jupyter-wrapper .jp-IFrame{width:100%;height:100%}.jupyter-wrapper .jp-IFrame>iframe{border:none}.jupyter-wrapper body.lm-mod-override-cursor .jp-IFrame{position:relative}.jupyter-wrapper body.lm-mod-override-cursor .jp-IFrame:before{content:\"\";position:absolute;top:0;left:0;right:0;bottom:0;background:transparent}.jupyter-wrapper .jp-Input-Boolean-Dialog{flex-direction:row-reverse;align-items:end;width:100%}.jupyter-wrapper .jp-Input-Boolean-Dialog>label{flex:1 1 auto}.jupyter-wrapper .jp-MainAreaWidget>:focus{outline:none}.jupyter-wrapper .jp-MainAreaWidget .jp-MainAreaWidget-error{padding:6px}.jupyter-wrapper .jp-MainAreaWidget .jp-MainAreaWidget-error>pre{width:auto;padding:10px;background:var(--jp-error-color3);border:var(--jp-border-width) solid var(--jp-error-color1);border-radius:var(--jp-border-radius);color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);white-space:pre-wrap;word-wrap:break-word}.jupyter-wrapper .jp-MainAreaWidget{contain:strict}.jupyter-wrapper :root{--md-red-50: #ffebee;--md-red-100: #ffcdd2;--md-red-200: #ef9a9a;--md-red-300: #e57373;--md-red-400: #ef5350;--md-red-500: #f44336;--md-red-600: #e53935;--md-red-700: #d32f2f;--md-red-800: #c62828;--md-red-900: #b71c1c;--md-red-A100: #ff8a80;--md-red-A200: #ff5252;--md-red-A400: #ff1744;--md-red-A700: #d50000;--md-pink-50: #fce4ec;--md-pink-100: #f8bbd0;--md-pink-200: #f48fb1;--md-pink-300: #f06292;--md-pink-400: #ec407a;--md-pink-500: #e91e63;--md-pink-600: #d81b60;--md-pink-700: #c2185b;--md-pink-800: #ad1457;--md-pink-900: #880e4f;--md-pink-A100: #ff80ab;--md-pink-A200: #ff4081;--md-pink-A400: #f50057;--md-pink-A700: #c51162;--md-purple-50: #f3e5f5;--md-purple-100: #e1bee7;--md-purple-200: #ce93d8;--md-purple-300: #ba68c8;--md-purple-400: #ab47bc;--md-purple-500: #9c27b0;--md-purple-600: #8e24aa;--md-purple-700: #7b1fa2;--md-purple-800: #6a1b9a;--md-purple-900: #4a148c;--md-purple-A100: #ea80fc;--md-purple-A200: #e040fb;--md-purple-A400: #d500f9;--md-purple-A700: #aa00ff;--md-deep-purple-50: #ede7f6;--md-deep-purple-100: #d1c4e9;--md-deep-purple-200: #b39ddb;--md-deep-purple-300: #9575cd;--md-deep-purple-400: #7e57c2;--md-deep-purple-500: #673ab7;--md-deep-purple-600: #5e35b1;--md-deep-purple-700: #512da8;--md-deep-purple-800: #4527a0;--md-deep-purple-900: #311b92;--md-deep-purple-A100: #b388ff;--md-deep-purple-A200: #7c4dff;--md-deep-purple-A400: #651fff;--md-deep-purple-A700: #6200ea;--md-indigo-50: #e8eaf6;--md-indigo-100: #c5cae9;--md-indigo-200: #9fa8da;--md-indigo-300: #7986cb;--md-indigo-400: #5c6bc0;--md-indigo-500: #3f51b5;--md-indigo-600: #3949ab;--md-indigo-700: #303f9f;--md-indigo-800: #283593;--md-indigo-900: #1a237e;--md-indigo-A100: #8c9eff;--md-indigo-A200: #536dfe;--md-indigo-A400: #3d5afe;--md-indigo-A700: #304ffe;--md-blue-50: #e3f2fd;--md-blue-100: #bbdefb;--md-blue-200: #90caf9;--md-blue-300: #64b5f6;--md-blue-400: #42a5f5;--md-blue-500: #2196f3;--md-blue-600: #1e88e5;--md-blue-700: #1976d2;--md-blue-800: #1565c0;--md-blue-900: #0d47a1;--md-blue-A100: #82b1ff;--md-blue-A200: #448aff;--md-blue-A400: #2979ff;--md-blue-A700: #2962ff;--md-light-blue-50: #e1f5fe;--md-light-blue-100: #b3e5fc;--md-light-blue-200: #81d4fa;--md-light-blue-300: #4fc3f7;--md-light-blue-400: #29b6f6;--md-light-blue-500: #03a9f4;--md-light-blue-600: #039be5;--md-light-blue-700: #0288d1;--md-light-blue-800: #0277bd;--md-light-blue-900: #01579b;--md-light-blue-A100: #80d8ff;--md-light-blue-A200: #40c4ff;--md-light-blue-A400: #00b0ff;--md-light-blue-A700: #0091ea;--md-cyan-50: #e0f7fa;--md-cyan-100: #b2ebf2;--md-cyan-200: #80deea;--md-cyan-300: #4dd0e1;--md-cyan-400: #26c6da;--md-cyan-500: #00bcd4;--md-cyan-600: #00acc1;--md-cyan-700: #0097a7;--md-cyan-800: #00838f;--md-cyan-900: #006064;--md-cyan-A100: #84ffff;--md-cyan-A200: #18ffff;--md-cyan-A400: #00e5ff;--md-cyan-A700: #00b8d4;--md-teal-50: #e0f2f1;--md-teal-100: #b2dfdb;--md-teal-200: #80cbc4;--md-teal-300: #4db6ac;--md-teal-400: #26a69a;--md-teal-500: #009688;--md-teal-600: #00897b;--md-teal-700: #00796b;--md-teal-800: #00695c;--md-teal-900: #004d40;--md-teal-A100: #a7ffeb;--md-teal-A200: #64ffda;--md-teal-A400: #1de9b6;--md-teal-A700: #00bfa5;--md-green-50: #e8f5e9;--md-green-100: #c8e6c9;--md-green-200: #a5d6a7;--md-green-300: #81c784;--md-green-400: #66bb6a;--md-green-500: #4caf50;--md-green-600: #43a047;--md-green-700: #388e3c;--md-green-800: #2e7d32;--md-green-900: #1b5e20;--md-green-A100: #b9f6ca;--md-green-A200: #69f0ae;--md-green-A400: #00e676;--md-green-A700: #00c853;--md-light-green-50: #f1f8e9;--md-light-green-100: #dcedc8;--md-light-green-200: #c5e1a5;--md-light-green-300: #aed581;--md-light-green-400: #9ccc65;--md-light-green-500: #8bc34a;--md-light-green-600: #7cb342;--md-light-green-700: #689f38;--md-light-green-800: #558b2f;--md-light-green-900: #33691e;--md-light-green-A100: #ccff90;--md-light-green-A200: #b2ff59;--md-light-green-A400: #76ff03;--md-light-green-A700: #64dd17;--md-lime-50: #f9fbe7;--md-lime-100: #f0f4c3;--md-lime-200: #e6ee9c;--md-lime-300: #dce775;--md-lime-400: #d4e157;--md-lime-500: #cddc39;--md-lime-600: #c0ca33;--md-lime-700: #afb42b;--md-lime-800: #9e9d24;--md-lime-900: #827717;--md-lime-A100: #f4ff81;--md-lime-A200: #eeff41;--md-lime-A400: #c6ff00;--md-lime-A700: #aeea00;--md-yellow-50: #fffde7;--md-yellow-100: #fff9c4;--md-yellow-200: #fff59d;--md-yellow-300: #fff176;--md-yellow-400: #ffee58;--md-yellow-500: #ffeb3b;--md-yellow-600: #fdd835;--md-yellow-700: #fbc02d;--md-yellow-800: #f9a825;--md-yellow-900: #f57f17;--md-yellow-A100: #ffff8d;--md-yellow-A200: #ffff00;--md-yellow-A400: #ffea00;--md-yellow-A700: #ffd600;--md-amber-50: #fff8e1;--md-amber-100: #ffecb3;--md-amber-200: #ffe082;--md-amber-300: #ffd54f;--md-amber-400: #ffca28;--md-amber-500: #ffc107;--md-amber-600: #ffb300;--md-amber-700: #ffa000;--md-amber-800: #ff8f00;--md-amber-900: #ff6f00;--md-amber-A100: #ffe57f;--md-amber-A200: #ffd740;--md-amber-A400: #ffc400;--md-amber-A700: #ffab00;--md-orange-50: #fff3e0;--md-orange-100: #ffe0b2;--md-orange-200: #ffcc80;--md-orange-300: #ffb74d;--md-orange-400: #ffa726;--md-orange-500: #ff9800;--md-orange-600: #fb8c00;--md-orange-700: #f57c00;--md-orange-800: #ef6c00;--md-orange-900: #e65100;--md-orange-A100: #ffd180;--md-orange-A200: #ffab40;--md-orange-A400: #ff9100;--md-orange-A700: #ff6d00;--md-deep-orange-50: #fbe9e7;--md-deep-orange-100: #ffccbc;--md-deep-orange-200: #ffab91;--md-deep-orange-300: #ff8a65;--md-deep-orange-400: #ff7043;--md-deep-orange-500: #ff5722;--md-deep-orange-600: #f4511e;--md-deep-orange-700: #e64a19;--md-deep-orange-800: #d84315;--md-deep-orange-900: #bf360c;--md-deep-orange-A100: #ff9e80;--md-deep-orange-A200: #ff6e40;--md-deep-orange-A400: #ff3d00;--md-deep-orange-A700: #dd2c00;--md-brown-50: #efebe9;--md-brown-100: #d7ccc8;--md-brown-200: #bcaaa4;--md-brown-300: #a1887f;--md-brown-400: #8d6e63;--md-brown-500: #795548;--md-brown-600: #6d4c41;--md-brown-700: #5d4037;--md-brown-800: #4e342e;--md-brown-900: #3e2723;--md-grey-50: #fafafa;--md-grey-100: #f5f5f5;--md-grey-200: #eeeeee;--md-grey-300: #e0e0e0;--md-grey-400: #bdbdbd;--md-grey-500: #9e9e9e;--md-grey-600: #757575;--md-grey-700: #616161;--md-grey-800: #424242;--md-grey-900: #212121;--md-blue-grey-50: #eceff1;--md-blue-grey-100: #cfd8dc;--md-blue-grey-200: #b0bec5;--md-blue-grey-300: #90a4ae;--md-blue-grey-400: #78909c;--md-blue-grey-500: #607d8b;--md-blue-grey-600: #546e7a;--md-blue-grey-700: #455a64;--md-blue-grey-800: #37474f;--md-blue-grey-900: #263238}.jupyter-wrapper .jp-Spinner{position:absolute;display:flex;justify-content:center;align-items:center;z-index:10;left:0;top:0;width:100%;height:100%;background:var(--jp-layout-color0);outline:none}.jupyter-wrapper .jp-SpinnerContent{font-size:10px;margin:50px auto;text-indent:-9999em;width:3em;height:3em;border-radius:50%;background:var(--jp-brand-color3);background:linear-gradient(to right,#f37626 10%,rgba(255,255,255,0) 42%);position:relative;animation:load3 1s infinite linear,fadeIn 1s}.jupyter-wrapper .jp-SpinnerContent:before{width:50%;height:50%;background:#f37626;border-radius:100% 0 0;position:absolute;top:0;left:0;content:\"\"}.jupyter-wrapper .jp-SpinnerContent:after{background:var(--jp-layout-color0);width:75%;height:75%;border-radius:50%;content:\"\";margin:auto;position:absolute;top:0;left:0;bottom:0;right:0}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes load3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.jupyter-wrapper button.jp-mod-styled{font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);border:none;box-sizing:border-box;text-align:center;line-height:32px;height:32px;padding:0 12px;letter-spacing:.8px;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper input.jp-mod-styled{background:var(--jp-input-background);height:28px;box-sizing:border-box;border:var(--jp-border-width) solid var(--jp-border-color1);padding-left:7px;padding-right:7px;font-size:var(--jp-ui-font-size2);color:var(--jp-ui-font-color0);outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper input[type=checkbox].jp-mod-styled{appearance:checkbox;-webkit-appearance:checkbox;-moz-appearance:checkbox;height:auto}.jupyter-wrapper input.jp-mod-styled:focus{border:var(--jp-border-width) solid var(--md-blue-500);box-shadow:inset 0 0 4px var(--md-blue-300)}.jupyter-wrapper .jp-FileDialog-Checkbox{margin-top:35px;display:flex;flex-direction:row;align-items:end;width:100%}.jupyter-wrapper .jp-FileDialog-Checkbox>label{flex:1 1 auto}.jupyter-wrapper .jp-select-wrapper{display:flex;position:relative;flex-direction:column;padding:1px;background-color:var(--jp-layout-color1);height:28px;box-sizing:border-box;margin-bottom:12px}.jupyter-wrapper .jp-select-wrapper.jp-mod-focused select.jp-mod-styled{border:var(--jp-border-width) solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow);background-color:var(--jp-input-active-background)}.jupyter-wrapper select.jp-mod-styled:hover{background-color:var(--jp-layout-color1);cursor:pointer;color:var(--jp-ui-font-color0);background-color:var(--jp-input-hover-background);box-shadow:inset 0 0 1px #00000080}.jupyter-wrapper select.jp-mod-styled{flex:1 1 auto;height:32px;width:100%;font-size:var(--jp-ui-font-size2);background:var(--jp-input-background);color:var(--jp-ui-font-color0);padding:0 25px 0 8px;border:var(--jp-border-width) solid var(--jp-input-border-color);border-radius:0;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper :root{--jp-private-toolbar-height: calc( 28px + var(--jp-border-width) )}.jupyter-wrapper .jp-Toolbar{color:var(--jp-ui-font-color1);flex:0 0 auto;display:flex;flex-direction:row;border-bottom:var(--jp-border-width) solid var(--jp-toolbar-border-color);box-shadow:var(--jp-toolbar-box-shadow);background:var(--jp-toolbar-background);min-height:var(--jp-toolbar-micro-height);padding:2px;z-index:8;overflow-x:hidden}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-item.jp-Toolbar-spacer{flex-grow:1;flex-shrink:1}.jupyter-wrapper .jp-Toolbar-item.jp-Toolbar-kernelStatus{display:inline-block;width:32px;background-repeat:no-repeat;background-position:center;background-size:16px}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-item{flex:0 0 auto;display:flex;padding-left:1px;padding-right:1px;font-size:var(--jp-ui-font-size1);line-height:var(--jp-private-toolbar-height);height:100%}.jupyter-wrapper div.jp-ToolbarButton{color:transparent;border:none;box-sizing:border-box;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none;padding:0;margin:0}.jupyter-wrapper button.jp-ToolbarButtonComponent{background:var(--jp-layout-color1);border:none;box-sizing:border-box;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none;padding:0 6px;margin:0;height:24px;border-radius:var(--jp-border-radius);display:flex;align-items:center;text-align:center;font-size:14px;min-width:unset;min-height:unset}.jupyter-wrapper button.jp-ToolbarButtonComponent:disabled{opacity:.4}.jupyter-wrapper button.jp-ToolbarButtonComponent span{padding:0;flex:0 0 auto}.jupyter-wrapper button.jp-ToolbarButtonComponent .jp-ToolbarButtonComponent-label{font-size:var(--jp-ui-font-size1);line-height:100%;padding-left:2px;color:var(--jp-ui-font-color1)}.jupyter-wrapper #jp-main-dock-panel[data-mode=single-document] .jp-MainAreaWidget>.jp-Toolbar.jp-Toolbar-micro{padding:0;min-height:0}.jupyter-wrapper #jp-main-dock-panel[data-mode=single-document] .jp-MainAreaWidget>.jp-Toolbar{border:none;box-shadow:none}.jupyter-wrapper body.p-mod-override-cursor *,.jupyter-wrapper body.lm-mod-override-cursor *{cursor:inherit!important}.jupyter-wrapper .jp-JSONEditor{display:flex;flex-direction:column;width:100%}.jupyter-wrapper .jp-JSONEditor-host{flex:1 1 auto;border:var(--jp-border-width) solid var(--jp-input-border-color);border-radius:0;background:var(--jp-layout-color0);min-height:50px;padding:1px}.jupyter-wrapper .jp-JSONEditor.jp-mod-error .jp-JSONEditor-host{border-color:red;outline-color:red}.jupyter-wrapper .jp-JSONEditor-header{display:flex;flex:1 0 auto;padding:0 0 0 12px}.jupyter-wrapper .jp-JSONEditor-header label{flex:0 0 auto}.jupyter-wrapper .jp-JSONEditor-commitButton{height:16px;width:16px;background-size:18px;background-repeat:no-repeat;background-position:center}.jupyter-wrapper .jp-JSONEditor-host.jp-mod-focused{background-color:var(--jp-input-active-background);border:1px solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow)}.jupyter-wrapper .jp-Editor.jp-mod-dropTarget{border:var(--jp-border-width) solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow)}.jupyter-wrapper .jp-Statusbar-ProgressCircle svg{display:block;margin:0 auto;width:16px;height:24px;align-self:normal}.jupyter-wrapper .jp-Statusbar-ProgressCircle path{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar{height:10px;width:100px;border:solid .25px var(--jp-brand-color2);border-radius:3px;overflow:hidden;align-self:center}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar>div{background-color:var(--jp-brand-color2);background-image:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%,transparent);background-size:40px 40px;float:left;width:0%;height:100%;font-size:12px;line-height:14px;color:#fff;text-align:center;animation:jp-Statusbar-ExecutionTime-progress-bar 2s linear infinite}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar p{color:var(--jp-ui-font-color1);font-family:var(--jp-ui-font-family);font-size:var(--jp-ui-font-size1);line-height:10px;width:100px}@keyframes jp-Statusbar-ExecutionTime-progress-bar{0%{background-position:0 0}to{background-position:40px 40px}}.jupyter-wrapper .CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.jupyter-wrapper .CodeMirror-lines{padding:4px 0}.jupyter-wrapper .CodeMirror pre.CodeMirror-line,.jupyter-wrapper .CodeMirror pre.CodeMirror-line-like{padding:0 4px}.jupyter-wrapper .CodeMirror-scrollbar-filler,.jupyter-wrapper .CodeMirror-gutter-filler{background-color:#fff}.jupyter-wrapper .CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.jupyter-wrapper .CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.jupyter-wrapper .CodeMirror-guttermarker{color:#000}.jupyter-wrapper .CodeMirror-guttermarker-subtle{color:#999}.jupyter-wrapper .CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.jupyter-wrapper .CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.jupyter-wrapper .cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.jupyter-wrapper .cm-fat-cursor div.CodeMirror-cursors{z-index:1}.jupyter-wrapper .cm-fat-cursor-mark{background-color:#14ff1480;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.jupyter-wrapper .cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.jupyter-wrapper .cm-tab{display:inline-block;text-decoration:inherit}.jupyter-wrapper .CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.jupyter-wrapper .CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.jupyter-wrapper .cm-s-default .cm-header{color:#00f}.jupyter-wrapper .cm-s-default .cm-quote{color:#090}.jupyter-wrapper .cm-negative{color:#d44}.jupyter-wrapper .cm-positive{color:#292}.jupyter-wrapper .cm-header,.jupyter-wrapper .cm-strong{font-weight:700}.jupyter-wrapper .cm-em{font-style:italic}.jupyter-wrapper .cm-link{text-decoration:underline}.jupyter-wrapper .cm-strikethrough{text-decoration:line-through}.jupyter-wrapper .cm-s-default .cm-keyword{color:#708}.jupyter-wrapper .cm-s-default .cm-atom{color:#219}.jupyter-wrapper .cm-s-default .cm-number{color:#164}.jupyter-wrapper .cm-s-default .cm-def{color:#00f}.jupyter-wrapper .cm-s-default .cm-variable-2{color:#05a}.jupyter-wrapper .cm-s-default .cm-variable-3,.jupyter-wrapper .cm-s-default .cm-type{color:#085}.jupyter-wrapper .cm-s-default .cm-comment{color:#a50}.jupyter-wrapper .cm-s-default .cm-string{color:#a11}.jupyter-wrapper .cm-s-default .cm-string-2{color:#f50}.jupyter-wrapper .cm-s-default .cm-meta,.jupyter-wrapper .cm-s-default .cm-qualifier{color:#555}.jupyter-wrapper .cm-s-default .cm-builtin{color:#30a}.jupyter-wrapper .cm-s-default .cm-bracket{color:#997}.jupyter-wrapper .cm-s-default .cm-tag{color:#170}.jupyter-wrapper .cm-s-default .cm-attribute{color:#00c}.jupyter-wrapper .cm-s-default .cm-hr{color:#999}.jupyter-wrapper .cm-s-default .cm-link{color:#00c}.jupyter-wrapper .cm-s-default .cm-error,.jupyter-wrapper .cm-invalidchar{color:red}.jupyter-wrapper .CodeMirror-composing{border-bottom:2px solid}.jupyter-wrapper div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}.jupyter-wrapper div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.jupyter-wrapper .CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.jupyter-wrapper .CodeMirror-activeline-background{background:#e8f2ff}.jupyter-wrapper .CodeMirror{position:relative;overflow:hidden;background:white}.jupyter-wrapper .CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative}.jupyter-wrapper .CodeMirror-sizer{position:relative;border-right:50px solid transparent}.jupyter-wrapper .CodeMirror-vscrollbar,.jupyter-wrapper .CodeMirror-hscrollbar,.jupyter-wrapper .CodeMirror-scrollbar-filler,.jupyter-wrapper .CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.jupyter-wrapper .CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.jupyter-wrapper .CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.jupyter-wrapper .CodeMirror-scrollbar-filler{right:0;bottom:0}.jupyter-wrapper .CodeMirror-gutter-filler{left:0;bottom:0}.jupyter-wrapper .CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.jupyter-wrapper .CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.jupyter-wrapper .CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.jupyter-wrapper .CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.jupyter-wrapper .CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.jupyter-wrapper .CodeMirror-gutter-wrapper ::selection{background-color:transparent}.jupyter-wrapper .CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.jupyter-wrapper .CodeMirror-lines{cursor:text;min-height:1px}.jupyter-wrapper .CodeMirror pre.CodeMirror-line,.jupyter-wrapper .CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.jupyter-wrapper .CodeMirror-wrap pre.CodeMirror-line,.jupyter-wrapper .CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.jupyter-wrapper .CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.jupyter-wrapper .CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.jupyter-wrapper .CodeMirror-rtl pre{direction:rtl}.jupyter-wrapper .CodeMirror-code{outline:none}.jupyter-wrapper .CodeMirror-scroll,.jupyter-wrapper .CodeMirror-sizer,.jupyter-wrapper .CodeMirror-gutter,.jupyter-wrapper .CodeMirror-gutters,.jupyter-wrapper .CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.jupyter-wrapper .CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.jupyter-wrapper .CodeMirror-cursor{position:absolute;pointer-events:none}.jupyter-wrapper .CodeMirror-measure pre{position:static}.jupyter-wrapper div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.jupyter-wrapper div.CodeMirror-dragcursors,.jupyter-wrapper .CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.jupyter-wrapper .CodeMirror-selected{background:#d9d9d9}.jupyter-wrapper .CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.jupyter-wrapper .CodeMirror-crosshair{cursor:crosshair}.jupyter-wrapper .CodeMirror-line::selection,.jupyter-wrapper .CodeMirror-line>span::selection,.jupyter-wrapper .CodeMirror-line>span>span::selection{background:#d7d4f0}.jupyter-wrapper .CodeMirror-line::-moz-selection,.jupyter-wrapper .CodeMirror-line>span::-moz-selection,.jupyter-wrapper .CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.jupyter-wrapper .cm-searching{background-color:#ffa;background-color:#ff06}.jupyter-wrapper .cm-force-border{padding-right:.1px}@media print{.jupyter-wrapper .CodeMirror div.CodeMirror-cursors{visibility:hidden}}.jupyter-wrapper .cm-tab-wrap-hack:after{content:\"\"}.jupyter-wrapper span.CodeMirror-selectedtext{background:none}.jupyter-wrapper .CodeMirror-dialog{position:absolute;left:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.jupyter-wrapper .CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.jupyter-wrapper .CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.jupyter-wrapper .CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.jupyter-wrapper .CodeMirror-dialog button{font-size:70%}.jupyter-wrapper .CodeMirror-foldmarker{color:#00f;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.jupyter-wrapper .CodeMirror-foldgutter{width:.7em}.jupyter-wrapper .CodeMirror-foldgutter-open,.jupyter-wrapper .CodeMirror-foldgutter-folded{cursor:pointer}.jupyter-wrapper .CodeMirror-foldgutter-open:after{content:\"\u25be\"}.jupyter-wrapper .CodeMirror-foldgutter-folded:after{content:\"\u25b8\"}.jupyter-wrapper .CodeMirror{line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);font-family:var(--jp-code-font-family);border:0;border-radius:0;height:auto}.jupyter-wrapper .CodeMirror pre{padding:0 var(--jp-code-padding)}.jupyter-wrapper .CodeMirror.cm-fat-cursor .cm-overlay.cm-searching{opacity:.5}.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-dialog{background-color:var(--jp-layout-color0);color:var(--jp-content-font-color1)}.jupyter-wrapper .CodeMirror-lines{padding:var(--jp-code-padding) 0}.jupyter-wrapper .CodeMirror-linenumber{padding:0 8px}.jupyter-wrapper .jp-CodeMirrorEditor{cursor:text}.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)}@media screen and (min-width: 2138px) and (max-width: 4319px){.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width1) solid var(--jp-editor-cursor-color)}}@media screen and (min-width: 4320px){.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width2) solid var(--jp-editor-cursor-color)}}.jupyter-wrapper .CodeMirror.jp-mod-readOnly .CodeMirror-cursor{display:none}.jupyter-wrapper .CodeMirror-gutters{border-right:1px solid var(--jp-border-color2);background-color:var(--jp-layout-color0)}.jupyter-wrapper .jp-CollaboratorCursor{border-left:5px solid transparent;border-right:5px solid transparent;border-top:none;border-bottom:3px solid;background-clip:content-box;margin-left:-5px;margin-right:-5px}.jupyter-wrapper .CodeMirror-selectedtext.cm-searching{background-color:var(--jp-search-selected-match-background-color)!important;color:var(--jp-search-selected-match-color)!important}.jupyter-wrapper .cm-searching{background-color:var(--jp-search-unselected-match-background-color)!important;color:var(--jp-search-unselected-match-color)!important}.jupyter-wrapper .cm-trailingspace{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAsElEQVQIHQGlAFr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7+r3zKmT0/+pk9P/7+r3zAAAAAAAAAAABAAAAAAAAAAA6OPzM+/q9wAAAAAA6OPzMwAAAAAAAAAAAgAAAAAAAAAAGR8NiRQaCgAZIA0AGR8NiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQyoYJ/SY80UAAAAASUVORK5CYII=);background-position:center left;background-repeat:repeat-x}.jupyter-wrapper .CodeMirror-focused .CodeMirror-selected{background-color:var(--jp-editor-selected-focused-background)}.jupyter-wrapper .CodeMirror-selected{background-color:var(--jp-editor-selected-background)}.jupyter-wrapper .jp-CollaboratorCursor-hover{position:absolute;z-index:1;transform:translate(-50%);color:#fff;border-radius:3px;padding:1px 4px;text-align:center;font-size:var(--jp-ui-font-size1);white-space:nowrap}.jupyter-wrapper .jp-CodeMirror-ruler{border-left:1px dashed var(--jp-border-color2)}.jupyter-wrapper .CodeMirror.cm-s-jupyter{background:var(--jp-layout-color0);color:var(--jp-content-font-color1)}.jupyter-wrapper .jp-CodeConsole .CodeMirror.cm-s-jupyter,.jupyter-wrapper .jp-Notebook .CodeMirror.cm-s-jupyter{background:transparent}.jupyter-wrapper .cm-s-jupyter .CodeMirror-cursor{border-left:var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)}.jupyter-wrapper .cm-s-jupyter span.cm-keyword{color:var(--jp-mirror-editor-keyword-color);font-weight:700}.jupyter-wrapper .cm-s-jupyter span.cm-atom{color:var(--jp-mirror-editor-atom-color)}.jupyter-wrapper .cm-s-jupyter span.cm-number{color:var(--jp-mirror-editor-number-color)}.jupyter-wrapper .cm-s-jupyter span.cm-def{color:var(--jp-mirror-editor-def-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable{color:var(--jp-mirror-editor-variable-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable-2{color:var(--jp-mirror-editor-variable-2-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable-3{color:var(--jp-mirror-editor-variable-3-color)}.jupyter-wrapper .cm-s-jupyter span.cm-punctuation{color:var(--jp-mirror-editor-punctuation-color)}.jupyter-wrapper .cm-s-jupyter span.cm-property{color:var(--jp-mirror-editor-property-color)}.jupyter-wrapper .cm-s-jupyter span.cm-operator{color:var(--jp-mirror-editor-operator-color);font-weight:700}.jupyter-wrapper .cm-s-jupyter span.cm-comment{color:var(--jp-mirror-editor-comment-color);font-style:italic}.jupyter-wrapper .cm-s-jupyter span.cm-string{color:var(--jp-mirror-editor-string-color)}.jupyter-wrapper .cm-s-jupyter span.cm-string-2{color:var(--jp-mirror-editor-string-2-color)}.jupyter-wrapper .cm-s-jupyter span.cm-meta{color:var(--jp-mirror-editor-meta-color)}.jupyter-wrapper .cm-s-jupyter span.cm-qualifier{color:var(--jp-mirror-editor-qualifier-color)}.jupyter-wrapper .cm-s-jupyter span.cm-builtin{color:var(--jp-mirror-editor-builtin-color)}.jupyter-wrapper .cm-s-jupyter span.cm-bracket{color:var(--jp-mirror-editor-bracket-color)}.jupyter-wrapper .cm-s-jupyter span.cm-tag{color:var(--jp-mirror-editor-tag-color)}.jupyter-wrapper .cm-s-jupyter span.cm-attribute{color:var(--jp-mirror-editor-attribute-color)}.jupyter-wrapper .cm-s-jupyter span.cm-header{color:var(--jp-mirror-editor-header-color)}.jupyter-wrapper .cm-s-jupyter span.cm-quote{color:var(--jp-mirror-editor-quote-color)}.jupyter-wrapper .cm-s-jupyter span.cm-link{color:var(--jp-mirror-editor-link-color)}.jupyter-wrapper .cm-s-jupyter span.cm-error{color:var(--jp-mirror-editor-error-color)}.jupyter-wrapper .cm-s-jupyter span.cm-hr{color:#999}.jupyter-wrapper .cm-s-jupyter span.cm-tab{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);background-position:right;background-repeat:no-repeat}.jupyter-wrapper .cm-s-jupyter .CodeMirror-activeline-background,.jupyter-wrapper .cm-s-jupyter .CodeMirror-gutter{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret{position:relative;border-left:2px solid black;margin-left:-1px;margin-right:-1px;box-sizing:border-box}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret>div{white-space:nowrap;position:absolute;top:-1.15em;padding-bottom:.05em;left:-2px;font-size:.95em;background-color:#fa8100;font-family:var(--jp-ui-font-family);font-weight:700;line-height:normal;-webkit-user-select:none;user-select:none;color:#fff;padding-left:2px;padding-right:2px;z-index:3;transition:opacity .3s ease-in-out}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret.hide-name>div{transition-delay:.7s;opacity:0}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret:hover>div[style]{opacity:1;transition-delay:0s}.jupyter-wrapper :root{--jp-private-code-span-padding: calc( (var(--jp-code-line-height) - 1) * var(--jp-code-font-size) / 2 )}.jupyter-wrapper .jp-RenderedText{text-align:left;padding-left:var(--jp-code-padding);line-height:var(--jp-code-line-height);font-family:var(--jp-code-font-family)}.jupyter-wrapper .jp-RenderedText pre,.jupyter-wrapper .jp-RenderedJavaScript pre,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore pre{color:var(--jp-content-font-color1);font-size:var(--jp-code-font-size);border:none;margin:0;padding:0}.jupyter-wrapper .jp-RenderedText pre a:link{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre a:hover{text-decoration:underline;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre a:visited{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre .ansi-black-fg{color:#3e424d}.jupyter-wrapper .jp-RenderedText pre .ansi-red-fg{color:#e75c58}.jupyter-wrapper .jp-RenderedText pre .ansi-green-fg{color:#00a250}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-fg{color:#ddb62b}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-fg{color:#208ffb}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-fg{color:#d160c4}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-fg{color:#60c6c8}.jupyter-wrapper .jp-RenderedText pre .ansi-white-fg{color:#c5c1b4}.jupyter-wrapper .jp-RenderedText pre .ansi-black-bg{background-color:#3e424d;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-red-bg{background-color:#e75c58;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-green-bg{background-color:#00a250;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-bg{background-color:#ddb62b;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-bg{background-color:#208ffb;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-bg{background-color:#d160c4;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-bg{background-color:#60c6c8;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-white-bg{background-color:#c5c1b4;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-black-intense-fg{color:#282c36}.jupyter-wrapper .jp-RenderedText pre .ansi-red-intense-fg{color:#b22b31}.jupyter-wrapper .jp-RenderedText pre .ansi-green-intense-fg{color:#007427}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-intense-fg{color:#b27d12}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-intense-fg{color:#0065ca}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-intense-fg{color:#a03196}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-intense-fg{color:#258f8f}.jupyter-wrapper .jp-RenderedText pre .ansi-white-intense-fg{color:#a1a6b2}.jupyter-wrapper .jp-RenderedText pre .ansi-black-intense-bg{background-color:#282c36;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-red-intense-bg{background-color:#b22b31;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-green-intense-bg{background-color:#007427;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-intense-bg{background-color:#b27d12;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-intense-bg{background-color:#0065ca;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-intense-bg{background-color:#a03196;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-intense-bg{background-color:#258f8f;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-white-intense-bg{background-color:#a1a6b2;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-default-inverse-fg{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .jp-RenderedText pre .ansi-default-inverse-bg{background-color:var(--jp-inverse-layout-color0);padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-bold{font-weight:700}.jupyter-wrapper .jp-RenderedText pre .ansi-underline{text-decoration:underline}.jupyter-wrapper .jp-RenderedText[data-mime-type=\"application/vnd.jupyter.stderr\"]{background:var(--jp-rendermime-error-background);padding-top:var(--jp-code-padding)}.jupyter-wrapper .jp-RenderedLatex{color:var(--jp-content-font-color1);font-size:var(--jp-content-font-size1);line-height:var(--jp-content-line-height)}.jupyter-wrapper .jp-OutputArea-output.jp-RenderedLatex{padding:var(--jp-code-padding);text-align:left}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore{color:var(--jp-content-font-color1);font-family:var(--jp-content-font-family);font-size:var(--jp-content-font-size1);line-height:var(--jp-content-line-height);padding-right:20px}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore em{font-style:italic}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore strong{font-weight:700}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore u{text-decoration:underline}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:link{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:hover{text-decoration:underline;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:visited{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6{line-height:var(--jp-content-heading-line-height);font-weight:var(--jp-content-heading-font-weight);font-style:normal;margin:var(--jp-content-heading-margin-top) 0 var(--jp-content-heading-margin-bottom) 0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6:first-child{margin-top:calc(.5 * var(--jp-content-heading-margin-top))}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6:last-child{margin-bottom:calc(.5 * var(--jp-content-heading-margin-bottom))}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1{font-size:var(--jp-content-font-size5)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2{font-size:var(--jp-content-font-size4)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3{font-size:var(--jp-content-font-size3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4{font-size:var(--jp-content-font-size2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5{font-size:var(--jp-content-font-size1)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6{font-size:var(--jp-content-font-size0)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul:not(.list-inline),.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol:not(.list-inline){padding-left:2em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul{list-style:disc}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul{list-style:square}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul ul{list-style:circle}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol{list-style:decimal}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol{list-style:upper-alpha}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol{list-style:lower-alpha}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol ol{list-style:lower-roman}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol ol ol{list-style:decimal}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ol,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ul,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore hr{color:var(--jp-border-color2);background-color:var(--jp-border-color1);margin-top:1em;margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>pre{margin:1.5em 2em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore pre,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore code{border:0;background-color:var(--jp-layout-color0);color:var(--jp-content-font-color1);font-family:var(--jp-code-font-family);font-size:inherit;line-height:var(--jp-code-line-height);padding:0;white-space:pre-wrap}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore :not(pre)>code{background-color:var(--jp-layout-color2);padding:1px 5px}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore table{border-collapse:collapse;border-spacing:0;border:none;color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);table-layout:fixed;margin-left:auto;margin-right:auto}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore thead{border-bottom:var(--jp-border-width) solid var(--jp-border-color1);vertical-align:bottom}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore th,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tr{vertical-align:middle;padding:.5em;line-height:normal;white-space:normal;max-width:none;border:none}.jupyter-wrapper .jp-RenderedMarkdown.jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper .jp-RenderedMarkdown.jp-RenderedHTMLCommon-ignore th{max-width:none}.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore th,.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore tr{text-align:right}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore th{font-weight:700}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:nth-child(odd){background:var(--jp-layout-color0)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:nth-child(2n){background:var(--jp-rendermime-table-row-background)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:hover{background:var(--jp-rendermime-table-row-hover-background)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore table{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore p{text-align:left;margin:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore p{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img{-moz-force-broken-image-icon:1}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>img{display:block;margin-left:0;margin-right:0;margin-bottom:1em}.jupyter-wrapper [data-jp-theme-light=false] .jp-RenderedImage img.jp-needs-light-background,.jupyter-wrapper [data-jp-theme-light=true] .jp-RenderedImage img.jp-needs-dark-background{background-color:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img,.jupyter-wrapper .jp-RenderedImage img,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore svg,.jupyter-wrapper .jp-RenderedSVG svg{max-width:100%;height:auto}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedImage img.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore svg.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedSVG svg.jp-mod-unconfined{max-width:none}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert{padding:var(--jp-notebook-padding);border:var(--jp-border-width) solid transparent;border-radius:var(--jp-border-radius);margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info{color:var(--jp-info-color0);background-color:var(--jp-info-color3);border-color:var(--jp-info-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info hr{border-color:var(--jp-info-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning{color:var(--jp-warn-color0);background-color:var(--jp-warn-color3);border-color:var(--jp-warn-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning hr{border-color:var(--jp-warn-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success{color:var(--jp-success-color0);background-color:var(--jp-success-color3);border-color:var(--jp-success-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success hr{border-color:var(--jp-success-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger{color:var(--jp-error-color0);background-color:var(--jp-error-color3);border-color:var(--jp-error-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger hr{border-color:var(--jp-error-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore blockquote{margin:1em 2em;padding:0 1em;border-left:5px solid var(--jp-border-color2)}.jupyter-wrapper a.jp-InternalAnchorLink{visibility:hidden;margin-left:8px;color:var(--md-blue-800)}.jupyter-wrapper h1:hover .jp-InternalAnchorLink,.jupyter-wrapper h2:hover .jp-InternalAnchorLink,.jupyter-wrapper h3:hover .jp-InternalAnchorLink,.jupyter-wrapper h4:hover .jp-InternalAnchorLink,.jupyter-wrapper h5:hover .jp-InternalAnchorLink,.jupyter-wrapper h6:hover .jp-InternalAnchorLink{visibility:visible}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore kbd{background-color:var(--jp-rendermime-table-row-background);border:1px solid var(--jp-border-color0);border-bottom-color:var(--jp-border-color2);border-radius:3px;box-shadow:inset 0 -1px #00000040;display:inline-block;font-size:var(--jp-ui-font-size0);line-height:1em;padding:.2em .5em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>*:last-child{margin-bottom:.5em}.jupyter-wrapper .jp-MimeDocument{outline:none}.jupyter-wrapper :root{--jp-private-filebrowser-button-height: 28px;--jp-private-filebrowser-button-width: 48px}.jupyter-wrapper .jp-FileBrowser{display:flex;flex-direction:column;color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .jp-FileBrowser-toolbar.jp-Toolbar{border-bottom:none;height:auto;margin:8px 12px 0;padding:0;box-shadow:none;justify-content:flex-start}.jupyter-wrapper .jp-BreadCrumbs{flex:0 0 auto;margin:8px 12px}.jupyter-wrapper .jp-BreadCrumbs-item{margin:0 2px;padding:0 2px;border-radius:var(--jp-border-radius);cursor:pointer}.jupyter-wrapper .jp-BreadCrumbs-item:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-BreadCrumbs-item:first-child{margin-left:0}.jupyter-wrapper .jp-BreadCrumbs-item.jp-mod-dropTarget{background-color:var(--jp-brand-color2);opacity:.7}.jupyter-wrapper .jp-FileBrowser-toolbar>.jp-Toolbar-item{flex:0 0 auto;padding-left:0;padding-right:2px}.jupyter-wrapper .jp-FileBrowser-toolbar>.jp-Toolbar-item .jp-ToolbarButtonComponent{width:40px}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]{width:72px;background:var(--jp-brand-color1)}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]:hover,.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]:focus-visible{background-color:var(--jp-brand-color0)!important}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"] .jp-icon3{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-FileDialog.jp-mod-conflict input{color:var(--jp-error-color1)}.jupyter-wrapper .jp-FileDialog .jp-new-name-title{margin-top:12px}.jupyter-wrapper .jp-LastModified-hidden{display:none}.jupyter-wrapper .jp-FileBrowser-filterBox{padding:0;flex:0 0 auto;margin:8px 12px 0}.jupyter-wrapper .jp-DirListing{flex:1 1 auto;display:flex;flex-direction:column;outline:0}.jupyter-wrapper .jp-DirListing:focus-visible{outline:1px solid var(--jp-brand-color1);outline-offset:-2px}.jupyter-wrapper .jp-DirListing-header{flex:0 0 auto;display:flex;flex-direction:row;overflow:hidden;border-top:var(--jp-border-width) solid var(--jp-border-color2);border-bottom:var(--jp-border-width) solid var(--jp-border-color1);box-shadow:var(--jp-toolbar-box-shadow);z-index:2}.jupyter-wrapper .jp-DirListing-headerItem{padding:4px 12px 2px;font-weight:500}.jupyter-wrapper .jp-DirListing-headerItem:hover{background:var(--jp-layout-color2)}.jupyter-wrapper .jp-DirListing-headerItem.jp-id-name{flex:1 0 84px}.jupyter-wrapper .jp-DirListing-headerItem.jp-id-modified{flex:0 0 112px;border-left:var(--jp-border-width) solid var(--jp-border-color2);text-align:right}.jupyter-wrapper .jp-id-narrow{display:none;flex:0 0 5px;padding:4px;border-left:var(--jp-border-width) solid var(--jp-border-color2);text-align:right;color:var(--jp-border-color2)}.jupyter-wrapper .jp-DirListing-narrow .jp-id-narrow{display:block}.jupyter-wrapper .jp-DirListing-narrow .jp-id-modified,.jupyter-wrapper .jp-DirListing-narrow .jp-DirListing-itemModified{display:none}.jupyter-wrapper .jp-DirListing-headerItem.jp-mod-selected{font-weight:600}.jupyter-wrapper .jp-DirListing-content{flex:1 1 auto;margin:0;padding:0;list-style-type:none;overflow:auto;background-color:var(--jp-layout-color1)}.jupyter-wrapper .jp-DirListing-content mark{color:var(--jp-ui-font-color0);background-color:transparent;font-weight:700}.jupyter-wrapper .jp-DirListing-content .jp-DirListing-item.jp-mod-selected mark{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .jp-DirListing.jp-mod-native-drop .jp-DirListing-content{outline:5px dashed rgba(128,128,128,.5);outline-offset:-10px;cursor:copy}.jupyter-wrapper .jp-DirListing-item{display:flex;flex-direction:row;padding:4px 12px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .jp-DirListing-item[data-is-dot]{opacity:75%}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected{color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .jp-DirListing-item.jp-mod-dropTarget{background:var(--jp-brand-color3)}.jupyter-wrapper .jp-DirListing-item:hover:not(.jp-mod-selected){background:var(--jp-layout-color2)}.jupyter-wrapper .jp-DirListing-itemIcon{flex:0 0 20px;margin-right:4px}.jupyter-wrapper .jp-DirListing-itemText{flex:1 0 64px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;user-select:none}.jupyter-wrapper .jp-DirListing-itemModified{flex:0 0 125px;text-align:right}.jupyter-wrapper .jp-DirListing-editor{flex:1 0 64px;outline:none;border:none;color:var(--jp-ui-font-color1);background-color:var(--jp-layout-color1)}.jupyter-wrapper .jp-DirListing-item.jp-mod-running .jp-DirListing-itemIcon:before{color:var(--jp-success-color1);content:\"\u25cf\";font-size:8px;position:absolute;left:-8px}.jupyter-wrapper .jp-DirListing-item.jp-mod-running.jp-mod-selected .jp-DirListing-itemIcon:before{color:var(--jp-ui-inverse-font-color1)}.jupyter-wrapper .jp-DirListing-item.lm-mod-drag-image,.jupyter-wrapper .jp-DirListing-item.jp-mod-selected.lm-mod-drag-image{font-size:var(--jp-ui-font-size1);padding-left:4px;margin-left:4px;width:160px;background-color:var(--jp-ui-inverse-font-color2);box-shadow:var(--jp-elevation-z2);border-radius:0;color:var(--jp-ui-font-color1);transform:translate(-40%) translateY(-58%)}.jupyter-wrapper .jp-Document{min-width:120px;min-height:120px;outline:none}.jupyter-wrapper .jp-OutputArea{overflow-y:auto}.jupyter-wrapper .jp-OutputArea-child{display:flex;flex-direction:row}.jupyter-wrapper body[data-format=mobile] .jp-OutputArea-child{flex-direction:column}.jupyter-wrapper .jp-OutputPrompt{flex:0 0 var(--jp-cell-prompt-width);color:var(--jp-cell-outprompt-font-color);font-family:var(--jp-cell-prompt-font-family);padding:var(--jp-code-padding);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent;opacity:var(--jp-cell-prompt-opacity);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper body[data-format=mobile] .jp-OutputPrompt{flex:0 0 auto;text-align:left}.jupyter-wrapper .jp-OutputArea-output{height:auto;overflow:auto;user-select:text;-moz-user-select:text;-webkit-user-select:text;-ms-user-select:text}.jupyter-wrapper .jp-OutputArea-child .jp-OutputArea-output{flex-grow:1;flex-shrink:1}.jupyter-wrapper body[data-format=mobile] .jp-OutputArea-child .jp-OutputArea-output{margin-left:var(--jp-notebook-padding)}.jupyter-wrapper .jp-OutputArea-output.jp-mod-isolated{width:100%;display:block}.jupyter-wrapper body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated{position:relative}.jupyter-wrapper body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated:before{content:\"\";position:absolute;top:0;left:0;right:0;bottom:0;background:transparent}.jupyter-wrapper .jp-OutputArea-output pre{border:none;margin:0;padding:0;overflow-x:auto;overflow-y:auto;word-break:break-all;word-wrap:break-word;white-space:pre-wrap}.jupyter-wrapper .jp-OutputArea-output.jp-RenderedHTMLCommon-ignore table{margin-left:0;margin-right:0}.jupyter-wrapper .jp-OutputArea-output dl,.jupyter-wrapper .jp-OutputArea-output dt,.jupyter-wrapper .jp-OutputArea-output dd{display:block}.jupyter-wrapper .jp-OutputArea-output dl{width:100%;overflow:hidden;padding:0;margin:0}.jupyter-wrapper .jp-OutputArea-output dt{font-weight:700;float:left;width:20%;padding:0;margin:0}.jupyter-wrapper .jp-OutputArea-output dd{float:left;width:80%;padding:0;margin:0}.jupyter-wrapper .jp-TrimmedOutputs a{margin:10px;text-decoration:none;cursor:pointer}.jupyter-wrapper .jp-OutputArea .jp-OutputArea .jp-OutputArea-prompt{display:none}.jupyter-wrapper .jp-OutputArea-prompt:empty{padding:0;border:0}.jupyter-wrapper .jp-OutputArea-output.jp-OutputArea-executeResult{margin-left:0;flex:1 1 auto}.jupyter-wrapper .jp-OutputArea-executeResult .jp-RenderedText.jp-OutputArea-output{padding-top:var(--jp-code-padding);border-top:var(--jp-border-width) solid transparent}.jupyter-wrapper .jp-Stdin-prompt{color:var(--jp-content-font-color0);padding-right:var(--jp-code-padding);vertical-align:baseline;flex:0 0 auto}.jupyter-wrapper .jp-Stdin-input{font-family:var(--jp-code-font-family);font-size:inherit;color:inherit;background-color:inherit;width:42%;min-width:200px;vertical-align:baseline;padding:0 .25em;margin:0 .25em;flex:0 0 70%}.jupyter-wrapper .jp-Stdin-input::placeholder{opacity:0}.jupyter-wrapper .jp-Stdin-input:focus{box-shadow:none}.jupyter-wrapper .jp-Stdin-input:focus::placeholder{opacity:1}.jupyter-wrapper .jp-LinkedOutputView .jp-OutputArea{height:100%;display:block}.jupyter-wrapper .jp-LinkedOutputView .jp-OutputArea-output:only-child{height:100%}.jupyter-wrapper .jp-Collapser{flex:0 0 var(--jp-cell-collapser-width);padding:0;margin:0;border:none;outline:none;background:transparent;border-radius:var(--jp-border-radius);opacity:1}.jupyter-wrapper .jp-Collapser-child{display:block;width:100%;box-sizing:border-box;position:absolute;top:0;bottom:0}.jupyter-wrapper .jp-CellHeader,.jupyter-wrapper .jp-CellFooter{height:0px;width:100%;padding:0;margin:0;border:none;outline:none;background:transparent}.jupyter-wrapper .jp-InputArea{display:flex;flex-direction:row;overflow:hidden}.jupyter-wrapper body[data-format=mobile] .jp-InputArea{flex-direction:column}.jupyter-wrapper .jp-InputArea-editor{flex:1 1 auto;overflow:hidden}.jupyter-wrapper .jp-InputArea-editor{border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);border-radius:0;background:var(--jp-cell-editor-background)}.jupyter-wrapper body[data-format=mobile] .jp-InputArea-editor{margin-left:var(--jp-notebook-padding)}.jupyter-wrapper .jp-InputPrompt{flex:0 0 var(--jp-cell-prompt-width);color:var(--jp-cell-inprompt-font-color);font-family:var(--jp-cell-prompt-font-family);padding:var(--jp-code-padding);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent;opacity:var(--jp-cell-prompt-opacity);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper body[data-format=mobile] .jp-InputPrompt{flex:0 0 auto;text-align:left}.jupyter-wrapper .jp-Placeholder{display:flex;flex-direction:row;flex:1 1 auto}.jupyter-wrapper .jp-Placeholder-prompt{box-sizing:border-box}.jupyter-wrapper .jp-Placeholder-content{flex:1 1 auto;border:none;background:transparent;height:20px;box-sizing:border-box}.jupyter-wrapper .jp-Placeholder-content .jp-MoreHorizIcon{width:32px;height:16px;border:1px solid transparent;border-radius:var(--jp-border-radius)}.jupyter-wrapper .jp-Placeholder-content .jp-MoreHorizIcon:hover{border:1px solid var(--jp-border-color1);box-shadow:0 0 2px #00000040;background-color:var(--jp-layout-color0)}.jupyter-wrapper :root{--jp-private-cell-scrolling-output-offset: 5px}.jupyter-wrapper .jp-Cell{padding:var(--jp-cell-padding);margin:0;border:none;outline:none;background:transparent}.jupyter-wrapper .jp-Cell-inputWrapper,.jupyter-wrapper .jp-Cell-outputWrapper{display:flex;flex-direction:row;padding:0;margin:0;overflow:visible}.jupyter-wrapper .jp-Cell-inputArea,.jupyter-wrapper .jp-Cell-outputArea{flex:1 1 auto}.jupyter-wrapper .jp-Cell.jp-mod-noOutputs .jp-Cell-outputCollapser{border:none!important;background:transparent!important}.jupyter-wrapper .jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputCollapser{min-height:var(--jp-cell-collapser-min-height)}.jupyter-wrapper .jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputWrapper{margin-top:5px}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea{overflow-y:auto;max-height:24em;margin-left:var(--jp-private-cell-scrolling-output-offset)}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea:after{content:\" \";box-shadow:inset 0 0 6px 2px #0000004d;width:100%;height:100%;position:sticky;bottom:0;top:0;margin-top:-50%;float:left;display:block;pointer-events:none}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-child{padding-top:6px}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-prompt{flex:0 0 calc(var(--jp-cell-prompt-width) - var(--jp-private-cell-scrolling-output-offset))}.jupyter-wrapper .jp-MarkdownOutput{flex:1 1 auto;margin-top:0;margin-bottom:0;padding-left:var(--jp-code-padding)}.jupyter-wrapper .jp-MarkdownOutput.jp-RenderedHTMLCommon-ignore{overflow:auto}.jupyter-wrapper .jp-collapseHeadingButton{display:none;min-height:var(--jp-cell-collapser-min-height);font-size:var(--jp-code-font-size);position:absolute;right:0;top:0;bottom:0;background-color:transparent;background-size:25px;background-repeat:no-repeat;background-position-x:center;background-position-y:top;background-image:var(--jp-icon-caret-down);border:none;cursor:pointer}.jupyter-wrapper .jp-collapseHeadingButton:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-collapseHeadingButton.jp-mod-collapsed{background-image:var(--jp-icon-caret-right)}.jupyter-wrapper :is(.jp-MarkdownCell:hover,.jp-mod-active) .jp-collapseHeadingButton{display:flex}.jupyter-wrapper .jp-MarkdownCell .jp-InputPrompt{font-size:var(--jp-content-font-size1)}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"1\"]{font-size:var(--jp-content-font-size5);background-position-y:calc(.3 * var(--jp-content-font-size5))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"2\"]{font-size:var(--jp-content-font-size4);background-position-y:calc(.3 * var(--jp-content-font-size4))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"3\"]{font-size:var(--jp-content-font-size3);background-position-y:calc(.3 * var(--jp-content-font-size3))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"4\"]{font-size:var(--jp-content-font-size2);background-position-y:calc(.3 * var(--jp-content-font-size2))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"5\"]{font-size:var(--jp-content-font-size1);background-position-y:top}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"6\"]{font-size:var(--jp-content-font-size0);background-position-y:top}.jupyter-wrapper .jp-showHiddenCellsButton{margin-left:calc(var(--jp-cell-prompt-width) + 2 * var(--jp-code-padding));margin-top:var(--jp-code-padding);border:1px solid var(--jp-border-color2);background-color:var(--jp-border-color3)!important;color:var(--jp-content-font-color0)!important}.jupyter-wrapper .jp-showHiddenCellsButton:hover{background-color:var(--jp-border-color2)!important}.jupyter-wrapper :root{--jp-notebook-toolbar-padding: 2px 5px 2px 2px}.jupyter-wrapper .jp-NotebookPanel-toolbar{padding:var(--jp-notebook-toolbar-padding)}.jupyter-wrapper .jp-Toolbar-item.jp-Notebook-toolbarCellType .jp-select-wrapper.jp-mod-focused{border:none;box-shadow:none}.jupyter-wrapper .jp-Notebook-toolbarCellTypeDropdown select{height:24px;font-size:var(--jp-ui-font-size1);line-height:14px;border-radius:0;display:block}.jupyter-wrapper .jp-Notebook-toolbarCellTypeDropdown span{top:5px!important}.jupyter-wrapper .jp-Toolbar-responsive-popup{position:absolute;height:fit-content;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-end;border-bottom:var(--jp-border-width) solid var(--jp-toolbar-border-color);box-shadow:var(--jp-toolbar-box-shadow);background:var(--jp-toolbar-background);min-height:var(--jp-toolbar-micro-height);padding:var(--jp-notebook-toolbar-padding);z-index:1;right:0;top:0}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-responsive-opener{margin-left:auto}.jupyter-wrapper .jp-Notebook-ExecutionIndicator{position:relative;display:inline-block;height:100%;z-index:9997}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip{visibility:hidden;height:auto;width:max-content;width:-moz-max-content;background-color:var(--jp-layout-color2);color:var(--jp-ui-font-color1);text-align:justify;border-radius:6px;padding:0 5px;position:fixed;display:table}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.up{transform:translate(-50%) translateY(-100%) translateY(-32px)}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.down{transform:translate(calc(-100% + 16px)) translateY(5px)}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.hidden{display:none}.jupyter-wrapper .jp-Notebook-ExecutionIndicator:hover .jp-Notebook-ExecutionIndicator-tooltip{visibility:visible}.jupyter-wrapper .jp-Notebook-ExecutionIndicator span{font-size:var(--jp-ui-font-size1);font-family:var(--jp-ui-font-family);color:var(--jp-ui-font-color1);line-height:24px;display:block}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-progress-bar{display:flex;justify-content:center;height:100%}.jupyter-wrapper :root{--jp-private-notebook-dragImage-width: 304px;--jp-private-notebook-dragImage-height: 36px;--jp-private-notebook-selected-color: var(--md-blue-400);--jp-private-notebook-active-color: var(--md-green-400)}.jupyter-wrapper .jp-NotebookPanel{display:block;height:100%}.jupyter-wrapper .jp-NotebookPanel.jp-Document{min-width:240px;min-height:120px}.jupyter-wrapper .jp-Notebook{padding:var(--jp-notebook-padding);outline:none;overflow:auto}.jupyter-wrapper .jp-Notebook.jp-mod-scrollPastEnd:after{display:block;content:\"\";min-height:var(--jp-notebook-scroll-padding)}.jupyter-wrapper .jp-MainAreaWidget-ContainStrict .jp-Notebook *{contain:strict}.jupyter-wrapper .jp-Notebook .jp-Cell{overflow:visible}.jupyter-wrapper .jp-Notebook .jp-Cell .jp-InputPrompt{cursor:move;float:left}.jupyter-wrapper .jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-InputPrompt{opacity:var(--jp-cell-prompt-not-active-opacity);color:var(--jp-cell-prompt-not-active-font-color)}.jupyter-wrapper .jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-OutputPrompt{opacity:var(--jp-cell-prompt-not-active-opacity);color:var(--jp-cell-prompt-not-active-font-color)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser{background:var(--jp-brand-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt{color:var(--jp-warn-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt:before{color:var(--jp-warn-color1);content:\"\u2022\"}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active.jp-mod-dirty .jp-Collapser{background:var(--jp-warn-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell .jp-Collapser:hover{box-shadow:var(--jp-elevation-z2);background:var(--jp-brand-color1);opacity:var(--jp-cell-collapser-not-active-hover-opacity)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover{background:var(--jp-brand-color0);opacity:1}.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-selected{background:var(--jp-notebook-multiselected-color)}.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-active.jp-mod-selected:not(.jp-mod-multiSelected){background:transparent}.jupyter-wrapper .jp-Notebook.jp-mod-editMode .jp-Cell.jp-mod-active .jp-InputArea-editor{border:var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);box-shadow:var(--jp-input-box-shadow);background-color:var(--jp-cell-editor-active-background)}.jupyter-wrapper .jp-Notebook-cell.jp-mod-dropSource{opacity:.5}.jupyter-wrapper .jp-Notebook-cell.jp-mod-dropTarget,.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Notebook-cell.jp-mod-active.jp-mod-selected.jp-mod-dropTarget{border-top-color:var(--jp-private-notebook-selected-color);border-top-style:solid;border-top-width:2px}.jupyter-wrapper .jp-dragImage{display:block;flex-direction:row;width:var(--jp-private-notebook-dragImage-width);height:var(--jp-private-notebook-dragImage-height);border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);background:var(--jp-cell-editor-background);overflow:visible}.jupyter-wrapper .jp-dragImage-singlePrompt{box-shadow:2px 2px 4px #0000001f}.jupyter-wrapper .jp-dragImage .jp-dragImage-content{flex:1 1 auto;z-index:2;font-size:var(--jp-code-font-size);font-family:var(--jp-code-font-family);line-height:var(--jp-code-line-height);padding:var(--jp-code-padding);border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);background:var(--jp-cell-editor-background-color);color:var(--jp-content-font-color3);text-align:left;margin:4px 4px 4px 0}.jupyter-wrapper .jp-dragImage .jp-dragImage-prompt{flex:0 0 auto;min-width:36px;color:var(--jp-cell-inprompt-font-color);padding:var(--jp-code-padding);padding-left:12px;font-family:var(--jp-cell-prompt-font-family);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:1.9;font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent}.jupyter-wrapper .jp-dragImage-multipleBack{z-index:-1;position:absolute;height:32px;width:300px;top:8px;left:8px;background:var(--jp-layout-color2);border:var(--jp-border-width) solid var(--jp-input-border-color);box-shadow:2px 2px 4px #0000001f}.jupyter-wrapper .jp-NotebookTools{display:block;min-width:var(--jp-sidebar-min-width);color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1);overflow:auto}.jupyter-wrapper .jp-NotebookTools-tool{padding:0 12px}.jupyter-wrapper .jp-ActiveCellTool{padding:12px;background-color:var(--jp-layout-color1);border-top:none!important}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-prompt{flex:0 0 auto;padding-left:0}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-editor{flex:1 1 auto;background:var(--jp-cell-editor-background);border-color:var(--jp-cell-editor-border-color)}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-editor .CodeMirror{background:transparent}.jupyter-wrapper .jp-MetadataEditorTool{flex-direction:column;padding:12px 0}.jupyter-wrapper .jp-RankedPanel>:not(:first-child){margin-top:12px}.jupyter-wrapper .jp-KeySelector select.jp-mod-styled{font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);border:var(--jp-border-width) solid var(--jp-border-color1)}.jupyter-wrapper .jp-KeySelector label,.jupyter-wrapper .jp-MetadataEditorTool label{line-height:1.4}.jupyter-wrapper .jp-NotebookTools .jp-select-wrapper{margin-top:4px;margin-bottom:0}.jupyter-wrapper .jp-NotebookTools .jp-Collapse{margin-top:16px}.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook{--jp-content-font-size1: var(--jp-content-presentation-font-size1);--jp-code-font-size: var(--jp-code-presentation-font-size)}.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-InputPrompt,.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-OutputPrompt{flex:0 0 110px}.jupyter-wrapper :root{--jp-side-by-side-output-size: 1fr;--jp-side-by-side-resized-cell: var(--jp-side-by-side-output-size)}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-Notebook-cell{margin:3em 5%}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell{display:grid;grid-template-columns:minmax(0,1fr) min-content minmax(0,var(--jp-side-by-side-output-size));grid-template-rows:auto minmax(0,1fr) auto;grid-template-areas:\"header header header\" \"input handle output\" \"footer footer footer\"}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell{grid-template-columns:minmax(0,1fr) min-content minmax(0,var(--jp-side-by-side-resized-cell))}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellHeader{grid-area:header}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-inputWrapper{grid-area:input}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-outputWrapper{margin-top:0;grid-area:output}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellFooter{grid-area:footer}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle{grid-area:handle;-webkit-user-select:none;user-select:none;display:block;height:100%;cursor:ew-resize;padding:0 var(--jp-cell-padding)}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle:after{content:\"\";display:block;background:var(--jp-border-color2);height:100%;width:5px}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell .jp-CellResizeHandle:after{background:var(--jp-border-color0)}.jupyter-wrapper .jp-CellResizeHandle{display:none}.jupyter-wrapper .jp-Cell-Placeholder{padding-left:55px}.jupyter-wrapper .jp-Cell-Placeholder-wrapper{background:#fff;border:1px solid;border-color:#e5e6e9 #dfe0e4 #d0d1d5;border-radius:4px;-webkit-border-radius:4px;margin:10px 15px}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-inner{padding:15px;position:relative}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body{background-repeat:repeat;background-size:50% auto}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body div{background:#f6f7f8;background-image:-webkit-linear-gradient(left,#f6f7f8 0%,#edeef1 20%,#f6f7f8 40%,#f6f7f8 100%);background-repeat:no-repeat;background-size:800px 104px;height:104px;position:relative}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body div{position:absolute;right:15px;left:15px;top:15px}.jupyter-wrapper div.jp-Cell-Placeholder-h1{top:20px;height:20px;left:15px;width:150px}.jupyter-wrapper div.jp-Cell-Placeholder-h2{left:15px;top:50px;height:10px;width:100px}.jupyter-wrapper div.jp-Cell-Placeholder-content-1,.jupyter-wrapper div.jp-Cell-Placeholder-content-2,.jupyter-wrapper div.jp-Cell-Placeholder-content-3{left:15px;right:15px;height:10px}.jupyter-wrapper div.jp-Cell-Placeholder-content-1{top:100px}.jupyter-wrapper div.jp-Cell-Placeholder-content-2{top:120px}.jupyter-wrapper div.jp-Cell-Placeholder-content-3{top:140px}.jupyter-wrapper table.dataframe{table-layout:auto!important}.jupyter-wrapper .md-typeset__scrollwrap{margin:0}.jupyter-wrapper .jp-MarkdownOutput{padding:0}.jupyter-wrapper h1 .anchor-link,.jupyter-wrapper h2 .anchor-link,.jupyter-wrapper h3 .anchor-link,.jupyter-wrapper h4 .anchor-link,.jupyter-wrapper h5 .anchor-link,.jupyter-wrapper h6 .anchor-link{display:none;margin-left:.5rem;color:var(--md-default-fg-color--lighter)}.jupyter-wrapper h1 .anchor-link:hover,.jupyter-wrapper h2 .anchor-link:hover,.jupyter-wrapper h3 .anchor-link:hover,.jupyter-wrapper h4 .anchor-link:hover,.jupyter-wrapper h5 .anchor-link:hover,.jupyter-wrapper h6 .anchor-link:hover{text-decoration:none;color:var(--md-accent-fg-color)}.jupyter-wrapper h1:hover .anchor-link,.jupyter-wrapper h2:hover .anchor-link,.jupyter-wrapper h3:hover .anchor-link,.jupyter-wrapper h4:hover .anchor-link,.jupyter-wrapper h5:hover .anchor-link,.jupyter-wrapper h6:hover .anchor-link{display:inline-block}.jupyter-wrapper .jp-InputArea,.jupyter-wrapper .jp-Cell-inputArea,.jupyter-wrapper .jp-RenderedHTMLCommon{width:100%}.jupyter-wrapper .jp-Cell-inputWrapper .jp-InputPrompt{display:none}.jupyter-wrapper .jp-CodeCell .jp-Cell-inputWrapper .jp-InputPrompt{display:block}.jupyter-wrapper .jp-Cell .jp-InputPrompt{cursor:normal}.jupyter-wrapper .highlight pre{background-color:#f5f5f5;padding:10px;overflow:auto}.jupyter-wrapper .celltoolbar{border:none;background:#eee;border-radius:2px 2px 0 0;width:100%;height:29px;padding-right:4px;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;box-pack:end;justify-content:flex-start;display:-webkit-flex}.jupyter-wrapper .celltoolbar .tags_button_container{display:flex}.jupyter-wrapper .celltoolbar .tags_button_container .tag-container{display:flex;flex-direction:row;flex-grow:1;overflow:hidden;position:relative}.jupyter-wrapper .celltoolbar .tags_button_container .tag-container .cell-tag{display:inline-flex;align-items:center;background-color:#fff;white-space:nowrap;margin:3px 4px;padding:0 4px;border-radius:1px;border:1px solid #ccc;box-shadow:none;width:inherit;font-size:11px;font-family:Roboto Mono,SFMono-Regular,Consolas,Menlo,monospace;height:17px}.jupyter-wrapper .jp-InputArea-editor{width:1px}.jupyter-wrapper .jp-InputPrompt,.jupyter-wrapper .jp-OutputPrompt{overflow:unset}.jupyter-wrapper .jp-RenderedText{font-size:var(--jp-code-font-size)}.jupyter-wrapper .highlight-ipynb{overflow:auto}.jupyter-wrapper .highlight-ipynb pre{margin:0;padding:5px 10px}.jupyter-wrapper table{width:max-content}.jupyter-wrapper table.dataframe{margin-left:auto;margin-right:auto;border:none;border-collapse:collapse;border-spacing:0;color:#000;font-size:12px;table-layout:fixed}.jupyter-wrapper table.dataframe thead{border-bottom:1px solid black;vertical-align:bottom}.jupyter-wrapper table.dataframe tr,.jupyter-wrapper table.dataframe th,.jupyter-wrapper table.dataframe td{text-align:right;vertical-align:middle;padding:.5em;line-height:normal;white-space:normal;max-width:none;border:none}.jupyter-wrapper table.dataframe th{font-weight:700}.jupyter-wrapper table.dataframe tbody tr:nth-child(odd){background:#f5f5f5}.jupyter-wrapper table.dataframe tbody tr:hover{background:rgba(66,165,245,.2)}.jupyter-wrapper *+table{margin-top:1em}.jupyter-wrapper .jp-InputArea-editor{position:relative}.jupyter-wrapper .zeroclipboard-container{position:absolute;top:-3px;right:0;z-index:1}.jupyter-wrapper .zeroclipboard-container clipboard-copy{-webkit-appearance:button;-moz-appearance:button;padding:7px 5px;font:11px system-ui,sans-serif;display:inline-block;cursor:default}.jupyter-wrapper .zeroclipboard-container clipboard-copy:hover{cursor:pointer}.jupyter-wrapper .zeroclipboard-container .clipboard-copy-icon{width:15px;padding:2px 0;color:#57606a;vertical-align:text-bottom}.jupyter-wrapper .clipboard-copy-txt{display:none}[data-md-color-scheme=slate] .highlight pre{background-color:#21222c;padding:10px;overflow:auto}[data-md-color-scheme=slate] .clipboard-copy-icon{color:#555!important}[data-md-color-scheme=slate] .celltoolbar{background:#333!important}[data-md-color-scheme=slate] .celltoolbar .tags_button_container .tag-container .cell-tag{background-color:transparent!important;border:1px solid #666!important}[data-md-color-scheme=slate] table.dataframe{color:#e9ebfc}[data-md-color-scheme=slate] table.dataframe thead{border-bottom:1px solid rgba(233,235,252,.12)}[data-md-color-scheme=slate] table.dataframe tbody tr:nth-child(odd){background:#222}[data-md-color-scheme=slate] table.dataframe tbody tr:hover{background:rgba(66,165,245,.2)}table{width:max-content} .jupyter-wrapper{--jp-shadow-base-lightness: 0;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-400);--jp-border-color1: var(--md-grey-400);--jp-border-color2: var(--md-grey-300);--jp-border-color3: var(--md-grey-200);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(0, 0, 0, 1);--jp-ui-font-color1: rgba(0, 0, 0, .87);--jp-ui-font-color2: rgba(0, 0, 0, .54);--jp-ui-font-color3: rgba(0, 0, 0, .38);--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color2: rgba(255, 255, 255, .7);--jp-ui-inverse-font-color3: rgba(255, 255, 255, .5);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(0, 0, 0, 1);--jp-content-font-color1: rgba(0, 0, 0, .87);--jp-content-font-color2: rgba(0, 0, 0, .54);--jp-content-font-color3: rgba(0, 0, 0, .38);--jp-content-link-color: var(--md-blue-700);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: white;--jp-layout-color1: white;--jp-layout-color2: var(--md-grey-200);--jp-layout-color3: var(--md-grey-400);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: #111111;--jp-inverse-layout-color1: var(--md-grey-900);--jp-inverse-layout-color2: var(--md-grey-800);--jp-inverse-layout-color3: var(--md-grey-700);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-900);--jp-brand-color1: var(--md-blue-700);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-900);--jp-accent-color1: var(--md-green-700);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-900);--jp-warn-color1: var(--md-orange-700);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-900);--jp-error-color1: var(--md-red-700);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-900);--jp-success-color1: var(--md-green-700);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-900);--jp-info-color1: var(--md-cyan-700);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--md-grey-100);--jp-cell-editor-border-color: var(--md-grey-300);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: .5;--jp-cell-prompt-not-active-font-color: var(--md-grey-700);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: var(--md-blue-50);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: #fdd;--jp-rendermime-table-row-background: var(--md-grey-100);--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);--jp-dialog-background: rgba(0, 0, 0, .25);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color1);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .24);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--md-grey-300);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color1);--jp-input-hover-background: var(--jp-layout-color1);--jp-input-background: var(--md-grey-100);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: #d9d9d9;--jp-editor-selected-focused-background: #d7d4f0;--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: #008000;--jp-mirror-editor-atom-color: #88f;--jp-mirror-editor-number-color: #080;--jp-mirror-editor-def-color: #00f;--jp-mirror-editor-variable-color: var(--md-grey-900);--jp-mirror-editor-variable-2-color: #05a;--jp-mirror-editor-variable-3-color: #085;--jp-mirror-editor-punctuation-color: #05a;--jp-mirror-editor-property-color: #05a;--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ba2121;--jp-mirror-editor-string-2-color: #708;--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: #008000;--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: #170;--jp-mirror-editor-attribute-color: #00c;--jp-mirror-editor-header-color: blue;--jp-mirror-editor-quote-color: #090;--jp-mirror-editor-link-color: #00c;--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ffad8e;--jp-collaborator-color2: #dac83d;--jp-collaborator-color3: #72dd76;--jp-collaborator-color4: #00e4d0;--jp-collaborator-color5: #45d4ff;--jp-collaborator-color6: #e2b1ff;--jp-collaborator-color7: #ff9de6;--jp-vega-background: white;--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .5;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(245, 200, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-700);--jp-console-icon-background-color: var(--md-blue-700);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-800);--jp-terminal-icon-color: var(--md-grey-200);--jp-text-editor-icon-color: var(--md-grey-700);--jp-inspector-icon-color: var(--md-grey-700);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-900)} init_mathjax = function() { if (window.MathJax) { // MathJax loaded MathJax.Hub.Config({ TeX: { equationNumbers: { autoNumber: \"AMS\", useLabelIds: true } }, tex2jax: { inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ], displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ], processEscapes: true, processEnvironments: true }, displayAlign: 'center', CommonHTML: { linebreaks: { automatic: true } } }); MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]); } } init_mathjax(); document.addEventListener(\"DOMContentLoaded\", async () => { const diagrams = document.querySelectorAll(\".jp-Mermaid > pre.mermaid\"); // do not load mermaidjs if not needed if (!diagrams.length) { return; } const mermaid = (await import(\"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs\")).default; const parser = new DOMParser(); mermaid.initialize({ maxTextSize: 100000, maxEdges: 100000, startOnLoad: false, fontFamily: window .getComputedStyle(document.body) .getPropertyValue(\"--jp-ui-font-family\"), theme: document.querySelector(\"body[data-jp-theme-light='true']\") ? \"default\" : \"dark\", }); let _nextMermaidId = 0; function makeMermaidImage(svg) { const img = document.createElement(\"img\"); const doc = parser.parseFromString(svg, \"image/svg+xml\"); const svgEl = doc.querySelector(\"svg\"); const { maxWidth } = svgEl?.style || {}; const firstTitle = doc.querySelector(\"title\"); const firstDesc = doc.querySelector(\"desc\"); img.setAttribute(\"src\", `data:image/svg+xml,${encodeURIComponent(svg)}`); if (maxWidth) { img.width = parseInt(maxWidth); } if (firstTitle) { img.setAttribute(\"alt\", firstTitle.textContent); } if (firstDesc) { const caption = document.createElement(\"figcaption\"); caption.className = \"sr-only\"; caption.textContent = firstDesc.textContent; return [img, caption]; } return [img]; } async function makeMermaidError(text) { let errorMessage = \"\"; try { await mermaid.parse(text); } catch (err) { errorMessage = `${err}`; } const result = document.createElement(\"details\"); result.className = 'jp-RenderedMermaid-Details'; const summary = document.createElement(\"summary\"); summary.className = 'jp-RenderedMermaid-Summary'; const pre = document.createElement(\"pre\"); const code = document.createElement(\"code\"); code.innerText = text; pre.appendChild(code); summary.appendChild(pre); result.appendChild(summary); const warning = document.createElement(\"pre\"); warning.innerText = errorMessage; result.appendChild(warning); return [result]; } async function renderOneMarmaid(src) { const id = `jp-mermaid-${_nextMermaidId++}`; const parent = src.parentNode; let raw = src.textContent.trim(); const el = document.createElement(\"div\"); el.style.visibility = \"hidden\"; document.body.appendChild(el); let results = null; let output = null; try { let { svg } = await mermaid.render(id, raw, el); svg = cleanMermaidSvg(svg); results = makeMermaidImage(svg); output = document.createElement(\"figure\"); results.map(output.appendChild, output); } catch (err) { parent.classList.add(\"jp-mod-warning\"); results = await makeMermaidError(raw); output = results[0]; } finally { el.remove(); } parent.classList.add(\"jp-RenderedMermaid\"); parent.appendChild(output); } /** * Post-process to ensure mermaid diagrams contain only valid SVG and XHTML. */ function cleanMermaidSvg(svg) { return svg.replace(RE_VOID_ELEMENT, replaceVoidElement); } /** * A regular expression for all void elements, which may include attributes and * a slash. * * @see https://developer.mozilla.org/en-US/docs/Glossary/Void_element * * Of these, only `
    ` is generated by Mermaid in place of `\\n`, * but _any_ \"malformed\" tag will break the SVG rendering entirely. */ const RE_VOID_ELEMENT = /<\\s*(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\\s*([^>]*?)\\s*>/gi; /** * Ensure a void element is closed with a slash, preserving any attributes. */ function replaceVoidElement(match, tag, rest) { rest = rest.trim(); if (!rest.endsWith('/')) { rest = `${rest} /`; } return `<${tag} ${rest}>`; } void Promise.all([...diagrams].map(renderOneMarmaid)); }); .jp-Mermaid:not(.jp-RenderedMermaid) { display: none; } .jp-RenderedMermaid { overflow: auto; display: flex; } .jp-RenderedMermaid.jp-mod-warning { width: auto; padding: 0.5em; margin-top: 0.5em; border: var(--jp-border-width) solid var(--jp-warn-color2); border-radius: var(--jp-border-radius); color: var(--jp-ui-font-color1); font-size: var(--jp-ui-font-size1); white-space: pre-wrap; word-wrap: break-word; } .jp-RenderedMermaid figure { margin: 0; overflow: auto; max-width: 100%; } .jp-RenderedMermaid img { max-width: 100%; } .jp-RenderedMermaid-Details > pre { margin-top: 1em; } .jp-RenderedMermaid-Summary { color: var(--jp-warn-color2); } .jp-RenderedMermaid:not(.jp-mod-warning) pre { display: none; } .jp-RenderedMermaid-Summary > pre { display: inline-block; white-space: normal; } scPRINT use case on BPH \u00b6 In this use-case, also presented in Figure 5 of our manuscript , we perform an extensive analysis of a multi studies dataset of benign prostatic hyperplasia. Our biological question is to check if there exist pre-cancerous cells that exhibits behaviors of mature cancer cells at this early stage of the disease. In those cells, we want to know which genes might be implicated in cell state changes, and explore potentially novel targets in the treatment of prostate cancer and BPH. We will start with a fresh datasets coming from the cellXgene database and representing 2 studies of BPH . We will first explore these dataset to understand: what are the cell types that are present in the data what are the cell distributions (cell distributions? what are they?) what sequencers were used, etc. We also want to confirm existing target in prostate cancer through precancerous lesion analysis, and find potentially novel ones that would serve as less invasive BPH treatments than current ones. Finally we want to know how these targets interacts and are involved in biological pathways. We now showcase how to use scPRINT across its different functionalities to answer some of these questions. table of contents: \u00b6 Downloading and preprocessing Embedding and annotations Annotation cleanup Clustering and differential expression Denoising and differential expression Gene network inference In the notebook cancer_usecase_part2.ipynb you will see how to analyse cell type specific gene regulatory networks. In [1]: Copied! from scprint import scPrint from scdataloader import Preprocessor , utils from scprint.tasks import GNInfer , Embedder , Denoiser , withknn from bengrn import BenGRN , get_sroy_gt , compute_genie3 from bengrn.base import train_classifier from grnndata import utils as grnutils from grnndata import read_h5ad from anndata.utils import make_index_unique from anndata import concat import scanpy as sc from matplotlib import pyplot as plt import numpy as np import lamindb as ln % load_ext autoreload % autoreload 2 import torch torch . set_float32_matmul_precision ( 'medium' ) from scprint import scPrint from scdataloader import Preprocessor, utils from scprint.tasks import GNInfer, Embedder, Denoiser, withknn from bengrn import BenGRN, get_sroy_gt, compute_genie3 from bengrn.base import train_classifier from grnndata import utils as grnutils from grnndata import read_h5ad from anndata.utils import make_index_unique from anndata import concat import scanpy as sc from matplotlib import pyplot as plt import numpy as np import lamindb as ln %load_ext autoreload %autoreload 2 import torch torch.set_float32_matmul_precision('medium') \ud83d\udca1 connected lamindb: jkobject/scprint /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/umap/__init__.py:9: ImportWarning: Tensorflow not installed; ParametricUMAP will be unavailable warn( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/chex/_src/pytypes.py:53: DeprecationWarning: jax.core.Shape is deprecated. Use Shape = Sequence[int | Any]. Shape = jax.core.Shape /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/chex/_src/pytypes.py:54: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html PRNGKey = jax.random.KeyArray /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/_types.py:9: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html IntOrKey = Union[int, jax.random.KeyArray] /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_utils.py:40: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def validate_seed(seed: IntOrKey) -> jax.random.KeyArray: /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_kmeans.py:21: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def _initialize_random(X: jnp.ndarray, n_clusters: int, key: jax.random.KeyArray) -> jnp.ndarray: /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_kmeans.py:31: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def _initialize_plus_plus(X: jnp.ndarray, n_clusters: int, key: jax.random.KeyArray) -> jnp.ndarray: Downloading and preprocessing \u00b6 We now use lamindb to easily access cellxgene and download a dataset of normal and benign prostatic hyperplasia tissues. data is available here https://cellxgene.cziscience.com/e/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.cxg/ . We then use scDataloader's preprocessing method. This method is quite extensive and does a few things.. find our more about it on its documentation . On our end we are using the preprocessor to make sure that the the gene expression that we have are raw counts and that we have enough information to use scPRINT (i.e., enough genes expressed and enough counts per cells across the dataset). Finally, the preprocessor will also increase the size of the expression matrix to be a fixed set of genes defined by the latest version of ensemble. In [2]: Copied! cx_dataset = ln . Collection . using ( instance = \"laminlabs/cellxgene\" ) . filter ( name = \"cellxgene-census\" , version = '2023-12-15' ) . one () cx_dataset = ln.Collection.using(instance=\"laminlabs/cellxgene\").filter(name=\"cellxgene-census\", version='2023-12-15').one() In [3]: Copied! prostate_adata = cx_dataset . artifacts . filter ( key = 'cell-census/2023-12-15/h5ads/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.h5ad' ) . one () . load () sc . pl . umap ( prostate_adata ) prostate_adata = cx_dataset.artifacts.filter(key='cell-census/2023-12-15/h5ads/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.h5ad').one().load() sc.pl.umap(prostate_adata) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/asyncio/sslproto.py:320: ResourceWarning: unclosed transport _warn(f\"unclosed transport {self!r}\", ResourceWarning, source=self) ResourceWarning: Enable tracemalloc to get the object allocation traceback In [7]: Copied! # preprocessing using scDataloader prostate_adata . obs . drop ( columns = \"is_primary_data\" , inplace = True ) preprocessor = Preprocessor ( do_postp = False ) prostate_adata = preprocessor ( prostate_adata ) # preprocessing using scDataloader prostate_adata.obs.drop(columns=\"is_primary_data\", inplace=True) preprocessor = Preprocessor(do_postp=False) prostate_adata = preprocessor(prostate_adata) Dropping layers: KeysView(Layers with keys: ) checking raw counts removed 0 non primary cells, 83451 renamining filtered out 0 cells, 83451 renamining Removed 76 genes. validating /home/ml4ig1/Documents code/scPRINT/scDataLoader/scdataloader/preprocess.py:241: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]` data_utils.validate(adata, organism=adata.obs.organism_ontology_term_id[0]) startin QC Seeing 13047 outliers (15.63% of total dataset): done Embedding and annotations \u00b6 We now start to load a large version of scPRINT from a specific checkpoint. Please download the checkpoints following the instructions in the README. We will then use out Embedder class to embed the data and annotate the cells. These classes are how we parametrize and access the different functions of scPRINT . Find out more about its parameters in our documentation . In [6]: Copied! model = scPrint . load_from_checkpoint ( '../data/temp/o2uniqsx/epoch=18-step=133000.ckpt' , # make sure that you check if you have a GPU with flashattention or not (see README) # you need this else, the model will look for the file with the embeddings instead of getting them from the weights precpt_gene_emb = None ) model = scPrint.load_from_checkpoint('../data/temp/o2uniqsx/epoch=18-step=133000.ckpt', # make sure that you check if you have a GPU with flashattention or not (see README) # you need this else, the model will look for the file with the embeddings instead of getting them from the weights precpt_gene_emb = None) RuntimeError caught: scPrint is not attached to a `Trainer`. In [10]: Copied! embedder = Embedder ( # can work on random genes or most variables etc.. how = \"random expr\" , # number of genes to use max_len = 4000 , add_zero_genes = 0 , # for the dataloading num_workers = 8 , # we will only use the cell type embedding here. pred_embedding = [ \"cell_type_ontology_term_id\" ] ) #, \"disease_ontology_term_id\"]) embedder = Embedder( # can work on random genes or most variables etc.. how=\"random expr\", # number of genes to use max_len=4000, add_zero_genes=0, # for the dataloading num_workers=8, # we will only use the cell type embedding here. pred_embedding = [\"cell_type_ontology_term_id\"] )#, \"disease_ontology_term_id\"]) Using 16bit Automatic Mixed Precision (AMP) GPU available: True (cuda), used: True TPU available: False, using: 0 TPU cores IPU available: False, using: 0 IPUs HPU available: False, using: 0 HPUs In [ ]: Copied! # create the embedding prostate_adata , metrics = embedder ( model , prostate_adata , cache = False , output_expression = \"none\" ) # create the embedding prostate_adata, metrics = embedder(model, prostate_adata, cache=False, output_expression=\"none\") 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 1560/1560 [28:20<00:00, 1.09s/it] AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 424 obs: 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id' /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) couldn't log to tensorboard couldn't log to wandb couldn't log to wandb cell_type_ontology_term_id accuracy: 0.7250215374752068 disease_ontology_term_id accuracy: 0.8394506441207702 assay_ontology_term_id accuracy: 0.998988239536794 self_reported_ethnicity_ontology_term_id accuracy: 0.9504037024422495 sex_ontology_term_id accuracy: 0.9948911105323263 organism_ontology_term_id accuracy: 1.0 In [16]: Copied! prostate_adata prostate_adata Out[16]: AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 70116 obs: 'assay_ontology_term_id', 'donor_id', 'sex_ontology_term_id', 'disease_ontology_term_id', 'organism_ontology_term_id', 'suspension_type', 'cell_type_ontology_term_id', 'tissue_ontology_term_id', 'development_stage_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'cell_type', 'assay', 'disease', 'organism', 'sex', 'tissue', 'self_reported_ethnicity', 'development_stage', 'nnz', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb', 'outlier', 'mt_outlier', 'init_dataset', 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id', 'sprint_leiden' uns: 'init_dataset_colors' obsm: 'X_pca', 'X_umap', 'scprint_umap', 'scprint' Annotation cleanup \u00b6 scPRINT generates predictions over hundreds of possible labels for each cell. It is often advised to \"cleanup\" the predictions, e.g. making sure to remove low frequency cells and misslabellings. Here, we use the most straightforward approach which is to remove any annotations that appear a small number of times. A better approach would be doing majority voting over cell clusters as it would aggregate and smoothout the predictions over multiple cells. it would also remove most of the low frequency mistakes in the predictions. We will also have a look at the embeddings of scPRINT by plotting its UMAP visualization. In [30]: Copied! #cleaning up the cell types prostate_adata . obs [ 'cleaned_pred_cell_type_ontology_term_id' ] = prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . astype ( str ) prostate_adata . obs . loc [ ~ prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . isin ([ k for k , v in prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . value_counts () . items () if v > 400 ]), 'cleaned_pred_cell_type_ontology_term_id' ] = \"other\" prostate_adata . obs [ 'cleaned_pred_cell_type_ontology_term_id' ] . value_counts () . plot . pie () #cleaning up the cell types prostate_adata.obs['cleaned_pred_cell_type_ontology_term_id'] = prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].astype(str) prostate_adata.obs.loc[~prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].isin([k for k, v in prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].value_counts().items() if v > 400]), 'cleaned_pred_cell_type_ontology_term_id'] = \"other\" prostate_adata.obs['cleaned_pred_cell_type_ontology_term_id'].value_counts().plot.pie() Out[30]: In [31]: Copied! # cleaning up the diseases prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] = prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . astype ( str ) prostate_adata . obs . loc [ ~ prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . isin ([ k for k , v in prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . value_counts () . items () if v > 1000 ]), 'cleaned_pred_disease_ontology_term_id' ] = \"other\" prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () . plot . pie () # cleaning up the diseases prostate_adata.obs['cleaned_pred_disease_ontology_term_id'] = prostate_adata.obs['conv_pred_disease_ontology_term_id'].astype(str) prostate_adata.obs.loc[~prostate_adata.obs['conv_pred_disease_ontology_term_id'].isin([k for k, v in prostate_adata.obs['conv_pred_disease_ontology_term_id'].value_counts().items() if v > 1000]), 'cleaned_pred_disease_ontology_term_id'] = \"other\" prostate_adata.obs['cleaned_pred_disease_ontology_term_id'].value_counts().plot.pie() Out[31]: In [38]: Copied! sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'cleaned_pred_cell_type_ontology_term_id' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'cleaned_pred_disease_ontology_term_id' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'assay' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'disease' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'development_stage' ]) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['cleaned_pred_cell_type_ontology_term_id']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['cleaned_pred_disease_ontology_term_id']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['assay']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['disease']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['development_stage']) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) In [ ]: Copied! prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 20 ) prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id.value_counts().head(20) cleaned_pred_cell_type_ontology_term_id basal cell of epidermis 22449 mammary alveolar cell 9688 vasa recta descending limb cell 8777 CD1c-positive myeloid dendritic cell 5782 effector memory CD8-positive, alpha-beta T cell 5410 smooth muscle cell of the pulmonary artery 5007 other 4972 pancreatic acinar cell 4639 basal epithelial cell of prostatic duct 3405 serous cell of epithelium of trachea 3327 prostate gland microvascular endothelial cell 2747 paneth cell of epithelium of small intestine 2698 mast cell 2365 IgG-negative class switched memory B cell 2348 fibroblast of connective tissue of nonglandular part of prostate 2058 club cell 1794 pulmonary artery endothelial cell 1239 CD141-positive myeloid dendritic cell 1186 mucous neck cell 1039 smooth muscle cell of prostate 857 peptic cell 766 T-helper 17 cell 735 CD14-positive, CD16-negative classical monocyte 671 CD16-negative, CD56-bright natural killer cell, human 666 lung pericyte 663 alveolar type 2 fibroblast cell 646 type II pneumocyte 618 naive B cell 606 effector CD4-positive, alpha-beta T cell 506 fibroblast of connective tissue of glandular part of prostate 464 luminal epithelial cell of mammary gland 437 inflammatory macrophage 436 fibroblast of mammary gland 416 basal cell of epithelium of bronchus 409 Name: count, dtype: int64 In [39]: Copied! # we save for next time prostate_adata . write_h5ad ( \"../../data/prostate_adata_o2uniqsx.h5ad\" ) # we save for next time prostate_adata.write_h5ad(\"../../data/prostate_adata_o2uniqsx.h5ad\") In [2]: Copied! prostate_adata = sc . read_h5ad ( \"../../data/prostate_adata_o2uniqsx.h5ad\" ) prostate_adata = sc.read_h5ad(\"../../data/prostate_adata_o2uniqsx.h5ad\") Clustering and differential expression \u00b6 We will now cluster using the louvain algorithm on a kNN graph. Once we detect a cluster of interest we will perform differential expression analysis on it. Taking as example some B-cell clusters, we will use scanpy's implementation of rank_gene_groups for our differential expression In [15]: Copied! # do louvain mutliple times sc . pp . neighbors ( prostate_adata , n_neighbors = 10 , use_rep = \"scprint\" ) # using multiple resolutions can help spotting smaller clusters sc . tl . louvain ( prostate_adata , resolution = 0.5 , key_added = \"louvain_0.5\" ) sc . tl . louvain ( prostate_adata , resolution = 1.0 , key_added = \"louvain_1.0\" ) # do louvain mutliple times sc.pp.neighbors(prostate_adata, n_neighbors=10, use_rep=\"scprint\") # using multiple resolutions can help spotting smaller clusters sc.tl.louvain(prostate_adata, resolution=0.5, key_added=\"louvain_0.5\") sc.tl.louvain(prostate_adata, resolution=1.0, key_added=\"louvain_1.0\") In [20]: Copied! # check clusters sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = 'louvain_1.0' , show = False , legend_loc = \"on data\" ) # check clusters sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color='louvain_1.0', show=False, legend_loc=\"on data\") /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) Out[20]: In [21]: Copied! # check cluster 9 i = 9 loc = prostate_adata . obs [ 'louvain_1.0' ] == str ( i ) prostate_adata . obs [ loc ] . conv_pred_disease_ontology_term_id . value_counts () . head ( 2 ), prostate_adata . obs [ loc ] . conv_pred_cell_type_ontology_term_id . value_counts () . head ( 5 ) # check cluster 9 i=9 loc = prostate_adata.obs['louvain_1.0']==str(i) prostate_adata.obs[loc].conv_pred_disease_ontology_term_id.value_counts().head(2), prostate_adata.obs[loc].conv_pred_cell_type_ontology_term_id.value_counts().head(5) Out[21]: (conv_pred_disease_ontology_term_id benign prostatic hyperplasia 3554 normal 18 Name: count, dtype: int64, conv_pred_cell_type_ontology_term_id urethra urothelial cell 1703 luminal cell of prostate epithelium 703 mucous neck cell 566 basal epithelial cell of prostatic duct 372 club cell 174 Name: count, dtype: int64) In [6]: Copied! # check cluster 11 i = 11 loc = prostate_adata . obs [ 'louvain_1.0' ] == str ( i ) prostate_adata . obs [ loc ] . cleaned_pred_disease_ontology_term_id . value_counts () . head ( 2 ), prostate_adata . obs [ loc ] . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 5 ) # check cluster 11 i=11 loc = prostate_adata.obs['louvain_1.0']==str(i) prostate_adata.obs[loc].cleaned_pred_disease_ontology_term_id.value_counts().head(2), prostate_adata.obs[loc].cleaned_pred_cell_type_ontology_term_id.value_counts().head(5) Out[6]: (cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 2930 normal 68 Name: count, dtype: int64, cleaned_pred_cell_type_ontology_term_id IgG-negative class switched memory B cell 2840 other 142 CD1c-positive myeloid dendritic cell 8 basophil 7 CD4-positive, alpha-beta thymocyte 5 Name: count, dtype: int64) In [7]: Copied! # We have find a nice IgG-negative class switched memory B cell cluster. let's use it and define a clean annotation for a plot loc = loc & ( prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id == \"IgG-negative class switched memory B cell\" ) prostate_adata . obs [ loc ] . cleaned_pred_disease_ontology_term_id . value_counts () . head ( 2 ) # We have find a nice IgG-negative class switched memory B cell cluster. let's use it and define a clean annotation for a plot loc = loc&(prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id==\"IgG-negative class switched memory B cell\") prostate_adata.obs[loc].cleaned_pred_disease_ontology_term_id.value_counts().head(2) Out[7]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 2771 normal 60 Name: count, dtype: int64 In [8]: Copied! # making a \"focus\" annotation for the B-cell to generate a nice plot of the B-cell cluster only prostate_adata . obs [ 'focus' ] = \"other\" prostate_adata . obs . loc [ loc , 'focus' ] = \"memory B cell\" prostate_adata . obs . loc [ loc & ( prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] == 'benign prostatic hyperplasia' ), 'focus' ] = \"BPH associated memory B cell\" prostate_adata . obs [ 'focus' ] . value_counts () # making a \"focus\" annotation for the B-cell to generate a nice plot of the B-cell cluster only prostate_adata.obs['focus'] = \"other\" prostate_adata.obs.loc[loc, 'focus'] = \"memory B cell\" prostate_adata.obs.loc[loc & (prostate_adata.obs['cleaned_pred_disease_ontology_term_id']=='benign prostatic hyperplasia'), 'focus'] = \"BPH associated memory B cell\" prostate_adata.obs['focus'].value_counts() In [24]: Copied! import matplotlib.pyplot as plt import matplotlib.patches as patches import seaborn as sns color = sns . color_palette ()[ 1 ] fig , ax = plt . subplots ( figsize = ( 2 , 2 )) rect = patches . Rectangle (( 0 , 0 ), 1 , 1 , facecolor = color ) ax . add_patch ( rect ) ax . set_xlim ( 0 , 1 ) ax . set_ylim ( 0 , 1 ) ax . axis ( 'off' ) plt . show () import matplotlib.pyplot as plt import matplotlib.patches as patches import seaborn as sns color = sns.color_palette()[1] fig, ax = plt.subplots(figsize=(2, 2)) rect = patches.Rectangle((0, 0), 1, 1, facecolor=color) ax.add_patch(rect) ax.set_xlim(0, 1) ax.set_ylim(0, 1) ax.axis('off') plt.show() In [32]: Copied! # looking at the B-cell cluster. We can see some normal and BPH-associated memory B-cells sc . pl . embedding ( prostate_adata [( prostate_adata . obs [ 'louvain_1.0' ] == str ( i )) & ( prostate_adata . obsm [ 'scprint_umap' ][:, 0 ] > 4 )], basis = \"scprint_umap\" , color = 'focus' , show = False , size = 8 , title = \"Switched memory B-cell cluster\" , legend_loc = \"right margin\" ) # looking at the B-cell cluster. We can see some normal and BPH-associated memory B-cells sc.pl.embedding(prostate_adata[(prostate_adata.obs['louvain_1.0']==str(i)) & (prostate_adata.obsm['scprint_umap'][:,0]>4)], basis=\"scprint_umap\",color='focus', show=False, size=8, title=\"Switched memory B-cell cluster\", legend_loc=\"right margin\") ... storing 'focus' as categorical /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) Out[32]: In [ ]: Copied! # here we use a function of scdataloader to add some more gene annotations to our dataset so we can view HGNC symbols genedf = utils . load_genes ( prostate_adata . obs . organism_ontology_term_id . iloc [ 0 ]) # columns that create issues when saving anndatas prostate_adata . var = genedf . loc [ prostate_adata . var . index ] . drop ( columns = [ \"stable_id\" , \"created_at\" , \"updated_at\" ]) # here we use a function of scdataloader to add some more gene annotations to our dataset so we can view HGNC symbols genedf = utils.load_genes(prostate_adata.obs.organism_ontology_term_id.iloc[0]) # columns that create issues when saving anndatas prostate_adata.var = genedf.loc[prostate_adata.var.index].drop(columns=[\"stable_id\", \"created_at\", \"updated_at\"]) In [ ]: Copied! # now the diff expression between B-cells and the rest sc . tl . rank_genes_groups ( prostate_adata , groupby = 'cleaned_pred_cell_type_ontology_term_id' , groups = [ 'IgG-negative class switched memory B cell' ], reference = 'other' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # now the diff expression between B-cells and the rest sc.tl.rank_genes_groups(prostate_adata, groupby='cleaned_pred_cell_type_ontology_term_id', groups=['IgG-negative class switched memory B cell'], reference='other', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers ... storing 'focus' as categorical ... storing 'symbol' as categorical ... storing 'ncbi_gene_ids' as categorical ... storing 'biotype' as categorical ... storing 'description' as categorical ... storing 'synonyms' as categorical ... storing 'organism' as categorical WARNING: It seems you use rank_genes_groups on the raw count data. Please logarithmize your data before calling rank_genes_groups. /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/tools/_rank_genes_groups.py:420: RuntimeWarning: overflow encountered in expm1 self.expm1_func(mean_rest) + 1e-9 /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/tools/_rank_genes_groups.py:422: RuntimeWarning: divide by zero encountered in log2 self.stats[group_name, 'logfoldchanges'] = np.log2( Denoising and differential expression \u00b6 What we found out from our previous analysis is that there is not a lot of normal (i.e. healthy) B-cells in our cluster, most of them are BPH associated. In this case, if we wanted to compare BPH B-cells to normal B-cells we might be very underpowered... Instead of going to look for some other dataset, let's use scPRINT to increase the depth of the expression profile of the cells, virtually adding more signal to our dataset. We will use the Denoiser class (see more about the class in our documentation ) in a similar way Trainer is used in pytorch lightning to denoise the expression profile of the cells. We will then show the results of differential expression analysis before and after denoising. In [ ]: Copied! # in case you started from here prostate_adata = sc . read_h5ad ( \"../data/prostate_adata_o2uniqsx.h5ad\" ) prostate_adata # in case you started from here prostate_adata = sc.read_h5ad(\"../data/prostate_adata_o2uniqsx.h5ad\") prostate_adata AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 70116 obs: 'assay_ontology_term_id', 'donor_id', 'sex_ontology_term_id', 'disease_ontology_term_id', 'organism_ontology_term_id', 'suspension_type', 'cell_type_ontology_term_id', 'tissue_ontology_term_id', 'development_stage_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'cell_type', 'assay', 'disease', 'organism', 'sex', 'tissue', 'self_reported_ethnicity', 'development_stage', 'nnz', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb', 'outlier', 'mt_outlier', 'init_dataset', 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id', 'sprint_leiden', 'cleaned_pred_cell_type_ontology_term_id', 'cleaned_pred_disease_ontology_term_id', 'louvain_0.5', 'louvain_1.0', 'fibro' var: 'uid', 'symbol', 'ncbi_gene_ids', 'biotype', 'description', 'synonyms', 'organism_id', 'public_source_id', 'created_by_id', 'mt', 'ribo', 'hb', 'organism' uns: 'louvain', 'neighbors' obsm: 'X_pca', 'X_umap', 'scprint', 'scprint_umap' obsp: 'connectivities', 'distances' In [16]: Copied! # here we compare memory B-cell in BPH to normal memory B cells before denoising sc . tl . rank_genes_groups ( prostate_adata , groupby = 'focus' , groups = [ 'BPH associated memory B cell' ], reference = 'memory B cell' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # here we compare memory B-cell in BPH to normal memory B cells before denoising sc.tl.rank_genes_groups(prostate_adata, groupby='focus', groups=['BPH associated memory B cell'], reference='memory B cell', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers WARNING: It seems you use rank_genes_groups on the raw count data. Please logarithmize your data before calling rank_genes_groups. In [19]: Copied! # perform denoising denoise = Denoiser ( # could be on top differentially expressed genes or on random expressed genes in the cell (completed by random non expressed gene) how = \"random expr\" # the size of the minibatch (need to fit in memory) batch_size = 20 , # the number of genes to use max_len = 5000 , # the number of cells to use (here more than what we will use so we will use everything) plot_corr_size = 10_000 , doplot = False , # how much do we want to increase the depth / counts of the cells (here, 10x) predict_depth_mult = 10 , ) idx , genes , expr = denoise ( model , prostate_adata [ prostate_adata . obs [ 'focus' ] != \"other\" ]) # perform denoising denoise = Denoiser( # could be on top differentially expressed genes or on random expressed genes in the cell (completed by random non expressed gene) how=\"random expr\" # the size of the minibatch (need to fit in memory) batch_size=20, # the number of genes to use max_len=5000, # the number of cells to use (here more than what we will use so we will use everything) plot_corr_size=10_000, doplot=False, # how much do we want to increase the depth / counts of the cells (here, 10x) predict_depth_mult=10, ) idx, genes, expr = denoise(model, prostate_adata[prostate_adata.obs['focus']!=\"other\"]) 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 82/82 [00:50<00:00, 1.64it/s] In [20]: Copied! # now what we are doing here it to complete the expression profile with the denoised values. this is not done by default for now i = 0 prostate_adata . X = prostate_adata . X . tolil () for idx , val in enumerate ( prostate_adata . obs [ 'focus' ] != \"other\" ): if val : prostate_adata . X [ idx , prostate_adata . var . index . get_indexer ( np . array ( model . genes )[ genes [ i ]])] = expr [ i ] i += 1 prostate_adata . X = prostate_adata . X . tocsr () # now what we are doing here it to complete the expression profile with the denoised values. this is not done by default for now i = 0 prostate_adata.X = prostate_adata.X.tolil() for idx, val in enumerate(prostate_adata.obs['focus']!=\"other\"): if val: prostate_adata.X[idx, prostate_adata.var.index.get_indexer(np.array(model.genes)[genes[i]])] = expr[i] i += 1 prostate_adata.X = prostate_adata.X.tocsr() In [21]: Copied! # now we compare memory B-cell in BPH to normal memory B cells after denoising sc . tl . rank_genes_groups ( prostate_adata , groupby = 'focus' , groups = [ 'BPH associated memory B cell' ], reference = 'memory B cell' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # now we compare memory B-cell in BPH to normal memory B cells after denoising sc.tl.rank_genes_groups(prostate_adata, groupby='focus', groups=['BPH associated memory B cell'], reference='memory B cell', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers In [9]: Copied! prostate_adata . write_h5ad ( \"../../data/prostate_adata_denoised.h5ad\" ) prostate_adata.write_h5ad(\"../../data/prostate_adata_denoised.h5ad\") In [3]: Copied! prostate_adata = sc . read_h5ad ( \"../../data/prostate_adata_denoised.h5ad\" ) prostate_adata = sc.read_h5ad(\"../../data/prostate_adata_denoised.h5ad\") Gene network inference \u00b6 Finally we will use scPRINT to infer gene networks on another cell of interest, the fibroblasts, in both normal and BPH conditions. We will use the GRNfer class to infer gene networks. ( see the cancer_usecase_part2.ipynb for more details on how to analyse the gene networks. ) In [38]: Copied! prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 20 ) prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id.value_counts().head(20) Out[38]: cleaned_pred_cell_type_ontology_term_id basal epithelial cell of prostatic duct 25740 prostate gland microvascular endothelial cell 12165 urethra urothelial cell 10952 CD1c-positive myeloid dendritic cell 6898 other 5869 aortic smooth muscle cell 3970 effector CD8-positive, alpha-beta T cell 3925 pancreatic acinar cell 3711 luminal cell of prostate epithelium 3435 fibroblast of connective tissue of nonglandular part of prostate 3334 mucous neck cell 3260 IgG-negative class switched memory B cell 2932 basophil 1862 fibroblast of connective tissue of glandular part of prostate 1815 pancreatic ductal cell 1651 CD4-positive, alpha-beta thymocyte 1516 club cell 1226 smooth muscle cell of prostate 1000 effector memory CD8-positive, alpha-beta T cell 991 peptic cell 872 mature conventional dendritic cell 721 effector CD4-positive, alpha-beta T cell 686 mast cell 451 renal interstitial pericyte 440 retinal blood vessel endothelial cell 404 Name: count, dtype: int64 In [33]: Copied! loc = ( prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id == \"fibroblast of connective tissue of glandular part of prostate\" ) prostate_adata . obs [ loc ][ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () loc = (prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id==\"fibroblast of connective tissue of glandular part of prostate\") prostate_adata.obs[loc]['cleaned_pred_disease_ontology_term_id'].value_counts() Out[33]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 1482 normal 673 other 4 Name: count, dtype: int64 In [52]: Copied! prostate_adata . obs [ loc ][ 'louvain_1.0' ] . value_counts () . head ( 10 ) prostate_adata.obs[loc]['louvain_1.0'].value_counts().head(10) Out[52]: louvain_1.0 5 1458 4 671 17 10 8 8 7 7 0 3 9 2 6 0 3 0 1 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 2 0 18 0 Name: count, dtype: int64 In [34]: Copied! loc = loc & ( prostate_adata . obs [ 'louvain_1.0' ] == str ( 5 )) prostate_adata . obs [ loc ][ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () loc = loc & (prostate_adata.obs['louvain_1.0']==str(5)) prostate_adata.obs[loc]['cleaned_pred_disease_ontology_term_id'].value_counts() Out[34]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 790 normal 664 other 4 Name: count, dtype: int64 In [35]: Copied! prostate_adata . obs [ 'fibro' ] = None prostate_adata . obs . loc [ loc , 'fibro' ] = \"fibroblasts\" prostate_adata . obs . loc [ loc & ( prostate_adata . obs . cleaned_pred_disease_ontology_term_id == \"benign prostatic hyperplasia\" ), 'fibro' ] = \"BPH associated fibroblasts\" prostate_adata.obs['fibro'] = None prostate_adata.obs.loc[loc, 'fibro']=\"fibroblasts\" prostate_adata.obs.loc[loc & (prostate_adata.obs.cleaned_pred_disease_ontology_term_id==\"benign prostatic hyperplasia\"), 'fibro']=\"BPH associated fibroblasts\" In [37]: Copied! sc . pl . embedding ( prostate_adata [ prostate_adata . obs [ 'louvain_1.0' ] . isin ([ \"5\" , \"4\" ]) & ( prostate_adata . obsm [ 'scprint_umap' ][:, 1 ] > 10 )], basis = \"scprint_umap_rot\" , color = 'fibro' , show = False , size = 8 , title = \"Fibroblasts cluster\" , legend_loc = \"right margin\" ) sc.pl.embedding(prostate_adata[prostate_adata.obs['louvain_1.0'].isin([\"5\",\"4\"]) & (prostate_adata.obsm['scprint_umap'][:,1]>10)], basis=\"scprint_umap_rot\",color='fibro', show=False, size=8, title=\"Fibroblasts cluster\", legend_loc=\"right margin\") ... storing 'focus' as categorical ... storing 'fibro' as categorical /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) In [8]: Copied! grn_inferer = GNInfer ( # here we use the most variable genes across the fibroblasts vs the rest how = \"most var across\" , #how=\"random expr\", # we will preprocess the attention matrix with softmax preprocess = \"softmax\" , # we don't aggregate the heads here, we will do it manually head_agg = 'none' , # here if we generate the attention matrices by performing a task, like denoising or by just passing the expression profile through the model forward_mode = \"none\" , # the number of genes to use (here the 4000 most variable genes) num_genes = 4000 , # the max number of cell to use per cell type max_cells = 300 , doplot = False , batch_size = 16 , # the column in anndata the defines the cell type cell_type_col = 'fibro' , # list of layers to use layer = list ( range ( model . nlayers ))[:] ) grn_inferer = GNInfer( # here we use the most variable genes across the fibroblasts vs the rest how=\"most var across\", #how=\"random expr\", # we will preprocess the attention matrix with softmax preprocess=\"softmax\", # we don't aggregate the heads here, we will do it manually head_agg='none', # here if we generate the attention matrices by performing a task, like denoising or by just passing the expression profile through the model forward_mode=\"none\", # the number of genes to use (here the 4000 most variable genes) num_genes=4000, # the max number of cell to use per cell type max_cells=300, doplot=False, batch_size=16, # the column in anndata the defines the cell type cell_type_col='fibro', # list of layers to use layer=list(range(model.nlayers))[:] ) In [9]: Copied! # I was missing this from the model (not really necessary) model . organisms = [ 'NCBITaxon:9606' , 'NCBITaxon:10090' ] prostate_adata . obs . fibro = prostate_adata . obs . fibro . astype ( str ) prostate_adata . obs [ prostate_adata . obs . fibro == \"BPH associated fibroblasts\" ] . disease . value_counts () # I was missing this from the model (not really necessary) model.organisms = ['NCBITaxon:9606', 'NCBITaxon:10090'] prostate_adata.obs.fibro = prostate_adata.obs.fibro.astype(str) prostate_adata.obs[prostate_adata.obs.fibro==\"BPH associated fibroblasts\"].disease.value_counts() In [ ]: Copied! # compute GRNs on fibroblasts, we use all the atetetion layers grn = grn_inferer ( model , prostate_adata , cell_type = \"fibroblasts\" ) # highlight differential links on genes that are expressed in both grn . varp [ 'all' ] = grn . varp [ 'GRN' ] . copy () # now we aggregate the heads by taking their average grn . varp [ 'GRN' ] = grn . varp [ 'GRN' ] . mean ( - 1 ) grn . write_h5ad ( \"../../data/prostate_fibro_grn_all.h5ad\" ) # compute GRNs on fibroblasts, we use all the atetetion layers grn = grn_inferer(model, prostate_adata, cell_type=\"fibroblasts\") # highlight differential links on genes that are expressed in both grn.varp['all'] = grn.varp['GRN'].copy() # now we aggregate the heads by taking their average grn.varp['GRN'] = grn.varp['GRN'].mean(-1) grn.write_h5ad(\"../../data/prostate_fibro_grn_all.h5ad\") In [11]: Copied! #same on the BPH associated fibroblasts # I wanted to use only the ones that the labellers had defined as coing from BPH prostate_adata . obs . loc [( prostate_adata . obs . fibro == \"BPH associated fibroblasts\" ) & ( prostate_adata . obs . disease == \"benign prostatic hyperplasia\" ), 'fibro' ] = \"true BPH associated fibroblasts\" grn_c = grn_inferer ( model , prostate_adata , cell_type = \"true cancer associated fibroblasts\" ) # highlight differential links on genes that are expressed in both grn_c . varp [ 'all' ] = grn_c . varp [ 'GRN' ] . copy () grn_c . varp [ 'GRN' ] = grn_c . varp [ 'GRN' ] . mean ( - 1 ) grn_c . write_h5ad ( \"../../data/prostate_BPH_fibro_grn_all.h5ad\" ) #same on the BPH associated fibroblasts # I wanted to use only the ones that the labellers had defined as coing from BPH prostate_adata.obs.loc[(prostate_adata.obs.fibro==\"BPH associated fibroblasts\") & ( prostate_adata.obs.disease==\"benign prostatic hyperplasia\"), 'fibro'] = \"true BPH associated fibroblasts\" grn_c = grn_inferer(model, prostate_adata, cell_type=\"true cancer associated fibroblasts\") # highlight differential links on genes that are expressed in both grn_c.varp['all'] = grn_c.varp['GRN'].copy() grn_c.varp['GRN'] = grn_c.varp['GRN'].mean(-1) grn_c.write_h5ad(\"../../data/prostate_BPH_fibro_grn_all.h5ad\") ['pre { line-height: 125%; }\\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n.highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) }\\n.highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\\n.highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\\n.highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */\\n.highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\\n.highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\\n.highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\\n.highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\\n.highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\\n.highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\\n.highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\\n.highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\\n.highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\\n.highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\\n.highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\\n.highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\\n.highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\\n.highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\\n.highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\\n.highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\\n.highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\\n.highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\\n.highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\\n.highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\\n.highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\\n.highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\\n.highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\\n.highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\\n.highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\\n.highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\\n.highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\\n.highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\\n.highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\\n.highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\\n.highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\\n.highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\\n.highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\\n.highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\\n.highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\\n.highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\\n.highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\\n.highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\\n.highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */']","title":"scPRINT use case on BPH"},{"location":"notebooks/cancer_usecase/#scprint-use-case-on-bph","text":"In this use-case, also presented in Figure 5 of our manuscript , we perform an extensive analysis of a multi studies dataset of benign prostatic hyperplasia. Our biological question is to check if there exist pre-cancerous cells that exhibits behaviors of mature cancer cells at this early stage of the disease. In those cells, we want to know which genes might be implicated in cell state changes, and explore potentially novel targets in the treatment of prostate cancer and BPH. We will start with a fresh datasets coming from the cellXgene database and representing 2 studies of BPH . We will first explore these dataset to understand: what are the cell types that are present in the data what are the cell distributions (cell distributions? what are they?) what sequencers were used, etc. We also want to confirm existing target in prostate cancer through precancerous lesion analysis, and find potentially novel ones that would serve as less invasive BPH treatments than current ones. Finally we want to know how these targets interacts and are involved in biological pathways. We now showcase how to use scPRINT across its different functionalities to answer some of these questions.","title":"scPRINT use case on BPH"},{"location":"notebooks/cancer_usecase/#table-of-contents","text":"Downloading and preprocessing Embedding and annotations Annotation cleanup Clustering and differential expression Denoising and differential expression Gene network inference In the notebook cancer_usecase_part2.ipynb you will see how to analyse cell type specific gene regulatory networks. In [1]: Copied! from scprint import scPrint from scdataloader import Preprocessor , utils from scprint.tasks import GNInfer , Embedder , Denoiser , withknn from bengrn import BenGRN , get_sroy_gt , compute_genie3 from bengrn.base import train_classifier from grnndata import utils as grnutils from grnndata import read_h5ad from anndata.utils import make_index_unique from anndata import concat import scanpy as sc from matplotlib import pyplot as plt import numpy as np import lamindb as ln % load_ext autoreload % autoreload 2 import torch torch . set_float32_matmul_precision ( 'medium' ) from scprint import scPrint from scdataloader import Preprocessor, utils from scprint.tasks import GNInfer, Embedder, Denoiser, withknn from bengrn import BenGRN, get_sroy_gt, compute_genie3 from bengrn.base import train_classifier from grnndata import utils as grnutils from grnndata import read_h5ad from anndata.utils import make_index_unique from anndata import concat import scanpy as sc from matplotlib import pyplot as plt import numpy as np import lamindb as ln %load_ext autoreload %autoreload 2 import torch torch.set_float32_matmul_precision('medium') \ud83d\udca1 connected lamindb: jkobject/scprint /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/umap/__init__.py:9: ImportWarning: Tensorflow not installed; ParametricUMAP will be unavailable warn( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/chex/_src/pytypes.py:53: DeprecationWarning: jax.core.Shape is deprecated. Use Shape = Sequence[int | Any]. Shape = jax.core.Shape /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/chex/_src/pytypes.py:54: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html PRNGKey = jax.random.KeyArray /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/_types.py:9: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html IntOrKey = Union[int, jax.random.KeyArray] /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_utils.py:40: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def validate_seed(seed: IntOrKey) -> jax.random.KeyArray: /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_kmeans.py:21: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def _initialize_random(X: jnp.ndarray, n_clusters: int, key: jax.random.KeyArray) -> jnp.ndarray: /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_kmeans.py:31: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def _initialize_plus_plus(X: jnp.ndarray, n_clusters: int, key: jax.random.KeyArray) -> jnp.ndarray:","title":"table of contents:"},{"location":"notebooks/cancer_usecase/#downloading-and-preprocessing","text":"We now use lamindb to easily access cellxgene and download a dataset of normal and benign prostatic hyperplasia tissues. data is available here https://cellxgene.cziscience.com/e/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.cxg/ . We then use scDataloader's preprocessing method. This method is quite extensive and does a few things.. find our more about it on its documentation . On our end we are using the preprocessor to make sure that the the gene expression that we have are raw counts and that we have enough information to use scPRINT (i.e., enough genes expressed and enough counts per cells across the dataset). Finally, the preprocessor will also increase the size of the expression matrix to be a fixed set of genes defined by the latest version of ensemble. In [2]: Copied! cx_dataset = ln . Collection . using ( instance = \"laminlabs/cellxgene\" ) . filter ( name = \"cellxgene-census\" , version = '2023-12-15' ) . one () cx_dataset = ln.Collection.using(instance=\"laminlabs/cellxgene\").filter(name=\"cellxgene-census\", version='2023-12-15').one() In [3]: Copied! prostate_adata = cx_dataset . artifacts . filter ( key = 'cell-census/2023-12-15/h5ads/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.h5ad' ) . one () . load () sc . pl . umap ( prostate_adata ) prostate_adata = cx_dataset.artifacts.filter(key='cell-census/2023-12-15/h5ads/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.h5ad').one().load() sc.pl.umap(prostate_adata) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/asyncio/sslproto.py:320: ResourceWarning: unclosed transport _warn(f\"unclosed transport {self!r}\", ResourceWarning, source=self) ResourceWarning: Enable tracemalloc to get the object allocation traceback In [7]: Copied! # preprocessing using scDataloader prostate_adata . obs . drop ( columns = \"is_primary_data\" , inplace = True ) preprocessor = Preprocessor ( do_postp = False ) prostate_adata = preprocessor ( prostate_adata ) # preprocessing using scDataloader prostate_adata.obs.drop(columns=\"is_primary_data\", inplace=True) preprocessor = Preprocessor(do_postp=False) prostate_adata = preprocessor(prostate_adata) Dropping layers: KeysView(Layers with keys: ) checking raw counts removed 0 non primary cells, 83451 renamining filtered out 0 cells, 83451 renamining Removed 76 genes. validating /home/ml4ig1/Documents code/scPRINT/scDataLoader/scdataloader/preprocess.py:241: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]` data_utils.validate(adata, organism=adata.obs.organism_ontology_term_id[0]) startin QC Seeing 13047 outliers (15.63% of total dataset): done","title":"Downloading and preprocessing"},{"location":"notebooks/cancer_usecase/#embedding-and-annotations","text":"We now start to load a large version of scPRINT from a specific checkpoint. Please download the checkpoints following the instructions in the README. We will then use out Embedder class to embed the data and annotate the cells. These classes are how we parametrize and access the different functions of scPRINT . Find out more about its parameters in our documentation . In [6]: Copied! model = scPrint . load_from_checkpoint ( '../data/temp/o2uniqsx/epoch=18-step=133000.ckpt' , # make sure that you check if you have a GPU with flashattention or not (see README) # you need this else, the model will look for the file with the embeddings instead of getting them from the weights precpt_gene_emb = None ) model = scPrint.load_from_checkpoint('../data/temp/o2uniqsx/epoch=18-step=133000.ckpt', # make sure that you check if you have a GPU with flashattention or not (see README) # you need this else, the model will look for the file with the embeddings instead of getting them from the weights precpt_gene_emb = None) RuntimeError caught: scPrint is not attached to a `Trainer`. In [10]: Copied! embedder = Embedder ( # can work on random genes or most variables etc.. how = \"random expr\" , # number of genes to use max_len = 4000 , add_zero_genes = 0 , # for the dataloading num_workers = 8 , # we will only use the cell type embedding here. pred_embedding = [ \"cell_type_ontology_term_id\" ] ) #, \"disease_ontology_term_id\"]) embedder = Embedder( # can work on random genes or most variables etc.. how=\"random expr\", # number of genes to use max_len=4000, add_zero_genes=0, # for the dataloading num_workers=8, # we will only use the cell type embedding here. pred_embedding = [\"cell_type_ontology_term_id\"] )#, \"disease_ontology_term_id\"]) Using 16bit Automatic Mixed Precision (AMP) GPU available: True (cuda), used: True TPU available: False, using: 0 TPU cores IPU available: False, using: 0 IPUs HPU available: False, using: 0 HPUs In [ ]: Copied! # create the embedding prostate_adata , metrics = embedder ( model , prostate_adata , cache = False , output_expression = \"none\" ) # create the embedding prostate_adata, metrics = embedder(model, prostate_adata, cache=False, output_expression=\"none\") 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 1560/1560 [28:20<00:00, 1.09s/it] AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 424 obs: 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id' /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) couldn't log to tensorboard couldn't log to wandb couldn't log to wandb cell_type_ontology_term_id accuracy: 0.7250215374752068 disease_ontology_term_id accuracy: 0.8394506441207702 assay_ontology_term_id accuracy: 0.998988239536794 self_reported_ethnicity_ontology_term_id accuracy: 0.9504037024422495 sex_ontology_term_id accuracy: 0.9948911105323263 organism_ontology_term_id accuracy: 1.0 In [16]: Copied! prostate_adata prostate_adata Out[16]: AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 70116 obs: 'assay_ontology_term_id', 'donor_id', 'sex_ontology_term_id', 'disease_ontology_term_id', 'organism_ontology_term_id', 'suspension_type', 'cell_type_ontology_term_id', 'tissue_ontology_term_id', 'development_stage_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'cell_type', 'assay', 'disease', 'organism', 'sex', 'tissue', 'self_reported_ethnicity', 'development_stage', 'nnz', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb', 'outlier', 'mt_outlier', 'init_dataset', 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id', 'sprint_leiden' uns: 'init_dataset_colors' obsm: 'X_pca', 'X_umap', 'scprint_umap', 'scprint'","title":"Embedding and annotations"},{"location":"notebooks/cancer_usecase/#annotation-cleanup","text":"scPRINT generates predictions over hundreds of possible labels for each cell. It is often advised to \"cleanup\" the predictions, e.g. making sure to remove low frequency cells and misslabellings. Here, we use the most straightforward approach which is to remove any annotations that appear a small number of times. A better approach would be doing majority voting over cell clusters as it would aggregate and smoothout the predictions over multiple cells. it would also remove most of the low frequency mistakes in the predictions. We will also have a look at the embeddings of scPRINT by plotting its UMAP visualization. In [30]: Copied! #cleaning up the cell types prostate_adata . obs [ 'cleaned_pred_cell_type_ontology_term_id' ] = prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . astype ( str ) prostate_adata . obs . loc [ ~ prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . isin ([ k for k , v in prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . value_counts () . items () if v > 400 ]), 'cleaned_pred_cell_type_ontology_term_id' ] = \"other\" prostate_adata . obs [ 'cleaned_pred_cell_type_ontology_term_id' ] . value_counts () . plot . pie () #cleaning up the cell types prostate_adata.obs['cleaned_pred_cell_type_ontology_term_id'] = prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].astype(str) prostate_adata.obs.loc[~prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].isin([k for k, v in prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].value_counts().items() if v > 400]), 'cleaned_pred_cell_type_ontology_term_id'] = \"other\" prostate_adata.obs['cleaned_pred_cell_type_ontology_term_id'].value_counts().plot.pie() Out[30]: In [31]: Copied! # cleaning up the diseases prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] = prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . astype ( str ) prostate_adata . obs . loc [ ~ prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . isin ([ k for k , v in prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . value_counts () . items () if v > 1000 ]), 'cleaned_pred_disease_ontology_term_id' ] = \"other\" prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () . plot . pie () # cleaning up the diseases prostate_adata.obs['cleaned_pred_disease_ontology_term_id'] = prostate_adata.obs['conv_pred_disease_ontology_term_id'].astype(str) prostate_adata.obs.loc[~prostate_adata.obs['conv_pred_disease_ontology_term_id'].isin([k for k, v in prostate_adata.obs['conv_pred_disease_ontology_term_id'].value_counts().items() if v > 1000]), 'cleaned_pred_disease_ontology_term_id'] = \"other\" prostate_adata.obs['cleaned_pred_disease_ontology_term_id'].value_counts().plot.pie() Out[31]: In [38]: Copied! sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'cleaned_pred_cell_type_ontology_term_id' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'cleaned_pred_disease_ontology_term_id' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'assay' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'disease' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'development_stage' ]) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['cleaned_pred_cell_type_ontology_term_id']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['cleaned_pred_disease_ontology_term_id']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['assay']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['disease']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['development_stage']) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) In [ ]: Copied! prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 20 ) prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id.value_counts().head(20) cleaned_pred_cell_type_ontology_term_id basal cell of epidermis 22449 mammary alveolar cell 9688 vasa recta descending limb cell 8777 CD1c-positive myeloid dendritic cell 5782 effector memory CD8-positive, alpha-beta T cell 5410 smooth muscle cell of the pulmonary artery 5007 other 4972 pancreatic acinar cell 4639 basal epithelial cell of prostatic duct 3405 serous cell of epithelium of trachea 3327 prostate gland microvascular endothelial cell 2747 paneth cell of epithelium of small intestine 2698 mast cell 2365 IgG-negative class switched memory B cell 2348 fibroblast of connective tissue of nonglandular part of prostate 2058 club cell 1794 pulmonary artery endothelial cell 1239 CD141-positive myeloid dendritic cell 1186 mucous neck cell 1039 smooth muscle cell of prostate 857 peptic cell 766 T-helper 17 cell 735 CD14-positive, CD16-negative classical monocyte 671 CD16-negative, CD56-bright natural killer cell, human 666 lung pericyte 663 alveolar type 2 fibroblast cell 646 type II pneumocyte 618 naive B cell 606 effector CD4-positive, alpha-beta T cell 506 fibroblast of connective tissue of glandular part of prostate 464 luminal epithelial cell of mammary gland 437 inflammatory macrophage 436 fibroblast of mammary gland 416 basal cell of epithelium of bronchus 409 Name: count, dtype: int64 In [39]: Copied! # we save for next time prostate_adata . write_h5ad ( \"../../data/prostate_adata_o2uniqsx.h5ad\" ) # we save for next time prostate_adata.write_h5ad(\"../../data/prostate_adata_o2uniqsx.h5ad\") In [2]: Copied! prostate_adata = sc . read_h5ad ( \"../../data/prostate_adata_o2uniqsx.h5ad\" ) prostate_adata = sc.read_h5ad(\"../../data/prostate_adata_o2uniqsx.h5ad\")","title":"Annotation cleanup"},{"location":"notebooks/cancer_usecase/#clustering-and-differential-expression","text":"We will now cluster using the louvain algorithm on a kNN graph. Once we detect a cluster of interest we will perform differential expression analysis on it. Taking as example some B-cell clusters, we will use scanpy's implementation of rank_gene_groups for our differential expression In [15]: Copied! # do louvain mutliple times sc . pp . neighbors ( prostate_adata , n_neighbors = 10 , use_rep = \"scprint\" ) # using multiple resolutions can help spotting smaller clusters sc . tl . louvain ( prostate_adata , resolution = 0.5 , key_added = \"louvain_0.5\" ) sc . tl . louvain ( prostate_adata , resolution = 1.0 , key_added = \"louvain_1.0\" ) # do louvain mutliple times sc.pp.neighbors(prostate_adata, n_neighbors=10, use_rep=\"scprint\") # using multiple resolutions can help spotting smaller clusters sc.tl.louvain(prostate_adata, resolution=0.5, key_added=\"louvain_0.5\") sc.tl.louvain(prostate_adata, resolution=1.0, key_added=\"louvain_1.0\") In [20]: Copied! # check clusters sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = 'louvain_1.0' , show = False , legend_loc = \"on data\" ) # check clusters sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color='louvain_1.0', show=False, legend_loc=\"on data\") /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) Out[20]: In [21]: Copied! # check cluster 9 i = 9 loc = prostate_adata . obs [ 'louvain_1.0' ] == str ( i ) prostate_adata . obs [ loc ] . conv_pred_disease_ontology_term_id . value_counts () . head ( 2 ), prostate_adata . obs [ loc ] . conv_pred_cell_type_ontology_term_id . value_counts () . head ( 5 ) # check cluster 9 i=9 loc = prostate_adata.obs['louvain_1.0']==str(i) prostate_adata.obs[loc].conv_pred_disease_ontology_term_id.value_counts().head(2), prostate_adata.obs[loc].conv_pred_cell_type_ontology_term_id.value_counts().head(5) Out[21]: (conv_pred_disease_ontology_term_id benign prostatic hyperplasia 3554 normal 18 Name: count, dtype: int64, conv_pred_cell_type_ontology_term_id urethra urothelial cell 1703 luminal cell of prostate epithelium 703 mucous neck cell 566 basal epithelial cell of prostatic duct 372 club cell 174 Name: count, dtype: int64) In [6]: Copied! # check cluster 11 i = 11 loc = prostate_adata . obs [ 'louvain_1.0' ] == str ( i ) prostate_adata . obs [ loc ] . cleaned_pred_disease_ontology_term_id . value_counts () . head ( 2 ), prostate_adata . obs [ loc ] . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 5 ) # check cluster 11 i=11 loc = prostate_adata.obs['louvain_1.0']==str(i) prostate_adata.obs[loc].cleaned_pred_disease_ontology_term_id.value_counts().head(2), prostate_adata.obs[loc].cleaned_pred_cell_type_ontology_term_id.value_counts().head(5) Out[6]: (cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 2930 normal 68 Name: count, dtype: int64, cleaned_pred_cell_type_ontology_term_id IgG-negative class switched memory B cell 2840 other 142 CD1c-positive myeloid dendritic cell 8 basophil 7 CD4-positive, alpha-beta thymocyte 5 Name: count, dtype: int64) In [7]: Copied! # We have find a nice IgG-negative class switched memory B cell cluster. let's use it and define a clean annotation for a plot loc = loc & ( prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id == \"IgG-negative class switched memory B cell\" ) prostate_adata . obs [ loc ] . cleaned_pred_disease_ontology_term_id . value_counts () . head ( 2 ) # We have find a nice IgG-negative class switched memory B cell cluster. let's use it and define a clean annotation for a plot loc = loc&(prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id==\"IgG-negative class switched memory B cell\") prostate_adata.obs[loc].cleaned_pred_disease_ontology_term_id.value_counts().head(2) Out[7]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 2771 normal 60 Name: count, dtype: int64 In [8]: Copied! # making a \"focus\" annotation for the B-cell to generate a nice plot of the B-cell cluster only prostate_adata . obs [ 'focus' ] = \"other\" prostate_adata . obs . loc [ loc , 'focus' ] = \"memory B cell\" prostate_adata . obs . loc [ loc & ( prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] == 'benign prostatic hyperplasia' ), 'focus' ] = \"BPH associated memory B cell\" prostate_adata . obs [ 'focus' ] . value_counts () # making a \"focus\" annotation for the B-cell to generate a nice plot of the B-cell cluster only prostate_adata.obs['focus'] = \"other\" prostate_adata.obs.loc[loc, 'focus'] = \"memory B cell\" prostate_adata.obs.loc[loc & (prostate_adata.obs['cleaned_pred_disease_ontology_term_id']=='benign prostatic hyperplasia'), 'focus'] = \"BPH associated memory B cell\" prostate_adata.obs['focus'].value_counts() In [24]: Copied! import matplotlib.pyplot as plt import matplotlib.patches as patches import seaborn as sns color = sns . color_palette ()[ 1 ] fig , ax = plt . subplots ( figsize = ( 2 , 2 )) rect = patches . Rectangle (( 0 , 0 ), 1 , 1 , facecolor = color ) ax . add_patch ( rect ) ax . set_xlim ( 0 , 1 ) ax . set_ylim ( 0 , 1 ) ax . axis ( 'off' ) plt . show () import matplotlib.pyplot as plt import matplotlib.patches as patches import seaborn as sns color = sns.color_palette()[1] fig, ax = plt.subplots(figsize=(2, 2)) rect = patches.Rectangle((0, 0), 1, 1, facecolor=color) ax.add_patch(rect) ax.set_xlim(0, 1) ax.set_ylim(0, 1) ax.axis('off') plt.show() In [32]: Copied! # looking at the B-cell cluster. We can see some normal and BPH-associated memory B-cells sc . pl . embedding ( prostate_adata [( prostate_adata . obs [ 'louvain_1.0' ] == str ( i )) & ( prostate_adata . obsm [ 'scprint_umap' ][:, 0 ] > 4 )], basis = \"scprint_umap\" , color = 'focus' , show = False , size = 8 , title = \"Switched memory B-cell cluster\" , legend_loc = \"right margin\" ) # looking at the B-cell cluster. We can see some normal and BPH-associated memory B-cells sc.pl.embedding(prostate_adata[(prostate_adata.obs['louvain_1.0']==str(i)) & (prostate_adata.obsm['scprint_umap'][:,0]>4)], basis=\"scprint_umap\",color='focus', show=False, size=8, title=\"Switched memory B-cell cluster\", legend_loc=\"right margin\") ... storing 'focus' as categorical /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) Out[32]: In [ ]: Copied! # here we use a function of scdataloader to add some more gene annotations to our dataset so we can view HGNC symbols genedf = utils . load_genes ( prostate_adata . obs . organism_ontology_term_id . iloc [ 0 ]) # columns that create issues when saving anndatas prostate_adata . var = genedf . loc [ prostate_adata . var . index ] . drop ( columns = [ \"stable_id\" , \"created_at\" , \"updated_at\" ]) # here we use a function of scdataloader to add some more gene annotations to our dataset so we can view HGNC symbols genedf = utils.load_genes(prostate_adata.obs.organism_ontology_term_id.iloc[0]) # columns that create issues when saving anndatas prostate_adata.var = genedf.loc[prostate_adata.var.index].drop(columns=[\"stable_id\", \"created_at\", \"updated_at\"]) In [ ]: Copied! # now the diff expression between B-cells and the rest sc . tl . rank_genes_groups ( prostate_adata , groupby = 'cleaned_pred_cell_type_ontology_term_id' , groups = [ 'IgG-negative class switched memory B cell' ], reference = 'other' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # now the diff expression between B-cells and the rest sc.tl.rank_genes_groups(prostate_adata, groupby='cleaned_pred_cell_type_ontology_term_id', groups=['IgG-negative class switched memory B cell'], reference='other', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers ... storing 'focus' as categorical ... storing 'symbol' as categorical ... storing 'ncbi_gene_ids' as categorical ... storing 'biotype' as categorical ... storing 'description' as categorical ... storing 'synonyms' as categorical ... storing 'organism' as categorical WARNING: It seems you use rank_genes_groups on the raw count data. Please logarithmize your data before calling rank_genes_groups. /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/tools/_rank_genes_groups.py:420: RuntimeWarning: overflow encountered in expm1 self.expm1_func(mean_rest) + 1e-9 /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/tools/_rank_genes_groups.py:422: RuntimeWarning: divide by zero encountered in log2 self.stats[group_name, 'logfoldchanges'] = np.log2(","title":"Clustering and differential expression"},{"location":"notebooks/cancer_usecase/#denoising-and-differential-expression","text":"What we found out from our previous analysis is that there is not a lot of normal (i.e. healthy) B-cells in our cluster, most of them are BPH associated. In this case, if we wanted to compare BPH B-cells to normal B-cells we might be very underpowered... Instead of going to look for some other dataset, let's use scPRINT to increase the depth of the expression profile of the cells, virtually adding more signal to our dataset. We will use the Denoiser class (see more about the class in our documentation ) in a similar way Trainer is used in pytorch lightning to denoise the expression profile of the cells. We will then show the results of differential expression analysis before and after denoising. In [ ]: Copied! # in case you started from here prostate_adata = sc . read_h5ad ( \"../data/prostate_adata_o2uniqsx.h5ad\" ) prostate_adata # in case you started from here prostate_adata = sc.read_h5ad(\"../data/prostate_adata_o2uniqsx.h5ad\") prostate_adata AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 70116 obs: 'assay_ontology_term_id', 'donor_id', 'sex_ontology_term_id', 'disease_ontology_term_id', 'organism_ontology_term_id', 'suspension_type', 'cell_type_ontology_term_id', 'tissue_ontology_term_id', 'development_stage_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'cell_type', 'assay', 'disease', 'organism', 'sex', 'tissue', 'self_reported_ethnicity', 'development_stage', 'nnz', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb', 'outlier', 'mt_outlier', 'init_dataset', 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id', 'sprint_leiden', 'cleaned_pred_cell_type_ontology_term_id', 'cleaned_pred_disease_ontology_term_id', 'louvain_0.5', 'louvain_1.0', 'fibro' var: 'uid', 'symbol', 'ncbi_gene_ids', 'biotype', 'description', 'synonyms', 'organism_id', 'public_source_id', 'created_by_id', 'mt', 'ribo', 'hb', 'organism' uns: 'louvain', 'neighbors' obsm: 'X_pca', 'X_umap', 'scprint', 'scprint_umap' obsp: 'connectivities', 'distances' In [16]: Copied! # here we compare memory B-cell in BPH to normal memory B cells before denoising sc . tl . rank_genes_groups ( prostate_adata , groupby = 'focus' , groups = [ 'BPH associated memory B cell' ], reference = 'memory B cell' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # here we compare memory B-cell in BPH to normal memory B cells before denoising sc.tl.rank_genes_groups(prostate_adata, groupby='focus', groups=['BPH associated memory B cell'], reference='memory B cell', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers WARNING: It seems you use rank_genes_groups on the raw count data. Please logarithmize your data before calling rank_genes_groups. In [19]: Copied! # perform denoising denoise = Denoiser ( # could be on top differentially expressed genes or on random expressed genes in the cell (completed by random non expressed gene) how = \"random expr\" # the size of the minibatch (need to fit in memory) batch_size = 20 , # the number of genes to use max_len = 5000 , # the number of cells to use (here more than what we will use so we will use everything) plot_corr_size = 10_000 , doplot = False , # how much do we want to increase the depth / counts of the cells (here, 10x) predict_depth_mult = 10 , ) idx , genes , expr = denoise ( model , prostate_adata [ prostate_adata . obs [ 'focus' ] != \"other\" ]) # perform denoising denoise = Denoiser( # could be on top differentially expressed genes or on random expressed genes in the cell (completed by random non expressed gene) how=\"random expr\" # the size of the minibatch (need to fit in memory) batch_size=20, # the number of genes to use max_len=5000, # the number of cells to use (here more than what we will use so we will use everything) plot_corr_size=10_000, doplot=False, # how much do we want to increase the depth / counts of the cells (here, 10x) predict_depth_mult=10, ) idx, genes, expr = denoise(model, prostate_adata[prostate_adata.obs['focus']!=\"other\"]) 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 82/82 [00:50<00:00, 1.64it/s] In [20]: Copied! # now what we are doing here it to complete the expression profile with the denoised values. this is not done by default for now i = 0 prostate_adata . X = prostate_adata . X . tolil () for idx , val in enumerate ( prostate_adata . obs [ 'focus' ] != \"other\" ): if val : prostate_adata . X [ idx , prostate_adata . var . index . get_indexer ( np . array ( model . genes )[ genes [ i ]])] = expr [ i ] i += 1 prostate_adata . X = prostate_adata . X . tocsr () # now what we are doing here it to complete the expression profile with the denoised values. this is not done by default for now i = 0 prostate_adata.X = prostate_adata.X.tolil() for idx, val in enumerate(prostate_adata.obs['focus']!=\"other\"): if val: prostate_adata.X[idx, prostate_adata.var.index.get_indexer(np.array(model.genes)[genes[i]])] = expr[i] i += 1 prostate_adata.X = prostate_adata.X.tocsr() In [21]: Copied! # now we compare memory B-cell in BPH to normal memory B cells after denoising sc . tl . rank_genes_groups ( prostate_adata , groupby = 'focus' , groups = [ 'BPH associated memory B cell' ], reference = 'memory B cell' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # now we compare memory B-cell in BPH to normal memory B cells after denoising sc.tl.rank_genes_groups(prostate_adata, groupby='focus', groups=['BPH associated memory B cell'], reference='memory B cell', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers In [9]: Copied! prostate_adata . write_h5ad ( \"../../data/prostate_adata_denoised.h5ad\" ) prostate_adata.write_h5ad(\"../../data/prostate_adata_denoised.h5ad\") In [3]: Copied! prostate_adata = sc . read_h5ad ( \"../../data/prostate_adata_denoised.h5ad\" ) prostate_adata = sc.read_h5ad(\"../../data/prostate_adata_denoised.h5ad\")","title":"Denoising and differential expression"},{"location":"notebooks/cancer_usecase/#gene-network-inference","text":"Finally we will use scPRINT to infer gene networks on another cell of interest, the fibroblasts, in both normal and BPH conditions. We will use the GRNfer class to infer gene networks. ( see the cancer_usecase_part2.ipynb for more details on how to analyse the gene networks. ) In [38]: Copied! prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 20 ) prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id.value_counts().head(20) Out[38]: cleaned_pred_cell_type_ontology_term_id basal epithelial cell of prostatic duct 25740 prostate gland microvascular endothelial cell 12165 urethra urothelial cell 10952 CD1c-positive myeloid dendritic cell 6898 other 5869 aortic smooth muscle cell 3970 effector CD8-positive, alpha-beta T cell 3925 pancreatic acinar cell 3711 luminal cell of prostate epithelium 3435 fibroblast of connective tissue of nonglandular part of prostate 3334 mucous neck cell 3260 IgG-negative class switched memory B cell 2932 basophil 1862 fibroblast of connective tissue of glandular part of prostate 1815 pancreatic ductal cell 1651 CD4-positive, alpha-beta thymocyte 1516 club cell 1226 smooth muscle cell of prostate 1000 effector memory CD8-positive, alpha-beta T cell 991 peptic cell 872 mature conventional dendritic cell 721 effector CD4-positive, alpha-beta T cell 686 mast cell 451 renal interstitial pericyte 440 retinal blood vessel endothelial cell 404 Name: count, dtype: int64 In [33]: Copied! loc = ( prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id == \"fibroblast of connective tissue of glandular part of prostate\" ) prostate_adata . obs [ loc ][ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () loc = (prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id==\"fibroblast of connective tissue of glandular part of prostate\") prostate_adata.obs[loc]['cleaned_pred_disease_ontology_term_id'].value_counts() Out[33]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 1482 normal 673 other 4 Name: count, dtype: int64 In [52]: Copied! prostate_adata . obs [ loc ][ 'louvain_1.0' ] . value_counts () . head ( 10 ) prostate_adata.obs[loc]['louvain_1.0'].value_counts().head(10) Out[52]: louvain_1.0 5 1458 4 671 17 10 8 8 7 7 0 3 9 2 6 0 3 0 1 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 2 0 18 0 Name: count, dtype: int64 In [34]: Copied! loc = loc & ( prostate_adata . obs [ 'louvain_1.0' ] == str ( 5 )) prostate_adata . obs [ loc ][ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () loc = loc & (prostate_adata.obs['louvain_1.0']==str(5)) prostate_adata.obs[loc]['cleaned_pred_disease_ontology_term_id'].value_counts() Out[34]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 790 normal 664 other 4 Name: count, dtype: int64 In [35]: Copied! prostate_adata . obs [ 'fibro' ] = None prostate_adata . obs . loc [ loc , 'fibro' ] = \"fibroblasts\" prostate_adata . obs . loc [ loc & ( prostate_adata . obs . cleaned_pred_disease_ontology_term_id == \"benign prostatic hyperplasia\" ), 'fibro' ] = \"BPH associated fibroblasts\" prostate_adata.obs['fibro'] = None prostate_adata.obs.loc[loc, 'fibro']=\"fibroblasts\" prostate_adata.obs.loc[loc & (prostate_adata.obs.cleaned_pred_disease_ontology_term_id==\"benign prostatic hyperplasia\"), 'fibro']=\"BPH associated fibroblasts\" In [37]: Copied! sc . pl . embedding ( prostate_adata [ prostate_adata . obs [ 'louvain_1.0' ] . isin ([ \"5\" , \"4\" ]) & ( prostate_adata . obsm [ 'scprint_umap' ][:, 1 ] > 10 )], basis = \"scprint_umap_rot\" , color = 'fibro' , show = False , size = 8 , title = \"Fibroblasts cluster\" , legend_loc = \"right margin\" ) sc.pl.embedding(prostate_adata[prostate_adata.obs['louvain_1.0'].isin([\"5\",\"4\"]) & (prostate_adata.obsm['scprint_umap'][:,1]>10)], basis=\"scprint_umap_rot\",color='fibro', show=False, size=8, title=\"Fibroblasts cluster\", legend_loc=\"right margin\") ... storing 'focus' as categorical ... storing 'fibro' as categorical /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) In [8]: Copied! grn_inferer = GNInfer ( # here we use the most variable genes across the fibroblasts vs the rest how = \"most var across\" , #how=\"random expr\", # we will preprocess the attention matrix with softmax preprocess = \"softmax\" , # we don't aggregate the heads here, we will do it manually head_agg = 'none' , # here if we generate the attention matrices by performing a task, like denoising or by just passing the expression profile through the model forward_mode = \"none\" , # the number of genes to use (here the 4000 most variable genes) num_genes = 4000 , # the max number of cell to use per cell type max_cells = 300 , doplot = False , batch_size = 16 , # the column in anndata the defines the cell type cell_type_col = 'fibro' , # list of layers to use layer = list ( range ( model . nlayers ))[:] ) grn_inferer = GNInfer( # here we use the most variable genes across the fibroblasts vs the rest how=\"most var across\", #how=\"random expr\", # we will preprocess the attention matrix with softmax preprocess=\"softmax\", # we don't aggregate the heads here, we will do it manually head_agg='none', # here if we generate the attention matrices by performing a task, like denoising or by just passing the expression profile through the model forward_mode=\"none\", # the number of genes to use (here the 4000 most variable genes) num_genes=4000, # the max number of cell to use per cell type max_cells=300, doplot=False, batch_size=16, # the column in anndata the defines the cell type cell_type_col='fibro', # list of layers to use layer=list(range(model.nlayers))[:] ) In [9]: Copied! # I was missing this from the model (not really necessary) model . organisms = [ 'NCBITaxon:9606' , 'NCBITaxon:10090' ] prostate_adata . obs . fibro = prostate_adata . obs . fibro . astype ( str ) prostate_adata . obs [ prostate_adata . obs . fibro == \"BPH associated fibroblasts\" ] . disease . value_counts () # I was missing this from the model (not really necessary) model.organisms = ['NCBITaxon:9606', 'NCBITaxon:10090'] prostate_adata.obs.fibro = prostate_adata.obs.fibro.astype(str) prostate_adata.obs[prostate_adata.obs.fibro==\"BPH associated fibroblasts\"].disease.value_counts() In [ ]: Copied! # compute GRNs on fibroblasts, we use all the atetetion layers grn = grn_inferer ( model , prostate_adata , cell_type = \"fibroblasts\" ) # highlight differential links on genes that are expressed in both grn . varp [ 'all' ] = grn . varp [ 'GRN' ] . copy () # now we aggregate the heads by taking their average grn . varp [ 'GRN' ] = grn . varp [ 'GRN' ] . mean ( - 1 ) grn . write_h5ad ( \"../../data/prostate_fibro_grn_all.h5ad\" ) # compute GRNs on fibroblasts, we use all the atetetion layers grn = grn_inferer(model, prostate_adata, cell_type=\"fibroblasts\") # highlight differential links on genes that are expressed in both grn.varp['all'] = grn.varp['GRN'].copy() # now we aggregate the heads by taking their average grn.varp['GRN'] = grn.varp['GRN'].mean(-1) grn.write_h5ad(\"../../data/prostate_fibro_grn_all.h5ad\") In [11]: Copied! #same on the BPH associated fibroblasts # I wanted to use only the ones that the labellers had defined as coing from BPH prostate_adata . obs . loc [( prostate_adata . obs . fibro == \"BPH associated fibroblasts\" ) & ( prostate_adata . obs . disease == \"benign prostatic hyperplasia\" ), 'fibro' ] = \"true BPH associated fibroblasts\" grn_c = grn_inferer ( model , prostate_adata , cell_type = \"true cancer associated fibroblasts\" ) # highlight differential links on genes that are expressed in both grn_c . varp [ 'all' ] = grn_c . varp [ 'GRN' ] . copy () grn_c . varp [ 'GRN' ] = grn_c . varp [ 'GRN' ] . mean ( - 1 ) grn_c . write_h5ad ( \"../../data/prostate_BPH_fibro_grn_all.h5ad\" ) #same on the BPH associated fibroblasts # I wanted to use only the ones that the labellers had defined as coing from BPH prostate_adata.obs.loc[(prostate_adata.obs.fibro==\"BPH associated fibroblasts\") & ( prostate_adata.obs.disease==\"benign prostatic hyperplasia\"), 'fibro'] = \"true BPH associated fibroblasts\" grn_c = grn_inferer(model, prostate_adata, cell_type=\"true cancer associated fibroblasts\") # highlight differential links on genes that are expressed in both grn_c.varp['all'] = grn_c.varp['GRN'].copy() grn_c.varp['GRN'] = grn_c.varp['GRN'].mean(-1) grn_c.write_h5ad(\"../../data/prostate_BPH_fibro_grn_all.h5ad\") ['pre { line-height: 125%; }\\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n.highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) }\\n.highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\\n.highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\\n.highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */\\n.highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\\n.highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\\n.highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\\n.highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\\n.highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\\n.highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\\n.highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\\n.highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\\n.highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\\n.highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\\n.highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\\n.highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\\n.highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\\n.highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\\n.highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\\n.highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\\n.highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\\n.highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\\n.highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\\n.highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\\n.highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\\n.highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\\n.highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\\n.highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\\n.highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\\n.highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\\n.highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\\n.highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\\n.highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\\n.highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\\n.highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\\n.highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\\n.highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\\n.highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\\n.highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\\n.highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\\n.highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\\n.highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\\n.highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */']","title":"Gene network inference"},{"location":"notebooks/cancer_usecase_part2/","text":"(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.ClipboardCopyElement = factory()); }(this, function () { 'use strict'; function createNode(text) { const node = document.createElement('pre'); node.style.width = '1px'; node.style.height = '1px'; node.style.position = 'fixed'; node.style.top = '5px'; node.textContent = text; return node; } function copyNode(node) { if ('clipboard' in navigator) { // eslint-disable-next-line flowtype/no-flow-fix-me-comments // $FlowFixMe Clipboard is not defined in Flow yet. return navigator.clipboard.writeText(node.textContent); } const selection = getSelection(); if (selection == null) { return Promise.reject(new Error()); } selection.removeAllRanges(); const range = document.createRange(); range.selectNodeContents(node); selection.addRange(range); document.execCommand('copy'); selection.removeAllRanges(); return Promise.resolve(); } function copyText(text) { if ('clipboard' in navigator) { // eslint-disable-next-line flowtype/no-flow-fix-me-comments // $FlowFixMe Clipboard is not defined in Flow yet. return navigator.clipboard.writeText(text); } const body = document.body; if (!body) { return Promise.reject(new Error()); } const node = createNode(text); body.appendChild(node); copyNode(node); body.removeChild(node); return Promise.resolve(); } function copy(button) { const id = button.getAttribute('for'); const text = button.getAttribute('value'); function trigger() { button.dispatchEvent(new CustomEvent('clipboard-copy', { bubbles: true })); } if (text) { copyText(text).then(trigger); } else if (id) { const root = 'getRootNode' in Element.prototype ? button.getRootNode() : button.ownerDocument; if (!(root instanceof Document || 'ShadowRoot' in window && root instanceof ShadowRoot)) return; const node = root.getElementById(id); if (node) copyTarget(node).then(trigger); } } function copyTarget(content) { if (content instanceof HTMLInputElement || content instanceof HTMLTextAreaElement) { return copyText(content.value); } else if (content instanceof HTMLAnchorElement && content.hasAttribute('href')) { return copyText(content.href); } else { return copyNode(content); } } function clicked(event) { const button = event.currentTarget; if (button instanceof HTMLElement) { copy(button); } } function keydown(event) { if (event.key === ' ' || event.key === 'Enter') { const button = event.currentTarget; if (button instanceof HTMLElement) { event.preventDefault(); copy(button); } } } function focused(event) { event.currentTarget.addEventListener('keydown', keydown); } function blurred(event) { event.currentTarget.removeEventListener('keydown', keydown); } class ClipboardCopyElement extends HTMLElement { constructor() { super(); this.addEventListener('click', clicked); this.addEventListener('focus', focused); this.addEventListener('blur', blurred); } connectedCallback() { if (!this.hasAttribute('tabindex')) { this.setAttribute('tabindex', '0'); } if (!this.hasAttribute('role')) { this.setAttribute('role', 'button'); } } get value() { return this.getAttribute('value') || ''; } set value(text) { this.setAttribute('value', text); } } if (!window.customElements.get('clipboard-copy')) { window.ClipboardCopyElement = ClipboardCopyElement; window.customElements.define('clipboard-copy', ClipboardCopyElement); } return ClipboardCopyElement; })); document.addEventListener('clipboard-copy', function(event) { const notice = event.target.querySelector('.notice') notice.hidden = false setTimeout(function() { notice.hidden = true }, 1000) }) pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) } .highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) } .highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */ .highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */ .highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */ .highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */ .highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */ .highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */ .highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */ .highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */ .highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */ .highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */ .highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */ .highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */ .highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */ .highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */ .highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */ .highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */ .highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */ .highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */ .highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */ .highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */ .highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */ .highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */ .highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */ .highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */ .highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */ .highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */ .highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */ .highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */ .highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */ .highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */ .highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */ .highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */ .highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */ .highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */ .highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */ .highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */ .highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */ .highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */ .highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */ .highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */ .highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */ @charset \"UTF-8\";.jupyter-wrapper{--md-red-50: #ffebee;--md-red-100: #ffcdd2;--md-red-200: #ef9a9a;--md-red-300: #e57373;--md-red-400: #ef5350;--md-red-500: #f44336;--md-red-600: #e53935;--md-red-700: #d32f2f;--md-red-800: #c62828;--md-red-900: #b71c1c;--md-red-A100: #ff8a80;--md-red-A200: #ff5252;--md-red-A400: #ff1744;--md-red-A700: #d50000;--md-pink-50: #fce4ec;--md-pink-100: #f8bbd0;--md-pink-200: #f48fb1;--md-pink-300: #f06292;--md-pink-400: #ec407a;--md-pink-500: #e91e63;--md-pink-600: #d81b60;--md-pink-700: #c2185b;--md-pink-800: #ad1457;--md-pink-900: #880e4f;--md-pink-A100: #ff80ab;--md-pink-A200: #ff4081;--md-pink-A400: #f50057;--md-pink-A700: #c51162;--md-purple-50: #f3e5f5;--md-purple-100: #e1bee7;--md-purple-200: #ce93d8;--md-purple-300: #ba68c8;--md-purple-400: #ab47bc;--md-purple-500: #9c27b0;--md-purple-600: #8e24aa;--md-purple-700: #7b1fa2;--md-purple-800: #6a1b9a;--md-purple-900: #4a148c;--md-purple-A100: #ea80fc;--md-purple-A200: #e040fb;--md-purple-A400: #d500f9;--md-purple-A700: #aa00ff;--md-deep-purple-50: #ede7f6;--md-deep-purple-100: #d1c4e9;--md-deep-purple-200: #b39ddb;--md-deep-purple-300: #9575cd;--md-deep-purple-400: #7e57c2;--md-deep-purple-500: #673ab7;--md-deep-purple-600: #5e35b1;--md-deep-purple-700: #512da8;--md-deep-purple-800: #4527a0;--md-deep-purple-900: #311b92;--md-deep-purple-A100: #b388ff;--md-deep-purple-A200: #7c4dff;--md-deep-purple-A400: #651fff;--md-deep-purple-A700: #6200ea;--md-indigo-50: #e8eaf6;--md-indigo-100: #c5cae9;--md-indigo-200: #9fa8da;--md-indigo-300: #7986cb;--md-indigo-400: #5c6bc0;--md-indigo-500: #3f51b5;--md-indigo-600: #3949ab;--md-indigo-700: #303f9f;--md-indigo-800: #283593;--md-indigo-900: #1a237e;--md-indigo-A100: #8c9eff;--md-indigo-A200: #536dfe;--md-indigo-A400: #3d5afe;--md-indigo-A700: #304ffe;--md-blue-50: #e3f2fd;--md-blue-100: #bbdefb;--md-blue-200: #90caf9;--md-blue-300: #64b5f6;--md-blue-400: #42a5f5;--md-blue-500: #2196f3;--md-blue-600: #1e88e5;--md-blue-700: #1976d2;--md-blue-800: #1565c0;--md-blue-900: #0d47a1;--md-blue-A100: #82b1ff;--md-blue-A200: #448aff;--md-blue-A400: #2979ff;--md-blue-A700: #2962ff;--md-light-blue-50: #e1f5fe;--md-light-blue-100: #b3e5fc;--md-light-blue-200: #81d4fa;--md-light-blue-300: #4fc3f7;--md-light-blue-400: #29b6f6;--md-light-blue-500: #03a9f4;--md-light-blue-600: #039be5;--md-light-blue-700: #0288d1;--md-light-blue-800: #0277bd;--md-light-blue-900: #01579b;--md-light-blue-A100: #80d8ff;--md-light-blue-A200: #40c4ff;--md-light-blue-A400: #00b0ff;--md-light-blue-A700: #0091ea;--md-cyan-50: #e0f7fa;--md-cyan-100: #b2ebf2;--md-cyan-200: #80deea;--md-cyan-300: #4dd0e1;--md-cyan-400: #26c6da;--md-cyan-500: #00bcd4;--md-cyan-600: #00acc1;--md-cyan-700: #0097a7;--md-cyan-800: #00838f;--md-cyan-900: #006064;--md-cyan-A100: #84ffff;--md-cyan-A200: #18ffff;--md-cyan-A400: #00e5ff;--md-cyan-A700: #00b8d4;--md-teal-50: #e0f2f1;--md-teal-100: #b2dfdb;--md-teal-200: #80cbc4;--md-teal-300: #4db6ac;--md-teal-400: #26a69a;--md-teal-500: #009688;--md-teal-600: #00897b;--md-teal-700: #00796b;--md-teal-800: #00695c;--md-teal-900: #004d40;--md-teal-A100: #a7ffeb;--md-teal-A200: #64ffda;--md-teal-A400: #1de9b6;--md-teal-A700: #00bfa5;--md-green-50: #e8f5e9;--md-green-100: #c8e6c9;--md-green-200: #a5d6a7;--md-green-300: #81c784;--md-green-400: #66bb6a;--md-green-500: #4caf50;--md-green-600: #43a047;--md-green-700: #388e3c;--md-green-800: #2e7d32;--md-green-900: #1b5e20;--md-green-A100: #b9f6ca;--md-green-A200: #69f0ae;--md-green-A400: #00e676;--md-green-A700: #00c853;--md-light-green-50: #f1f8e9;--md-light-green-100: #dcedc8;--md-light-green-200: #c5e1a5;--md-light-green-300: #aed581;--md-light-green-400: #9ccc65;--md-light-green-500: #8bc34a;--md-light-green-600: #7cb342;--md-light-green-700: #689f38;--md-light-green-800: #558b2f;--md-light-green-900: #33691e;--md-light-green-A100: #ccff90;--md-light-green-A200: #b2ff59;--md-light-green-A400: #76ff03;--md-light-green-A700: #64dd17;--md-lime-50: #f9fbe7;--md-lime-100: #f0f4c3;--md-lime-200: #e6ee9c;--md-lime-300: #dce775;--md-lime-400: #d4e157;--md-lime-500: #cddc39;--md-lime-600: #c0ca33;--md-lime-700: #afb42b;--md-lime-800: #9e9d24;--md-lime-900: #827717;--md-lime-A100: #f4ff81;--md-lime-A200: #eeff41;--md-lime-A400: #c6ff00;--md-lime-A700: #aeea00;--md-yellow-50: #fffde7;--md-yellow-100: #fff9c4;--md-yellow-200: #fff59d;--md-yellow-300: #fff176;--md-yellow-400: #ffee58;--md-yellow-500: #ffeb3b;--md-yellow-600: #fdd835;--md-yellow-700: #fbc02d;--md-yellow-800: #f9a825;--md-yellow-900: #f57f17;--md-yellow-A100: #ffff8d;--md-yellow-A200: #ffff00;--md-yellow-A400: #ffea00;--md-yellow-A700: #ffd600;--md-amber-50: #fff8e1;--md-amber-100: #ffecb3;--md-amber-200: #ffe082;--md-amber-300: #ffd54f;--md-amber-400: #ffca28;--md-amber-500: #ffc107;--md-amber-600: #ffb300;--md-amber-700: #ffa000;--md-amber-800: #ff8f00;--md-amber-900: #ff6f00;--md-amber-A100: #ffe57f;--md-amber-A200: #ffd740;--md-amber-A400: #ffc400;--md-amber-A700: #ffab00;--md-orange-50: #fff3e0;--md-orange-100: #ffe0b2;--md-orange-200: #ffcc80;--md-orange-300: #ffb74d;--md-orange-400: #ffa726;--md-orange-500: #ff9800;--md-orange-600: #fb8c00;--md-orange-700: #f57c00;--md-orange-800: #ef6c00;--md-orange-900: #e65100;--md-orange-A100: #ffd180;--md-orange-A200: #ffab40;--md-orange-A400: #ff9100;--md-orange-A700: #ff6d00;--md-deep-orange-50: #fbe9e7;--md-deep-orange-100: #ffccbc;--md-deep-orange-200: #ffab91;--md-deep-orange-300: #ff8a65;--md-deep-orange-400: #ff7043;--md-deep-orange-500: #ff5722;--md-deep-orange-600: #f4511e;--md-deep-orange-700: #e64a19;--md-deep-orange-800: #d84315;--md-deep-orange-900: #bf360c;--md-deep-orange-A100: #ff9e80;--md-deep-orange-A200: #ff6e40;--md-deep-orange-A400: #ff3d00;--md-deep-orange-A700: #dd2c00;--md-brown-50: #efebe9;--md-brown-100: #d7ccc8;--md-brown-200: #bcaaa4;--md-brown-300: #a1887f;--md-brown-400: #8d6e63;--md-brown-500: #795548;--md-brown-600: #6d4c41;--md-brown-700: #5d4037;--md-brown-800: #4e342e;--md-brown-900: #3e2723;--md-grey-50: #fafafa;--md-grey-100: #f5f5f5;--md-grey-200: #eeeeee;--md-grey-300: #e0e0e0;--md-grey-400: #bdbdbd;--md-grey-500: #9e9e9e;--md-grey-600: #757575;--md-grey-700: #616161;--md-grey-800: #424242;--md-grey-900: #212121;--md-blue-grey-50: #eceff1;--md-blue-grey-100: #cfd8dc;--md-blue-grey-200: #b0bec5;--md-blue-grey-300: #90a4ae;--md-blue-grey-400: #78909c;--md-blue-grey-500: #607d8b;--md-blue-grey-600: #546e7a;--md-blue-grey-700: #455a64;--md-blue-grey-800: #37474f;--md-blue-grey-900: #263238}.jupyter-wrapper{--jp-shadow-base-lightness: 0;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-400);--jp-border-color1: var(--md-grey-400);--jp-border-color2: var(--md-grey-300);--jp-border-color3: var(--md-grey-200);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(0, 0, 0, 1);--jp-ui-font-color1: rgba(0, 0, 0, .87);--jp-ui-font-color2: rgba(0, 0, 0, .54);--jp-ui-font-color3: rgba(0, 0, 0, .38);--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color2: rgba(255, 255, 255, .7);--jp-ui-inverse-font-color3: rgba(255, 255, 255, .5);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(0, 0, 0, 1);--jp-content-font-color1: rgba(0, 0, 0, .87);--jp-content-font-color2: rgba(0, 0, 0, .54);--jp-content-font-color3: rgba(0, 0, 0, .38);--jp-content-link-color: var(--md-blue-700);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: white;--jp-layout-color1: white;--jp-layout-color2: var(--md-grey-200);--jp-layout-color3: var(--md-grey-400);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: #111111;--jp-inverse-layout-color1: var(--md-grey-900);--jp-inverse-layout-color2: var(--md-grey-800);--jp-inverse-layout-color3: var(--md-grey-700);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-900);--jp-brand-color1: var(--md-blue-700);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-900);--jp-accent-color1: var(--md-green-700);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-900);--jp-warn-color1: var(--md-orange-700);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-900);--jp-error-color1: var(--md-red-700);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-900);--jp-success-color1: var(--md-green-700);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-900);--jp-info-color1: var(--md-cyan-700);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--md-grey-100);--jp-cell-editor-border-color: var(--md-grey-300);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: .5;--jp-cell-prompt-not-active-font-color: var(--md-grey-700);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: var(--md-blue-50);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: #fdd;--jp-rendermime-table-row-background: var(--md-grey-100);--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);--jp-dialog-background: rgba(0, 0, 0, .25);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color1);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .24);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--md-grey-300);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color1);--jp-input-hover-background: var(--jp-layout-color1);--jp-input-background: var(--md-grey-100);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: #d9d9d9;--jp-editor-selected-focused-background: #d7d4f0;--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: #008000;--jp-mirror-editor-atom-color: #88f;--jp-mirror-editor-number-color: #080;--jp-mirror-editor-def-color: #00f;--jp-mirror-editor-variable-color: var(--md-grey-900);--jp-mirror-editor-variable-2-color: #05a;--jp-mirror-editor-variable-3-color: #085;--jp-mirror-editor-punctuation-color: #05a;--jp-mirror-editor-property-color: #05a;--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ba2121;--jp-mirror-editor-string-2-color: #708;--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: #008000;--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: #170;--jp-mirror-editor-attribute-color: #00c;--jp-mirror-editor-header-color: blue;--jp-mirror-editor-quote-color: #090;--jp-mirror-editor-link-color: #00c;--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ffad8e;--jp-collaborator-color2: #dac83d;--jp-collaborator-color3: #72dd76;--jp-collaborator-color4: #00e4d0;--jp-collaborator-color5: #45d4ff;--jp-collaborator-color6: #e2b1ff;--jp-collaborator-color7: #ff9de6;--jp-vega-background: white;--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .5;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(245, 200, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-700);--jp-console-icon-background-color: var(--md-blue-700);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-800);--jp-terminal-icon-color: var(--md-grey-200);--jp-text-editor-icon-color: var(--md-grey-700);--jp-inspector-icon-color: var(--md-grey-700);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-900)}[data-md-color-scheme=slate] .jupyter-wrapper{--jp-shadow-base-lightness: 32;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-700);--jp-border-color1: var(--md-grey-700);--jp-border-color2: var(--md-grey-800);--jp-border-color3: var(--md-grey-900);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(255, 255, 255, 1);--jp-ui-font-color1: rgba(255, 255, 255, .87);--jp-ui-font-color2: rgba(255, 255, 255, .54);--jp-ui-font-color3: rgba(255, 255, 255, .38);--jp-ui-inverse-font-color0: rgba(0, 0, 0, 1);--jp-ui-inverse-font-color1: rgba(0, 0, 0, .8);--jp-ui-inverse-font-color2: rgba(0, 0, 0, .5);--jp-ui-inverse-font-color3: rgba(0, 0, 0, .3);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(255, 255, 255, 1);--jp-content-font-color1: rgba(255, 255, 255, 1);--jp-content-font-color2: rgba(255, 255, 255, .7);--jp-content-font-color3: rgba(255, 255, 255, .5);--jp-content-link-color: var(--md-blue-300);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: #111111;--jp-layout-color1: var(--md-grey-900);--jp-layout-color2: var(--md-grey-800);--jp-layout-color3: var(--md-grey-700);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: white;--jp-inverse-layout-color1: white;--jp-inverse-layout-color2: var(--md-grey-200);--jp-inverse-layout-color3: var(--md-grey-400);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-700);--jp-brand-color1: var(--md-blue-500);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-700);--jp-accent-color1: var(--md-green-500);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-700);--jp-warn-color1: var(--md-orange-500);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-700);--jp-error-color1: var(--md-red-500);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-700);--jp-success-color1: var(--md-green-500);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-700);--jp-info-color1: var(--md-cyan-500);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--jp-layout-color1);--jp-cell-editor-border-color: var(--md-grey-700);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: 1;--jp-cell-prompt-not-active-font-color: var(--md-grey-300);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: rgba(33, 150, 243, .24);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: rgba(244, 67, 54, .28);--jp-rendermime-table-row-background: var(--md-grey-900);--jp-rendermime-table-row-hover-background: rgba(3, 169, 244, .2);--jp-dialog-background: rgba(0, 0, 0, .6);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color2);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .8);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--jp-layout-color0);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color0);--jp-input-hover-background: var(--jp-layout-color2);--jp-input-background: var(--md-grey-800);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: var(--jp-layout-color2);--jp-editor-selected-focused-background: rgba(33, 150, 243, .24);--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: var(--md-green-500);--jp-mirror-editor-atom-color: var(--md-blue-300);--jp-mirror-editor-number-color: var(--md-green-400);--jp-mirror-editor-def-color: var(--md-blue-600);--jp-mirror-editor-variable-color: var(--md-grey-300);--jp-mirror-editor-variable-2-color: var(--md-blue-400);--jp-mirror-editor-variable-3-color: var(--md-green-600);--jp-mirror-editor-punctuation-color: var(--md-blue-400);--jp-mirror-editor-property-color: var(--md-blue-400);--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ff7070;--jp-mirror-editor-string-2-color: var(--md-purple-300);--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: var(--md-green-600);--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: var(--md-green-700);--jp-mirror-editor-attribute-color: var(--md-blue-700);--jp-mirror-editor-header-color: var(--md-blue-500);--jp-mirror-editor-quote-color: var(--md-green-300);--jp-mirror-editor-link-color: var(--md-blue-700);--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ad4a00;--jp-collaborator-color2: #7b6a00;--jp-collaborator-color3: #007e00;--jp-collaborator-color4: #008772;--jp-collaborator-color5: #0079b9;--jp-collaborator-color6: #8b45c6;--jp-collaborator-color7: #be208b;--jp-vega-background: var(--md-grey-400);--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .6;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(255, 225, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-scrollbar-background-color: #3f4244;--jp-scrollbar-thumb-color: 88, 96, 97;--jp-scrollbar-endpad: 3px;--jp-scrollbar-thumb-margin: 3.5px;--jp-scrollbar-thumb-radius: 9px;--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-500);--jp-console-icon-background-color: var(--md-blue-500);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-200);--jp-terminal-icon-color: var(--md-grey-800);--jp-text-editor-icon-color: var(--md-grey-200);--jp-inspector-icon-color: var(--md-grey-200);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-700)}.jupyter-wrapper [data-jp-theme-scrollbars=true]{scrollbar-color:rgb(var(--jp-scrollbar-thumb-color)) var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar{scrollbar-color:rgba(var(--jp-scrollbar-thumb-color),.5) transparent}.jupyter-wrapper .jp-scrollbar-tiny{scrollbar-color:rgba(var(--jp-scrollbar-thumb-color),.5) transparent;scrollbar-width:thin}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-corner{background:var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-thumb{background:rgb(var(--jp-scrollbar-thumb-color));border:var(--jp-scrollbar-thumb-margin) solid transparent;background-clip:content-box;border-radius:var(--jp-scrollbar-thumb-radius)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-track:horizontal{border-left:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color);border-right:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-track:vertical{border-top:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color);border-bottom:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-corner,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-corner{background-color:transparent}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-thumb,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-thumb{background:rgba(var(--jp-scrollbar-thumb-color),.5);border:var(--jp-scrollbar-thumb-margin) solid transparent;background-clip:content-box;border-radius:var(--jp-scrollbar-thumb-radius)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-track:horizontal{border-left:var(--jp-scrollbar-endpad) solid transparent;border-right:var(--jp-scrollbar-endpad) solid transparent}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-track:vertical{border-top:var(--jp-scrollbar-endpad) solid transparent;border-bottom:var(--jp-scrollbar-endpad) solid transparent}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar,.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-corner{background-color:transparent;height:4px;width:4px}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-thumb{background:rgba(var(--jp-scrollbar-thumb-color),.5)}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-track:horizontal{border-left:0px solid transparent;border-right:0px solid transparent}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-track:vertical{border-top:0px solid transparent;border-bottom:0px solid transparent}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal]{min-height:16px;max-height:16px;min-width:45px;border-top:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical]{min-width:16px;max-width:16px;min-height:45px;border-left:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar-button{background-color:#f0f0f0;background-position:center center;min-height:15px;max-height:15px;min-width:15px;max-width:15px}.jupyter-wrapper .lm-ScrollBar-button:hover{background-color:#dadada}.jupyter-wrapper .lm-ScrollBar-button.lm-mod-active{background-color:#cdcdcd}.jupyter-wrapper .lm-ScrollBar-track{background:#f0f0f0}.jupyter-wrapper .lm-ScrollBar-thumb{background:#cdcdcd}.jupyter-wrapper .lm-ScrollBar-thumb:hover{background:#bababa}.jupyter-wrapper .lm-ScrollBar-thumb.lm-mod-active{background:#a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-thumb{height:100%;min-width:15px;border-left:1px solid #a0a0a0;border-right:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-thumb{width:100%;min-height:15px;border-top:1px solid #a0a0a0;border-bottom:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-button[data-action=decrement]{background-image:var(--jp-icon-caret-left);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-button[data-action=increment]{background-image:var(--jp-icon-caret-right);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-button[data-action=decrement]{background-image:var(--jp-icon-caret-up);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-button[data-action=increment]{background-image:var(--jp-icon-caret-down);background-size:17px}.jupyter-wrapper .p-Widget,.jupyter-wrapper .lm-Widget{box-sizing:border-box;position:relative;overflow:hidden;cursor:default}.jupyter-wrapper .p-Widget.p-mod-hidden,.jupyter-wrapper .lm-Widget.lm-mod-hidden{display:none!important}.jupyter-wrapper .lm-AccordionPanel[data-orientation=horizontal]>.lm-AccordionPanel-title{display:block;transform-origin:top left;transform:rotate(-90deg) translate(-100%)}.jupyter-wrapper .p-CommandPalette,.jupyter-wrapper .lm-CommandPalette{display:flex;flex-direction:column;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-CommandPalette-search,.jupyter-wrapper .lm-CommandPalette-search{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-content,.jupyter-wrapper .lm-CommandPalette-content{flex:1 1 auto;margin:0;padding:0;min-height:0;overflow:auto;list-style-type:none}.jupyter-wrapper .p-CommandPalette-header,.jupyter-wrapper .lm-CommandPalette-header{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .p-CommandPalette-item,.jupyter-wrapper .lm-CommandPalette-item{display:flex;flex-direction:row}.jupyter-wrapper .p-CommandPalette-itemIcon,.jupyter-wrapper .lm-CommandPalette-itemIcon{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-itemContent,.jupyter-wrapper .lm-CommandPalette-itemContent{flex:1 1 auto;overflow:hidden}.jupyter-wrapper .p-CommandPalette-itemShortcut,.jupyter-wrapper .lm-CommandPalette-itemShortcut{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-itemLabel,.jupyter-wrapper .lm-CommandPalette-itemLabel{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .lm-close-icon{border:1px solid transparent;background-color:transparent;position:absolute;z-index:1;right:3%;top:0;bottom:0;margin:auto;padding:7px 0;display:none;vertical-align:middle;outline:0;cursor:pointer}.jupyter-wrapper .lm-close-icon:after{content:\"X\";display:block;width:15px;height:15px;text-align:center;color:#000;font-weight:400;font-size:12px;cursor:pointer}.jupyter-wrapper .p-DockPanel,.jupyter-wrapper .lm-DockPanel,.jupyter-wrapper .p-DockPanel-widget,.jupyter-wrapper .lm-DockPanel-widget{z-index:0}.jupyter-wrapper .p-DockPanel-tabBar,.jupyter-wrapper .lm-DockPanel-tabBar{z-index:1}.jupyter-wrapper .p-DockPanel-handle,.jupyter-wrapper .lm-DockPanel-handle{z-index:2}.jupyter-wrapper .p-DockPanel-handle.p-mod-hidden,.jupyter-wrapper .lm-DockPanel-handle.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-DockPanel-handle:after,.jupyter-wrapper .lm-DockPanel-handle:after{position:absolute;top:0;left:0;width:100%;height:100%;content:\"\"}.jupyter-wrapper .p-DockPanel-handle[data-orientation=horizontal],.jupyter-wrapper .lm-DockPanel-handle[data-orientation=horizontal]{cursor:ew-resize}.jupyter-wrapper .p-DockPanel-handle[data-orientation=vertical],.jupyter-wrapper .lm-DockPanel-handle[data-orientation=vertical]{cursor:ns-resize}.jupyter-wrapper .p-DockPanel-handle[data-orientation=horizontal]:after,.jupyter-wrapper .lm-DockPanel-handle[data-orientation=horizontal]:after{left:50%;min-width:8px;transform:translate(-50%)}.jupyter-wrapper .p-DockPanel-handle[data-orientation=vertical]:after,.jupyter-wrapper .lm-DockPanel-handle[data-orientation=vertical]:after{top:50%;min-height:8px;transform:translateY(-50%)}.jupyter-wrapper .p-DockPanel-overlay,.jupyter-wrapper .lm-DockPanel-overlay{z-index:3;box-sizing:border-box;pointer-events:none}.jupyter-wrapper .p-DockPanel-overlay.p-mod-hidden,.jupyter-wrapper .lm-DockPanel-overlay.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-Menu,.jupyter-wrapper .lm-Menu{z-index:10000;position:absolute;white-space:nowrap;overflow-x:hidden;overflow-y:auto;outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-Menu-content,.jupyter-wrapper .lm-Menu-content{margin:0;padding:0;display:table;list-style-type:none}.jupyter-wrapper .p-Menu-item,.jupyter-wrapper .lm-Menu-item{display:table-row}.jupyter-wrapper .p-Menu-item.p-mod-hidden,.jupyter-wrapper .p-Menu-item.p-mod-collapsed,.jupyter-wrapper .lm-Menu-item.lm-mod-hidden,.jupyter-wrapper .lm-Menu-item.lm-mod-collapsed{display:none!important}.jupyter-wrapper .p-Menu-itemIcon,.jupyter-wrapper .p-Menu-itemSubmenuIcon,.jupyter-wrapper .lm-Menu-itemIcon,.jupyter-wrapper .lm-Menu-itemSubmenuIcon{display:table-cell;text-align:center}.jupyter-wrapper .p-Menu-itemLabel,.jupyter-wrapper .lm-Menu-itemLabel{display:table-cell;text-align:left}.jupyter-wrapper .p-Menu-itemShortcut,.jupyter-wrapper .lm-Menu-itemShortcut{display:table-cell;text-align:right}.jupyter-wrapper .p-MenuBar,.jupyter-wrapper .lm-MenuBar{outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-MenuBar-content,.jupyter-wrapper .lm-MenuBar-content{margin:0;padding:0;display:flex;flex-direction:row;list-style-type:none}.jupyter-wrapper .p--MenuBar-item,.jupyter-wrapper .lm-MenuBar-item{box-sizing:border-box}.jupyter-wrapper .p-MenuBar-itemIcon,.jupyter-wrapper .p-MenuBar-itemLabel,.jupyter-wrapper .lm-MenuBar-itemIcon,.jupyter-wrapper .lm-MenuBar-itemLabel{display:inline-block}.jupyter-wrapper .p-ScrollBar,.jupyter-wrapper .lm-ScrollBar{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-ScrollBar[data-orientation=horizontal],.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal]{flex-direction:row}.jupyter-wrapper .p-ScrollBar[data-orientation=vertical],.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical]{flex-direction:column}.jupyter-wrapper .p-ScrollBar-button,.jupyter-wrapper .lm-ScrollBar-button{box-sizing:border-box;flex:0 0 auto}.jupyter-wrapper .p-ScrollBar-track,.jupyter-wrapper .lm-ScrollBar-track{box-sizing:border-box;position:relative;overflow:hidden;flex:1 1 auto}.jupyter-wrapper .p-ScrollBar-thumb,.jupyter-wrapper .lm-ScrollBar-thumb{box-sizing:border-box;position:absolute}.jupyter-wrapper .p-SplitPanel-child,.jupyter-wrapper .lm-SplitPanel-child{z-index:0}.jupyter-wrapper .p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel-handle{z-index:1}.jupyter-wrapper .p-SplitPanel-handle.p-mod-hidden,.jupyter-wrapper .lm-SplitPanel-handle.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel-handle:after{position:absolute;top:0;left:0;width:100%;height:100%;content:\"\"}.jupyter-wrapper .p-SplitPanel[data-orientation=horizontal]>.p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel[data-orientation=horizontal]>.lm-SplitPanel-handle{cursor:ew-resize}.jupyter-wrapper .p-SplitPanel[data-orientation=vertical]>.p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel[data-orientation=vertical]>.lm-SplitPanel-handle{cursor:ns-resize}.jupyter-wrapper .p-SplitPanel[data-orientation=horizontal]>.p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel[data-orientation=horizontal]>.lm-SplitPanel-handle:after{left:50%;min-width:8px;transform:translate(-50%)}.jupyter-wrapper .p-SplitPanel[data-orientation=vertical]>.p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel[data-orientation=vertical]>.lm-SplitPanel-handle:after{top:50%;min-height:8px;transform:translateY(-50%)}.jupyter-wrapper .p-TabBar,.jupyter-wrapper .lm-TabBar{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-TabBar[data-orientation=horizontal],.jupyter-wrapper .lm-TabBar[data-orientation=horizontal]{flex-direction:row;align-items:flex-end}.jupyter-wrapper .p-TabBar[data-orientation=vertical],.jupyter-wrapper .lm-TabBar[data-orientation=vertical]{flex-direction:column;align-items:flex-end}.jupyter-wrapper .p-TabBar-content,.jupyter-wrapper .lm-TabBar-content{margin:0;padding:0;display:flex;flex:1 1 auto;list-style-type:none}.jupyter-wrapper .p-TabBar[data-orientation=horizontal]>.p-TabBar-content,.jupyter-wrapper .lm-TabBar[data-orientation=horizontal]>.lm-TabBar-content{flex-direction:row}.jupyter-wrapper .p-TabBar[data-orientation=vertical]>.p-TabBar-content,.jupyter-wrapper .lm-TabBar[data-orientation=vertical]>.lm-TabBar-content{flex-direction:column}.jupyter-wrapper .p-TabBar-tab,.jupyter-wrapper .lm-TabBar-tab{display:flex;flex-direction:row;box-sizing:border-box;overflow:hidden;touch-action:none}.jupyter-wrapper .p-TabBar-tabIcon,.jupyter-wrapper .p-TabBar-tabCloseIcon,.jupyter-wrapper .lm-TabBar-tabIcon,.jupyter-wrapper .lm-TabBar-tabCloseIcon{flex:0 0 auto}.jupyter-wrapper .p-TabBar-tabLabel,.jupyter-wrapper .lm-TabBar-tabLabel{flex:1 1 auto;overflow:hidden;white-space:nowrap}.jupyter-wrapper .lm-TabBar-tabInput{-webkit-user-select:all;user-select:all;width:100%;box-sizing:border-box}.jupyter-wrapper .p-TabBar-tab.p-mod-hidden,.jupyter-wrapper .lm-TabBar-tab.lm-mod-hidden,.jupyter-wrapper .lm-TabBar-addButton.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-TabBar.p-mod-dragging .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging .lm-TabBar-tab{position:relative}.jupyter-wrapper .p-TabBar.p-mod-dragging[data-orientation=horizontal] .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging[data-orientation=horizontal] .lm-TabBar-tab{left:0;transition:left .15s ease}.jupyter-wrapper .p-TabBar.p-mod-dragging[data-orientation=vertical] .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging[data-orientation=vertical] .lm-TabBar-tab{top:0;transition:top .15s ease}.jupyter-wrapper .p-TabBar.p-mod-dragging .p-TabBar-tab.p-mod-dragging,.jupyter-wrapper .lm-TabBar.lm-mod-dragging .lm-TabBar-tab.lm-mod-dragging{transition:none}.jupyter-wrapper .lm-TabBar-tabLabel .lm-TabBar-tabInput{-webkit-user-select:all;user-select:all;width:100%;box-sizing:border-box;background:inherit}.jupyter-wrapper .p-TabPanel-tabBar,.jupyter-wrapper .lm-TabPanel-tabBar{z-index:1}.jupyter-wrapper .p-TabPanel-stackedPanel,.jupyter-wrapper .lm-TabPanel-stackedPanel{z-index:0}.jupyter-wrapper html{-webkit-box-sizing:border-box;box-sizing:border-box}.jupyter-wrapper *,.jupyter-wrapper *:before,.jupyter-wrapper *:after{-webkit-box-sizing:inherit;box-sizing:inherit}.jupyter-wrapper body{font-size:14px;font-weight:400;letter-spacing:0;line-height:1.28581;text-transform:none;color:#182026;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,Icons16,sans-serif}.jupyter-wrapper p{margin-bottom:10px;margin-top:0}.jupyter-wrapper small{font-size:12px}.jupyter-wrapper strong{font-weight:600}.jupyter-wrapper ::-moz-selection{background:rgba(125,188,255,.6)}.jupyter-wrapper ::selection{background:rgba(125,188,255,.6)}.jupyter-wrapper .bp3-heading{color:#182026;font-weight:600;margin:0 0 10px;padding:0}.jupyter-wrapper .bp3-dark .bp3-heading{color:#f5f8fa}.jupyter-wrapper h1.bp3-heading,.jupyter-wrapper .bp3-running-text h1{font-size:36px;line-height:40px}.jupyter-wrapper h2.bp3-heading,.jupyter-wrapper .bp3-running-text h2{font-size:28px;line-height:32px}.jupyter-wrapper h3.bp3-heading,.jupyter-wrapper .bp3-running-text h3{font-size:22px;line-height:25px}.jupyter-wrapper h4.bp3-heading,.jupyter-wrapper .bp3-running-text h4{font-size:18px;line-height:21px}.jupyter-wrapper h5.bp3-heading,.jupyter-wrapper .bp3-running-text h5{font-size:16px;line-height:19px}.jupyter-wrapper h6.bp3-heading,.jupyter-wrapper .bp3-running-text h6{font-size:14px;line-height:16px}.jupyter-wrapper .bp3-ui-text{font-size:14px;font-weight:400;letter-spacing:0;line-height:1.28581;text-transform:none}.jupyter-wrapper .bp3-monospace-text{font-family:monospace;text-transform:none}.jupyter-wrapper .bp3-text-muted{color:#5c7080}.jupyter-wrapper .bp3-dark .bp3-text-muted{color:#a7b6c2}.jupyter-wrapper .bp3-text-disabled{color:#5c708099}.jupyter-wrapper .bp3-dark .bp3-text-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-text-overflow-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal}.jupyter-wrapper .bp3-running-text{font-size:14px;line-height:1.5}.jupyter-wrapper .bp3-running-text h1{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h1{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h2{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h2{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h3{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h3{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h4{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h4{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h5{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h5{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h6{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h6{color:#f5f8fa}.jupyter-wrapper .bp3-running-text hr{border:none;border-bottom:1px solid rgba(16,22,26,.15);margin:20px 0}.jupyter-wrapper .bp3-dark .bp3-running-text hr{border-color:#ffffff26}.jupyter-wrapper .bp3-running-text p{margin:0 0 10px;padding:0}.jupyter-wrapper .bp3-text-large{font-size:16px}.jupyter-wrapper .bp3-text-small{font-size:12px}.jupyter-wrapper a .bp3-icon,.jupyter-wrapper a .bp3-icon-standard,.jupyter-wrapper a .bp3-icon-large,.jupyter-wrapper a code,.jupyter-wrapper .bp3-dark a code{color:inherit}.jupyter-wrapper .bp3-dark a,.jupyter-wrapper .bp3-dark a:hover{color:#48aff0}.jupyter-wrapper .bp3-dark a .bp3-icon,.jupyter-wrapper .bp3-dark a .bp3-icon-standard,.jupyter-wrapper .bp3-dark a .bp3-icon-large,.jupyter-wrapper .bp3-dark a:hover .bp3-icon,.jupyter-wrapper .bp3-dark a:hover .bp3-icon-standard,.jupyter-wrapper .bp3-dark a:hover .bp3-icon-large{color:inherit}.jupyter-wrapper .bp3-running-text code,.jupyter-wrapper .bp3-code{font-family:monospace;text-transform:none;background:rgba(255,255,255,.7);border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33;color:#5c7080;font-size:smaller;padding:2px 5px}.jupyter-wrapper .bp3-dark .bp3-running-text code,.jupyter-wrapper .bp3-running-text .bp3-dark code,.jupyter-wrapper .bp3-dark .bp3-code{background:rgba(16,22,26,.3);-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66;color:#a7b6c2}.jupyter-wrapper .bp3-running-text a>code,.jupyter-wrapper a>.bp3-code{color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-running-text a>code,.jupyter-wrapper .bp3-running-text .bp3-dark a>code,.jupyter-wrapper .bp3-dark a>.bp3-code{color:inherit}.jupyter-wrapper .bp3-running-text pre,.jupyter-wrapper .bp3-code-block{font-family:monospace;text-transform:none;background:rgba(255,255,255,.7);border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26;color:#182026;display:block;font-size:13px;line-height:1.4;margin:10px 0;padding:13px 15px 12px;word-break:break-all;word-wrap:break-word}.jupyter-wrapper .bp3-dark .bp3-running-text pre,.jupyter-wrapper .bp3-running-text .bp3-dark pre,.jupyter-wrapper .bp3-dark .bp3-code-block{background:rgba(16,22,26,.3);-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-running-text pre>code,.jupyter-wrapper .bp3-code-block>code{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit;font-size:inherit;padding:0}.jupyter-wrapper .bp3-running-text kbd,.jupyter-wrapper .bp3-key{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#ffffff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;color:#5c7080;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-family:inherit;font-size:12px;height:24px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:24px;min-width:24px;padding:3px 6px;vertical-align:middle}.jupyter-wrapper .bp3-running-text kbd .bp3-icon,.jupyter-wrapper .bp3-key .bp3-icon,.jupyter-wrapper .bp3-running-text kbd .bp3-icon-standard,.jupyter-wrapper .bp3-key .bp3-icon-standard,.jupyter-wrapper .bp3-running-text kbd .bp3-icon-large,.jupyter-wrapper .bp3-key .bp3-icon-large{margin-right:5px}.jupyter-wrapper .bp3-dark .bp3-running-text kbd,.jupyter-wrapper .bp3-running-text .bp3-dark kbd,.jupyter-wrapper .bp3-dark .bp3-key{background:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66;color:#a7b6c2}.jupyter-wrapper .bp3-running-text blockquote,.jupyter-wrapper .bp3-blockquote{border-left:solid 4px rgba(167,182,194,.5);margin:0 0 10px;padding:0 20px}.jupyter-wrapper .bp3-dark .bp3-running-text blockquote,.jupyter-wrapper .bp3-running-text .bp3-dark blockquote,.jupyter-wrapper .bp3-dark .bp3-blockquote{border-color:#73869480}.jupyter-wrapper .bp3-running-text ul,.jupyter-wrapper .bp3-running-text ol,.jupyter-wrapper .bp3-list{margin:10px 0;padding-left:30px}.jupyter-wrapper .bp3-running-text ul li:not(:last-child),.jupyter-wrapper .bp3-running-text ol li:not(:last-child),.jupyter-wrapper .bp3-list li:not(:last-child){margin-bottom:5px}.jupyter-wrapper .bp3-running-text ul ol,.jupyter-wrapper .bp3-running-text ol ol,.jupyter-wrapper .bp3-list ol,.jupyter-wrapper .bp3-running-text ul ul,.jupyter-wrapper .bp3-running-text ol ul,.jupyter-wrapper .bp3-list ul{margin-top:5px}.jupyter-wrapper .bp3-list-unstyled{list-style:none;margin:0;padding:0}.jupyter-wrapper .bp3-list-unstyled li{padding:0}.jupyter-wrapper .bp3-rtl{text-align:right}.jupyter-wrapper .bp3-dark{color:#f5f8fa}.jupyter-wrapper :focus{outline:rgba(19,124,189,.6) auto 2px;outline-offset:2px;-moz-outline-radius:6px}.jupyter-wrapper .bp3-focus-disabled :focus{outline:none!important}.jupyter-wrapper .bp3-focus-disabled :focus~.bp3-control-indicator{outline:none!important}.jupyter-wrapper .bp3-alert{max-width:400px;padding:20px}.jupyter-wrapper .bp3-alert-body{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-alert-body .bp3-icon{font-size:40px;margin-right:20px;margin-top:0}.jupyter-wrapper .bp3-alert-contents{word-break:break-word}.jupyter-wrapper .bp3-alert-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;margin-top:10px}.jupyter-wrapper .bp3-alert-footer .bp3-button{margin-left:10px}.jupyter-wrapper .bp3-breadcrumbs{-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:default;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;height:30px;list-style:none;margin:0;padding:0}.jupyter-wrapper .bp3-breadcrumbs>li{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-breadcrumbs>li:after{background:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.71 7.29l-4-4a1.003 1.003 0 00-1.42 1.42L8.59 8 5.3 11.29c-.19.18-.3.43-.3.71a1.003 1.003 0 001.71.71l4-4c.18-.18.29-.43.29-.71 0-.28-.11-.53-.29-.71z' fill='%235C7080'/%3e%3c/svg%3e\");content:\"\";display:block;height:16px;margin:0 5px;width:16px}.jupyter-wrapper .bp3-breadcrumbs>li:last-of-type:after{display:none}.jupyter-wrapper .bp3-breadcrumb,.jupyter-wrapper .bp3-breadcrumb-current,.jupyter-wrapper .bp3-breadcrumbs-collapsed{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:16px}.jupyter-wrapper .bp3-breadcrumb,.jupyter-wrapper .bp3-breadcrumbs-collapsed{color:#5c7080}.jupyter-wrapper .bp3-breadcrumb:hover{text-decoration:none}.jupyter-wrapper .bp3-breadcrumb.bp3-disabled{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-breadcrumb .bp3-icon{margin-right:5px}.jupyter-wrapper .bp3-breadcrumb-current{color:inherit;font-weight:600}.jupyter-wrapper .bp3-breadcrumb-current .bp3-input{font-size:inherit;font-weight:inherit;vertical-align:baseline}.jupyter-wrapper .bp3-breadcrumbs-collapsed{background:#ced9e0;border:none;border-radius:3px;cursor:pointer;margin-right:2px;padding:1px 5px;vertical-align:text-bottom}.jupyter-wrapper .bp3-breadcrumbs-collapsed:before{background:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cg fill='%235C7080'%3e%3ccircle cx='2' cy='8.03' r='2'/%3e%3ccircle cx='14' cy='8.03' r='2'/%3e%3ccircle cx='8' cy='8.03' r='2'/%3e%3c/g%3e%3c/svg%3e\") center no-repeat;content:\"\";display:block;height:16px;width:16px}.jupyter-wrapper .bp3-breadcrumbs-collapsed:hover{background:#bfccd6;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-dark .bp3-breadcrumb,.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs>li:after{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-breadcrumb.bp3-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-breadcrumb-current{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed:hover{background:rgba(16,22,26,.6);color:#f5f8fa}.jupyter-wrapper .bp3-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;border-radius:3px;cursor:pointer;font-size:14px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:5px 10px;text-align:left;vertical-align:middle;min-height:30px;min-width:30px}.jupyter-wrapper .bp3-button>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-button>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-button:before,.jupyter-wrapper .bp3-button>*{margin-right:7px}.jupyter-wrapper .bp3-button:empty:before,.jupyter-wrapper .bp3-button>:last-child{margin-right:0}.jupyter-wrapper .bp3-button:empty{padding:0!important}.jupyter-wrapper .bp3-button:disabled,.jupyter-wrapper .bp3-button.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-button.bp3-align-right,.jupyter-wrapper .bp3-align-right .bp3-button{text-align:right}.jupyter-wrapper .bp3-button.bp3-align-left,.jupyter-wrapper .bp3-align-left .bp3-button{text-align:left}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]){background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active:hover,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-button.bp3-intent-primary{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-primary:hover{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-active{background-color:#0e5a8a;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-disabled{background-color:#137cbd80;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-success{background-color:#0f9960;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-success:hover{background-color:#0d8050;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-active{background-color:#0a6640;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-disabled{background-color:#0f996080;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-warning{background-color:#d9822b;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-warning:hover{background-color:#bf7326;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-active{background-color:#a66321;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-disabled{background-color:#d9822b80;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-danger{background-color:#db3737;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-danger:hover{background-color:#c23030;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-active{background-color:#a82a2a;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-disabled{background-color:#db373780;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-button-spinner .bp3-spinner-head{stroke:#fff}.jupyter-wrapper .bp3-button.bp3-large,.jupyter-wrapper .bp3-large .bp3-button{min-height:40px;min-width:40px;font-size:16px;padding:5px 15px}.jupyter-wrapper .bp3-button.bp3-large:before,.jupyter-wrapper .bp3-button.bp3-large>*,.jupyter-wrapper .bp3-large .bp3-button:before,.jupyter-wrapper .bp3-large .bp3-button>*{margin-right:10px}.jupyter-wrapper .bp3-button.bp3-large:empty:before,.jupyter-wrapper .bp3-button.bp3-large>:last-child,.jupyter-wrapper .bp3-large .bp3-button:empty:before,.jupyter-wrapper .bp3-large .bp3-button>:last-child{margin-right:0}.jupyter-wrapper .bp3-button.bp3-small,.jupyter-wrapper .bp3-small .bp3-button{min-height:24px;min-width:24px;padding:0 7px}.jupyter-wrapper .bp3-button.bp3-loading{position:relative}.jupyter-wrapper .bp3-button.bp3-loading[class*=bp3-icon-]:before{visibility:hidden}.jupyter-wrapper .bp3-button.bp3-loading .bp3-button-spinner{margin:0;position:absolute}.jupyter-wrapper .bp3-button.bp3-loading>:not(.bp3-button-spinner){visibility:hidden}.jupyter-wrapper .bp3-button[class*=bp3-icon-]:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#5c7080}.jupyter-wrapper .bp3-button .bp3-icon,.jupyter-wrapper .bp3-button .bp3-icon-standard,.jupyter-wrapper .bp3-button .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-button .bp3-icon.bp3-align-right,.jupyter-wrapper .bp3-button .bp3-icon-standard.bp3-align-right,.jupyter-wrapper .bp3-button .bp3-icon-large.bp3-align-right{margin-left:7px}.jupyter-wrapper .bp3-button .bp3-icon:first-child:last-child,.jupyter-wrapper .bp3-button .bp3-spinner+.bp3-icon:last-child{margin:0 -7px}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]){background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):hover,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):disabled,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-])[class*=bp3-icon-]:before{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon-large{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-],.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:active,.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-].bp3-active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:disabled,.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-].bp3-disabled{background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#ffffff4d}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-] .bp3-button-spinner .bp3-spinner-head{stroke:#8a9ba8}.jupyter-wrapper .bp3-button:disabled:before,.jupyter-wrapper .bp3-button:disabled .bp3-icon,.jupyter-wrapper .bp3-button:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-button:disabled .bp3-icon-large,.jupyter-wrapper .bp3-button.bp3-disabled:before,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon-standard,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon-large,.jupyter-wrapper .bp3-button[class*=bp3-intent-]:before,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon-standard,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon-large{color:inherit!important}.jupyter-wrapper .bp3-button.bp3-minimal{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-button.bp3-minimal:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-button.bp3-minimal:disabled:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-minimal:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined{background:none;-webkit-box-shadow:none;box-shadow:none;border:1px solid rgba(24,32,38,.2);-webkit-box-sizing:border-box;box-sizing:border-box}.jupyter-wrapper .bp3-button.bp3-outlined:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-outlined:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover{border-color:#5c70801a}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined{border-color:#fff6}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover{border-color:#fff3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary{border-color:#106ba399}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{border-color:#106ba333}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary{border-color:#48aff099}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{border-color:#48aff033}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success{border-color:#0d805099}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{border-color:#0d805033}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success{border-color:#3dcc9199}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{border-color:#3dcc9133}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning{border-color:#bf732699}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{border-color:#bf732633}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning{border-color:#ffb36699}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{border-color:#ffb36633}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger{border-color:#c2303099}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{border-color:#c2303033}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger{border-color:#ff737399}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{border-color:#ff737333}.jupyter-wrapper a.bp3-button{text-align:center;text-decoration:none;-webkit-transition:none;transition:none}.jupyter-wrapper a.bp3-button,.jupyter-wrapper a.bp3-button:hover,.jupyter-wrapper a.bp3-button:active{color:#182026}.jupyter-wrapper a.bp3-button.bp3-disabled{color:#5c708099}.jupyter-wrapper .bp3-button-text{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.jupyter-wrapper .bp3-button.bp3-align-left .bp3-button-text,.jupyter-wrapper .bp3-button.bp3-align-right .bp3-button-text,.jupyter-wrapper .bp3-button-group.bp3-align-left .bp3-button-text,.jupyter-wrapper .bp3-button-group.bp3-align-right .bp3-button-text{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.jupyter-wrapper .bp3-button-group .bp3-button{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;position:relative;z-index:4}.jupyter-wrapper .bp3-button-group .bp3-button:focus{z-index:5}.jupyter-wrapper .bp3-button-group .bp3-button:hover{z-index:6}.jupyter-wrapper .bp3-button-group .bp3-button:active,.jupyter-wrapper .bp3-button-group .bp3-button.bp3-active{z-index:7}.jupyter-wrapper .bp3-button-group .bp3-button:disabled,.jupyter-wrapper .bp3-button-group .bp3-button.bp3-disabled{z-index:3}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]{z-index:9}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:focus{z-index:10}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:hover{z-index:11}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:active,.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-].bp3-active{z-index:12}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:disabled,.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-].bp3-disabled{z-index:8}.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:first-child) .bp3-button,.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:hover,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button-group .bp3-popover-wrapper,.jupyter-wrapper .bp3-button-group .bp3-popover-target{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-button-group .bp3-button.bp3-fill,.jupyter-wrapper .bp3-button-group.bp3-fill .bp3-button:not(.bp3-fixed){-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group.bp3-vertical{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;vertical-align:top}.jupyter-wrapper .bp3-button-group.bp3-vertical.bp3-fill{height:100%;width:unset}.jupyter-wrapper .bp3-button-group.bp3-vertical .bp3-button{margin-right:0!important;width:100%}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:first-child .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:first-child{border-radius:3px 3px 0 0}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:last-child .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:last-child{border-radius:0 0 3px 3px}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:not(:last-child){margin-bottom:-1px}.jupyter-wrapper .bp3-button-group.bp3-align-left .bp3-button{text-align:left}.jupyter-wrapper .bp3-dark .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-dark .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:last-child){margin-right:1px}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-vertical>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-vertical>.bp3-button:not(:last-child){margin-bottom:1px}.jupyter-wrapper .bp3-callout{font-size:14px;line-height:1.5;background-color:#8a9ba826;border-radius:3px;padding:10px 12px 9px;position:relative;width:100%}.jupyter-wrapper .bp3-callout[class*=bp3-icon-]{padding-left:40px}.jupyter-wrapper .bp3-callout[class*=bp3-icon-]:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#5c7080;left:10px;position:absolute;top:10px}.jupyter-wrapper .bp3-callout.bp3-callout-icon{padding-left:40px}.jupyter-wrapper .bp3-callout.bp3-callout-icon>.bp3-icon:first-child{color:#5c7080;left:10px;position:absolute;top:10px}.jupyter-wrapper .bp3-callout .bp3-heading{line-height:20px;margin-bottom:5px;margin-top:0}.jupyter-wrapper .bp3-callout .bp3-heading:last-child{margin-bottom:0}.jupyter-wrapper .bp3-dark .bp3-callout{background-color:#8a9ba833}.jupyter-wrapper .bp3-dark .bp3-callout[class*=bp3-icon-]:before{color:#a7b6c2}.jupyter-wrapper .bp3-callout.bp3-intent-primary{background-color:#137cbd26}.jupyter-wrapper .bp3-callout.bp3-intent-primary[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-primary>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-primary .bp3-heading{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary{background-color:#137cbd40}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary .bp3-heading{color:#48aff0}.jupyter-wrapper .bp3-callout.bp3-intent-success{background-color:#0f996026}.jupyter-wrapper .bp3-callout.bp3-intent-success[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-success>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-success .bp3-heading{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success{background-color:#0f996040}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success .bp3-heading{color:#3dcc91}.jupyter-wrapper .bp3-callout.bp3-intent-warning{background-color:#d9822b26}.jupyter-wrapper .bp3-callout.bp3-intent-warning[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-warning>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-warning .bp3-heading{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning{background-color:#d9822b40}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning .bp3-heading{color:#ffb366}.jupyter-wrapper .bp3-callout.bp3-intent-danger{background-color:#db373726}.jupyter-wrapper .bp3-callout.bp3-intent-danger[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-danger>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-danger .bp3-heading{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger{background-color:#db373740}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger .bp3-heading{color:#ff7373}.jupyter-wrapper .bp3-running-text .bp3-callout{margin:20px 0}.jupyter-wrapper .bp3-card{background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.15),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a26,0 0 #10161a00,0 0 #10161a00;padding:20px;-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),box-shadow .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-card.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a66,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-0{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.15),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a26,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-0.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-0{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a66,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-1{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33}.jupyter-wrapper .bp3-elevation-1.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-1{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-elevation-2{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 1px 1px rgba(16,22,26,.2),0 2px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 1px 1px #10161a33,0 2px 6px #10161a33}.jupyter-wrapper .bp3-elevation-2.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-2{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.4),0 2px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a66,0 2px 6px #10161a66}.jupyter-wrapper .bp3-elevation-3{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33}.jupyter-wrapper .bp3-elevation-3.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-3{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-elevation-4{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33}.jupyter-wrapper .bp3-elevation-4.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-4{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66}.jupyter-wrapper .bp3-card.bp3-interactive:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;cursor:pointer}.jupyter-wrapper .bp3-card.bp3-interactive:hover.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card.bp3-interactive:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-card.bp3-interactive:active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;opacity:.9;-webkit-transition-duration:0;transition-duration:0}.jupyter-wrapper .bp3-card.bp3-interactive:active.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card.bp3-interactive:active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-collapse{height:0;overflow-y:hidden;-webkit-transition:height .2s cubic-bezier(.4,1,.75,.9);transition:height .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-collapse .bp3-collapse-body{-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-collapse .bp3-collapse-body[aria-hidden=true]{display:none}.jupyter-wrapper .bp3-context-menu .bp3-popover-target{display:block}.jupyter-wrapper .bp3-context-menu-popover-target{position:fixed}.jupyter-wrapper .bp3-dialog-container{opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;min-height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-enter>.bp3-dialog,.jupyter-wrapper .bp3-dialog-container.bp3-overlay-appear>.bp3-dialog{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-enter-active>.bp3-dialog,.jupyter-wrapper .bp3-dialog-container.bp3-overlay-appear-active>.bp3-dialog{opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-exit>.bp3-dialog{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-exit-active>.bp3-dialog{opacity:0;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-dialog{background:#ebf1f5;border-radius:6px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:30px 0;padding-bottom:20px;pointer-events:all;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;width:500px}.jupyter-wrapper .bp3-dialog:focus{outline:0}.jupyter-wrapper .bp3-dialog.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-dialog{background:#293742;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dialog-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#ffffff;border-radius:6px 6px 0 0;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;min-height:40px;padding-left:20px;padding-right:5px;z-index:30}.jupyter-wrapper .bp3-dialog-header .bp3-icon-large,.jupyter-wrapper .bp3-dialog-header .bp3-icon{color:#5c7080;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-right:10px}.jupyter-wrapper .bp3-dialog-header .bp3-heading{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:inherit;margin:0}.jupyter-wrapper .bp3-dialog-header .bp3-heading:last-child{margin-right:20px}.jupyter-wrapper .bp3-dark .bp3-dialog-header{background:#30404d;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.4);box-shadow:0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-dialog-header .bp3-icon-large,.jupyter-wrapper .bp3-dark .bp3-dialog-header .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dialog-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:18px;margin:20px}.jupyter-wrapper .bp3-dialog-footer{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin:0 20px}.jupyter-wrapper .bp3-dialog-footer-actions{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.jupyter-wrapper .bp3-dialog-footer-actions .bp3-button{margin-left:10px}.jupyter-wrapper .bp3-multistep-dialog-panels{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-multistep-dialog-left-panel{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-left-panel{background:#202b33}.jupyter-wrapper .bp3-multistep-dialog-right-panel{background-color:#f5f8fa;border-left:1px solid rgba(16,22,26,.15);border-radius:0 0 6px;-webkit-box-flex:3;-ms-flex:3;flex:3;min-width:0}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-right-panel{background-color:#293742;border-left:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-multistep-dialog-footer{background-color:#fff;border-radius:0 0 6px;border-top:1px solid rgba(16,22,26,.15);padding:10px}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-footer{background:#30404d;border-top:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dialog-step-container{background-color:#f5f8fa;border-bottom:1px solid rgba(16,22,26,.15)}.jupyter-wrapper .bp3-dark .bp3-dialog-step-container{background:#293742;border-bottom:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dialog-step-container.bp3-dialog-step-viewed{background-color:#fff}.jupyter-wrapper .bp3-dark .bp3-dialog-step-container.bp3-dialog-step-viewed{background:#30404d}.jupyter-wrapper .bp3-dialog-step{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#f5f8fa;border-radius:6px;cursor:not-allowed;display:-webkit-box;display:-ms-flexbox;display:flex;margin:4px;padding:6px 14px}.jupyter-wrapper .bp3-dark .bp3-dialog-step{background:#293742}.jupyter-wrapper .bp3-dialog-step-viewed .bp3-dialog-step{background-color:#fff;cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-dialog-step-viewed .bp3-dialog-step{background:#30404d}.jupyter-wrapper .bp3-dialog-step:hover{background-color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-dialog-step:hover{background:#293742}.jupyter-wrapper .bp3-dialog-step-icon{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#5c708099;border-radius:50%;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;height:25px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:25px}.jupyter-wrapper .bp3-dark .bp3-dialog-step-icon{background-color:#a7b6c299}.jupyter-wrapper .bp3-active.bp3-dialog-step-viewed .bp3-dialog-step-icon{background-color:#2b95d6}.jupyter-wrapper .bp3-dialog-step-viewed .bp3-dialog-step-icon{background-color:#8a9ba8}.jupyter-wrapper .bp3-dialog-step-title{color:#5c708099;-webkit-box-flex:1;-ms-flex:1;flex:1;padding-left:10px}.jupyter-wrapper .bp3-dark .bp3-dialog-step-title{color:#a7b6c299}.jupyter-wrapper .bp3-active.bp3-dialog-step-viewed .bp3-dialog-step-title{color:#2b95d6}.jupyter-wrapper .bp3-dialog-step-viewed:not(.bp3-active) .bp3-dialog-step-title{color:#182026}.jupyter-wrapper .bp3-dark .bp3-dialog-step-viewed:not(.bp3-active) .bp3-dialog-step-title{color:#f5f8fa}.jupyter-wrapper .bp3-drawer{background:#ffffff;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0;padding:0}.jupyter-wrapper .bp3-drawer:focus{outline:0}.jupyter-wrapper .bp3-drawer.bp3-position-top{height:50%;left:0;right:0;top:0}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-appear{-webkit-transform:translateY(-100%);transform:translateY(-100%)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-exit-active{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom{bottom:0;height:50%;left:0;right:0}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-appear{-webkit-transform:translateY(100%);transform:translateY(100%)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-exit-active{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-left{bottom:0;left:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-appear{-webkit-transform:translateX(-100%);transform:translate(-100%)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-exit-active{-webkit-transform:translateX(-100%);transform:translate(-100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-right{bottom:0;right:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-appear{-webkit-transform:translateX(100%);transform:translate(100%)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical){bottom:0;right:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-enter,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-appear{-webkit-transform:translateX(100%);transform:translate(100%)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical{bottom:0;height:50%;left:0;right:0}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-appear{-webkit-transform:translateY(100%);transform:translateY(100%)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-exit-active{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-drawer{background:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-drawer-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:0;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;min-height:40px;padding:5px 5px 5px 20px;position:relative}.jupyter-wrapper .bp3-drawer-header .bp3-icon-large,.jupyter-wrapper .bp3-drawer-header .bp3-icon{color:#5c7080;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-right:10px}.jupyter-wrapper .bp3-drawer-header .bp3-heading{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:inherit;margin:0}.jupyter-wrapper .bp3-drawer-header .bp3-heading:last-child{margin-right:20px}.jupyter-wrapper .bp3-dark .bp3-drawer-header{-webkit-box-shadow:0 1px 0 rgba(16,22,26,.4);box-shadow:0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-drawer-header .bp3-icon-large,.jupyter-wrapper .bp3-dark .bp3-drawer-header .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-drawer-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:18px;overflow:auto}.jupyter-wrapper .bp3-drawer-footer{-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;padding:10px 20px;position:relative}.jupyter-wrapper .bp3-dark .bp3-drawer-footer{-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.4);box-shadow:inset 0 1px #10161a66}.jupyter-wrapper .bp3-editable-text{cursor:text;display:inline-block;max-width:100%;position:relative;vertical-align:top;white-space:nowrap}.jupyter-wrapper .bp3-editable-text:before{bottom:-3px;left:-3px;position:absolute;right:-3px;top:-3px;border-radius:3px;content:\"\";-webkit-transition:background-color .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-editable-text:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-editable-text.bp3-editable-text-editing:before{background-color:#fff;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-disabled:before{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-primary .bp3-editable-text-content{color:#137cbd}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(19,124,189,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd66}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-success .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-success .bp3-editable-text-content{color:#0f9960}.jupyter-wrapper .bp3-editable-text.bp3-intent-success:hover:before{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px rgba(15,153,96,.4);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f996066}.jupyter-wrapper .bp3-editable-text.bp3-intent-success.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-warning .bp3-editable-text-content{color:#d9822b}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning:hover:before{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px rgba(217,130,43,.4);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b66}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-danger .bp3-editable-text-content{color:#db3737}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger:hover:before{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px rgba(219,55,55,.4);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db373766}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-dark .bp3-editable-text:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(255,255,255,.15);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #ffffff26}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-editable-text-editing:before{background-color:#10161a4d;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-disabled:before{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary .bp3-editable-text-content{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary:hover:before{-webkit-box-shadow:0 0 0 0 rgba(72,175,240,0),0 0 0 0 rgba(72,175,240,0),inset 0 0 0 1px rgba(72,175,240,.4);box-shadow:0 0 #48aff000,0 0 #48aff000,inset 0 0 0 1px #48aff066}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #48aff0,0 0 0 3px rgba(72,175,240,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #48aff0,0 0 0 3px #48aff04d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success .bp3-editable-text-content{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success:hover:before{-webkit-box-shadow:0 0 0 0 rgba(61,204,145,0),0 0 0 0 rgba(61,204,145,0),inset 0 0 0 1px rgba(61,204,145,.4);box-shadow:0 0 #3dcc9100,0 0 #3dcc9100,inset 0 0 0 1px #3dcc9166}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #3dcc91,0 0 0 3px rgba(61,204,145,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #3dcc91,0 0 0 3px #3dcc914d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning .bp3-editable-text-content{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning:hover:before{-webkit-box-shadow:0 0 0 0 rgba(255,179,102,0),0 0 0 0 rgba(255,179,102,0),inset 0 0 0 1px rgba(255,179,102,.4);box-shadow:0 0 #ffb36600,0 0 #ffb36600,inset 0 0 0 1px #ffb36666}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #ffb366,0 0 0 3px rgba(255,179,102,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #ffb366,0 0 0 3px #ffb3664d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger .bp3-editable-text-content{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger:hover:before{-webkit-box-shadow:0 0 0 0 rgba(255,115,115,0),0 0 0 0 rgba(255,115,115,0),inset 0 0 0 1px rgba(255,115,115,.4);box-shadow:0 0 #ff737300,0 0 #ff737300,inset 0 0 0 1px #ff737366}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #ff7373,0 0 0 3px rgba(255,115,115,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #ff7373,0 0 0 3px #ff73734d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text-content{color:inherit;display:inherit;font:inherit;letter-spacing:inherit;max-width:inherit;min-width:inherit;position:relative;resize:none;text-transform:inherit;vertical-align:top}.jupyter-wrapper .bp3-editable-text-input{background:none;border:none;-webkit-box-shadow:none;box-shadow:none;padding:0;white-space:pre-wrap;width:100%}.jupyter-wrapper .bp3-editable-text-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input:focus{outline:none}.jupyter-wrapper .bp3-editable-text-input::-ms-clear{display:none}.jupyter-wrapper .bp3-editable-text-content{overflow:hidden;padding-right:2px;text-overflow:ellipsis;white-space:pre}.jupyter-wrapper .bp3-editable-text-editing>.bp3-editable-text-content{left:0;position:absolute;visibility:hidden}.jupyter-wrapper .bp3-editable-text-placeholder>.bp3-editable-text-content{color:#5c708099}.jupyter-wrapper .bp3-dark .bp3-editable-text-placeholder>.bp3-editable-text-content{color:#a7b6c299}.jupyter-wrapper .bp3-editable-text.bp3-multiline{display:block}.jupyter-wrapper .bp3-editable-text.bp3-multiline .bp3-editable-text-content{overflow:auto;white-space:pre-wrap;word-wrap:break-word}.jupyter-wrapper .bp3-divider{border-bottom:1px solid rgba(16,22,26,.15);border-right:1px solid rgba(16,22,26,.15);margin:5px}.jupyter-wrapper .bp3-dark .bp3-divider{border-color:#10161a66}.jupyter-wrapper .bp3-control-group{-webkit-transform:translateZ(0);transform:translateZ(0);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.jupyter-wrapper .bp3-control-group>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-control-group>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-control-group .bp3-button,.jupyter-wrapper .bp3-control-group .bp3-html-select,.jupyter-wrapper .bp3-control-group .bp3-input,.jupyter-wrapper .bp3-control-group .bp3-select{position:relative}.jupyter-wrapper .bp3-control-group .bp3-input{border-radius:inherit;z-index:2}.jupyter-wrapper .bp3-control-group .bp3-input:focus{border-radius:3px;z-index:14}.jupyter-wrapper .bp3-control-group .bp3-input[class*=bp3-intent]{z-index:13}.jupyter-wrapper .bp3-control-group .bp3-input[class*=bp3-intent]:focus{z-index:15}.jupyter-wrapper .bp3-control-group .bp3-input[readonly],.jupyter-wrapper .bp3-control-group .bp3-input:disabled,.jupyter-wrapper .bp3-control-group .bp3-input.bp3-disabled{z-index:1}.jupyter-wrapper .bp3-control-group .bp3-input-group[class*=bp3-intent] .bp3-input{z-index:13}.jupyter-wrapper .bp3-control-group .bp3-input-group[class*=bp3-intent] .bp3-input:focus{z-index:15}.jupyter-wrapper .bp3-control-group .bp3-button,.jupyter-wrapper .bp3-control-group .bp3-html-select select,.jupyter-wrapper .bp3-control-group .bp3-select select{-webkit-transform:translateZ(0);transform:translateZ(0);border-radius:inherit;z-index:4}.jupyter-wrapper .bp3-control-group .bp3-button:focus,.jupyter-wrapper .bp3-control-group .bp3-html-select select:focus,.jupyter-wrapper .bp3-control-group .bp3-select select:focus{z-index:5}.jupyter-wrapper .bp3-control-group .bp3-button:hover,.jupyter-wrapper .bp3-control-group .bp3-html-select select:hover,.jupyter-wrapper .bp3-control-group .bp3-select select:hover{z-index:6}.jupyter-wrapper .bp3-control-group .bp3-button:active,.jupyter-wrapper .bp3-control-group .bp3-html-select select:active,.jupyter-wrapper .bp3-control-group .bp3-select select:active{z-index:7}.jupyter-wrapper .bp3-control-group .bp3-button[readonly],.jupyter-wrapper .bp3-control-group .bp3-button:disabled,.jupyter-wrapper .bp3-control-group .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[readonly],.jupyter-wrapper .bp3-control-group .bp3-html-select select:disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[readonly],.jupyter-wrapper .bp3-control-group .bp3-select select:disabled,.jupyter-wrapper .bp3-control-group .bp3-select select.bp3-disabled{z-index:3}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent],.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent],.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]{z-index:9}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:focus,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:focus,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:focus{z-index:10}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:hover,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:hover,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:hover{z-index:11}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:active,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:active,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:active{z-index:12}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent].bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent].bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent].bp3-disabled{z-index:8}.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-icon,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-button,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-input-action{z-index:16}.jupyter-wrapper .bp3-control-group .bp3-select:after,.jupyter-wrapper .bp3-control-group .bp3-html-select:after,.jupyter-wrapper .bp3-control-group .bp3-select>.bp3-icon,.jupyter-wrapper .bp3-control-group .bp3-html-select>.bp3-icon{z-index:17}.jupyter-wrapper .bp3-control-group .bp3-select:focus-within{z-index:5}.jupyter-wrapper .bp3-control-group:not(.bp3-vertical)>*:not(.bp3-divider){margin-right:-1px}.jupyter-wrapper .bp3-control-group:not(.bp3-vertical)>.bp3-divider:not(:first-child){margin-left:6px}.jupyter-wrapper .bp3-dark .bp3-control-group:not(.bp3-vertical)>*:not(.bp3-divider){margin-right:0}.jupyter-wrapper .bp3-dark .bp3-control-group:not(.bp3-vertical)>.bp3-button+.bp3-button{margin-left:1px}.jupyter-wrapper .bp3-control-group .bp3-popover-wrapper,.jupyter-wrapper .bp3-control-group .bp3-popover-target{border-radius:inherit}.jupyter-wrapper .bp3-control-group>:first-child{border-radius:3px 0 0 3px}.jupyter-wrapper .bp3-control-group>:last-child{border-radius:0 3px 3px 0;margin-right:0}.jupyter-wrapper .bp3-control-group>:only-child{border-radius:3px;margin-right:0}.jupyter-wrapper .bp3-control-group .bp3-input-group .bp3-button{border-radius:3px}.jupyter-wrapper .bp3-control-group .bp3-numeric-input:not(:first-child) .bp3-input-group{border-bottom-left-radius:0;border-top-left-radius:0}.jupyter-wrapper .bp3-control-group.bp3-fill{width:100%}.jupyter-wrapper .bp3-control-group>.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-control-group.bp3-fill>*:not(.bp3-fixed){-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-control-group.bp3-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-control-group.bp3-vertical>*{margin-top:-1px}.jupyter-wrapper .bp3-control-group.bp3-vertical>:first-child{border-radius:3px 3px 0 0;margin-top:0}.jupyter-wrapper .bp3-control-group.bp3-vertical>:last-child{border-radius:0 0 3px 3px}.jupyter-wrapper .bp3-control{cursor:pointer;display:block;margin-bottom:10px;position:relative;text-transform:none}.jupyter-wrapper .bp3-control input:checked~.bp3-control-indicator{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-control:hover input:checked~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-control input:not(:disabled):active:checked~.bp3-control-indicator{background:#0e5a8a;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control input:disabled:checked~.bp3-control-indicator{background:rgba(19,124,189,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-control input:checked~.bp3-control-indicator{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control:hover input:checked~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control input:not(:disabled):active:checked~.bp3-control-indicator{background-color:#0e5a8a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control input:disabled:checked~.bp3-control-indicator{background:rgba(14,90,138,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-control:not(.bp3-align-right){padding-left:26px}.jupyter-wrapper .bp3-control:not(.bp3-align-right) .bp3-control-indicator{margin-left:-26px}.jupyter-wrapper .bp3-control.bp3-align-right{padding-right:26px}.jupyter-wrapper .bp3-control.bp3-align-right .bp3-control-indicator{margin-right:-26px}.jupyter-wrapper .bp3-control.bp3-disabled{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-control.bp3-inline{display:inline-block;margin-right:20px}.jupyter-wrapper .bp3-control input{left:0;opacity:0;position:absolute;top:0;z-index:-1}.jupyter-wrapper .bp3-control .bp3-control-indicator{background-clip:padding-box;background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));border:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;cursor:pointer;display:inline-block;font-size:16px;height:1em;margin-right:10px;margin-top:-3px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;width:1em}.jupyter-wrapper .bp3-control .bp3-control-indicator:before{content:\"\";display:block;height:1em;width:1em}.jupyter-wrapper .bp3-control:hover .bp3-control-indicator{background-color:#ebf1f5}.jupyter-wrapper .bp3-control input:not(:disabled):active~.bp3-control-indicator{background:#d8e1e8;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control input:disabled~.bp3-control-indicator{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;cursor:not-allowed}.jupyter-wrapper .bp3-control input:focus~.bp3-control-indicator{outline:rgba(19,124,189,.6) auto 2px;outline-offset:2px;-moz-outline-radius:6px}.jupyter-wrapper .bp3-control.bp3-align-right .bp3-control-indicator{float:right;margin-left:10px;margin-top:1px}.jupyter-wrapper .bp3-control.bp3-large{font-size:16px}.jupyter-wrapper .bp3-control.bp3-large:not(.bp3-align-right){padding-left:30px}.jupyter-wrapper .bp3-control.bp3-large:not(.bp3-align-right) .bp3-control-indicator{margin-left:-30px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right{padding-right:30px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right .bp3-control-indicator{margin-right:-30px}.jupyter-wrapper .bp3-control.bp3-large .bp3-control-indicator{font-size:20px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right .bp3-control-indicator{margin-top:0}.jupyter-wrapper .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-control.bp3-checkbox:hover input:indeterminate~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-control.bp3-checkbox input:not(:disabled):active:indeterminate~.bp3-control-indicator{background:#0e5a8a;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{background:rgba(19,124,189,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox:hover input:indeterminate~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:not(:disabled):active:indeterminate~.bp3-control-indicator{background-color:#0e5a8a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{background:rgba(14,90,138,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-control.bp3-checkbox .bp3-control-indicator{border-radius:3px}.jupyter-wrapper .bp3-control.bp3-checkbox input:checked~.bp3-control-indicator:before{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='white'/%3e%3c/svg%3e\")}.jupyter-wrapper .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator:before{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 7H5c-.55 0-1 .45-1 1s.45 1 1 1h6c.55 0 1-.45 1-1s-.45-1-1-1z' fill='white'/%3e%3c/svg%3e\")}.jupyter-wrapper .bp3-control.bp3-radio .bp3-control-indicator{border-radius:50%}.jupyter-wrapper .bp3-control.bp3-radio input:checked~.bp3-control-indicator:before{background-image:radial-gradient(#ffffff,#ffffff 28%,transparent 32%)}.jupyter-wrapper .bp3-control.bp3-radio input:checked:disabled~.bp3-control-indicator:before{opacity:.5}.jupyter-wrapper .bp3-control.bp3-radio input:focus~.bp3-control-indicator{-moz-outline-radius:16px}.jupyter-wrapper .bp3-control.bp3-switch input~.bp3-control-indicator{background:rgba(167,182,194,.5)}.jupyter-wrapper .bp3-control.bp3-switch:hover input~.bp3-control-indicator{background:rgba(115,134,148,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:not(:disabled):active~.bp3-control-indicator{background:rgba(92,112,128,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:disabled~.bp3-control-indicator{background:rgba(206,217,224,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:disabled~.bp3-control-indicator:before{background:rgba(255,255,255,.8)}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator{background:#137cbd}.jupyter-wrapper .bp3-control.bp3-switch:hover input:checked~.bp3-control-indicator{background:#106ba3}.jupyter-wrapper .bp3-control.bp3-switch input:checked:not(:disabled):active~.bp3-control-indicator{background:#0e5a8a}.jupyter-wrapper .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator{background:rgba(19,124,189,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator:before{background:rgba(255,255,255,.8)}.jupyter-wrapper .bp3-control.bp3-switch:not(.bp3-align-right){padding-left:38px}.jupyter-wrapper .bp3-control.bp3-switch:not(.bp3-align-right) .bp3-control-indicator{margin-left:-38px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-align-right{padding-right:38px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-align-right .bp3-control-indicator{margin-right:-38px}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator{border:none;border-radius:1.75em;-webkit-box-shadow:none!important;box-shadow:none!important;min-width:1.75em;-webkit-transition:background-color .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9);width:auto}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator:before{background:#ffffff;border-radius:50%;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;height:calc(1em - 4px);left:0;margin:2px;position:absolute;-webkit-transition:left .1s cubic-bezier(.4,1,.75,.9);transition:left .1s cubic-bezier(.4,1,.75,.9);width:calc(1em - 4px)}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator:before{left:calc(100% - 1em)}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large:not(.bp3-align-right){padding-left:45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large:not(.bp3-align-right) .bp3-control-indicator{margin-left:-45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large.bp3-align-right{padding-right:45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large.bp3-align-right .bp3-control-indicator{margin-right:-45px}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input~.bp3-control-indicator{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch:hover input~.bp3-control-indicator{background:rgba(16,22,26,.7)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:not(:disabled):active~.bp3-control-indicator{background:rgba(16,22,26,.9)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:disabled~.bp3-control-indicator{background:rgba(57,75,89,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:disabled~.bp3-control-indicator:before{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked~.bp3-control-indicator{background:#137cbd}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch:hover input:checked~.bp3-control-indicator{background:#106ba3}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:not(:disabled):active~.bp3-control-indicator{background:#0e5a8a}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator{background:rgba(14,90,138,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator:before{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch .bp3-control-indicator:before{background:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked~.bp3-control-indicator:before{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-control.bp3-switch .bp3-switch-inner-text{font-size:.7em;text-align:center}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator-child:first-child{line-height:0;margin-left:.5em;margin-right:1.2em;visibility:hidden}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator-child:last-child{line-height:1em;margin-left:1.2em;margin-right:.5em;visibility:visible}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator .bp3-control-indicator-child:first-child{line-height:1em;visibility:visible}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator .bp3-control-indicator-child:last-child{line-height:0;visibility:hidden}.jupyter-wrapper .bp3-dark .bp3-control{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-control.bp3-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-control .bp3-control-indicator{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control:hover .bp3-control-indicator{background-color:#30404d}.jupyter-wrapper .bp3-dark .bp3-control input:not(:disabled):active~.bp3-control-indicator{background:#202b33;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control input:disabled~.bp3-control-indicator{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:checked~.bp3-control-indicator,.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{color:#a7b6c299}.jupyter-wrapper .bp3-file-input{cursor:pointer;display:inline-block;height:30px;position:relative}.jupyter-wrapper .bp3-file-input input{margin:0;min-width:200px;opacity:0}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active:hover,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input:after,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-file-input.bp3-file-input-has-selection .bp3-file-upload-input{color:#182026}.jupyter-wrapper .bp3-dark .bp3-file-input.bp3-file-input-has-selection .bp3-file-upload-input{color:#f5f8fa}.jupyter-wrapper .bp3-file-input.bp3-fill{width:100%}.jupyter-wrapper .bp3-file-input.bp3-large,.jupyter-wrapper .bp3-large .bp3-file-input{height:40px}.jupyter-wrapper .bp3-file-input .bp3-file-upload-input-custom-text:after{content:attr(bp3-button-text)}.jupyter-wrapper .bp3-file-upload-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff;border:none;border-radius:3px;-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33;color:#182026;font-size:14px;font-weight:400;height:30px;line-height:30px;outline:none;padding:0 80px 0 10px;-webkit-transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;color:#5c708099;left:0;position:absolute;right:0;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-file-upload-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input:focus,.jupyter-wrapper .bp3-file-upload-input.bp3-active{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-file-upload-input[type=search],.jupyter-wrapper .bp3-file-upload-input.bp3-round{border-radius:30px;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:10px}.jupyter-wrapper .bp3-file-upload-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-file-upload-input:disabled,.jupyter-wrapper .bp3-file-upload-input.bp3-disabled{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-file-upload-input:after{background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;min-height:24px;min-width:24px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;border-radius:3px;content:\"Browse\";line-height:24px;margin:3px;position:absolute;right:0;text-align:center;top:0;width:70px}.jupyter-wrapper .bp3-file-upload-input:after:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-file-upload-input:after .bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-file-upload-input:after:disabled,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-file-upload-input:after:disabled .bp3-active,.jupyter-wrapper .bp3-file-upload-input:after:disabled .bp3-active:hover,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled.bp3-active,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-file-upload-input:hover:after{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-file-upload-input:active:after{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-large .bp3-file-upload-input{font-size:16px;height:40px;line-height:40px;padding-right:95px}.jupyter-wrapper .bp3-large .bp3-file-upload-input[type=search],.jupyter-wrapper .bp3-large .bp3-file-upload-input.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-large .bp3-file-upload-input:after{min-height:30px;min-width:30px;line-height:30px;margin:5px;width:85px}.jupyter-wrapper .bp3-dark .bp3-file-upload-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:disabled,.jupyter-wrapper .bp3-dark .bp3-file-upload-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:hover,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:disabled,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:disabled .bp3-active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:hover:after{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:active:after{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-file-upload-input:after{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 0 15px}.jupyter-wrapper .bp3-form-group label.bp3-label{margin-bottom:5px}.jupyter-wrapper .bp3-form-group .bp3-control{margin-top:7px}.jupyter-wrapper .bp3-form-group .bp3-form-helper-text{color:#5c7080;font-size:12px;margin-top:5px}.jupyter-wrapper .bp3-form-group.bp3-intent-primary .bp3-form-helper-text{color:#106ba3}.jupyter-wrapper .bp3-form-group.bp3-intent-success .bp3-form-helper-text{color:#0d8050}.jupyter-wrapper .bp3-form-group.bp3-intent-warning .bp3-form-helper-text{color:#bf7326}.jupyter-wrapper .bp3-form-group.bp3-intent-danger .bp3-form-helper-text{color:#c23030}.jupyter-wrapper .bp3-form-group.bp3-inline{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.jupyter-wrapper .bp3-form-group.bp3-inline.bp3-large label.bp3-label{line-height:40px;margin:0 10px 0 0}.jupyter-wrapper .bp3-form-group.bp3-inline label.bp3-label{line-height:30px;margin:0 10px 0 0}.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-label,.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-text-muted,.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-form-helper-text{color:#5c708099!important}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-primary .bp3-form-helper-text{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-success .bp3-form-helper-text{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-warning .bp3-form-helper-text{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-danger .bp3-form-helper-text{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-form-group .bp3-form-helper-text{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-label,.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-text-muted,.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-form-helper-text{color:#a7b6c299!important}.jupyter-wrapper .bp3-input-group{display:block;position:relative}.jupyter-wrapper .bp3-input-group .bp3-input{position:relative;width:100%}.jupyter-wrapper .bp3-input-group .bp3-input:not(:first-child){padding-left:30px}.jupyter-wrapper .bp3-input-group .bp3-input:not(:last-child){padding-right:30px}.jupyter-wrapper .bp3-input-group .bp3-input-action,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-input-group>.bp3-button,.jupyter-wrapper .bp3-input-group>.bp3-icon{position:absolute;top:0}.jupyter-wrapper .bp3-input-group .bp3-input-action:first-child,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container:first-child,.jupyter-wrapper .bp3-input-group>.bp3-button:first-child,.jupyter-wrapper .bp3-input-group>.bp3-icon:first-child{left:0}.jupyter-wrapper .bp3-input-group .bp3-input-action:last-child,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container:last-child,.jupyter-wrapper .bp3-input-group>.bp3-button:last-child,.jupyter-wrapper .bp3-input-group>.bp3-icon:last-child{right:0}.jupyter-wrapper .bp3-input-group .bp3-button{min-height:24px;min-width:24px;margin:3px;padding:0 7px}.jupyter-wrapper .bp3-input-group .bp3-button:empty{padding:0}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-input-group>.bp3-icon{z-index:1}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group>.bp3-icon{color:#5c7080}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon:empty,.jupyter-wrapper .bp3-input-group>.bp3-icon:empty{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group>.bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input-action>.bp3-spinner{margin:7px}.jupyter-wrapper .bp3-input-group .bp3-tag{margin:5px}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus),.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus){color:#5c7080}.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus),.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus){color:#a7b6c2}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-large,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled{color:#5c708099!important}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon-large,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon-large{color:#5c708099!important}.jupyter-wrapper .bp3-input-group.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-input-group.bp3-disabled .bp3-icon{color:#5c708099}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-button{min-height:30px;min-width:30px;margin:5px}.jupyter-wrapper .bp3-input-group.bp3-large>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-large>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input-action>.bp3-spinner{margin:12px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input{font-size:16px;height:40px;line-height:40px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input[type=search],.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input:not(:first-child){padding-left:40px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input:not(:last-child){padding-right:40px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-button,.jupyter-wrapper .bp3-input-group.bp3-small .bp3-tag{min-height:20px;min-width:20px;margin:2px}.jupyter-wrapper .bp3-input-group.bp3-small>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-small>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input-action>.bp3-spinner{margin:4px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input{font-size:12px;height:24px;line-height:24px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input[type=search],.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input.bp3-round{padding:0 12px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input:not(:first-child){padding-left:24px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input:not(:last-child){padding-right:24px}.jupyter-wrapper .bp3-input-group.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:100%}.jupyter-wrapper .bp3-input-group.bp3-round .bp3-button,.jupyter-wrapper .bp3-input-group.bp3-round .bp3-input,.jupyter-wrapper .bp3-input-group.bp3-round .bp3-tag{border-radius:30px}.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-disabled .bp3-icon{color:#a7b6c299}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-primary>.bp3-icon{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-primary>.bp3-icon{color:#48aff0}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-success>.bp3-icon{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-success>.bp3-icon{color:#3dcc91}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-warning>.bp3-icon{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-warning>.bp3-icon{color:#ffb366}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-danger>.bp3-icon{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-danger>.bp3-icon{color:#ff7373}.jupyter-wrapper .bp3-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff;border:none;border-radius:3px;-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33;color:#182026;font-size:14px;font-weight:400;height:30px;line-height:30px;outline:none;padding:0 10px;-webkit-transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);vertical-align:middle}.jupyter-wrapper .bp3-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input:focus,.jupyter-wrapper .bp3-input.bp3-active{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input[type=search],.jupyter-wrapper .bp3-input.bp3-round{border-radius:30px;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:10px}.jupyter-wrapper .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-input:disabled,.jupyter-wrapper .bp3-input.bp3-disabled{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-input.bp3-large{font-size:16px;height:40px;line-height:40px}.jupyter-wrapper .bp3-input.bp3-large[type=search],.jupyter-wrapper .bp3-input.bp3-large.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-input.bp3-small{font-size:12px;height:24px;line-height:24px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-input.bp3-small[type=search],.jupyter-wrapper .bp3-input.bp3-small.bp3-round{padding:0 12px}.jupyter-wrapper .bp3-input.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:100%}.jupyter-wrapper .bp3-dark .bp3-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-input.bp3-intent-primary{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-primary:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-primary[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-input.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-input.bp3-intent-primary.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-success{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-success:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-success[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-input.bp3-intent-success:disabled,.jupyter-wrapper .bp3-input.bp3-intent-success.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #0f996000,0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #0f9960,0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-warning{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-warning:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-warning[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-input.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-input.bp3-intent-warning.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #d9822b00,0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #d9822b,0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-danger{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-danger:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-danger[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-input.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-input.bp3-intent-danger.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #db373700,0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #db3737,0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input::-ms-clear{display:none}.jupyter-wrapper textarea.bp3-input{max-width:100%;padding:10px}.jupyter-wrapper textarea.bp3-input,.jupyter-wrapper textarea.bp3-input.bp3-large,.jupyter-wrapper textarea.bp3-input.bp3-small{height:auto;line-height:inherit}.jupyter-wrapper textarea.bp3-input.bp3-small{padding:8px}.jupyter-wrapper .bp3-dark textarea.bp3-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark textarea.bp3-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark textarea.bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark textarea.bp3-input:disabled,.jupyter-wrapper .bp3-dark textarea.bp3-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper label.bp3-label{display:block;margin-bottom:15px;margin-top:0}.jupyter-wrapper label.bp3-label .bp3-html-select,.jupyter-wrapper label.bp3-label .bp3-input,.jupyter-wrapper label.bp3-label .bp3-select,.jupyter-wrapper label.bp3-label .bp3-slider,.jupyter-wrapper label.bp3-label .bp3-popover-wrapper{display:block;margin-top:5px;text-transform:none}.jupyter-wrapper label.bp3-label .bp3-button-group{margin-top:5px}.jupyter-wrapper label.bp3-label .bp3-select select,.jupyter-wrapper label.bp3-label .bp3-html-select select{font-weight:400;vertical-align:top;width:100%}.jupyter-wrapper label.bp3-label.bp3-disabled,.jupyter-wrapper label.bp3-label.bp3-disabled .bp3-text-muted{color:#5c708099}.jupyter-wrapper label.bp3-label.bp3-inline{line-height:30px}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-html-select,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input-group,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-select,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-popover-wrapper{display:inline-block;margin:0 0 0 5px;vertical-align:top}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-button-group{margin:0 0 0 5px}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input-group .bp3-input{margin-left:0}.jupyter-wrapper label.bp3-label.bp3-inline.bp3-large{line-height:40px}.jupyter-wrapper label.bp3-label:not(.bp3-inline) .bp3-popover-target{display:block}.jupyter-wrapper .bp3-dark label.bp3-label{color:#f5f8fa}.jupyter-wrapper .bp3-dark label.bp3-label.bp3-disabled,.jupyter-wrapper .bp3-dark label.bp3-label.bp3-disabled .bp3-text-muted{color:#a7b6c299}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button{-webkit-box-flex:1;-ms-flex:1 1 14px;flex:1 1 14px;min-height:0;padding:0;width:30px}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button:first-child{border-radius:0 3px 0 0}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button:last-child{border-radius:0 0 3px}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical:first-child>.bp3-button:first-child{border-radius:3px 0 0}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical:first-child>.bp3-button:last-child{border-radius:0 0 0 3px}.jupyter-wrapper .bp3-numeric-input.bp3-large .bp3-button-group.bp3-vertical>.bp3-button{width:40px}.jupyter-wrapper form{display:block}.jupyter-wrapper .bp3-html-select select,.jupyter-wrapper .bp3-select select{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;cursor:pointer;font-size:14px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:left;vertical-align:middle;background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;-moz-appearance:none;-webkit-appearance:none;border-radius:3px;height:30px;padding:0 25px 0 10px;width:100%}.jupyter-wrapper .bp3-html-select select>*,.jupyter-wrapper .bp3-select select>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-html-select select>.bp3-fill,.jupyter-wrapper .bp3-select select>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-html-select select:before,.jupyter-wrapper .bp3-select select:before,.jupyter-wrapper .bp3-html-select select>*,.jupyter-wrapper .bp3-select select>*{margin-right:7px}.jupyter-wrapper .bp3-html-select select:empty:before,.jupyter-wrapper .bp3-select select:empty:before,.jupyter-wrapper .bp3-html-select select>:last-child,.jupyter-wrapper .bp3-select select>:last-child{margin-right:0}.jupyter-wrapper .bp3-html-select select:hover,.jupyter-wrapper .bp3-select select:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-html-select select:active,.jupyter-wrapper .bp3-select select:active,.jupyter-wrapper .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-select select.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-html-select select:disabled,.jupyter-wrapper .bp3-select select:disabled,.jupyter-wrapper .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-select select.bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-html-select select:disabled.bp3-active,.jupyter-wrapper .bp3-select select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select select:disabled.bp3-active:hover,.jupyter-wrapper .bp3-select select:disabled.bp3-active:hover,.jupyter-wrapper .bp3-html-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select select.bp3-disabled.bp3-active:hover,.jupyter-wrapper .bp3-select select.bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-html-select.bp3-minimal select,.jupyter-wrapper .bp3-select.bp3-minimal select{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal select:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-html-select.bp3-large select,.jupyter-wrapper .bp3-select.bp3-large select{font-size:16px;height:40px;padding-right:35px}.jupyter-wrapper .bp3-dark .bp3-html-select select,.jupyter-wrapper .bp3-dark .bp3-select select{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select select:hover,.jupyter-wrapper .bp3-dark .bp3-select select:hover,.jupyter-wrapper .bp3-dark .bp3-html-select select:active,.jupyter-wrapper .bp3-dark .bp3-select select:active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select select:hover,.jupyter-wrapper .bp3-dark .bp3-select select:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-html-select select:active,.jupyter-wrapper .bp3-dark .bp3-select select:active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-html-select select:disabled,.jupyter-wrapper .bp3-dark .bp3-select select:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-html-select select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-html-select select .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-dark .bp3-select select .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-html-select select:disabled,.jupyter-wrapper .bp3-select select:disabled{background-color:#ced9e080;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-select .bp3-icon,.jupyter-wrapper .bp3-select:after{color:#5c7080;pointer-events:none;position:absolute;right:7px;top:7px}.jupyter-wrapper .bp3-html-select .bp3-disabled.bp3-icon,.jupyter-wrapper .bp3-select .bp3-disabled.bp3-icon,.jupyter-wrapper .bp3-disabled.bp3-select:after{color:#5c708099}.jupyter-wrapper .bp3-html-select,.jupyter-wrapper .bp3-select{display:inline-block;letter-spacing:normal;position:relative;vertical-align:middle}.jupyter-wrapper .bp3-html-select select::-ms-expand,.jupyter-wrapper .bp3-select select::-ms-expand{display:none}.jupyter-wrapper .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-select .bp3-icon{color:#5c7080}.jupyter-wrapper .bp3-html-select .bp3-icon:hover,.jupyter-wrapper .bp3-select .bp3-icon:hover{color:#182026}.jupyter-wrapper .bp3-dark .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-select .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-html-select .bp3-icon:hover,.jupyter-wrapper .bp3-dark .bp3-select .bp3-icon:hover{color:#f5f8fa}.jupyter-wrapper .bp3-html-select.bp3-large:after,.jupyter-wrapper .bp3-html-select.bp3-large .bp3-icon,.jupyter-wrapper .bp3-select.bp3-large:after,.jupyter-wrapper .bp3-select.bp3-large .bp3-icon{right:12px;top:12px}.jupyter-wrapper .bp3-html-select.bp3-fill,.jupyter-wrapper .bp3-html-select.bp3-fill select,.jupyter-wrapper .bp3-select.bp3-fill,.jupyter-wrapper .bp3-select.bp3-fill select{width:100%}.jupyter-wrapper .bp3-dark .bp3-html-select option,.jupyter-wrapper .bp3-dark .bp3-select option{background-color:#30404d;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select option:disabled,.jupyter-wrapper .bp3-dark .bp3-select option:disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-html-select:after,.jupyter-wrapper .bp3-dark .bp3-select:after{color:#a7b6c2}.jupyter-wrapper .bp3-select:after{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;content:\"\ue6c6\"}.jupyter-wrapper .bp3-running-text table,.jupyter-wrapper table.bp3-html-table{border-spacing:0;font-size:14px}.jupyter-wrapper .bp3-running-text table th,.jupyter-wrapper table.bp3-html-table th,.jupyter-wrapper .bp3-running-text table td,.jupyter-wrapper table.bp3-html-table td{padding:11px;text-align:left;vertical-align:top}.jupyter-wrapper .bp3-running-text table th,.jupyter-wrapper table.bp3-html-table th{color:#182026;font-weight:600}.jupyter-wrapper .bp3-running-text table td,.jupyter-wrapper table.bp3-html-table td{color:#182026}.jupyter-wrapper .bp3-running-text table tbody tr:first-child th,.jupyter-wrapper table.bp3-html-table tbody tr:first-child th,.jupyter-wrapper .bp3-running-text table tbody tr:first-child td,.jupyter-wrapper table.bp3-html-table tbody tr:first-child td,.jupyter-wrapper .bp3-running-text table tfoot tr:first-child th,.jupyter-wrapper table.bp3-html-table tfoot tr:first-child th,.jupyter-wrapper .bp3-running-text table tfoot tr:first-child td,.jupyter-wrapper table.bp3-html-table tfoot tr:first-child td{-webkit-box-shadow:inset 0 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26}.jupyter-wrapper .bp3-dark .bp3-running-text table th,.jupyter-wrapper .bp3-running-text .bp3-dark table th,.jupyter-wrapper .bp3-dark table.bp3-html-table th,.jupyter-wrapper .bp3-dark .bp3-running-text table td,.jupyter-wrapper .bp3-running-text .bp3-dark table td,.jupyter-wrapper .bp3-dark table.bp3-html-table td{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-running-text table tbody tr:first-child th,.jupyter-wrapper .bp3-running-text .bp3-dark table tbody tr:first-child th,.jupyter-wrapper .bp3-dark table.bp3-html-table tbody tr:first-child th,.jupyter-wrapper .bp3-dark .bp3-running-text table tbody tr:first-child td,.jupyter-wrapper .bp3-running-text .bp3-dark table tbody tr:first-child td,.jupyter-wrapper .bp3-dark table.bp3-html-table tbody tr:first-child td,.jupyter-wrapper .bp3-dark .bp3-running-text table tfoot tr:first-child th,.jupyter-wrapper .bp3-running-text .bp3-dark table tfoot tr:first-child th,.jupyter-wrapper .bp3-dark table.bp3-html-table tfoot tr:first-child th,.jupyter-wrapper .bp3-dark .bp3-running-text table tfoot tr:first-child td,.jupyter-wrapper .bp3-running-text .bp3-dark table tfoot tr:first-child td,.jupyter-wrapper .bp3-dark table.bp3-html-table tfoot tr:first-child td{-webkit-box-shadow:inset 0 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 0 1px #ffffff26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-condensed th,.jupyter-wrapper table.bp3-html-table.bp3-html-table-condensed td,.jupyter-wrapper table.bp3-html-table.bp3-small th,.jupyter-wrapper table.bp3-html-table.bp3-small td{padding-bottom:6px;padding-top:6px}.jupyter-wrapper table.bp3-html-table.bp3-html-table-striped tbody tr:nth-child(odd) td{background:rgba(191,204,214,.15)}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered th:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 0 #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tbody tr td,.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tfoot tr td{-webkit-box-shadow:inset 0 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tbody tr td:not(:first-child),.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tfoot tr td:not(:first-child){-webkit-box-shadow:inset 1px 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 1px #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 0 #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-interactive tbody tr:hover td{background-color:#bfccd64d;cursor:pointer}.jupyter-wrapper table.bp3-html-table.bp3-interactive tbody tr:active td{background-color:#bfccd666}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-striped tbody tr:nth-child(odd) td{background:rgba(92,112,128,.15)}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered th:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 0 #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tbody tr td,.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tfoot tr td{-webkit-box-shadow:inset 0 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 0 1px #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tbody tr td:not(:first-child),.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tfoot tr td:not(:first-child){-webkit-box-shadow:inset 1px 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 1px #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td{-webkit-box-shadow:inset 1px 0 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 0 #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td:first-child{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-interactive tbody tr:hover td{background-color:#5c70804d;cursor:pointer}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-interactive tbody tr:active td{background-color:#5c708066}.jupyter-wrapper .bp3-key-combo{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.jupyter-wrapper .bp3-key-combo>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-key-combo>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-key-combo:before,.jupyter-wrapper .bp3-key-combo>*{margin-right:5px}.jupyter-wrapper .bp3-key-combo:empty:before,.jupyter-wrapper .bp3-key-combo>:last-child{margin-right:0}.jupyter-wrapper .bp3-hotkey-dialog{padding-bottom:0;top:40px}.jupyter-wrapper .bp3-hotkey-dialog .bp3-dialog-body{margin:0;padding:0}.jupyter-wrapper .bp3-hotkey-dialog .bp3-hotkey-label{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.jupyter-wrapper .bp3-hotkey-column{margin:auto;max-height:80vh;overflow-y:auto;padding:30px}.jupyter-wrapper .bp3-hotkey-column .bp3-heading{margin-bottom:20px}.jupyter-wrapper .bp3-hotkey-column .bp3-heading:not(:first-child){margin-top:40px}.jupyter-wrapper .bp3-hotkey{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin-left:0;margin-right:0}.jupyter-wrapper .bp3-hotkey:not(:last-child){margin-bottom:10px}.jupyter-wrapper .bp3-icon{display:inline-block;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;vertical-align:text-bottom}.jupyter-wrapper .bp3-icon:not(:empty):before{content:\"\"!important;content:unset!important}.jupyter-wrapper .bp3-icon>svg{display:block}.jupyter-wrapper .bp3-icon>svg:not([fill]){fill:currentColor}.jupyter-wrapper .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-icon-large.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-icon-large.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-icon-large.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-icon-large.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-danger{color:#ff7373}.jupyter-wrapper span.bp3-icon-standard{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block}.jupyter-wrapper span.bp3-icon-large{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block}.jupyter-wrapper span.bp3-icon:empty{font-family:Icons20;font-size:inherit;font-style:normal;font-weight:400;line-height:1}.jupyter-wrapper span.bp3-icon:empty:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.jupyter-wrapper .bp3-icon-add:before{content:\"\ue63e\"}.jupyter-wrapper .bp3-icon-add-column-left:before{content:\"\ue6f9\"}.jupyter-wrapper .bp3-icon-add-column-right:before{content:\"\ue6fa\"}.jupyter-wrapper .bp3-icon-add-row-bottom:before{content:\"\ue6f8\"}.jupyter-wrapper .bp3-icon-add-row-top:before{content:\"\ue6f7\"}.jupyter-wrapper .bp3-icon-add-to-artifact:before{content:\"\ue67c\"}.jupyter-wrapper .bp3-icon-add-to-folder:before{content:\"\ue6d2\"}.jupyter-wrapper .bp3-icon-airplane:before{content:\"\ue74b\"}.jupyter-wrapper .bp3-icon-align-center:before{content:\"\ue603\"}.jupyter-wrapper .bp3-icon-align-justify:before{content:\"\ue605\"}.jupyter-wrapper .bp3-icon-align-left:before{content:\"\ue602\"}.jupyter-wrapper .bp3-icon-align-right:before{content:\"\ue604\"}.jupyter-wrapper .bp3-icon-alignment-bottom:before{content:\"\ue727\"}.jupyter-wrapper .bp3-icon-alignment-horizontal-center:before{content:\"\ue726\"}.jupyter-wrapper .bp3-icon-alignment-left:before{content:\"\ue722\"}.jupyter-wrapper .bp3-icon-alignment-right:before{content:\"\ue724\"}.jupyter-wrapper .bp3-icon-alignment-top:before{content:\"\ue725\"}.jupyter-wrapper .bp3-icon-alignment-vertical-center:before{content:\"\ue723\"}.jupyter-wrapper .bp3-icon-annotation:before{content:\"\ue6f0\"}.jupyter-wrapper .bp3-icon-application:before{content:\"\ue735\"}.jupyter-wrapper .bp3-icon-applications:before{content:\"\ue621\"}.jupyter-wrapper .bp3-icon-archive:before{content:\"\ue907\"}.jupyter-wrapper .bp3-icon-arrow-bottom-left:before{content:\"\u2199\"}.jupyter-wrapper .bp3-icon-arrow-bottom-right:before{content:\"\u2198\"}.jupyter-wrapper .bp3-icon-arrow-down:before{content:\"\u2193\"}.jupyter-wrapper .bp3-icon-arrow-left:before{content:\"\u2190\"}.jupyter-wrapper .bp3-icon-arrow-right:before{content:\"\u2192\"}.jupyter-wrapper .bp3-icon-arrow-top-left:before{content:\"\u2196\"}.jupyter-wrapper .bp3-icon-arrow-top-right:before{content:\"\u2197\"}.jupyter-wrapper .bp3-icon-arrow-up:before{content:\"\u2191\"}.jupyter-wrapper .bp3-icon-arrows-horizontal:before{content:\"\u2194\"}.jupyter-wrapper .bp3-icon-arrows-vertical:before{content:\"\u2195\"}.jupyter-wrapper .bp3-icon-asterisk:before{content:\"*\"}.jupyter-wrapper .bp3-icon-automatic-updates:before{content:\"\ue65f\"}.jupyter-wrapper .bp3-icon-badge:before{content:\"\ue6e3\"}.jupyter-wrapper .bp3-icon-ban-circle:before{content:\"\ue69d\"}.jupyter-wrapper .bp3-icon-bank-account:before{content:\"\ue76f\"}.jupyter-wrapper .bp3-icon-barcode:before{content:\"\ue676\"}.jupyter-wrapper .bp3-icon-blank:before{content:\"\ue900\"}.jupyter-wrapper .bp3-icon-blocked-person:before{content:\"\ue768\"}.jupyter-wrapper .bp3-icon-bold:before{content:\"\ue606\"}.jupyter-wrapper .bp3-icon-book:before{content:\"\ue6b8\"}.jupyter-wrapper .bp3-icon-bookmark:before{content:\"\ue61a\"}.jupyter-wrapper .bp3-icon-box:before{content:\"\ue6bf\"}.jupyter-wrapper .bp3-icon-briefcase:before{content:\"\ue674\"}.jupyter-wrapper .bp3-icon-bring-data:before{content:\"\ue90a\"}.jupyter-wrapper .bp3-icon-build:before{content:\"\ue72d\"}.jupyter-wrapper .bp3-icon-calculator:before{content:\"\ue70b\"}.jupyter-wrapper .bp3-icon-calendar:before{content:\"\ue62b\"}.jupyter-wrapper .bp3-icon-camera:before{content:\"\ue69e\"}.jupyter-wrapper .bp3-icon-caret-down:before{content:\"\u2304\"}.jupyter-wrapper .bp3-icon-caret-left:before{content:\"\u2329\"}.jupyter-wrapper .bp3-icon-caret-right:before{content:\"\u232a\"}.jupyter-wrapper .bp3-icon-caret-up:before{content:\"\u2303\"}.jupyter-wrapper .bp3-icon-cell-tower:before{content:\"\ue770\"}.jupyter-wrapper .bp3-icon-MKDOCS_changes:before{content:\"\ue623\"}.jupyter-wrapper .bp3-icon-chart:before{content:\"\ue67e\"}.jupyter-wrapper .bp3-icon-chat:before{content:\"\ue689\"}.jupyter-wrapper .bp3-icon-chevron-backward:before{content:\"\ue6df\"}.jupyter-wrapper .bp3-icon-chevron-down:before{content:\"\ue697\"}.jupyter-wrapper .bp3-icon-chevron-forward:before{content:\"\ue6e0\"}.jupyter-wrapper .bp3-icon-chevron-left:before{content:\"\ue694\"}.jupyter-wrapper .bp3-icon-chevron-right:before{content:\"\ue695\"}.jupyter-wrapper .bp3-icon-chevron-up:before{content:\"\ue696\"}.jupyter-wrapper .bp3-icon-circle:before{content:\"\ue66a\"}.jupyter-wrapper .bp3-icon-circle-arrow-down:before{content:\"\ue68e\"}.jupyter-wrapper .bp3-icon-circle-arrow-left:before{content:\"\ue68c\"}.jupyter-wrapper .bp3-icon-circle-arrow-right:before{content:\"\ue68b\"}.jupyter-wrapper .bp3-icon-circle-arrow-up:before{content:\"\ue68d\"}.jupyter-wrapper .bp3-icon-citation:before{content:\"\ue61b\"}.jupyter-wrapper .bp3-icon-clean:before{content:\"\ue7c5\"}.jupyter-wrapper .bp3-icon-clipboard:before{content:\"\ue61d\"}.jupyter-wrapper .bp3-icon-cloud:before{content:\"\u2601\"}.jupyter-wrapper .bp3-icon-cloud-download:before{content:\"\ue690\"}.jupyter-wrapper .bp3-icon-cloud-upload:before{content:\"\ue691\"}.jupyter-wrapper .bp3-icon-code:before{content:\"\ue661\"}.jupyter-wrapper .bp3-icon-code-block:before{content:\"\ue6c5\"}.jupyter-wrapper .bp3-icon-cog:before{content:\"\ue645\"}.jupyter-wrapper .bp3-icon-collapse-all:before{content:\"\ue763\"}.jupyter-wrapper .bp3-icon-column-layout:before{content:\"\ue6da\"}.jupyter-wrapper .bp3-icon-comment:before{content:\"\ue68a\"}.jupyter-wrapper .bp3-icon-comparison:before{content:\"\ue637\"}.jupyter-wrapper .bp3-icon-compass:before{content:\"\ue79c\"}.jupyter-wrapper .bp3-icon-compressed:before{content:\"\ue6c0\"}.jupyter-wrapper .bp3-icon-confirm:before{content:\"\ue639\"}.jupyter-wrapper .bp3-icon-console:before{content:\"\ue79b\"}.jupyter-wrapper .bp3-icon-contrast:before{content:\"\ue6cb\"}.jupyter-wrapper .bp3-icon-control:before{content:\"\ue67f\"}.jupyter-wrapper .bp3-icon-credit-card:before{content:\"\ue649\"}.jupyter-wrapper .bp3-icon-cross:before{content:\"\u2717\"}.jupyter-wrapper .bp3-icon-crown:before{content:\"\ue7b4\"}.jupyter-wrapper .bp3-icon-cube:before{content:\"\ue7c8\"}.jupyter-wrapper .bp3-icon-cube-add:before{content:\"\ue7c9\"}.jupyter-wrapper .bp3-icon-cube-remove:before{content:\"\ue7d0\"}.jupyter-wrapper .bp3-icon-curved-range-chart:before{content:\"\ue71b\"}.jupyter-wrapper .bp3-icon-cut:before{content:\"\ue6ef\"}.jupyter-wrapper .bp3-icon-dashboard:before{content:\"\ue751\"}.jupyter-wrapper .bp3-icon-data-lineage:before{content:\"\ue908\"}.jupyter-wrapper .bp3-icon-database:before{content:\"\ue683\"}.jupyter-wrapper .bp3-icon-delete:before{content:\"\ue644\"}.jupyter-wrapper .bp3-icon-delta:before{content:\"\u0394\"}.jupyter-wrapper .bp3-icon-derive-column:before{content:\"\ue739\"}.jupyter-wrapper .bp3-icon-desktop:before{content:\"\ue6af\"}.jupyter-wrapper .bp3-icon-diagnosis:before{content:\"\ue90d\"}.jupyter-wrapper .bp3-icon-diagram-tree:before{content:\"\ue7b3\"}.jupyter-wrapper .bp3-icon-direction-left:before{content:\"\ue681\"}.jupyter-wrapper .bp3-icon-direction-right:before{content:\"\ue682\"}.jupyter-wrapper .bp3-icon-disable:before{content:\"\ue600\"}.jupyter-wrapper .bp3-icon-document:before{content:\"\ue630\"}.jupyter-wrapper .bp3-icon-document-open:before{content:\"\ue71e\"}.jupyter-wrapper .bp3-icon-document-share:before{content:\"\ue71f\"}.jupyter-wrapper .bp3-icon-dollar:before{content:\"$\"}.jupyter-wrapper .bp3-icon-dot:before{content:\"\u2022\"}.jupyter-wrapper .bp3-icon-double-caret-horizontal:before{content:\"\ue6c7\"}.jupyter-wrapper .bp3-icon-double-caret-vertical:before{content:\"\ue6c6\"}.jupyter-wrapper .bp3-icon-double-chevron-down:before{content:\"\ue703\"}.jupyter-wrapper .bp3-icon-double-chevron-left:before{content:\"\ue6ff\"}.jupyter-wrapper .bp3-icon-double-chevron-right:before{content:\"\ue701\"}.jupyter-wrapper .bp3-icon-double-chevron-up:before{content:\"\ue702\"}.jupyter-wrapper .bp3-icon-doughnut-chart:before{content:\"\ue6ce\"}.jupyter-wrapper .bp3-icon-download:before{content:\"\ue62f\"}.jupyter-wrapper .bp3-icon-drag-handle-horizontal:before{content:\"\ue716\"}.jupyter-wrapper .bp3-icon-drag-handle-vertical:before{content:\"\ue715\"}.jupyter-wrapper .bp3-icon-draw:before{content:\"\ue66b\"}.jupyter-wrapper .bp3-icon-drive-time:before{content:\"\ue615\"}.jupyter-wrapper .bp3-icon-duplicate:before{content:\"\ue69c\"}.jupyter-wrapper .bp3-icon-edit:before{content:\"\u270e\"}.jupyter-wrapper .bp3-icon-eject:before{content:\"\u23cf\"}.jupyter-wrapper .bp3-icon-endorsed:before{content:\"\ue75f\"}.jupyter-wrapper .bp3-icon-envelope:before{content:\"\u2709\"}.jupyter-wrapper .bp3-icon-equals:before{content:\"\ue7d9\"}.jupyter-wrapper .bp3-icon-eraser:before{content:\"\ue773\"}.jupyter-wrapper .bp3-icon-error:before{content:\"\ue648\"}.jupyter-wrapper .bp3-icon-euro:before{content:\"\u20ac\"}.jupyter-wrapper .bp3-icon-MKDOCS_exchange:before{content:\"\ue636\"}.jupyter-wrapper .bp3-icon-exclude-row:before{content:\"\ue6ea\"}.jupyter-wrapper .bp3-icon-expand-all:before{content:\"\ue764\"}.jupyter-wrapper .bp3-icon-export:before{content:\"\ue633\"}.jupyter-wrapper .bp3-icon-eye-off:before{content:\"\ue6cc\"}.jupyter-wrapper .bp3-icon-eye-on:before{content:\"\ue75a\"}.jupyter-wrapper .bp3-icon-eye-open:before{content:\"\ue66f\"}.jupyter-wrapper .bp3-icon-fast-backward:before{content:\"\ue6a8\"}.jupyter-wrapper .bp3-icon-fast-forward:before{content:\"\ue6ac\"}.jupyter-wrapper .bp3-icon-feed:before{content:\"\ue656\"}.jupyter-wrapper .bp3-icon-feed-subscribed:before{content:\"\ue78f\"}.jupyter-wrapper .bp3-icon-film:before{content:\"\ue6a1\"}.jupyter-wrapper .bp3-icon-filter:before{content:\"\ue638\"}.jupyter-wrapper .bp3-icon-filter-keep:before{content:\"\ue78c\"}.jupyter-wrapper .bp3-icon-filter-list:before{content:\"\ue6ee\"}.jupyter-wrapper .bp3-icon-filter-open:before{content:\"\ue7d7\"}.jupyter-wrapper .bp3-icon-filter-remove:before{content:\"\ue78d\"}.jupyter-wrapper .bp3-icon-flag:before{content:\"\u2691\"}.jupyter-wrapper .bp3-icon-flame:before{content:\"\ue7a9\"}.jupyter-wrapper .bp3-icon-flash:before{content:\"\ue6b3\"}.jupyter-wrapper .bp3-icon-floppy-disk:before{content:\"\ue6b7\"}.jupyter-wrapper .bp3-icon-flow-branch:before{content:\"\ue7c1\"}.jupyter-wrapper .bp3-icon-flow-end:before{content:\"\ue7c4\"}.jupyter-wrapper .bp3-icon-flow-linear:before{content:\"\ue7c0\"}.jupyter-wrapper .bp3-icon-flow-review:before{content:\"\ue7c2\"}.jupyter-wrapper .bp3-icon-flow-review-branch:before{content:\"\ue7c3\"}.jupyter-wrapper .bp3-icon-flows:before{content:\"\ue659\"}.jupyter-wrapper .bp3-icon-folder-close:before{content:\"\ue652\"}.jupyter-wrapper .bp3-icon-folder-new:before{content:\"\ue7b0\"}.jupyter-wrapper .bp3-icon-folder-open:before{content:\"\ue651\"}.jupyter-wrapper .bp3-icon-folder-shared:before{content:\"\ue653\"}.jupyter-wrapper .bp3-icon-folder-shared-open:before{content:\"\ue670\"}.jupyter-wrapper .bp3-icon-follower:before{content:\"\ue760\"}.jupyter-wrapper .bp3-icon-following:before{content:\"\ue761\"}.jupyter-wrapper .bp3-icon-font:before{content:\"\ue6b4\"}.jupyter-wrapper .bp3-icon-fork:before{content:\"\ue63a\"}.jupyter-wrapper .bp3-icon-form:before{content:\"\ue795\"}.jupyter-wrapper .bp3-icon-full-circle:before{content:\"\ue685\"}.jupyter-wrapper .bp3-icon-full-stacked-chart:before{content:\"\ue75e\"}.jupyter-wrapper .bp3-icon-fullscreen:before{content:\"\ue699\"}.jupyter-wrapper .bp3-icon-function:before{content:\"\ue6e5\"}.jupyter-wrapper .bp3-icon-gantt-chart:before{content:\"\ue6f4\"}.jupyter-wrapper .bp3-icon-geolocation:before{content:\"\ue640\"}.jupyter-wrapper .bp3-icon-geosearch:before{content:\"\ue613\"}.jupyter-wrapper .bp3-icon-git-branch:before{content:\"\ue72a\"}.jupyter-wrapper .bp3-icon-git-commit:before{content:\"\ue72b\"}.jupyter-wrapper .bp3-icon-git-merge:before{content:\"\ue729\"}.jupyter-wrapper .bp3-icon-git-new-branch:before{content:\"\ue749\"}.jupyter-wrapper .bp3-icon-git-pull:before{content:\"\ue728\"}.jupyter-wrapper .bp3-icon-git-push:before{content:\"\ue72c\"}.jupyter-wrapper .bp3-icon-git-repo:before{content:\"\ue748\"}.jupyter-wrapper .bp3-icon-glass:before{content:\"\ue6b1\"}.jupyter-wrapper .bp3-icon-globe:before{content:\"\ue666\"}.jupyter-wrapper .bp3-icon-globe-network:before{content:\"\ue7b5\"}.jupyter-wrapper .bp3-icon-graph:before{content:\"\ue673\"}.jupyter-wrapper .bp3-icon-graph-remove:before{content:\"\ue609\"}.jupyter-wrapper .bp3-icon-greater-than:before{content:\"\ue7e1\"}.jupyter-wrapper .bp3-icon-greater-than-or-equal-to:before{content:\"\ue7e2\"}.jupyter-wrapper .bp3-icon-grid:before{content:\"\ue6d0\"}.jupyter-wrapper .bp3-icon-grid-view:before{content:\"\ue6e4\"}.jupyter-wrapper .bp3-icon-group-objects:before{content:\"\ue60a\"}.jupyter-wrapper .bp3-icon-grouped-bar-chart:before{content:\"\ue75d\"}.jupyter-wrapper .bp3-icon-hand:before{content:\"\ue6de\"}.jupyter-wrapper .bp3-icon-hand-down:before{content:\"\ue6bb\"}.jupyter-wrapper .bp3-icon-hand-left:before{content:\"\ue6bc\"}.jupyter-wrapper .bp3-icon-hand-right:before{content:\"\ue6b9\"}.jupyter-wrapper .bp3-icon-hand-up:before{content:\"\ue6ba\"}.jupyter-wrapper .bp3-icon-header:before{content:\"\ue6b5\"}.jupyter-wrapper .bp3-icon-header-one:before{content:\"\ue793\"}.jupyter-wrapper .bp3-icon-header-two:before{content:\"\ue794\"}.jupyter-wrapper .bp3-icon-headset:before{content:\"\ue6dc\"}.jupyter-wrapper .bp3-icon-heart:before{content:\"\u2665\"}.jupyter-wrapper .bp3-icon-heart-broken:before{content:\"\ue7a2\"}.jupyter-wrapper .bp3-icon-heat-grid:before{content:\"\ue6f3\"}.jupyter-wrapper .bp3-icon-heatmap:before{content:\"\ue614\"}.jupyter-wrapper .bp3-icon-help:before{content:\"?\"}.jupyter-wrapper .bp3-icon-helper-management:before{content:\"\ue66d\"}.jupyter-wrapper .bp3-icon-highlight:before{content:\"\ue6ed\"}.jupyter-wrapper .bp3-icon-history:before{content:\"\ue64a\"}.jupyter-wrapper .bp3-icon-home:before{content:\"\u2302\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart:before{content:\"\ue70c\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart-asc:before{content:\"\ue75c\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart-desc:before{content:\"\ue71d\"}.jupyter-wrapper .bp3-icon-horizontal-distribution:before{content:\"\ue720\"}.jupyter-wrapper .bp3-icon-id-number:before{content:\"\ue771\"}.jupyter-wrapper .bp3-icon-image-rotate-left:before{content:\"\ue73a\"}.jupyter-wrapper .bp3-icon-image-rotate-right:before{content:\"\ue73b\"}.jupyter-wrapper .bp3-icon-import:before{content:\"\ue632\"}.jupyter-wrapper .bp3-icon-inbox:before{content:\"\ue629\"}.jupyter-wrapper .bp3-icon-inbox-filtered:before{content:\"\ue7d1\"}.jupyter-wrapper .bp3-icon-inbox-geo:before{content:\"\ue7d2\"}.jupyter-wrapper .bp3-icon-inbox-search:before{content:\"\ue7d3\"}.jupyter-wrapper .bp3-icon-inbox-update:before{content:\"\ue7d4\"}.jupyter-wrapper .bp3-icon-info-sign:before{content:\"\u2139\"}.jupyter-wrapper .bp3-icon-inheritance:before{content:\"\ue7d5\"}.jupyter-wrapper .bp3-icon-inner-join:before{content:\"\ue7a3\"}.jupyter-wrapper .bp3-icon-insert:before{content:\"\ue66c\"}.jupyter-wrapper .bp3-icon-intersection:before{content:\"\ue765\"}.jupyter-wrapper .bp3-icon-ip-address:before{content:\"\ue772\"}.jupyter-wrapper .bp3-icon-issue:before{content:\"\ue774\"}.jupyter-wrapper .bp3-icon-issue-closed:before{content:\"\ue776\"}.jupyter-wrapper .bp3-icon-issue-new:before{content:\"\ue775\"}.jupyter-wrapper .bp3-icon-italic:before{content:\"\ue607\"}.jupyter-wrapper .bp3-icon-join-table:before{content:\"\ue738\"}.jupyter-wrapper .bp3-icon-key:before{content:\"\ue78e\"}.jupyter-wrapper .bp3-icon-key-backspace:before{content:\"\ue707\"}.jupyter-wrapper .bp3-icon-key-command:before{content:\"\ue705\"}.jupyter-wrapper .bp3-icon-key-control:before{content:\"\ue704\"}.jupyter-wrapper .bp3-icon-key-delete:before{content:\"\ue708\"}.jupyter-wrapper .bp3-icon-key-enter:before{content:\"\ue70a\"}.jupyter-wrapper .bp3-icon-key-escape:before{content:\"\ue709\"}.jupyter-wrapper .bp3-icon-key-option:before{content:\"\ue742\"}.jupyter-wrapper .bp3-icon-key-shift:before{content:\"\ue706\"}.jupyter-wrapper .bp3-icon-key-tab:before{content:\"\ue757\"}.jupyter-wrapper .bp3-icon-known-vehicle:before{content:\"\ue73c\"}.jupyter-wrapper .bp3-icon-lab-test:before{content:\"\ue90e\"}.jupyter-wrapper .bp3-icon-label:before{content:\"\ue665\"}.jupyter-wrapper .bp3-icon-layer:before{content:\"\ue6cf\"}.jupyter-wrapper .bp3-icon-layers:before{content:\"\ue618\"}.jupyter-wrapper .bp3-icon-layout:before{content:\"\ue60c\"}.jupyter-wrapper .bp3-icon-layout-auto:before{content:\"\ue60d\"}.jupyter-wrapper .bp3-icon-layout-balloon:before{content:\"\ue6d3\"}.jupyter-wrapper .bp3-icon-layout-circle:before{content:\"\ue60e\"}.jupyter-wrapper .bp3-icon-layout-grid:before{content:\"\ue610\"}.jupyter-wrapper .bp3-icon-layout-group-by:before{content:\"\ue611\"}.jupyter-wrapper .bp3-icon-layout-hierarchy:before{content:\"\ue60f\"}.jupyter-wrapper .bp3-icon-layout-linear:before{content:\"\ue6c3\"}.jupyter-wrapper .bp3-icon-layout-skew-grid:before{content:\"\ue612\"}.jupyter-wrapper .bp3-icon-layout-sorted-clusters:before{content:\"\ue6d4\"}.jupyter-wrapper .bp3-icon-learning:before{content:\"\ue904\"}.jupyter-wrapper .bp3-icon-left-join:before{content:\"\ue7a4\"}.jupyter-wrapper .bp3-icon-less-than:before{content:\"\ue7e3\"}.jupyter-wrapper .bp3-icon-less-than-or-equal-to:before{content:\"\ue7e4\"}.jupyter-wrapper .bp3-icon-lifesaver:before{content:\"\ue7c7\"}.jupyter-wrapper .bp3-icon-lightbulb:before{content:\"\ue6b0\"}.jupyter-wrapper .bp3-icon-link:before{content:\"\ue62d\"}.jupyter-wrapper .bp3-icon-list:before{content:\"\u2630\"}.jupyter-wrapper .bp3-icon-list-columns:before{content:\"\ue7b9\"}.jupyter-wrapper .bp3-icon-list-detail-view:before{content:\"\ue743\"}.jupyter-wrapper .bp3-icon-locate:before{content:\"\ue619\"}.jupyter-wrapper .bp3-icon-lock:before{content:\"\ue625\"}.jupyter-wrapper .bp3-icon-log-in:before{content:\"\ue69a\"}.jupyter-wrapper .bp3-icon-log-out:before{content:\"\ue64c\"}.jupyter-wrapper .bp3-icon-manual:before{content:\"\ue6f6\"}.jupyter-wrapper .bp3-icon-manually-entered-data:before{content:\"\ue74a\"}.jupyter-wrapper .bp3-icon-map:before{content:\"\ue662\"}.jupyter-wrapper .bp3-icon-map-create:before{content:\"\ue741\"}.jupyter-wrapper .bp3-icon-map-marker:before{content:\"\ue67d\"}.jupyter-wrapper .bp3-icon-maximize:before{content:\"\ue635\"}.jupyter-wrapper .bp3-icon-media:before{content:\"\ue62c\"}.jupyter-wrapper .bp3-icon-menu:before{content:\"\ue762\"}.jupyter-wrapper .bp3-icon-menu-closed:before{content:\"\ue655\"}.jupyter-wrapper .bp3-icon-menu-open:before{content:\"\ue654\"}.jupyter-wrapper .bp3-icon-merge-columns:before{content:\"\ue74f\"}.jupyter-wrapper .bp3-icon-merge-links:before{content:\"\ue60b\"}.jupyter-wrapper .bp3-icon-minimize:before{content:\"\ue634\"}.jupyter-wrapper .bp3-icon-minus:before{content:\"\u2212\"}.jupyter-wrapper .bp3-icon-mobile-phone:before{content:\"\ue717\"}.jupyter-wrapper .bp3-icon-mobile-video:before{content:\"\ue69f\"}.jupyter-wrapper .bp3-icon-moon:before{content:\"\ue754\"}.jupyter-wrapper .bp3-icon-more:before{content:\"\ue62a\"}.jupyter-wrapper .bp3-icon-mountain:before{content:\"\ue7b1\"}.jupyter-wrapper .bp3-icon-move:before{content:\"\ue693\"}.jupyter-wrapper .bp3-icon-mugshot:before{content:\"\ue6db\"}.jupyter-wrapper .bp3-icon-multi-select:before{content:\"\ue680\"}.jupyter-wrapper .bp3-icon-music:before{content:\"\ue6a6\"}.jupyter-wrapper .bp3-icon-new-drawing:before{content:\"\ue905\"}.jupyter-wrapper .bp3-icon-new-grid-item:before{content:\"\ue747\"}.jupyter-wrapper .bp3-icon-new-layer:before{content:\"\ue902\"}.jupyter-wrapper .bp3-icon-new-layers:before{content:\"\ue903\"}.jupyter-wrapper .bp3-icon-new-link:before{content:\"\ue65c\"}.jupyter-wrapper .bp3-icon-new-object:before{content:\"\ue65d\"}.jupyter-wrapper .bp3-icon-new-person:before{content:\"\ue6e9\"}.jupyter-wrapper .bp3-icon-new-prescription:before{content:\"\ue78b\"}.jupyter-wrapper .bp3-icon-new-text-box:before{content:\"\ue65b\"}.jupyter-wrapper .bp3-icon-ninja:before{content:\"\ue675\"}.jupyter-wrapper .bp3-icon-not-equal-to:before{content:\"\ue7e0\"}.jupyter-wrapper .bp3-icon-notifications:before{content:\"\ue624\"}.jupyter-wrapper .bp3-icon-notifications-updated:before{content:\"\ue7b8\"}.jupyter-wrapper .bp3-icon-numbered-list:before{content:\"\ue746\"}.jupyter-wrapper .bp3-icon-numerical:before{content:\"\ue756\"}.jupyter-wrapper .bp3-icon-office:before{content:\"\ue69b\"}.jupyter-wrapper .bp3-icon-offline:before{content:\"\ue67a\"}.jupyter-wrapper .bp3-icon-oil-field:before{content:\"\ue73f\"}.jupyter-wrapper .bp3-icon-one-column:before{content:\"\ue658\"}.jupyter-wrapper .bp3-icon-outdated:before{content:\"\ue7a8\"}.jupyter-wrapper .bp3-icon-page-layout:before{content:\"\ue660\"}.jupyter-wrapper .bp3-icon-panel-stats:before{content:\"\ue777\"}.jupyter-wrapper .bp3-icon-panel-table:before{content:\"\ue778\"}.jupyter-wrapper .bp3-icon-paperclip:before{content:\"\ue664\"}.jupyter-wrapper .bp3-icon-paragraph:before{content:\"\ue76c\"}.jupyter-wrapper .bp3-icon-path:before{content:\"\ue753\"}.jupyter-wrapper .bp3-icon-path-search:before{content:\"\ue65e\"}.jupyter-wrapper .bp3-icon-pause:before{content:\"\ue6a9\"}.jupyter-wrapper .bp3-icon-people:before{content:\"\ue63d\"}.jupyter-wrapper .bp3-icon-percentage:before{content:\"\ue76a\"}.jupyter-wrapper .bp3-icon-person:before{content:\"\ue63c\"}.jupyter-wrapper .bp3-icon-phone:before{content:\"\u260e\"}.jupyter-wrapper .bp3-icon-pie-chart:before{content:\"\ue684\"}.jupyter-wrapper .bp3-icon-pin:before{content:\"\ue646\"}.jupyter-wrapper .bp3-icon-pivot:before{content:\"\ue6f1\"}.jupyter-wrapper .bp3-icon-pivot-table:before{content:\"\ue6eb\"}.jupyter-wrapper .bp3-icon-play:before{content:\"\ue6ab\"}.jupyter-wrapper .bp3-icon-plus:before{content:\"+\"}.jupyter-wrapper .bp3-icon-polygon-filter:before{content:\"\ue6d1\"}.jupyter-wrapper .bp3-icon-power:before{content:\"\ue6d9\"}.jupyter-wrapper .bp3-icon-predictive-analysis:before{content:\"\ue617\"}.jupyter-wrapper .bp3-icon-prescription:before{content:\"\ue78a\"}.jupyter-wrapper .bp3-icon-presentation:before{content:\"\ue687\"}.jupyter-wrapper .bp3-icon-print:before{content:\"\u2399\"}.jupyter-wrapper .bp3-icon-projects:before{content:\"\ue622\"}.jupyter-wrapper .bp3-icon-properties:before{content:\"\ue631\"}.jupyter-wrapper .bp3-icon-property:before{content:\"\ue65a\"}.jupyter-wrapper .bp3-icon-publish-function:before{content:\"\ue752\"}.jupyter-wrapper .bp3-icon-pulse:before{content:\"\ue6e8\"}.jupyter-wrapper .bp3-icon-random:before{content:\"\ue698\"}.jupyter-wrapper .bp3-icon-record:before{content:\"\ue6ae\"}.jupyter-wrapper .bp3-icon-redo:before{content:\"\ue6c4\"}.jupyter-wrapper .bp3-icon-refresh:before{content:\"\ue643\"}.jupyter-wrapper .bp3-icon-regression-chart:before{content:\"\ue758\"}.jupyter-wrapper .bp3-icon-remove:before{content:\"\ue63f\"}.jupyter-wrapper .bp3-icon-remove-column:before{content:\"\ue755\"}.jupyter-wrapper .bp3-icon-remove-column-left:before{content:\"\ue6fd\"}.jupyter-wrapper .bp3-icon-remove-column-right:before{content:\"\ue6fe\"}.jupyter-wrapper .bp3-icon-remove-row-bottom:before{content:\"\ue6fc\"}.jupyter-wrapper .bp3-icon-remove-row-top:before{content:\"\ue6fb\"}.jupyter-wrapper .bp3-icon-repeat:before{content:\"\ue692\"}.jupyter-wrapper .bp3-icon-reset:before{content:\"\ue7d6\"}.jupyter-wrapper .bp3-icon-resolve:before{content:\"\ue672\"}.jupyter-wrapper .bp3-icon-rig:before{content:\"\ue740\"}.jupyter-wrapper .bp3-icon-right-join:before{content:\"\ue7a5\"}.jupyter-wrapper .bp3-icon-ring:before{content:\"\ue6f2\"}.jupyter-wrapper .bp3-icon-rotate-document:before{content:\"\ue6e1\"}.jupyter-wrapper .bp3-icon-rotate-page:before{content:\"\ue6e2\"}.jupyter-wrapper .bp3-icon-satellite:before{content:\"\ue76b\"}.jupyter-wrapper .bp3-icon-saved:before{content:\"\ue6b6\"}.jupyter-wrapper .bp3-icon-scatter-plot:before{content:\"\ue73e\"}.jupyter-wrapper .bp3-icon-search:before{content:\"\ue64b\"}.jupyter-wrapper .bp3-icon-search-around:before{content:\"\ue608\"}.jupyter-wrapper .bp3-icon-search-template:before{content:\"\ue628\"}.jupyter-wrapper .bp3-icon-search-text:before{content:\"\ue663\"}.jupyter-wrapper .bp3-icon-segmented-control:before{content:\"\ue6ec\"}.jupyter-wrapper .bp3-icon-select:before{content:\"\ue616\"}.jupyter-wrapper .bp3-icon-selection:before{content:\"\u29bf\"}.jupyter-wrapper .bp3-icon-send-to:before{content:\"\ue66e\"}.jupyter-wrapper .bp3-icon-send-to-graph:before{content:\"\ue736\"}.jupyter-wrapper .bp3-icon-send-to-map:before{content:\"\ue737\"}.jupyter-wrapper .bp3-icon-series-add:before{content:\"\ue796\"}.jupyter-wrapper .bp3-icon-series-configuration:before{content:\"\ue79a\"}.jupyter-wrapper .bp3-icon-series-derived:before{content:\"\ue799\"}.jupyter-wrapper .bp3-icon-series-filtered:before{content:\"\ue798\"}.jupyter-wrapper .bp3-icon-series-search:before{content:\"\ue797\"}.jupyter-wrapper .bp3-icon-settings:before{content:\"\ue6a2\"}.jupyter-wrapper .bp3-icon-share:before{content:\"\ue62e\"}.jupyter-wrapper .bp3-icon-shield:before{content:\"\ue7b2\"}.jupyter-wrapper .bp3-icon-shop:before{content:\"\ue6c2\"}.jupyter-wrapper .bp3-icon-shopping-cart:before{content:\"\ue6c1\"}.jupyter-wrapper .bp3-icon-signal-search:before{content:\"\ue909\"}.jupyter-wrapper .bp3-icon-sim-card:before{content:\"\ue718\"}.jupyter-wrapper .bp3-icon-slash:before{content:\"\ue769\"}.jupyter-wrapper .bp3-icon-small-cross:before{content:\"\ue6d7\"}.jupyter-wrapper .bp3-icon-small-minus:before{content:\"\ue70e\"}.jupyter-wrapper .bp3-icon-small-plus:before{content:\"\ue70d\"}.jupyter-wrapper .bp3-icon-small-tick:before{content:\"\ue6d8\"}.jupyter-wrapper .bp3-icon-snowflake:before{content:\"\ue7b6\"}.jupyter-wrapper .bp3-icon-social-media:before{content:\"\ue671\"}.jupyter-wrapper .bp3-icon-sort:before{content:\"\ue64f\"}.jupyter-wrapper .bp3-icon-sort-alphabetical:before{content:\"\ue64d\"}.jupyter-wrapper .bp3-icon-sort-alphabetical-desc:before{content:\"\ue6c8\"}.jupyter-wrapper .bp3-icon-sort-asc:before{content:\"\ue6d5\"}.jupyter-wrapper .bp3-icon-sort-desc:before{content:\"\ue6d6\"}.jupyter-wrapper .bp3-icon-sort-numerical:before{content:\"\ue64e\"}.jupyter-wrapper .bp3-icon-sort-numerical-desc:before{content:\"\ue6c9\"}.jupyter-wrapper .bp3-icon-split-columns:before{content:\"\ue750\"}.jupyter-wrapper .bp3-icon-square:before{content:\"\ue686\"}.jupyter-wrapper .bp3-icon-stacked-chart:before{content:\"\ue6e7\"}.jupyter-wrapper .bp3-icon-star:before{content:\"\u2605\"}.jupyter-wrapper .bp3-icon-star-empty:before{content:\"\u2606\"}.jupyter-wrapper .bp3-icon-step-backward:before{content:\"\ue6a7\"}.jupyter-wrapper .bp3-icon-step-chart:before{content:\"\ue70f\"}.jupyter-wrapper .bp3-icon-step-forward:before{content:\"\ue6ad\"}.jupyter-wrapper .bp3-icon-stop:before{content:\"\ue6aa\"}.jupyter-wrapper .bp3-icon-stopwatch:before{content:\"\ue901\"}.jupyter-wrapper .bp3-icon-strikethrough:before{content:\"\ue7a6\"}.jupyter-wrapper .bp3-icon-style:before{content:\"\ue601\"}.jupyter-wrapper .bp3-icon-swap-horizontal:before{content:\"\ue745\"}.jupyter-wrapper .bp3-icon-swap-vertical:before{content:\"\ue744\"}.jupyter-wrapper .bp3-icon-symbol-circle:before{content:\"\ue72e\"}.jupyter-wrapper .bp3-icon-symbol-cross:before{content:\"\ue731\"}.jupyter-wrapper .bp3-icon-symbol-diamond:before{content:\"\ue730\"}.jupyter-wrapper .bp3-icon-symbol-square:before{content:\"\ue72f\"}.jupyter-wrapper .bp3-icon-symbol-triangle-down:before{content:\"\ue733\"}.jupyter-wrapper .bp3-icon-symbol-triangle-up:before{content:\"\ue732\"}.jupyter-wrapper .bp3-icon-tag:before{content:\"\ue61c\"}.jupyter-wrapper .bp3-icon-take-action:before{content:\"\ue6ca\"}.jupyter-wrapper .bp3-icon-taxi:before{content:\"\ue79e\"}.jupyter-wrapper .bp3-icon-text-highlight:before{content:\"\ue6dd\"}.jupyter-wrapper .bp3-icon-th:before{content:\"\ue667\"}.jupyter-wrapper .bp3-icon-th-derived:before{content:\"\ue669\"}.jupyter-wrapper .bp3-icon-th-disconnect:before{content:\"\ue7d8\"}.jupyter-wrapper .bp3-icon-th-filtered:before{content:\"\ue7c6\"}.jupyter-wrapper .bp3-icon-th-list:before{content:\"\ue668\"}.jupyter-wrapper .bp3-icon-thumbs-down:before{content:\"\ue6be\"}.jupyter-wrapper .bp3-icon-thumbs-up:before{content:\"\ue6bd\"}.jupyter-wrapper .bp3-icon-tick:before{content:\"\u2713\"}.jupyter-wrapper .bp3-icon-tick-circle:before{content:\"\ue779\"}.jupyter-wrapper .bp3-icon-time:before{content:\"\u23f2\"}.jupyter-wrapper .bp3-icon-timeline-area-chart:before{content:\"\ue6cd\"}.jupyter-wrapper .bp3-icon-timeline-bar-chart:before{content:\"\ue620\"}.jupyter-wrapper .bp3-icon-timeline-events:before{content:\"\ue61e\"}.jupyter-wrapper .bp3-icon-timeline-line-chart:before{content:\"\ue61f\"}.jupyter-wrapper .bp3-icon-tint:before{content:\"\ue6b2\"}.jupyter-wrapper .bp3-icon-torch:before{content:\"\ue677\"}.jupyter-wrapper .bp3-icon-tractor:before{content:\"\ue90c\"}.jupyter-wrapper .bp3-icon-train:before{content:\"\ue79f\"}.jupyter-wrapper .bp3-icon-translate:before{content:\"\ue759\"}.jupyter-wrapper .bp3-icon-trash:before{content:\"\ue63b\"}.jupyter-wrapper .bp3-icon-tree:before{content:\"\ue7b7\"}.jupyter-wrapper .bp3-icon-trending-down:before{content:\"\ue71a\"}.jupyter-wrapper .bp3-icon-trending-up:before{content:\"\ue719\"}.jupyter-wrapper .bp3-icon-truck:before{content:\"\ue90b\"}.jupyter-wrapper .bp3-icon-two-columns:before{content:\"\ue657\"}.jupyter-wrapper .bp3-icon-unarchive:before{content:\"\ue906\"}.jupyter-wrapper .bp3-icon-underline:before{content:\"\u2381\"}.jupyter-wrapper .bp3-icon-undo:before{content:\"\u238c\"}.jupyter-wrapper .bp3-icon-ungroup-objects:before{content:\"\ue688\"}.jupyter-wrapper .bp3-icon-unknown-vehicle:before{content:\"\ue73d\"}.jupyter-wrapper .bp3-icon-unlock:before{content:\"\ue626\"}.jupyter-wrapper .bp3-icon-unpin:before{content:\"\ue650\"}.jupyter-wrapper .bp3-icon-unresolve:before{content:\"\ue679\"}.jupyter-wrapper .bp3-icon-updated:before{content:\"\ue7a7\"}.jupyter-wrapper .bp3-icon-upload:before{content:\"\ue68f\"}.jupyter-wrapper .bp3-icon-user:before{content:\"\ue627\"}.jupyter-wrapper .bp3-icon-variable:before{content:\"\ue6f5\"}.jupyter-wrapper .bp3-icon-vertical-bar-chart-asc:before{content:\"\ue75b\"}.jupyter-wrapper .bp3-icon-vertical-bar-chart-desc:before{content:\"\ue71c\"}.jupyter-wrapper .bp3-icon-vertical-distribution:before{content:\"\ue721\"}.jupyter-wrapper .bp3-icon-video:before{content:\"\ue6a0\"}.jupyter-wrapper .bp3-icon-volume-down:before{content:\"\ue6a4\"}.jupyter-wrapper .bp3-icon-volume-off:before{content:\"\ue6a3\"}.jupyter-wrapper .bp3-icon-volume-up:before{content:\"\ue6a5\"}.jupyter-wrapper .bp3-icon-walk:before{content:\"\ue79d\"}.jupyter-wrapper .bp3-icon-warning-sign:before{content:\"\ue647\"}.jupyter-wrapper .bp3-icon-waterfall-chart:before{content:\"\ue6e6\"}.jupyter-wrapper .bp3-icon-widget:before{content:\"\ue678\"}.jupyter-wrapper .bp3-icon-widget-button:before{content:\"\ue790\"}.jupyter-wrapper .bp3-icon-widget-footer:before{content:\"\ue792\"}.jupyter-wrapper .bp3-icon-widget-header:before{content:\"\ue791\"}.jupyter-wrapper .bp3-icon-wrench:before{content:\"\ue734\"}.jupyter-wrapper .bp3-icon-zoom-in:before{content:\"\ue641\"}.jupyter-wrapper .bp3-icon-zoom-out:before{content:\"\ue642\"}.jupyter-wrapper .bp3-icon-zoom-to-fit:before{content:\"\ue67b\"}.jupyter-wrapper .bp3-submenu>.bp3-popover-wrapper{display:block}.jupyter-wrapper .bp3-submenu .bp3-popover-target{display:block}.jupyter-wrapper .bp3-submenu.bp3-popover{-webkit-box-shadow:none;box-shadow:none;padding:0 5px}.jupyter-wrapper .bp3-submenu.bp3-popover>.bp3-popover-content{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33}.jupyter-wrapper .bp3-dark .bp3-submenu.bp3-popover,.jupyter-wrapper .bp3-submenu.bp3-popover.bp3-dark{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-submenu.bp3-popover>.bp3-popover-content,.jupyter-wrapper .bp3-submenu.bp3-popover.bp3-dark>.bp3-popover-content{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-menu{background:#ffffff;border-radius:3px;color:#182026;list-style:none;margin:0;min-width:180px;padding:5px;text-align:left}.jupyter-wrapper .bp3-menu-divider{border-top:1px solid rgba(16,22,26,.15);display:block;margin:5px}.jupyter-wrapper .bp3-dark .bp3-menu-divider{border-top-color:#ffffff26}.jupyter-wrapper .bp3-menu-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;border-radius:2px;color:inherit;line-height:20px;padding:5px 7px;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-menu-item>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-menu-item>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item>*{margin-right:7px}.jupyter-wrapper .bp3-menu-item:empty:before,.jupyter-wrapper .bp3-menu-item>:last-child{margin-right:0}.jupyter-wrapper .bp3-menu-item>.bp3-fill{word-break:break-word}.jupyter-wrapper .bp3-menu-item:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item{background-color:#a7b6c24d;cursor:pointer;text-decoration:none}.jupyter-wrapper .bp3-menu-item.bp3-disabled{background-color:inherit;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-menu-item{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-menu-item{background-color:#8a9ba826;color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled{background-color:inherit;color:#a7b6c299}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary .bp3-menu-item-label{color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active{background-color:#137cbd}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active{background-color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success .bp3-menu-item-label{color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active{background-color:#0f9960}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active{background-color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning .bp3-menu-item-label{color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active{background-color:#d9822b}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active{background-color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger .bp3-menu-item-label{color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active{background-color:#db3737}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active{background-color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-right:7px}.jupyter-wrapper .bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item>.bp3-icon{color:#5c7080;margin-top:2px}.jupyter-wrapper .bp3-menu-item .bp3-menu-item-label{color:#5c7080}.jupyter-wrapper .bp3-menu-item:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-active,.jupyter-wrapper .bp3-menu-item:active{background-color:#7386944d}.jupyter-wrapper .bp3-menu-item.bp3-disabled{background-color:inherit!important;color:#5c708099!important;cursor:not-allowed!important;outline:none!important}.jupyter-wrapper .bp3-menu-item.bp3-disabled:before,.jupyter-wrapper .bp3-menu-item.bp3-disabled>.bp3-icon,.jupyter-wrapper .bp3-menu-item.bp3-disabled .bp3-menu-item-label{color:#5c708099!important}.jupyter-wrapper .bp3-large .bp3-menu-item{font-size:16px;line-height:22px;padding:9px 7px}.jupyter-wrapper .bp3-large .bp3-menu-item .bp3-icon{margin-top:3px}.jupyter-wrapper .bp3-large .bp3-menu-item:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-right:10px;margin-top:1px}.jupyter-wrapper button.bp3-menu-item{background:none;border:none;text-align:left;width:100%}.jupyter-wrapper .bp3-menu-header{border-top:1px solid rgba(16,22,26,.15);display:block;margin:5px;cursor:default;padding-left:2px}.jupyter-wrapper .bp3-dark .bp3-menu-header{border-top-color:#ffffff26}.jupyter-wrapper .bp3-menu-header:first-of-type{border-top:none}.jupyter-wrapper .bp3-menu-header>h6{color:#182026;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;line-height:17px;margin:0;padding:10px 7px 0 1px}.jupyter-wrapper .bp3-menu-header:first-of-type>h6{padding-top:0}.jupyter-wrapper .bp3-large .bp3-menu-header>h6{font-size:18px;padding-bottom:5px;padding-top:15px}.jupyter-wrapper .bp3-large .bp3-menu-header:first-of-type>h6{padding-top:0}.jupyter-wrapper .bp3-dark .bp3-menu{background:#30404d;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary .bp3-menu-item-label{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active{background-color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active{background-color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success .bp3-menu-item-label{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active{background-color:#0f9960}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active{background-color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning .bp3-menu-item-label{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active{background-color:#d9822b}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active{background-color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger .bp3-menu-item-label{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active{background-color:#db3737}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active{background-color:#c23030}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item>.bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-menu-item .bp3-menu-item-label{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item:active{background-color:#8a9ba84d}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled{color:#a7b6c299!important}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled .bp3-menu-item-label{color:#a7b6c299!important}.jupyter-wrapper .bp3-dark .bp3-menu-divider,.jupyter-wrapper .bp3-dark .bp3-menu-header{border-color:#ffffff26}.jupyter-wrapper .bp3-dark .bp3-menu-header>h6{color:#f5f8fa}.jupyter-wrapper .bp3-label .bp3-menu{margin-top:5px}.jupyter-wrapper .bp3-navbar{background-color:#fff;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;height:50px;padding:0 15px;position:relative;width:100%;z-index:10}.jupyter-wrapper .bp3-navbar.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-navbar{background-color:#394b59}.jupyter-wrapper .bp3-navbar.bp3-dark{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-navbar{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-navbar.bp3-fixed-top{left:0;position:fixed;right:0;top:0}.jupyter-wrapper .bp3-navbar-heading{font-size:16px;margin-right:15px}.jupyter-wrapper .bp3-navbar-group{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:50px}.jupyter-wrapper .bp3-navbar-group.bp3-align-left{float:left}.jupyter-wrapper .bp3-navbar-group.bp3-align-right{float:right}.jupyter-wrapper .bp3-navbar-divider{border-left:1px solid rgba(16,22,26,.15);height:20px;margin:0 10px}.jupyter-wrapper .bp3-dark .bp3-navbar-divider{border-left-color:#ffffff26}.jupyter-wrapper .bp3-non-ideal-state{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%}.jupyter-wrapper .bp3-non-ideal-state>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-non-ideal-state>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-non-ideal-state:before,.jupyter-wrapper .bp3-non-ideal-state>*{margin-bottom:20px}.jupyter-wrapper .bp3-non-ideal-state:empty:before,.jupyter-wrapper .bp3-non-ideal-state>:last-child{margin-bottom:0}.jupyter-wrapper .bp3-non-ideal-state>*{max-width:400px}.jupyter-wrapper .bp3-non-ideal-state-visual{color:#5c708099;font-size:60px}.jupyter-wrapper .bp3-dark .bp3-non-ideal-state-visual{color:#a7b6c299}.jupyter-wrapper .bp3-overflow-list{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;min-width:0}.jupyter-wrapper .bp3-overflow-list-spacer{-ms-flex-negative:1;flex-shrink:1;width:1px}.jupyter-wrapper body.bp3-overlay-open{overflow:hidden}.jupyter-wrapper .bp3-overlay{bottom:0;left:0;position:static;right:0;top:0;z-index:20}.jupyter-wrapper .bp3-overlay:not(.bp3-overlay-open){pointer-events:none}.jupyter-wrapper .bp3-overlay.bp3-overlay-container{overflow:hidden;position:fixed}.jupyter-wrapper .bp3-overlay.bp3-overlay-container.bp3-overlay-inline{position:absolute}.jupyter-wrapper .bp3-overlay.bp3-overlay-scroll-container{overflow:auto;position:fixed}.jupyter-wrapper .bp3-overlay.bp3-overlay-scroll-container.bp3-overlay-inline{position:absolute}.jupyter-wrapper .bp3-overlay.bp3-overlay-inline{display:inline;overflow:visible}.jupyter-wrapper .bp3-overlay-content{position:fixed;z-index:20}.jupyter-wrapper .bp3-overlay-inline .bp3-overlay-content,.jupyter-wrapper .bp3-overlay-scroll-container .bp3-overlay-content{position:absolute}.jupyter-wrapper .bp3-overlay-backdrop{bottom:0;left:0;position:fixed;right:0;top:0;opacity:1;background-color:#10161ab3;overflow:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:20}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-enter,.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-appear{opacity:0}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-enter-active,.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-appear-active{opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-exit{opacity:1}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-exit-active{opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-overlay-backdrop:focus{outline:none}.jupyter-wrapper .bp3-overlay-inline .bp3-overlay-backdrop{position:absolute}.jupyter-wrapper .bp3-panel-stack{overflow:hidden;position:relative}.jupyter-wrapper .bp3-panel-stack-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-shadow:0 1px rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;height:30px;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack-header{-webkit-box-shadow:0 1px rgba(255,255,255,.15);box-shadow:0 1px #ffffff26}.jupyter-wrapper .bp3-panel-stack-header>span{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1}.jupyter-wrapper .bp3-panel-stack-header .bp3-heading{margin:0 5px}.jupyter-wrapper .bp3-button.bp3-panel-stack-header-back{margin-left:5px;padding-left:0;white-space:nowrap}.jupyter-wrapper .bp3-button.bp3-panel-stack-header-back .bp3-icon{margin:0 2px}.jupyter-wrapper .bp3-panel-stack-view{bottom:0;left:0;position:absolute;right:0;top:0;background-color:#fff;border-right:1px solid rgba(16,22,26,.15);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:-1px;overflow-y:auto;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack-view{background-color:#30404d}.jupyter-wrapper .bp3-panel-stack-view:nth-last-child(n+4){display:none}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-enter,.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-appear{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-enter-active,.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-exit-active{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-enter,.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-appear{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-enter-active,.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2{overflow:hidden;position:relative}.jupyter-wrapper .bp3-panel-stack2-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-shadow:0 1px rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;height:30px;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack2-header{-webkit-box-shadow:0 1px rgba(255,255,255,.15);box-shadow:0 1px #ffffff26}.jupyter-wrapper .bp3-panel-stack2-header>span{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1}.jupyter-wrapper .bp3-panel-stack2-header .bp3-heading{margin:0 5px}.jupyter-wrapper .bp3-button.bp3-panel-stack2-header-back{margin-left:5px;padding-left:0;white-space:nowrap}.jupyter-wrapper .bp3-button.bp3-panel-stack2-header-back .bp3-icon{margin:0 2px}.jupyter-wrapper .bp3-panel-stack2-view{bottom:0;left:0;position:absolute;right:0;top:0;background-color:#fff;border-right:1px solid rgba(16,22,26,.15);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:-1px;overflow-y:auto;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack2-view{background-color:#30404d}.jupyter-wrapper .bp3-panel-stack2-view:nth-last-child(n+4){display:none}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-enter,.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-appear{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-enter-active,.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-exit-active{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-enter,.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-appear{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-enter-active,.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-popover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;-webkit-transform:scale(1);transform:scale(1);border-radius:3px;display:inline-block;z-index:20}.jupyter-wrapper .bp3-popover .bp3-popover-arrow{height:30px;position:absolute;width:30px}.jupyter-wrapper .bp3-popover .bp3-popover-arrow:before{height:20px;margin:5px;width:20px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover{margin-bottom:17px;margin-top:-17px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow{bottom:-11px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover{margin-left:17px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow{left:-11px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(0);transform:rotate(0)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover{margin-top:17px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow{top:-11px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover{margin-left:-17px;margin-right:17px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow{right:-11px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.jupyter-wrapper .bp3-tether-element-attached-middle>.bp3-popover>.bp3-popover-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.jupyter-wrapper .bp3-tether-element-attached-center>.bp3-popover>.bp3-popover-arrow{right:50%;-webkit-transform:translateX(50%);transform:translate(50%)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow{top:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow{right:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow{left:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow{bottom:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:top left;transform-origin:top left}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:top center;transform-origin:top center}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:top right;transform-origin:top right}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:center left;transform-origin:center left}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:center center;transform-origin:center center}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:center right;transform-origin:center right}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:bottom left;transform-origin:bottom left}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:bottom center;transform-origin:bottom center}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:bottom right;transform-origin:bottom right}.jupyter-wrapper .bp3-popover .bp3-popover-content{background:#ffffff;color:inherit}.jupyter-wrapper .bp3-popover .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.2);box-shadow:1px 1px 6px #10161a33}.jupyter-wrapper .bp3-popover .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.1}.jupyter-wrapper .bp3-popover .bp3-popover-arrow-fill{fill:#fff}.jupyter-wrapper .bp3-popover-enter>.bp3-popover,.jupyter-wrapper .bp3-popover-appear>.bp3-popover{-webkit-transform:scale(.3);transform:scale(.3)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-popover,.jupyter-wrapper .bp3-popover-appear-active>.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-popover-exit>.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-popover{-webkit-transform:scale(.3);transform:scale(.3);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-popover .bp3-popover-content{border-radius:3px;position:relative}.jupyter-wrapper .bp3-popover.bp3-popover-content-sizing .bp3-popover-content{max-width:350px;padding:20px}.jupyter-wrapper .bp3-popover-target+.bp3-overlay .bp3-popover.bp3-popover-content-sizing{width:350px}.jupyter-wrapper .bp3-popover.bp3-minimal{margin:0!important}.jupyter-wrapper .bp3-popover.bp3-minimal .bp3-popover-arrow{display:none}.jupyter-wrapper .bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-enter>.bp3-popover.bp3-minimal.bp3-popover,.jupyter-wrapper .bp3-popover-appear>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-popover.bp3-minimal.bp3-popover,.jupyter-wrapper .bp3-popover-appear-active>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover-exit>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-popover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-content,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-content{background:#30404d;color:inherit}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow:before,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.4);box-shadow:1px 1px 6px #10161a66}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow-border,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.2}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow-fill,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow-fill{fill:#30404d}.jupyter-wrapper .bp3-popover-arrow:before{border-radius:2px;content:\"\";display:block;position:absolute;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.jupyter-wrapper .bp3-tether-pinned .bp3-popover-arrow{display:none}.jupyter-wrapper .bp3-popover-backdrop{background:rgba(255,255,255,0)}.jupyter-wrapper .bp3-transition-container{opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;z-index:20}.jupyter-wrapper .bp3-transition-container.bp3-popover-enter,.jupyter-wrapper .bp3-transition-container.bp3-popover-appear{opacity:0}.jupyter-wrapper .bp3-transition-container.bp3-popover-enter-active,.jupyter-wrapper .bp3-transition-container.bp3-popover-appear-active{opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-transition-container.bp3-popover-exit{opacity:1}.jupyter-wrapper .bp3-transition-container.bp3-popover-exit-active{opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-transition-container:focus{outline:none}.jupyter-wrapper .bp3-transition-container.bp3-popover-leave .bp3-popover-content{pointer-events:none}.jupyter-wrapper .bp3-transition-container[data-x-out-of-boundaries]{display:none}.jupyter-wrapper span.bp3-popover-target{display:inline-block}.jupyter-wrapper .bp3-popover-wrapper.bp3-fill{width:100%}.jupyter-wrapper .bp3-portal{left:0;position:absolute;right:0;top:0}@-webkit-keyframes linear-progress-bar-stripes{0%{background-position:0 0}to{background-position:30px 0}}@keyframes linear-progress-bar-stripes{0%{background-position:0 0}to{background-position:30px 0}}.jupyter-wrapper .bp3-progress-bar{background:rgba(92,112,128,.2);border-radius:40px;display:block;height:8px;overflow:hidden;position:relative;width:100%}.jupyter-wrapper .bp3-progress-bar .bp3-progress-meter{background:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%);background-color:#5c7080cc;background-size:30px 30px;border-radius:40px;height:100%;position:absolute;-webkit-transition:width .2s cubic-bezier(.4,1,.75,.9);transition:width .2s cubic-bezier(.4,1,.75,.9);width:100%}.jupyter-wrapper .bp3-progress-bar:not(.bp3-no-animation):not(.bp3-no-stripes) .bp3-progress-meter{animation:linear-progress-bar-stripes .3s linear infinite reverse}.jupyter-wrapper .bp3-progress-bar.bp3-no-stripes .bp3-progress-meter{background-image:none}.jupyter-wrapper .bp3-dark .bp3-progress-bar{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-dark .bp3-progress-bar .bp3-progress-meter{background-color:#8a9ba8}.jupyter-wrapper .bp3-progress-bar.bp3-intent-primary .bp3-progress-meter{background-color:#137cbd}.jupyter-wrapper .bp3-progress-bar.bp3-intent-success .bp3-progress-meter{background-color:#0f9960}.jupyter-wrapper .bp3-progress-bar.bp3-intent-warning .bp3-progress-meter{background-color:#d9822b}.jupyter-wrapper .bp3-progress-bar.bp3-intent-danger .bp3-progress-meter{background-color:#db3737}@-webkit-keyframes skeleton-glow{0%{background:rgba(206,217,224,.2);border-color:#ced9e033}to{background:rgba(92,112,128,.2);border-color:#5c708033}}@keyframes skeleton-glow{0%{background:rgba(206,217,224,.2);border-color:#ced9e033}to{background:rgba(92,112,128,.2);border-color:#5c708033}}.jupyter-wrapper .bp3-skeleton{-webkit-animation:1s linear infinite alternate skeleton-glow;animation:1s linear infinite alternate skeleton-glow;background:rgba(206,217,224,.2);background-clip:padding-box!important;border-color:#ced9e033!important;border-radius:2px;-webkit-box-shadow:none!important;box-shadow:none!important;color:transparent!important;cursor:default;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-skeleton:before,.jupyter-wrapper .bp3-skeleton:after,.jupyter-wrapper .bp3-skeleton *{visibility:hidden!important}.jupyter-wrapper .bp3-slider{height:40px;min-width:150px;width:100%;cursor:default;outline:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-slider:hover{cursor:pointer}.jupyter-wrapper .bp3-slider:active{cursor:-webkit-grabbing;cursor:grabbing}.jupyter-wrapper .bp3-slider.bp3-disabled{cursor:not-allowed;opacity:.5}.jupyter-wrapper .bp3-slider.bp3-slider-unlabeled{height:16px}.jupyter-wrapper .bp3-slider-track,.jupyter-wrapper .bp3-slider-progress{height:6px;left:0;right:0;top:5px;position:absolute}.jupyter-wrapper .bp3-slider-track{border-radius:3px;overflow:hidden}.jupyter-wrapper .bp3-slider-progress{background:rgba(92,112,128,.2)}.jupyter-wrapper .bp3-dark .bp3-slider-progress{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-slider-progress.bp3-intent-primary{background-color:#137cbd}.jupyter-wrapper .bp3-slider-progress.bp3-intent-success{background-color:#0f9960}.jupyter-wrapper .bp3-slider-progress.bp3-intent-warning{background-color:#d9822b}.jupyter-wrapper .bp3-slider-progress.bp3-intent-danger{background-color:#db3737}.jupyter-wrapper .bp3-slider-handle{background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;cursor:pointer;height:16px;left:0;position:absolute;top:0;width:16px}.jupyter-wrapper .bp3-slider-handle:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-slider-handle:active,.jupyter-wrapper .bp3-slider-handle.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-slider-handle:disabled,.jupyter-wrapper .bp3-slider-handle.bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-slider-handle:disabled.bp3-active,.jupyter-wrapper .bp3-slider-handle:disabled.bp3-active:hover,.jupyter-wrapper .bp3-slider-handle.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-slider-handle.bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-slider-handle:focus{z-index:1}.jupyter-wrapper .bp3-slider-handle:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;cursor:-webkit-grab;cursor:grab;z-index:2}.jupyter-wrapper .bp3-slider-handle.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),inset 0 1px 1px rgba(16,22,26,.1);box-shadow:0 0 0 1px #10161a33,inset 0 1px 1px #10161a1a;cursor:-webkit-grabbing;cursor:grabbing}.jupyter-wrapper .bp3-disabled .bp3-slider-handle{background:#bfccd6;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.jupyter-wrapper .bp3-dark .bp3-slider-handle{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover,.jupyter-wrapper .bp3-dark .bp3-slider-handle:active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-slider-handle:active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-slider-handle:disabled,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-slider-handle:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-slider-handle .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-slider-handle,.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover{background-color:#394b59}.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{background-color:#293742}.jupyter-wrapper .bp3-dark .bp3-disabled .bp3-slider-handle{background:#5c7080;border-color:#5c7080;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-slider-handle .bp3-slider-label{background:#394b59;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;color:#f5f8fa;margin-left:8px}.jupyter-wrapper .bp3-dark .bp3-slider-handle .bp3-slider-label{background:#e1e8ed;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66;color:#394b59}.jupyter-wrapper .bp3-disabled .bp3-slider-handle .bp3-slider-label{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-slider-handle.bp3-start,.jupyter-wrapper .bp3-slider-handle.bp3-end{width:8px}.jupyter-wrapper .bp3-slider-handle.bp3-start{border-bottom-right-radius:0;border-top-right-radius:0}.jupyter-wrapper .bp3-slider-handle.bp3-end{border-bottom-left-radius:0;border-top-left-radius:0;margin-left:8px}.jupyter-wrapper .bp3-slider-handle.bp3-end .bp3-slider-label{margin-left:0}.jupyter-wrapper .bp3-slider-label{-webkit-transform:translate(-50%,20px);transform:translate(-50%,20px);display:inline-block;font-size:12px;line-height:1;padding:2px 5px;position:absolute;vertical-align:top}.jupyter-wrapper .bp3-slider.bp3-vertical{height:150px;min-width:40px;width:40px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-track,.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-progress{bottom:0;height:auto;left:5px;top:0;width:6px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-progress{top:auto}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-label{-webkit-transform:translate(20px,50%);transform:translate(20px,50%)}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle{top:auto}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle .bp3-slider-label{margin-left:0;margin-top:-8px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-end,.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start{height:8px;margin-left:0;width:16px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start{border-bottom-right-radius:3px;border-top-left-radius:0}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start .bp3-slider-label{-webkit-transform:translate(20px);transform:translate(20px)}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-end{border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:3px;margin-bottom:8px}@-webkit-keyframes pt-spinner-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes pt-spinner-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.jupyter-wrapper .bp3-spinner{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:visible;vertical-align:middle}.jupyter-wrapper .bp3-spinner svg{display:block}.jupyter-wrapper .bp3-spinner path{fill-opacity:0}.jupyter-wrapper .bp3-spinner .bp3-spinner-head{stroke:#5c7080cc;stroke-linecap:round;-webkit-transform-origin:center;transform-origin:center;-webkit-transition:stroke-dashoffset .2s cubic-bezier(.4,1,.75,.9);transition:stroke-dashoffset .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-spinner .bp3-spinner-track{stroke:#5c708033}.jupyter-wrapper .bp3-spinner-animation{-webkit-animation:pt-spinner-animation .5s linear infinite;animation:pt-spinner-animation .5s linear infinite}.jupyter-wrapper .bp3-no-spin>.bp3-spinner-animation{-webkit-animation:none;animation:none}.jupyter-wrapper .bp3-dark .bp3-spinner .bp3-spinner-head{stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-spinner .bp3-spinner-track{stroke:#10161a80}.jupyter-wrapper .bp3-spinner.bp3-intent-primary .bp3-spinner-head{stroke:#137cbd}.jupyter-wrapper .bp3-spinner.bp3-intent-success .bp3-spinner-head{stroke:#0f9960}.jupyter-wrapper .bp3-spinner.bp3-intent-warning .bp3-spinner-head{stroke:#d9822b}.jupyter-wrapper .bp3-spinner.bp3-intent-danger .bp3-spinner-head{stroke:#db3737}.jupyter-wrapper .bp3-tabs.bp3-vertical{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab{border-radius:3px;padding:0 10px;width:100%}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab[aria-selected=true]{background-color:#137cbd33;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab-indicator-wrapper .bp3-tab-indicator{background-color:#137cbd33;border-radius:3px;bottom:0;height:auto;left:0;right:0;top:0}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-panel{margin-top:0;padding-left:20px}.jupyter-wrapper .bp3-tab-list{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;border:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;list-style:none;margin:0;padding:0;position:relative}.jupyter-wrapper .bp3-tab-list>*:not(:last-child){margin-right:20px}.jupyter-wrapper .bp3-tab{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;color:#182026;cursor:pointer;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;font-size:14px;line-height:30px;max-width:100%;position:relative;vertical-align:top}.jupyter-wrapper .bp3-tab a{color:inherit;display:block;text-decoration:none}.jupyter-wrapper .bp3-tab-indicator-wrapper~.bp3-tab{background-color:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}.jupyter-wrapper .bp3-tab[aria-disabled=true]{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tab[aria-selected=true]{border-radius:0;-webkit-box-shadow:inset 0 -3px 0 #106ba3;box-shadow:inset 0 -3px #106ba3}.jupyter-wrapper .bp3-tab[aria-selected=true],.jupyter-wrapper .bp3-tab:not([aria-disabled=true]):hover{color:#106ba3}.jupyter-wrapper .bp3-tab:focus{-moz-outline-radius:0}.jupyter-wrapper .bp3-large>.bp3-tab{font-size:16px;line-height:40px}.jupyter-wrapper .bp3-tab-panel{margin-top:20px}.jupyter-wrapper .bp3-tab-panel[aria-hidden=true]{display:none}.jupyter-wrapper .bp3-tab-indicator-wrapper{left:0;pointer-events:none;position:absolute;top:0;-webkit-transform:translateX(0),translateY(0);transform:translate(0),translateY(0);-webkit-transition:height,width,-webkit-transform;transition:height,width,-webkit-transform;transition:height,transform,width;transition:height,transform,width,-webkit-transform;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tab-indicator-wrapper .bp3-tab-indicator{background-color:#106ba3;bottom:0;height:3px;left:0;position:absolute;right:0}.jupyter-wrapper .bp3-tab-indicator-wrapper.bp3-no-animation{-webkit-transition:none;transition:none}.jupyter-wrapper .bp3-dark .bp3-tab{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tab[aria-disabled=true]{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tab[aria-selected=true]{-webkit-box-shadow:inset 0 -3px 0 #48aff0;box-shadow:inset 0 -3px #48aff0}.jupyter-wrapper .bp3-dark .bp3-tab[aria-selected=true],.jupyter-wrapper .bp3-dark .bp3-tab:not([aria-disabled=true]):hover{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-tab-indicator{background-color:#48aff0}.jupyter-wrapper .bp3-flex-expander{-webkit-box-flex:1;-ms-flex:1 1;flex:1 1}.jupyter-wrapper .bp3-tag{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#5c7080;border:none;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;color:#f5f8fa;font-size:12px;line-height:16px;max-width:100%;min-height:20px;min-width:20px;padding:2px 6px;position:relative}.jupyter-wrapper .bp3-tag.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-interactive:hover{background-color:#5c7080d9}.jupyter-wrapper .bp3-tag.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-interactive:active{background-color:#5c7080b3}.jupyter-wrapper .bp3-tag>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag:before,.jupyter-wrapper .bp3-tag>*{margin-right:4px}.jupyter-wrapper .bp3-tag:empty:before,.jupyter-wrapper .bp3-tag>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag:focus{outline:rgba(19,124,189,.6) auto 2px;outline-offset:0;-moz-outline-radius:6px}.jupyter-wrapper .bp3-tag.bp3-round{border-radius:30px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-dark .bp3-tag{background-color:#bfccd6;color:#182026}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive:hover{background-color:#bfccd6d9}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive:active{background-color:#bfccd6b3}.jupyter-wrapper .bp3-dark .bp3-tag>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tag .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tag .bp3-icon-large{fill:currentColor}.jupyter-wrapper .bp3-tag>.bp3-icon,.jupyter-wrapper .bp3-tag .bp3-icon-standard,.jupyter-wrapper .bp3-tag .bp3-icon-large{fill:#fff}.jupyter-wrapper .bp3-tag.bp3-large,.jupyter-wrapper .bp3-large .bp3-tag{font-size:14px;line-height:20px;min-height:30px;min-width:30px;padding:5px 10px}.jupyter-wrapper .bp3-tag.bp3-large:before,.jupyter-wrapper .bp3-tag.bp3-large>*,.jupyter-wrapper .bp3-large .bp3-tag:before,.jupyter-wrapper .bp3-large .bp3-tag>*{margin-right:7px}.jupyter-wrapper .bp3-tag.bp3-large:empty:before,.jupyter-wrapper .bp3-tag.bp3-large>:last-child,.jupyter-wrapper .bp3-large .bp3-tag:empty:before,.jupyter-wrapper .bp3-large .bp3-tag>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag.bp3-large.bp3-round,.jupyter-wrapper .bp3-large .bp3-tag.bp3-round{padding-left:12px;padding-right:12px}.jupyter-wrapper .bp3-tag.bp3-intent-primary{background:#137cbd;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbdd9}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive:active{background-color:#137cbdb3}.jupyter-wrapper .bp3-tag.bp3-intent-success{background:#0f9960;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive:hover{background-color:#0f9960d9}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive:active{background-color:#0f9960b3}.jupyter-wrapper .bp3-tag.bp3-intent-warning{background:#d9822b;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822bd9}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive:active{background-color:#d9822bb3}.jupyter-wrapper .bp3-tag.bp3-intent-danger{background:#db3737;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive:hover{background-color:#db3737d9}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive:active{background-color:#db3737b3}.jupyter-wrapper .bp3-tag.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-tag.bp3-minimal>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal .bp3-icon-large{fill:#5c7080}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]){background-color:#8a9ba833;color:#182026}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:hover{background-color:#5c70804d}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:active{background-color:#5c708066}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]){color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:hover{background-color:#bfccd64d}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:active{background-color:#bfccd666}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-])>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]) .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]) .bp3-icon-large{fill:#a7b6c2}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary{background-color:#137cbd26;color:#106ba3}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbd40}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:active{background-color:#137cbd59}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary .bp3-icon-large{fill:#137cbd}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary{background-color:#137cbd40;color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbd59}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:active{background-color:#137cbd73}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success{background-color:#0f996026;color:#0d8050}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:hover{background-color:#0f996040}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:active{background-color:#0f996059}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success .bp3-icon-large{fill:#0f9960}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success{background-color:#0f996040;color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:hover{background-color:#0f996059}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:active{background-color:#0f996073}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning{background-color:#d9822b26;color:#bf7326}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822b40}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:active{background-color:#d9822b59}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning .bp3-icon-large{fill:#d9822b}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning{background-color:#d9822b40;color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822b59}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:active{background-color:#d9822b73}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger{background-color:#db373726;color:#c23030}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:hover{background-color:#db373740}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:active{background-color:#db373759}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger .bp3-icon-large{fill:#db3737}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger{background-color:#db373740;color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:hover{background-color:#db373759}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:active{background-color:#db373773}.jupyter-wrapper .bp3-tag-remove{background:none;border:none;color:inherit;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:-2px;margin-right:-6px!important;margin-top:-2px;opacity:.5;padding:2px 2px 2px 0}.jupyter-wrapper .bp3-tag-remove:hover{background:none;opacity:.8;text-decoration:none}.jupyter-wrapper .bp3-tag-remove:active{opacity:1}.jupyter-wrapper .bp3-tag-remove:empty:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;content:\"\ue6d7\"}.jupyter-wrapper .bp3-large .bp3-tag-remove{margin-right:-10px!important;padding:0 5px 0 0}.jupyter-wrapper .bp3-large .bp3-tag-remove:empty:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1}.jupyter-wrapper .bp3-tag-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;cursor:text;height:auto;line-height:inherit;min-height:30px;padding-left:5px;padding-right:0}.jupyter-wrapper .bp3-tag-input>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag-input>.bp3-tag-input-values{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-icon{color:#5c7080;margin-left:2px;margin-right:7px;margin-top:7px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-item-align:stretch;align-self:stretch;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:7px;margin-top:5px;min-width:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:before,.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{margin-right:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:empty:before,.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:first-child .bp3-input-ghost:first-child{padding-left:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{margin-bottom:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag{overflow-wrap:break-word}.jupyter-wrapper .bp3-tag-input .bp3-tag.bp3-active{outline:rgba(19,124,189,.6) auto 2px;outline-offset:0;-moz-outline-radius:6px}.jupyter-wrapper .bp3-tag-input .bp3-input-ghost{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:20px;width:80px}.jupyter-wrapper .bp3-tag-input .bp3-input-ghost:disabled,.jupyter-wrapper .bp3-tag-input .bp3-input-ghost.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-tag-input .bp3-button,.jupyter-wrapper .bp3-tag-input .bp3-spinner{margin:3px 3px 3px 0}.jupyter-wrapper .bp3-tag-input .bp3-button{min-height:24px;min-width:24px;padding:0 7px}.jupyter-wrapper .bp3-tag-input.bp3-large{height:auto;min-height:40px}.jupyter-wrapper .bp3-tag-input.bp3-large:before,.jupyter-wrapper .bp3-tag-input.bp3-large>*{margin-right:10px}.jupyter-wrapper .bp3-tag-input.bp3-large:empty:before,.jupyter-wrapper .bp3-tag-input.bp3-large>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-tag-input-icon{margin-left:5px;margin-top:10px}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-input-ghost{line-height:30px}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-button{min-height:30px;min-width:30px;padding:5px 10px;margin:5px 5px 5px 0}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-spinner{margin:8px 8px 8px 0}.jupyter-wrapper .bp3-tag-input.bp3-active{background-color:#fff;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-primary{-webkit-box-shadow:0 0 0 1px #106ba3,0 0 0 3px rgba(16,107,163,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #106ba3,0 0 0 3px #106ba34d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-success{-webkit-box-shadow:0 0 0 1px #0d8050,0 0 0 3px rgba(13,128,80,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0d8050,0 0 0 3px #0d80504d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-warning{-webkit-box-shadow:0 0 0 1px #bf7326,0 0 0 3px rgba(191,115,38,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #bf7326,0 0 0 3px #bf73264d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-danger{-webkit-box-shadow:0 0 0 1px #c23030,0 0 0 3px rgba(194,48,48,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #c23030,0 0 0 3px #c230304d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-tag-input-icon,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-tag-input-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-webkit-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-moz-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost:-ms-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-ms-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active{background-color:#10161a4d;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-primary,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-primary{-webkit-box-shadow:0 0 0 1px #106ba3,0 0 0 3px rgba(16,107,163,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #106ba3,0 0 0 3px #106ba34d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-success,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-success{-webkit-box-shadow:0 0 0 1px #0d8050,0 0 0 3px rgba(13,128,80,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #0d8050,0 0 0 3px #0d80504d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-warning,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-warning{-webkit-box-shadow:0 0 0 1px #bf7326,0 0 0 3px rgba(191,115,38,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #bf7326,0 0 0 3px #bf73264d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-danger,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-danger{-webkit-box-shadow:0 0 0 1px #c23030,0 0 0 3px rgba(194,48,48,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #c23030,0 0 0 3px #c230304d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-input-ghost{background:none;border:none;-webkit-box-shadow:none;box-shadow:none;padding:0}.jupyter-wrapper .bp3-input-ghost::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost:focus{outline:none!important}.jupyter-wrapper .bp3-toast{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;margin:20px 0 0;max-width:500px;min-width:300px;pointer-events:all;position:relative!important}.jupyter-wrapper .bp3-toast.bp3-toast-enter,.jupyter-wrapper .bp3-toast.bp3-toast-appear{-webkit-transform:translateY(-40px);transform:translateY(-40px)}.jupyter-wrapper .bp3-toast.bp3-toast-enter-active,.jupyter-wrapper .bp3-toast.bp3-toast-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-toast.bp3-toast-enter~.bp3-toast,.jupyter-wrapper .bp3-toast.bp3-toast-appear~.bp3-toast{-webkit-transform:translateY(-40px);transform:translateY(-40px)}.jupyter-wrapper .bp3-toast.bp3-toast-enter-active~.bp3-toast,.jupyter-wrapper .bp3-toast.bp3-toast-appear-active~.bp3-toast{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-toast.bp3-toast-exit{opacity:1;-webkit-filter:blur(0);filter:blur(0)}.jupyter-wrapper .bp3-toast.bp3-toast-exit-active{opacity:0;-webkit-filter:blur(10px);filter:blur(10px);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:opacity,filter;transition-property:opacity,filter,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-toast.bp3-toast-exit~.bp3-toast{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-toast.bp3-toast-exit-active~.bp3-toast{-webkit-transform:translateY(-40px);transform:translateY(-40px);-webkit-transition-delay:50ms;transition-delay:50ms;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-toast .bp3-button-group{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;padding:5px 5px 5px 0}.jupyter-wrapper .bp3-toast>.bp3-icon{color:#5c7080;margin:12px 0 12px 12px}.jupyter-wrapper .bp3-toast.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-toast{background-color:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-toast.bp3-dark>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-toast>.bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] a{color:#ffffffb3}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] a:hover{color:#fff}.jupyter-wrapper .bp3-toast[class*=bp3-intent-]>.bp3-icon{color:#fff}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:before,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button .bp3-icon,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:active{color:#ffffffb3!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:focus{outline-color:#ffffff80}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:hover{background-color:#ffffff26!important;color:#fff!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:active{background-color:#ffffff4d!important;color:#fff!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:after{background:rgba(255,255,255,.3)!important}.jupyter-wrapper .bp3-toast.bp3-intent-primary{background-color:#137cbd;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-success{background-color:#0f9960;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-warning{background-color:#d9822b;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-danger{background-color:#db3737;color:#fff}.jupyter-wrapper .bp3-toast-message{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:11px;word-break:break-word}.jupyter-wrapper .bp3-toast-container{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;left:0;overflow:hidden;padding:0 20px 20px;pointer-events:none;right:0;z-index:40}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-in-portal{position:fixed}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-inline{position:absolute}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-top{top:0}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-bottom{bottom:0;-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;top:auto}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-left{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-right{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-enter:not(.bp3-toast-enter-active),.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-enter:not(.bp3-toast-enter-active)~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-appear:not(.bp3-toast-appear-active),.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-appear:not(.bp3-toast-appear-active)~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-exit-active~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-leave-active~.bp3-toast{-webkit-transform:translateY(60px);transform:translateY(60px)}.jupyter-wrapper .bp3-tooltip{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow{height:22px;position:absolute;width:22px}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow:before{height:14px;margin:4px;width:14px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip{margin-bottom:11px;margin-top:-11px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow{bottom:-8px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip{margin-left:11px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow{left:-8px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(0);transform:rotate(0)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip{margin-top:11px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow{top:-8px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip{margin-left:-11px;margin-right:11px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow{right:-8px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.jupyter-wrapper .bp3-tether-element-attached-middle>.bp3-tooltip>.bp3-popover-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.jupyter-wrapper .bp3-tether-element-attached-center>.bp3-tooltip>.bp3-popover-arrow{right:50%;-webkit-transform:translateX(50%);transform:translate(50%)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow{top:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow{right:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow{left:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow{bottom:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:top left;transform-origin:top left}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:top center;transform-origin:top center}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:top right;transform-origin:top right}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:center left;transform-origin:center left}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:center center;transform-origin:center center}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:center right;transform-origin:center right}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:bottom left;transform-origin:bottom left}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:bottom center;transform-origin:bottom center}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:bottom right;transform-origin:bottom right}.jupyter-wrapper .bp3-tooltip .bp3-popover-content{background:#394b59;color:#f5f8fa}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.2);box-shadow:1px 1px 6px #10161a33}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.1}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow-fill{fill:#394b59}.jupyter-wrapper .bp3-popover-enter>.bp3-tooltip,.jupyter-wrapper .bp3-popover-appear>.bp3-tooltip{-webkit-transform:scale(.8);transform:scale(.8)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-tooltip,.jupyter-wrapper .bp3-popover-appear-active>.bp3-tooltip{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover-exit>.bp3-tooltip{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-tooltip{-webkit-transform:scale(.8);transform:scale(.8);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tooltip .bp3-popover-content{padding:10px 12px}.jupyter-wrapper .bp3-tooltip.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-tooltip{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-content,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-content{background:#e1e8ed;color:#394b59}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow:before,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.4);box-shadow:1px 1px 6px #10161a66}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow-border,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.2}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow-fill,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow-fill{fill:#e1e8ed}.jupyter-wrapper .bp3-tooltip.bp3-intent-primary .bp3-popover-content{background:#137cbd;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-primary .bp3-popover-arrow-fill{fill:#137cbd}.jupyter-wrapper .bp3-tooltip.bp3-intent-success .bp3-popover-content{background:#0f9960;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-success .bp3-popover-arrow-fill{fill:#0f9960}.jupyter-wrapper .bp3-tooltip.bp3-intent-warning .bp3-popover-content{background:#d9822b;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-warning .bp3-popover-arrow-fill{fill:#d9822b}.jupyter-wrapper .bp3-tooltip.bp3-intent-danger .bp3-popover-content{background:#db3737;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-danger .bp3-popover-arrow-fill{fill:#db3737}.jupyter-wrapper .bp3-tooltip-indicator{border-bottom:dotted 1px;cursor:help}.jupyter-wrapper .bp3-tree .bp3-icon,.jupyter-wrapper .bp3-tree .bp3-icon-standard,.jupyter-wrapper .bp3-tree .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-primary{color:#137cbd}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-success{color:#0f9960}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-warning{color:#d9822b}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-danger{color:#db3737}.jupyter-wrapper .bp3-tree-node-list{list-style:none;margin:0;padding-left:0}.jupyter-wrapper .bp3-tree-root{background-color:transparent;cursor:default;padding-left:0;position:relative}.jupyter-wrapper .bp3-tree-node-content-0{padding-left:0}.jupyter-wrapper .bp3-tree-node-content-1{padding-left:23px}.jupyter-wrapper .bp3-tree-node-content-2{padding-left:46px}.jupyter-wrapper .bp3-tree-node-content-3{padding-left:69px}.jupyter-wrapper .bp3-tree-node-content-4{padding-left:92px}.jupyter-wrapper .bp3-tree-node-content-5{padding-left:115px}.jupyter-wrapper .bp3-tree-node-content-6{padding-left:138px}.jupyter-wrapper .bp3-tree-node-content-7{padding-left:161px}.jupyter-wrapper .bp3-tree-node-content-8{padding-left:184px}.jupyter-wrapper .bp3-tree-node-content-9{padding-left:207px}.jupyter-wrapper .bp3-tree-node-content-10{padding-left:230px}.jupyter-wrapper .bp3-tree-node-content-11{padding-left:253px}.jupyter-wrapper .bp3-tree-node-content-12{padding-left:276px}.jupyter-wrapper .bp3-tree-node-content-13{padding-left:299px}.jupyter-wrapper .bp3-tree-node-content-14{padding-left:322px}.jupyter-wrapper .bp3-tree-node-content-15{padding-left:345px}.jupyter-wrapper .bp3-tree-node-content-16{padding-left:368px}.jupyter-wrapper .bp3-tree-node-content-17{padding-left:391px}.jupyter-wrapper .bp3-tree-node-content-18{padding-left:414px}.jupyter-wrapper .bp3-tree-node-content-19{padding-left:437px}.jupyter-wrapper .bp3-tree-node-content-20{padding-left:460px}.jupyter-wrapper .bp3-tree-node-content{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:30px;padding-right:5px;width:100%}.jupyter-wrapper .bp3-tree-node-content:hover{background-color:#bfccd666}.jupyter-wrapper .bp3-tree-node-caret,.jupyter-wrapper .bp3-tree-node-caret-none{min-width:30px}.jupyter-wrapper .bp3-tree-node-caret{color:#5c7080;cursor:pointer;padding:7px;-webkit-transform:rotate(0deg);transform:rotate(0);-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tree-node-caret:hover{color:#182026}.jupyter-wrapper .bp3-dark .bp3-tree-node-caret{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tree-node-caret:hover{color:#f5f8fa}.jupyter-wrapper .bp3-tree-node-caret.bp3-tree-node-caret-open{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tree-node-caret.bp3-icon-standard:before{content:\"\ue695\"}.jupyter-wrapper .bp3-tree-node-icon{margin-right:7px;position:relative}.jupyter-wrapper .bp3-tree-node-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-tree-node-label span{display:inline}.jupyter-wrapper .bp3-tree-node-secondary-label{padding:0 5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-tree-node-secondary-label .bp3-popover-wrapper,.jupyter-wrapper .bp3-tree-node-secondary-label .bp3-popover-target{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-content{background-color:inherit;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-caret,.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-icon{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content{background-color:#137cbd}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon-standard,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon-large{color:#fff}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-tree-node-caret:before{color:#ffffffb3}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-tree-node-caret:hover:before{color:#fff}.jupyter-wrapper .bp3-dark .bp3-tree-node-content:hover{background-color:#5c70804d}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-primary{color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-success{color:#0f9960}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-warning{color:#d9822b}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-danger{color:#db3737}.jupyter-wrapper .bp3-dark .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content{background-color:#137cbd}.jupyter-wrapper .bp3-omnibar{-webkit-filter:blur(0);filter:blur(0);opacity:1;background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;left:calc(50% - 250px);top:20vh;width:500px;z-index:21}.jupyter-wrapper .bp3-omnibar.bp3-overlay-enter,.jupyter-wrapper .bp3-omnibar.bp3-overlay-appear{-webkit-filter:blur(20px);filter:blur(20px);opacity:.2}.jupyter-wrapper .bp3-omnibar.bp3-overlay-enter-active,.jupyter-wrapper .bp3-omnibar.bp3-overlay-appear-active{-webkit-filter:blur(0);filter:blur(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:filter,opacity;transition-property:filter,opacity,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-omnibar.bp3-overlay-exit{-webkit-filter:blur(0);filter:blur(0);opacity:1}.jupyter-wrapper .bp3-omnibar.bp3-overlay-exit-active{-webkit-filter:blur(20px);filter:blur(20px);opacity:.2;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:filter,opacity;transition-property:filter,opacity,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-omnibar .bp3-input{background-color:transparent;border-radius:0}.jupyter-wrapper .bp3-omnibar .bp3-input,.jupyter-wrapper .bp3-omnibar .bp3-input:focus{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-omnibar .bp3-menu{background-color:transparent;border-radius:0;-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26;max-height:calc(60vh - 40px);overflow:auto}.jupyter-wrapper .bp3-omnibar .bp3-menu:empty{display:none}.jupyter-wrapper .bp3-dark .bp3-omnibar,.jupyter-wrapper .bp3-omnibar.bp3-dark{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66}.jupyter-wrapper .bp3-omnibar-overlay .bp3-overlay-backdrop{background-color:#10161a33}.jupyter-wrapper .bp3-multi-select{min-width:150px}.jupyter-wrapper .bp3-multi-select-popover .bp3-menu{max-height:300px;max-width:400px;overflow:auto}.jupyter-wrapper .bp3-select-popover .bp3-popover-content{padding:5px}.jupyter-wrapper .bp3-select-popover .bp3-input-group{margin-bottom:0}.jupyter-wrapper .bp3-select-popover .bp3-menu{max-height:300px;max-width:400px;overflow:auto;padding:0}.jupyter-wrapper .bp3-select-popover .bp3-menu:not(:first-child){padding-top:5px}.jupyter-wrapper :root{--jp-icon-add-above: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5MikiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik00Ljc1IDQuOTMwNjZINi42MjVWNi44MDU2NkM2LjYyNSA3LjAxMTkxIDYuNzkzNzUgNy4xODA2NiA3IDcuMTgwNjZDNy4yMDYyNSA3LjE4MDY2IDcuMzc1IDcuMDExOTEgNy4zNzUgNi44MDU2NlY0LjkzMDY2SDkuMjVDOS40NTYyNSA0LjkzMDY2IDkuNjI1IDQuNzYxOTEgOS42MjUgNC41NTU2NkM5LjYyNSA0LjM0OTQxIDkuNDU2MjUgNC4xODA2NiA5LjI1IDQuMTgwNjZINy4zNzVWMi4zMDU2NkM3LjM3NSAyLjA5OTQxIDcuMjA2MjUgMS45MzA2NiA3IDEuOTMwNjZDNi43OTM3NSAxLjkzMDY2IDYuNjI1IDIuMDk5NDEgNi42MjUgMi4zMDU2NlY0LjE4MDY2SDQuNzVDNC41NDM3NSA0LjE4MDY2IDQuMzc1IDQuMzQ5NDEgNC4zNzUgNC41NTU2NkM0LjM3NSA0Ljc2MTkxIDQuNTQzNzUgNC45MzA2NiA0Ljc1IDQuOTMwNjZaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC43Ii8+CjwvZz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTExLjUgOS41VjExLjVMMi41IDExLjVWOS41TDExLjUgOS41Wk0xMiA4QzEyLjU1MjMgOCAxMyA4LjQ0NzcyIDEzIDlWMTJDMTMgMTIuNTUyMyAxMi41NTIzIDEzIDEyIDEzTDIgMTNDMS40NDc3MiAxMyAxIDEyLjU1MjMgMSAxMlY5QzEgOC40NDc3MiAxLjQ0NzcxIDggMiA4TDEyIDhaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5MiI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KC0xIDAgMCAxIDEwIDEuNTU1NjYpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==);--jp-icon-add-below: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5OCkiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik05LjI1IDEwLjA2OTNMNy4zNzUgMTAuMDY5M0w3LjM3NSA4LjE5NDM0QzcuMzc1IDcuOTg4MDkgNy4yMDYyNSA3LjgxOTM0IDcgNy44MTkzNEM2Ljc5Mzc1IDcuODE5MzQgNi42MjUgNy45ODgwOSA2LjYyNSA4LjE5NDM0TDYuNjI1IDEwLjA2OTNMNC43NSAxMC4wNjkzQzQuNTQzNzUgMTAuMDY5MyA0LjM3NSAxMC4yMzgxIDQuMzc1IDEwLjQ0NDNDNC4zNzUgMTAuNjUwNiA0LjU0Mzc1IDEwLjgxOTMgNC43NSAxMC44MTkzTDYuNjI1IDEwLjgxOTNMNi42MjUgMTIuNjk0M0M2LjYyNSAxMi45MDA2IDYuNzkzNzUgMTMuMDY5MyA3IDEzLjA2OTNDNy4yMDYyNSAxMy4wNjkzIDcuMzc1IDEyLjkwMDYgNy4zNzUgMTIuNjk0M0w3LjM3NSAxMC44MTkzTDkuMjUgMTAuODE5M0M5LjQ1NjI1IDEwLjgxOTMgOS42MjUgMTAuNjUwNiA5LjYyNSAxMC40NDQzQzkuNjI1IDEwLjIzODEgOS40NTYyNSAxMC4wNjkzIDkuMjUgMTAuMDY5M1oiIGZpbGw9IiM2MTYxNjEiIHN0cm9rZT0iIzYxNjE2MSIgc3Ryb2tlLXdpZHRoPSIwLjciLz4KPC9nPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMi41IDUuNUwyLjUgMy41TDExLjUgMy41TDExLjUgNS41TDIuNSA1LjVaTTIgN0MxLjQ0NzcyIDcgMSA2LjU1MjI4IDEgNkwxIDNDMSAyLjQ0NzcyIDEuNDQ3NzIgMiAyIDJMMTIgMkMxMi41NTIzIDIgMTMgMi40NDc3MiAxMyAzTDEzIDZDMTMgNi41NTIyOSAxMi41NTIzIDcgMTIgN0wyIDdaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5OCI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KDEgMS43NDg0NmUtMDcgMS43NDg0NmUtMDcgLTEgNCAxMy40NDQzKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=);--jp-icon-add: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDEzaC02djZoLTJ2LTZINXYtMmg2VjVoMnY2aDZ2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-bell: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiB2ZXJzaW9uPSIxLjEiPgogICA8cGF0aCBjbGFzcz0ianAtaWNvbjIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzMzMzMzIgogICAgICBkPSJtOCAwLjI5Yy0xLjQgMC0yLjcgMC43My0zLjYgMS44LTEuMiAxLjUtMS40IDMuNC0xLjUgNS4yLTAuMTggMi4yLTAuNDQgNC0yLjMgNS4zbDAuMjggMS4zaDVjMC4wMjYgMC42NiAwLjMyIDEuMSAwLjcxIDEuNSAwLjg0IDAuNjEgMiAwLjYxIDIuOCAwIDAuNTItMC40IDAuNi0xIDAuNzEtMS41aDVsMC4yOC0xLjNjLTEuOS0wLjk3LTIuMi0zLjMtMi4zLTUuMy0wLjEzLTEuOC0wLjI2LTMuNy0xLjUtNS4yLTAuODUtMS0yLjItMS44LTMuNi0xLjh6bTAgMS40YzAuODggMCAxLjkgMC41NSAyLjUgMS4zIDAuODggMS4xIDEuMSAyLjcgMS4yIDQuNCAwLjEzIDEuNyAwLjIzIDMuNiAxLjMgNS4yaC0xMGMxLjEtMS42IDEuMi0zLjQgMS4zLTUuMiAwLjEzLTEuNyAwLjMtMy4zIDEuMi00LjQgMC41OS0wLjcyIDEuNi0xLjMgMi41LTEuM3ptLTAuNzQgMTJoMS41Yy0wLjAwMTUgMC4yOCAwLjAxNSAwLjc5LTAuNzQgMC43OS0wLjczIDAuMDAxNi0wLjcyLTAuNTMtMC43NC0wLjc5eiIgLz4KPC9zdmc+Cg==);--jp-icon-bug-dot: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiPgogICAgICAgIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTcuMTkgOEgyMFYxMEgxNy45MUMxNy45NiAxMC4zMyAxOCAxMC42NiAxOCAxMVYxMkgyMFYxNEgxOC41SDE4VjE0LjAyNzVDMTUuNzUgMTQuMjc2MiAxNCAxNi4xODM3IDE0IDE4LjVDMTQgMTkuMjA4IDE0LjE2MzUgMTkuODc3OSAxNC40NTQ5IDIwLjQ3MzlDMTMuNzA2MyAyMC44MTE3IDEyLjg3NTcgMjEgMTIgMjFDOS43OCAyMSA3Ljg1IDE5Ljc5IDYuODEgMThINFYxNkg2LjA5QzYuMDQgMTUuNjcgNiAxNS4zNCA2IDE1VjE0SDRWMTJINlYxMUM2IDEwLjY2IDYuMDQgMTAuMzMgNi4wOSAxMEg0VjhINi44MUM3LjI2IDcuMjIgNy44OCA2LjU1IDguNjIgNi4wNEw3IDQuNDFMOC40MSAzTDEwLjU5IDUuMTdDMTEuMDQgNS4wNiAxMS41MSA1IDEyIDVDMTIuNDkgNSAxMi45NiA1LjA2IDEzLjQyIDUuMTdMMTUuNTkgM0wxNyA0LjQxTDE1LjM3IDYuMDRDMTYuMTIgNi41NSAxNi43NCA3LjIyIDE3LjE5IDhaTTEwIDE2SDE0VjE0SDEwVjE2Wk0xMCAxMkgxNFYxMEgxMFYxMloiIGZpbGw9IiM2MTYxNjEiLz4KICAgICAgICA8cGF0aCBkPSJNMjIgMTguNUMyMiAyMC40MzMgMjAuNDMzIDIyIDE4LjUgMjJDMTYuNTY3IDIyIDE1IDIwLjQzMyAxNSAxOC41QzE1IDE2LjU2NyAxNi41NjcgMTUgMTguNSAxNUMyMC40MzMgMTUgMjIgMTYuNTY3IDIyIDE4LjVaIiBmaWxsPSIjNjE2MTYxIi8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-bug: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yMCA4aC0yLjgxYy0uNDUtLjc4LTEuMDctMS40NS0xLjgyLTEuOTZMMTcgNC40MSAxNS41OSAzbC0yLjE3IDIuMTdDMTIuOTYgNS4wNiAxMi40OSA1IDEyIDVjLS40OSAwLS45Ni4wNi0xLjQxLjE3TDguNDEgMyA3IDQuNDFsMS42MiAxLjYzQzcuODggNi41NSA3LjI2IDcuMjIgNi44MSA4SDR2MmgyLjA5Yy0uMDUuMzMtLjA5LjY2LS4wOSAxdjFINHYyaDJ2MWMwIC4zNC4wNC42Ny4wOSAxSDR2MmgyLjgxYzEuMDQgMS43OSAyLjk3IDMgNS4xOSAzczQuMTUtMS4yMSA1LjE5LTNIMjB2LTJoLTIuMDljLjA1LS4zMy4wOS0uNjYuMDktMXYtMWgydi0yaC0ydi0xYzAtLjM0LS4wNC0uNjctLjA5LTFIMjBWOHptLTYgOGgtNHYtMmg0djJ6bTAtNGgtNHYtMmg0djJ6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-build: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE0LjkgMTcuNDVDMTYuMjUgMTcuNDUgMTcuMzUgMTYuMzUgMTcuMzUgMTVDMTcuMzUgMTMuNjUgMTYuMjUgMTIuNTUgMTQuOSAxMi41NUMxMy41NCAxMi41NSAxMi40NSAxMy42NSAxMi40NSAxNUMxMi40NSAxNi4zNSAxMy41NCAxNy40NSAxNC45IDE3LjQ1Wk0yMC4xIDE1LjY4TDIxLjU4IDE2Ljg0QzIxLjcxIDE2Ljk1IDIxLjc1IDE3LjEzIDIxLjY2IDE3LjI5TDIwLjI2IDE5LjcxQzIwLjE3IDE5Ljg2IDIwIDE5LjkyIDE5LjgzIDE5Ljg2TDE4LjA5IDE5LjE2QzE3LjczIDE5LjQ0IDE3LjMzIDE5LjY3IDE2LjkxIDE5Ljg1TDE2LjY0IDIxLjdDMTYuNjIgMjEuODcgMTYuNDcgMjIgMTYuMyAyMkgxMy41QzEzLjMyIDIyIDEzLjE4IDIxLjg3IDEzLjE1IDIxLjdMMTIuODkgMTkuODVDMTIuNDYgMTkuNjcgMTIuMDcgMTkuNDQgMTEuNzEgMTkuMTZMOS45NjAwMiAxOS44NkM5LjgxMDAyIDE5LjkyIDkuNjIwMDIgMTkuODYgOS41NDAwMiAxOS43MUw4LjE0MDAyIDE3LjI5QzguMDUwMDIgMTcuMTMgOC4wOTAwMiAxNi45NSA4LjIyMDAyIDE2Ljg0TDkuNzAwMDIgMTUuNjhMOS42NTAwMSAxNUw5LjcwMDAyIDE0LjMxTDguMjIwMDIgMTMuMTZDOC4wOTAwMiAxMy4wNSA4LjA1MDAyIDEyLjg2IDguMTQwMDIgMTIuNzFMOS41NDAwMiAxMC4yOUM5LjYyMDAyIDEwLjEzIDkuODEwMDIgMTAuMDcgOS45NjAwMiAxMC4xM0wxMS43MSAxMC44NEMxMi4wNyAxMC41NiAxMi40NiAxMC4zMiAxMi44OSAxMC4xNUwxMy4xNSA4LjI4OTk4QzEzLjE4IDguMTI5OTggMTMuMzIgNy45OTk5OCAxMy41IDcuOTk5OThIMTYuM0MxNi40NyA3Ljk5OTk4IDE2LjYyIDguMTI5OTggMTYuNjQgOC4yODk5OEwxNi45MSAxMC4xNUMxNy4zMyAxMC4zMiAxNy43MyAxMC41NiAxOC4wOSAxMC44NEwxOS44MyAxMC4xM0MyMCAxMC4wNyAyMC4xNyAxMC4xMyAyMC4yNiAxMC4yOUwyMS42NiAxMi43MUMyMS43NSAxMi44NiAyMS43MSAxMy4wNSAyMS41OCAxMy4xNkwyMC4xIDE0LjMxTDIwLjE1IDE1TDIwLjEgMTUuNjhaIi8+CiAgICA8cGF0aCBkPSJNNy4zMjk2NiA3LjQ0NDU0QzguMDgzMSA3LjAwOTU0IDguMzM5MzIgNi4wNTMzMiA3LjkwNDMyIDUuMjk5ODhDNy40NjkzMiA0LjU0NjQzIDYuNTA4MSA0LjI4MTU2IDUuNzU0NjYgNC43MTY1NkM1LjM5MTc2IDQuOTI2MDggNS4xMjY5NSA1LjI3MTE4IDUuMDE4NDkgNS42NzU5NEM0LjkxMDA0IDYuMDgwNzEgNC45NjY4MiA2LjUxMTk4IDUuMTc2MzQgNi44NzQ4OEM1LjYxMTM0IDcuNjI4MzIgNi41NzYyMiA3Ljg3OTU0IDcuMzI5NjYgNy40NDQ1NFpNOS42NTcxOCA0Ljc5NTkzTDEwLjg2NzIgNC45NTE3OUMxMC45NjI4IDQuOTc3NDEgMTEuMDQwMiA1LjA3MTMzIDExLjAzODIgNS4xODc5M0wxMS4wMzg4IDYuOTg4OTNDMTEuMDQ1NSA3LjEwMDU0IDEwLjk2MTYgNy4xOTUxOCAxMC44NTUgNy4yMTA1NEw5LjY2MDAxIDcuMzgwODNMOS4yMzkxNSA4LjEzMTg4TDkuNjY5NjEgOS4yNTc0NUM5LjcwNzI5IDkuMzYyNzEgOS42NjkzNCA5LjQ3Njk5IDkuNTc0MDggOS41MzE5OUw4LjAxNTIzIDEwLjQzMkM3LjkxMTMxIDEwLjQ5MiA3Ljc5MzM3IDEwLjQ2NzcgNy43MjEwNSAxMC4zODI0TDYuOTg3NDggOS40MzE4OEw2LjEwOTMxIDkuNDMwODNMNS4zNDcwNCAxMC4zOTA1QzUuMjg5MDkgMTAuNDcwMiA1LjE3MzgzIDEwLjQ5MDUgNS4wNzE4NyAxMC40MzM5TDMuNTEyNDUgOS41MzI5M0MzLjQxMDQ5IDkuNDc2MzMgMy4zNzY0NyA5LjM1NzQxIDMuNDEwNzUgOS4yNTY3OUwzLjg2MzQ3IDguMTQwOTNMMy42MTc0OSA3Ljc3NDg4TDMuNDIzNDcgNy4zNzg4M0wyLjIzMDc1IDcuMjEyOTdDMi4xMjY0NyA3LjE5MjM1IDIuMDQwNDkgNy4xMDM0MiAyLjA0MjQ1IDYuOTg2ODJMMi4wNDE4NyA1LjE4NTgyQzIuMDQzODMgNS4wNjkyMiAyLjExOTA5IDQuOTc5NTggMi4yMTcwNCA0Ljk2OTIyTDMuNDIwNjUgNC43OTM5M0wzLjg2NzQ5IDQuMDI3ODhMMy40MTEwNSAyLjkxNzMxQzMuMzczMzcgMi44MTIwNCAzLjQxMTMxIDIuNjk3NzYgMy41MTUyMyAyLjYzNzc2TDUuMDc0MDggMS43Mzc3NkM1LjE2OTM0IDEuNjgyNzYgNS4yODcyOSAxLjcwNzA0IDUuMzU5NjEgMS43OTIzMUw2LjExOTE1IDIuNzI3ODhMNi45ODAwMSAyLjczODkzTDcuNzI0OTYgMS43ODkyMkM3Ljc5MTU2IDEuNzA0NTggNy45MTU0OCAxLjY3OTIyIDguMDA4NzkgMS43NDA4Mkw5LjU2ODIxIDIuNjQxODJDOS42NzAxNyAyLjY5ODQyIDkuNzEyODUgMi44MTIzNCA5LjY4NzIzIDIuOTA3OTdMOS4yMTcxOCA0LjAzMzgzTDkuNDYzMTYgNC4zOTk4OEw5LjY1NzE4IDQuNzk1OTNaIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-caret-down-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iOS45LDEzLjYgMy42LDcuNCA0LjQsNi42IDkuOSwxMi4yIDE1LjQsNi43IDE2LjEsNy40ICIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-caret-down-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNS45TDksOS43bDMuOC0zLjhsMS4yLDEuMmwtNC45LDVsLTQuOS01TDUuMiw1Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-caret-down: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNy41TDksMTEuMmwzLjgtMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-caret-left: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik0xMC44LDEyLjhMNy4xLDlsMy44LTMuOGwwLDcuNkgxMC44eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-caret-right: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik03LjIsNS4yTDEwLjksOWwtMy44LDMuOFY1LjJINy4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-caret-up-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iMTUuNCwxMy4zIDkuOSw3LjcgNC40LDEzLjIgMy42LDEyLjUgOS45LDYuMyAxNi4xLDEyLjYgIi8+Cgk8L2c+Cjwvc3ZnPgo=);--jp-icon-caret-up: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik01LjIsMTAuNUw5LDYuOGwzLjgsMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-case-sensitive: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgogIDxnIGNsYXNzPSJqcC1pY29uLWFjY2VudDIiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTcuNiw4aDAuOWwzLjUsOGgtMS4xTDEwLDE0SDZsLTAuOSwySDRMNy42LDh6IE04LDkuMUw2LjQsMTNoMy4yTDgsOS4xeiIvPgogICAgPHBhdGggZD0iTTE2LjYsOS44Yy0wLjIsMC4xLTAuNCwwLjEtMC43LDAuMWMtMC4yLDAtMC40LTAuMS0wLjYtMC4yYy0wLjEtMC4xLTAuMi0wLjQtMC4yLTAuNyBjLTAuMywwLjMtMC42LDAuNS0wLjksMC43Yy0wLjMsMC4xLTAuNywwLjItMS4xLDAuMmMtMC4zLDAtMC41LDAtMC43LTAuMWMtMC4yLTAuMS0wLjQtMC4yLTAuNi0wLjNjLTAuMi0wLjEtMC4zLTAuMy0wLjQtMC41IGMtMC4xLTAuMi0wLjEtMC40LTAuMS0wLjdjMC0wLjMsMC4xLTAuNiwwLjItMC44YzAuMS0wLjIsMC4zLTAuNCwwLjQtMC41QzEyLDcsMTIuMiw2LjksMTIuNSw2LjhjMC4yLTAuMSwwLjUtMC4xLDAuNy0wLjIgYzAuMy0wLjEsMC41LTAuMSwwLjctMC4xYzAuMiwwLDAuNC0wLjEsMC42LTAuMWMwLjIsMCwwLjMtMC4xLDAuNC0wLjJjMC4xLTAuMSwwLjItMC4yLDAuMi0wLjRjMC0xLTEuMS0xLTEuMy0xIGMtMC40LDAtMS40LDAtMS40LDEuMmgtMC45YzAtMC40LDAuMS0wLjcsMC4yLTFjMC4xLTAuMiwwLjMtMC40LDAuNS0wLjZjMC4yLTAuMiwwLjUtMC4zLDAuOC0wLjNDMTMuMyw0LDEzLjYsNCwxMy45LDQgYzAuMywwLDAuNSwwLDAuOCwwLjFjMC4zLDAsMC41LDAuMSwwLjcsMC4yYzAuMiwwLjEsMC40LDAuMywwLjUsMC41QzE2LDUsMTYsNS4yLDE2LDUuNnYyLjljMCwwLjIsMCwwLjQsMCwwLjUgYzAsMC4xLDAuMSwwLjIsMC4zLDAuMmMwLjEsMCwwLjIsMCwwLjMsMFY5Ljh6IE0xNS4yLDYuOWMtMS4yLDAuNi0zLjEsMC4yLTMuMSwxLjRjMCwxLjQsMy4xLDEsMy4xLTAuNVY2Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-check: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-circle-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDJDNi40NyAyIDIgNi40NyAyIDEyczQuNDcgMTAgMTAgMTAgMTAtNC40NyAxMC0xMFMxNy41MyAyIDEyIDJ6bTAgMThjLTQuNDEgMC04LTMuNTktOC04czMuNTktOCA4LTggOCAzLjU5IDggOC0zLjU5IDgtOCA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-circle: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iOSIgY3k9IjkiIHI9IjgiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-clear: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8bWFzayBpZD0iZG9udXRIb2xlIj4KICAgIDxyZWN0IHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0id2hpdGUiIC8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSI4IiBmaWxsPSJibGFjayIvPgogIDwvbWFzaz4KCiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxyZWN0IGhlaWdodD0iMTgiIHdpZHRoPSIyIiB4PSIxMSIgeT0iMyIgdHJhbnNmb3JtPSJyb3RhdGUoMzE1LCAxMiwgMTIpIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIgbWFzaz0idXJsKCNkb251dEhvbGUpIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-close: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1ub25lIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIGpwLWljb24zLWhvdmVyIiBmaWxsPSJub25lIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjExIi8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIGpwLWljb24tYWNjZW50Mi1ob3ZlciIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPgogIDwvZz4KCiAgPGcgY2xhc3M9ImpwLWljb24tbm9uZSBqcC1pY29uLWJ1c3kiIGZpbGw9Im5vbmUiPgogICAgPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iNyIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-code: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTExLjQgMTguNkw2LjggMTRMMTEuNCA5LjRMMTAgOEw0IDE0TDEwIDIwTDExLjQgMTguNlpNMTYuNiAxOC42TDIxLjIgMTRMMTYuNiA5LjRMMTggOEwyNCAxNEwxOCAyMEwxNi42IDE4LjZWMTguNloiLz4KCTwvZz4KPC9zdmc+Cg==);--jp-icon-console: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwMCAyMDAiPgogIDxnIGNsYXNzPSJqcC1jb25zb2xlLWljb24tYmFja2dyb3VuZC1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMjg4RDEiPgogICAgPHBhdGggZD0iTTIwIDE5LjhoMTYwdjE1OS45SDIweiIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtY29uc29sZS1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIj4KICAgIDxwYXRoIGQ9Ik0xMDUgMTI3LjNoNDB2MTIuOGgtNDB6TTUxLjEgNzdMNzQgOTkuOWwtMjMuMyAyMy4zIDEwLjUgMTAuNSAyMy4zLTIzLjNMOTUgOTkuOSA4NC41IDg5LjQgNjEuNiA2Ni41eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-copy: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTExLjksMUgzLjJDMi40LDEsMS43LDEuNywxLjcsMi41djEwLjJoMS41VjIuNWg4LjdWMXogTTE0LjEsMy45aC04Yy0wLjgsMC0xLjUsMC43LTEuNSwxLjV2MTAuMmMwLDAuOCwwLjcsMS41LDEuNSwxLjVoOCBjMC44LDAsMS41LTAuNywxLjUtMS41VjUuNEMxNS41LDQuNiwxNC45LDMuOSwxNC4xLDMuOXogTTE0LjEsMTUuNWgtOFY1LjRoOFYxNS41eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-copyright: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCI+CiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0xMS44OCw5LjE0YzEuMjgsMC4wNiwxLjYxLDEuMTUsMS42MywxLjY2aDEuNzljLTAuMDgtMS45OC0xLjQ5LTMuMTktMy40NS0zLjE5QzkuNjQsNy42MSw4LDksOCwxMi4xNCBjMCwxLjk0LDAuOTMsNC4yNCwzLjg0LDQuMjRjMi4yMiwwLDMuNDEtMS42NSwzLjQ0LTIuOTVoLTEuNzljLTAuMDMsMC41OS0wLjQ1LDEuMzgtMS42MywxLjQ0QzEwLjU1LDE0LjgzLDEwLDEzLjgxLDEwLDEyLjE0IEMxMCw5LjI1LDExLjI4LDkuMTYsMTEuODgsOS4xNHogTTEyLDJDNi40OCwyLDIsNi40OCwyLDEyczQuNDgsMTAsMTAsMTBzMTAtNC40OCwxMC0xMFMxNy41MiwyLDEyLDJ6IE0xMiwyMGMtNC40MSwwLTgtMy41OS04LTggczMuNTktOCw4LThzOCwzLjU5LDgsOFMxNi40MSwyMCwxMiwyMHoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-cut: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkuNjQgNy42NGMuMjMtLjUuMzYtMS4wNS4zNi0xLjY0IDAtMi4yMS0xLjc5LTQtNC00UzIgMy43OSAyIDZzMS43OSA0IDQgNGMuNTkgMCAxLjE0LS4xMyAxLjY0LS4zNkwxMCAxMmwtMi4zNiAyLjM2QzcuMTQgMTQuMTMgNi41OSAxNCA2IDE0Yy0yLjIxIDAtNCAxLjc5LTQgNHMxLjc5IDQgNCA0IDQtMS43OSA0LTRjMC0uNTktLjEzLTEuMTQtLjM2LTEuNjRMMTIgMTRsNyA3aDN2LTFMOS42NCA3LjY0ek02IDhjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTAgMTJjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTYtNy41Yy0uMjggMC0uNS0uMjItLjUtLjVzLjIyLS41LjUtLjUuNS4yMi41LjUtLjIyLjUtLjUuNXpNMTkgM2wtNiA2IDIgMiA3LTdWM3oiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-delete: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCI+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjI2MjYyIiBkPSJNNiAxOWMwIDEuMS45IDIgMiAyaDhjMS4xIDAgMi0uOSAyLTJWN0g2djEyek0xOSA0aC0zLjVsLTEtMWgtNWwtMSAxSDV2MmgxNFY0eiIgLz4KPC9zdmc+Cg==);--jp-icon-download: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDloLTRWM0g5djZINWw3IDcgNy03ek01IDE4djJoMTR2LTJINXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-duplicate: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIuNzk5OTggMC44NzVIOC44OTU4MkM5LjIwMDYxIDAuODc1IDkuNDQ5OTggMS4xMzkxNCA5LjQ0OTk4IDEuNDYxOThDOS40NDk5OCAxLjc4NDgyIDkuMjAwNjEgMi4wNDg5NiA4Ljg5NTgyIDIuMDQ4OTZIMy4zNTQxNUMzLjA0OTM2IDIuMDQ4OTYgMi43OTk5OCAyLjMxMzEgMi43OTk5OCAyLjYzNTk0VjkuNjc5NjlDMi43OTk5OCAxMC4wMDI1IDIuNTUwNjEgMTAuMjY2NyAyLjI0NTgyIDEwLjI2NjdDMS45NDEwMyAxMC4yNjY3IDEuNjkxNjUgMTAuMDAyNSAxLjY5MTY1IDkuNjc5NjlWMi4wNDg5NkMxLjY5MTY1IDEuNDAzMjggMi4xOTA0IDAuODc1IDIuNzk5OTggMC44NzVaTTUuMzY2NjUgMTEuOVY0LjU1SDExLjA4MzNWMTEuOUg1LjM2NjY1Wk00LjE0MTY1IDQuMTQxNjdDNC4xNDE2NSAzLjY5MDYzIDQuNTA3MjggMy4zMjUgNC45NTgzMiAzLjMyNUgxMS40OTE3QzExLjk0MjcgMy4zMjUgMTIuMzA4MyAzLjY5MDYzIDEyLjMwODMgNC4xNDE2N1YxMi4zMDgzQzEyLjMwODMgMTIuNzU5NCAxMS45NDI3IDEzLjEyNSAxMS40OTE3IDEzLjEyNUg0Ljk1ODMyQzQuNTA3MjggMTMuMTI1IDQuMTQxNjUgMTIuNzU5NCA0LjE0MTY1IDEyLjMwODNWNC4xNDE2N1oiIGZpbGw9IiM2MTYxNjEiLz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNOS40MzU3NCA4LjI2NTA3SDguMzY0MzFWOS4zMzY1QzguMzY0MzEgOS40NTQzNSA4LjI2Nzg4IDkuNTUwNzggOC4xNTAwMiA5LjU1MDc4QzguMDMyMTcgOS41NTA3OCA3LjkzNTc0IDkuNDU0MzUgNy45MzU3NCA5LjMzNjVWOC4yNjUwN0g2Ljg2NDMxQzYuNzQ2NDUgOC4yNjUwNyA2LjY1MDAyIDguMTY4NjQgNi42NTAwMiA4LjA1MDc4QzYuNjUwMDIgNy45MzI5MiA2Ljc0NjQ1IDcuODM2NSA2Ljg2NDMxIDcuODM2NUg3LjkzNTc0VjYuNzY1MDdDNy45MzU3NCA2LjY0NzIxIDguMDMyMTcgNi41NTA3OCA4LjE1MDAyIDYuNTUwNzhDOC4yNjc4OCA2LjU1MDc4IDguMzY0MzEgNi42NDcyMSA4LjM2NDMxIDYuNzY1MDdWNy44MzY1SDkuNDM1NzRDOS41NTM2IDcuODM2NSA5LjY1MDAyIDcuOTMyOTIgOS42NTAwMiA4LjA1MDc4QzkuNjUwMDIgOC4xNjg2NCA5LjU1MzYgOC4yNjUwNyA5LjQzNTc0IDguMjY1MDdaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC41Ii8+Cjwvc3ZnPgo=);--jp-icon-edit: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMgMTcuMjVWMjFoMy43NUwxNy44MSA5Ljk0bC0zLjc1LTMuNzVMMyAxNy4yNXpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-ellipses: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iNSIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxOSIgY3k9IjEyIiByPSIyIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-extension: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwLjUgMTFIMTlWN2MwLTEuMS0uOS0yLTItMmgtNFYzLjVDMTMgMi4xMiAxMS44OCAxIDEwLjUgMVM4IDIuMTIgOCAzLjVWNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAydjMuOEgzLjVjMS40OSAwIDIuNyAxLjIxIDIuNyAyLjdzLTEuMjEgMi43LTIuNyAyLjdIMlYyMGMwIDEuMS45IDIgMiAyaDMuOHYtMS41YzAtMS40OSAxLjIxLTIuNyAyLjctMi43IDEuNDkgMCAyLjcgMS4yMSAyLjcgMi43VjIySDE3YzEuMSAwIDItLjkgMi0ydi00aDEuNWMxLjM4IDAgMi41LTEuMTIgMi41LTIuNVMyMS44OCAxMSAyMC41IDExeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-fast-forward: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTQgMThsOC41LTZMNCA2djEyem05LTEydjEybDguNS02TDEzIDZ6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-file-upload: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkgMTZoNnYtNmg0bC03LTctNyA3aDR6bS00IDJoMTR2Mkg1eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-file: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuMyA4LjJsLTUuNS01LjVjLS4zLS4zLS43LS41LTEuMi0uNUgzLjljLS44LjEtMS42LjktMS42IDEuOHYxNC4xYzAgLjkuNyAxLjYgMS42IDEuNmgxNC4yYy45IDAgMS42LS43IDEuNi0xLjZWOS40Yy4xLS41LS4xLS45LS40LTEuMnptLTUuOC0zLjNsMy40IDMuNmgtMy40VjQuOXptMy45IDEyLjdINC43Yy0uMSAwLS4yIDAtLjItLjJWNC43YzAtLjIuMS0uMy4yLS4zaDcuMnY0LjRzMCAuOC4zIDEuMWMuMy4zIDEuMS4zIDEuMS4zaDQuM3Y3LjJzLS4xLjItLjIuMnoiLz4KPC9zdmc+Cg==);--jp-icon-filter-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEwIDE4aDR2LTJoLTR2MnpNMyA2djJoMThWNkgzem0zIDdoMTJ2LTJINnYyeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-folder-favorite: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggY2xhc3M9ImpwLWljb24zIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxNjE2MSIgZD0iTTIwIDZoLThsLTItMkg0Yy0xLjEgMC0yIC45LTIgMnYxMmMwIDEuMS45IDIgMiAyaDE2YzEuMSAwIDItLjkgMi0yVjhjMC0xLjEtLjktMi0yLTJ6bS0yLjA2IDExTDE1IDE1LjI4IDEyLjA2IDE3bC43OC0zLjMzLTIuNTktMi4yNCAzLjQxLS4yOUwxNSA4bDEuMzQgMy4xNCAzLjQxLjI5LTIuNTkgMi4yNC43OCAzLjMzeiIvPgo8L3N2Zz4K);--jp-icon-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY4YzAtMS4xLS45LTItMi0yaC04bC0yLTJ6Ii8+Cjwvc3ZnPgo=);--jp-icon-home: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xMCAyMHYtNmg0djZoNXYtOGgzTDEyIDMgMiAxMmgzdjh6Ii8+Cjwvc3ZnPgo=);--jp-icon-html5: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uMCBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMDAiIGQ9Ik0xMDguNCAwaDIzdjIyLjhoMjEuMlYwaDIzdjY5aC0yM1Y0NmgtMjF2MjNoLTIzLjJNMjA2IDIzaC0yMC4zVjBoNjMuN3YyM0gyMjl2NDZoLTIzbTUzLjUtNjloMjQuMWwxNC44IDI0LjNMMzEzLjIgMGgyNC4xdjY5aC0yM1YzNC44bC0xNi4xIDI0LjgtMTYuMS0yNC44VjY5aC0yMi42bTg5LjItNjloMjN2NDYuMmgzMi42VjY5aC01NS42Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2U0NGQyNiIgZD0iTTEwNy42IDQ3MWwtMzMtMzcwLjRoMzYyLjhsLTMzIDM3MC4yTDI1NS43IDUxMiIvPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNmMTY1MjkiIGQ9Ik0yNTYgNDgwLjVWMTMxaDE0OC4zTDM3NiA0NDciLz4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNlYmViZWIiIGQ9Ik0xNDIgMTc2LjNoMTE0djQ1LjRoLTY0LjJsNC4yIDQ2LjVoNjB2NDUuM0gxNTQuNG0yIDIyLjhIMjAybDMuMiAzNi4zIDUwLjggMTMuNnY0Ny40bC05My4yLTI2Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIiBkPSJNMzY5LjYgMTc2LjNIMjU1Ljh2NDUuNGgxMDkuNm0tNC4xIDQ2LjVIMjU1Ljh2NDUuNGg1NmwtNS4zIDU5LTUwLjcgMTMuNnY0Ny4ybDkzLTI1LjgiLz4KPC9zdmc+Cg==);--jp-icon-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1icmFuZDQganAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNGRkYiIGQ9Ik0yLjIgMi4yaDE3LjV2MTcuNUgyLjJ6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzNGNTFCNSIgZD0iTTIuMiAyLjJ2MTcuNWgxNy41bC4xLTE3LjVIMi4yem0xMi4xIDIuMmMxLjIgMCAyLjIgMSAyLjIgMi4ycy0xIDIuMi0yLjIgMi4yLTIuMi0xLTIuMi0yLjIgMS0yLjIgMi4yLTIuMnpNNC40IDE3LjZsMy4zLTguOCAzLjMgNi42IDIuMi0zLjIgNC40IDUuNEg0LjR6Ii8+Cjwvc3ZnPgo=);--jp-icon-inspector: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaW5zcGVjdG9yLWljb24tY29sb3IganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yem0tNSAxNEg0di00aDExdjR6bTAtNUg0VjloMTF2NHptNSA1aC00VjloNHY5eiIvPgo8L3N2Zz4K);--jp-icon-json: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtanNvbi1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0Y5QTgyNSI+CiAgICA8cGF0aCBkPSJNMjAuMiAxMS44Yy0xLjYgMC0xLjcuNS0xLjcgMSAwIC40LjEuOS4xIDEuMy4xLjUuMS45LjEgMS4zIDAgMS43LTEuNCAyLjMtMy41IDIuM2gtLjl2LTEuOWguNWMxLjEgMCAxLjQgMCAxLjQtLjggMC0uMyAwLS42LS4xLTEgMC0uNC0uMS0uOC0uMS0xLjIgMC0xLjMgMC0xLjggMS4zLTItMS4zLS4yLTEuMy0uNy0xLjMtMiAwLS40LjEtLjguMS0xLjIuMS0uNC4xLS43LjEtMSAwLS44LS40LS43LTEuNC0uOGgtLjVWNC4xaC45YzIuMiAwIDMuNS43IDMuNSAyLjMgMCAuNC0uMS45LS4xIDEuMy0uMS41LS4xLjktLjEgMS4zIDAgLjUuMiAxIDEuNyAxdjEuOHpNMS44IDEwLjFjMS42IDAgMS43LS41IDEuNy0xIDAtLjQtLjEtLjktLjEtMS4zLS4xLS41LS4xLS45LS4xLTEuMyAwLTEuNiAxLjQtMi4zIDMuNS0yLjNoLjl2MS45aC0uNWMtMSAwLTEuNCAwLTEuNC44IDAgLjMgMCAuNi4xIDEgMCAuMi4xLjYuMSAxIDAgMS4zIDAgMS44LTEuMyAyQzYgMTEuMiA2IDExLjcgNiAxM2MwIC40LS4xLjgtLjEgMS4yLS4xLjMtLjEuNy0uMSAxIDAgLjguMy44IDEuNC44aC41djEuOWgtLjljLTIuMSAwLTMuNS0uNi0zLjUtMi4zIDAtLjQuMS0uOS4xLTEuMy4xLS41LjEtLjkuMS0xLjMgMC0uNS0uMi0xLTEuNy0xdi0xLjl6Ii8+CiAgICA8Y2lyY2xlIGN4PSIxMSIgY3k9IjEzLjgiIHI9IjIuMSIvPgogICAgPGNpcmNsZSBjeD0iMTEiIGN5PSI4LjIiIHI9IjIuMSIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-julia: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDMyNSAzMDAiPgogIDxnIGNsYXNzPSJqcC1icmFuZDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjY2IzYzMzIj4KICAgIDxwYXRoIGQ9Ik0gMTUwLjg5ODQzOCAyMjUgQyAxNTAuODk4NDM4IDI2Ni40MjE4NzUgMTE3LjMyMDMxMiAzMDAgNzUuODk4NDM4IDMwMCBDIDM0LjQ3NjU2MiAzMDAgMC44OTg0MzggMjY2LjQyMTg3NSAwLjg5ODQzOCAyMjUgQyAwLjg5ODQzOCAxODMuNTc4MTI1IDM0LjQ3NjU2MiAxNTAgNzUuODk4NDM4IDE1MCBDIDExNy4zMjAzMTIgMTUwIDE1MC44OTg0MzggMTgzLjU3ODEyNSAxNTAuODk4NDM4IDIyNSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzM4OTgyNiI+CiAgICA8cGF0aCBkPSJNIDIzNy41IDc1IEMgMjM3LjUgMTE2LjQyMTg3NSAyMDMuOTIxODc1IDE1MCAxNjIuNSAxNTAgQyAxMjEuMDc4MTI1IDE1MCA4Ny41IDExNi40MjE4NzUgODcuNSA3NSBDIDg3LjUgMzMuNTc4MTI1IDEyMS4wNzgxMjUgMCAxNjIuNSAwIEMgMjAzLjkyMTg3NSAwIDIzNy41IDMzLjU3ODEyNSAyMzcuNSA3NSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzk1NThiMiI+CiAgICA8cGF0aCBkPSJNIDMyNC4xMDE1NjIgMjI1IEMgMzI0LjEwMTU2MiAyNjYuNDIxODc1IDI5MC41MjM0MzggMzAwIDI0OS4xMDE1NjIgMzAwIEMgMjA3LjY3OTY4OCAzMDAgMTc0LjEwMTU2MiAyNjYuNDIxODc1IDE3NC4xMDE1NjIgMjI1IEMgMTc0LjEwMTU2MiAxODMuNTc4MTI1IDIwNy42Nzk2ODggMTUwIDI0OS4xMDE1NjIgMTUwIEMgMjkwLjUyMzQzOCAxNTAgMzI0LjEwMTU2MiAxODMuNTc4MTI1IDMyNC4xMDE1NjIgMjI1Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-jupyter-favicon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUyIiBoZWlnaHQ9IjE2NSIgdmlld0JveD0iMCAwIDE1MiAxNjUiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgPGcgY2xhc3M9ImpwLWp1cHl0ZXItaWNvbi1jb2xvciIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA3ODk0NywgMTEwLjU4MjkyNykiIGQ9Ik03NS45NDIyODQyLDI5LjU4MDQ1NjEgQzQzLjMwMjM5NDcsMjkuNTgwNDU2MSAxNC43OTY3ODMyLDE3LjY1MzQ2MzQgMCwwIEM1LjUxMDgzMjExLDE1Ljg0MDY4MjkgMTUuNzgxNTM4OSwyOS41NjY3NzMyIDI5LjM5MDQ5NDcsMzkuMjc4NDE3MSBDNDIuOTk5Nyw0OC45ODk4NTM3IDU5LjI3MzcsNTQuMjA2NzgwNSA3NS45NjA1Nzg5LDU0LjIwNjc4MDUgQzkyLjY0NzQ1NzksNTQuMjA2NzgwNSAxMDguOTIxNDU4LDQ4Ljk4OTg1MzcgMTIyLjUzMDY2MywzOS4yNzg0MTcxIEMxMzYuMTM5NDUzLDI5LjU2Njc3MzIgMTQ2LjQxMDI4NCwxNS44NDA2ODI5IDE1MS45MjExNTgsMCBDMTM3LjA4Nzg2OCwxNy42NTM0NjM0IDEwOC41ODI1ODksMjkuNTgwNDU2MSA3NS45NDIyODQyLDI5LjU4MDQ1NjEgTDc1Ljk0MjI4NDIsMjkuNTgwNDU2MSBaIiAvPgogICAgPHBhdGggdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMzczNjgsIDAuNzA0ODc4KSIgZD0iTTc1Ljk3ODQ1NzksMjQuNjI2NDA3MyBDMTA4LjYxODc2MywyNC42MjY0MDczIDEzNy4xMjQ0NTgsMzYuNTUzNDQxNSAxNTEuOTIxMTU4LDU0LjIwNjc4MDUgQzE0Ni40MTAyODQsMzguMzY2MjIyIDEzNi4xMzk0NTMsMjQuNjQwMTMxNyAxMjIuNTMwNjYzLDE0LjkyODQ4NzggQzEwOC45MjE0NTgsNS4yMTY4NDM5IDkyLjY0NzQ1NzksMCA3NS45NjA1Nzg5LDAgQzU5LjI3MzcsMCA0Mi45OTk3LDUuMjE2ODQzOSAyOS4zOTA0OTQ3LDE0LjkyODQ4NzggQzE1Ljc4MTUzODksMjQuNjQwMTMxNyA1LjUxMDgzMjExLDM4LjM2NjIyMiAwLDU0LjIwNjc4MDUgQzE0LjgzMzA4MTYsMzYuNTg5OTI5MyA0My4zMzg1Njg0LDI0LjYyNjQwNzMgNzUuOTc4NDU3OSwyNC42MjY0MDczIEw3NS45Nzg0NTc5LDI0LjYyNjQwNzMgWiIgLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-jupyter: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzkiIGhlaWdodD0iNTEiIHZpZXdCb3g9IjAgMCAzOSA1MSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTYzOCAtMjI4MSkiPgogICAgIDxnIGNsYXNzPSJqcC1qdXB5dGVyLWljb24tY29sb3IiIGZpbGw9IiNGMzc3MjYiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5Ljc0IDIzMTEuOTgpIiBkPSJNIDE4LjI2NDYgNy4xMzQxMUMgMTAuNDE0NSA3LjEzNDExIDMuNTU4NzIgNC4yNTc2IDAgMEMgMS4zMjUzOSAzLjgyMDQgMy43OTU1NiA3LjEzMDgxIDcuMDY4NiA5LjQ3MzAzQyAxMC4zNDE3IDExLjgxNTIgMTQuMjU1NyAxMy4wNzM0IDE4LjI2OSAxMy4wNzM0QyAyMi4yODIzIDEzLjA3MzQgMjYuMTk2MyAxMS44MTUyIDI5LjQ2OTQgOS40NzMwM0MgMzIuNzQyNCA3LjEzMDgxIDM1LjIxMjYgMy44MjA0IDM2LjUzOCAwQyAzMi45NzA1IDQuMjU3NiAyNi4xMTQ4IDcuMTM0MTEgMTguMjY0NiA3LjEzNDExWiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5LjczIDIyODUuNDgpIiBkPSJNIDE4LjI3MzMgNS45MzkzMUMgMjYuMTIzNSA1LjkzOTMxIDMyLjk3OTMgOC44MTU4MyAzNi41MzggMTMuMDczNEMgMzUuMjEyNiA5LjI1MzAzIDMyLjc0MjQgNS45NDI2MiAyOS40Njk0IDMuNjAwNEMgMjYuMTk2MyAxLjI1ODE4IDIyLjI4MjMgMCAxOC4yNjkgMEMgMTQuMjU1NyAwIDEwLjM0MTcgMS4yNTgxOCA3LjA2ODYgMy42MDA0QyAzLjc5NTU2IDUuOTQyNjIgMS4zMjUzOSA5LjI1MzAzIDAgMTMuMDczNEMgMy41Njc0NSA4LjgyNDYzIDEwLjQyMzIgNS45MzkzMSAxOC4yNzMzIDUuOTM5MzFaIi8+CiAgICA8L2c+CiAgICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjY5LjMgMjI4MS4zMSkiIGQ9Ik0gNS44OTM1MyAyLjg0NEMgNS45MTg4OSAzLjQzMTY1IDUuNzcwODUgNC4wMTM2NyA1LjQ2ODE1IDQuNTE2NDVDIDUuMTY1NDUgNS4wMTkyMiA0LjcyMTY4IDUuNDIwMTUgNC4xOTI5OSA1LjY2ODUxQyAzLjY2NDMgNS45MTY4OCAzLjA3NDQ0IDYuMDAxNTEgMi40OTgwNSA1LjkxMTcxQyAxLjkyMTY2IDUuODIxOSAxLjM4NDYzIDUuNTYxNyAwLjk1NDg5OCA1LjE2NDAxQyAwLjUyNTE3IDQuNzY2MzMgMC4yMjIwNTYgNC4yNDkwMyAwLjA4MzkwMzcgMy42Nzc1N0MgLTAuMDU0MjQ4MyAzLjEwNjExIC0wLjAyMTIzIDIuNTA2MTcgMC4xNzg3ODEgMS45NTM2NEMgMC4zNzg3OTMgMS40MDExIDAuNzM2ODA5IDAuOTIwODE3IDEuMjA3NTQgMC41NzM1MzhDIDEuNjc4MjYgMC4yMjYyNTkgMi4yNDA1NSAwLjAyNzU5MTkgMi44MjMyNiAwLjAwMjY3MjI5QyAzLjYwMzg5IC0wLjAzMDcxMTUgNC4zNjU3MyAwLjI0OTc4OSA0Ljk0MTQyIDAuNzgyNTUxQyA1LjUxNzExIDEuMzE1MzEgNS44NTk1NiAyLjA1Njc2IDUuODkzNTMgMi44NDRaIi8+CiAgICAgIDxwYXRoIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2MzkuOCAyMzIzLjgxKSIgZD0iTSA3LjQyNzg5IDMuNTgzMzhDIDcuNDYwMDggNC4zMjQzIDcuMjczNTUgNS4wNTgxOSA2Ljg5MTkzIDUuNjkyMTNDIDYuNTEwMzEgNi4zMjYwNyA1Ljk1MDc1IDYuODMxNTYgNS4yODQxMSA3LjE0NDZDIDQuNjE3NDcgNy40NTc2MyAzLjg3MzcxIDcuNTY0MTQgMy4xNDcwMiA3LjQ1MDYzQyAyLjQyMDMyIDcuMzM3MTIgMS43NDMzNiA3LjAwODcgMS4yMDE4NCA2LjUwNjk1QyAwLjY2MDMyOCA2LjAwNTIgMC4yNzg2MSA1LjM1MjY4IDAuMTA1MDE3IDQuNjMyMDJDIC0wLjA2ODU3NTcgMy45MTEzNSAtMC4wMjYyMzYxIDMuMTU0OTQgMC4yMjY2NzUgMi40NTg1NkMgMC40Nzk1ODcgMS43NjIxNyAwLjkzMTY5NyAxLjE1NzEzIDEuNTI1NzYgMC43MjAwMzNDIDIuMTE5ODMgMC4yODI5MzUgMi44MjkxNCAwLjAzMzQzOTUgMy41NjM4OSAwLjAwMzEzMzQ0QyA0LjU0NjY3IC0wLjAzNzQwMzMgNS41MDUyOSAwLjMxNjcwNiA2LjIyOTYxIDAuOTg3ODM1QyA2Ljk1MzkzIDEuNjU4OTYgNy4zODQ4NCAyLjU5MjM1IDcuNDI3ODkgMy41ODMzOEwgNy40Mjc4OSAzLjU4MzM4WiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM4LjM2IDIyODYuMDYpIiBkPSJNIDIuMjc0NzEgNC4zOTYyOUMgMS44NDM2MyA0LjQxNTA4IDEuNDE2NzEgNC4zMDQ0NSAxLjA0Nzk5IDQuMDc4NDNDIDAuNjc5MjY4IDMuODUyNCAwLjM4NTMyOCAzLjUyMTE0IDAuMjAzMzcxIDMuMTI2NTZDIDAuMDIxNDEzNiAyLjczMTk4IC0wLjA0MDM3OTggMi4yOTE4MyAwLjAyNTgxMTYgMS44NjE4MUMgMC4wOTIwMDMxIDEuNDMxOCAwLjI4MzIwNCAxLjAzMTI2IDAuNTc1MjEzIDAuNzEwODgzQyAwLjg2NzIyMiAwLjM5MDUxIDEuMjQ2OTEgMC4xNjQ3MDggMS42NjYyMiAwLjA2MjA1OTJDIDIuMDg1NTMgLTAuMDQwNTg5NyAyLjUyNTYxIC0wLjAxNTQ3MTQgMi45MzA3NiAwLjEzNDIzNUMgMy4zMzU5MSAwLjI4Mzk0MSAzLjY4NzkyIDAuNTUxNTA1IDMuOTQyMjIgMC45MDMwNkMgNC4xOTY1MiAxLjI1NDYyIDQuMzQxNjkgMS42NzQzNiA0LjM1OTM1IDIuMTA5MTZDIDQuMzgyOTkgMi42OTEwNyA0LjE3Njc4IDMuMjU4NjkgMy43ODU5NyAzLjY4NzQ2QyAzLjM5NTE2IDQuMTE2MjQgMi44NTE2NiA0LjM3MTE2IDIuMjc0NzEgNC4zOTYyOUwgMi4yNzQ3MSA0LjM5NjI5WiIvPgogICAgPC9nPgogIDwvZz4+Cjwvc3ZnPgo=);--jp-icon-jupyterlab-wordmark: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIHZpZXdCb3g9IjAgMCAxODYwLjggNDc1Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0RTRFNEUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ4MC4xMzY0MDEsIDY0LjI3MTQ5MykiPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDU4Ljg3NTU2NikiPgogICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA4NzYwMywgMC4xNDAyOTQpIj4KICAgICAgICA8cGF0aCBkPSJNLTQyNi45LDE2OS44YzAsNDguNy0zLjcsNjQuNy0xMy42LDc2LjRjLTEwLjgsMTAtMjUsMTUuNS0zOS43LDE1LjVsMy43LDI5IGMyMi44LDAuMyw0NC44LTcuOSw2MS45LTIzLjFjMTcuOC0xOC41LDI0LTQ0LjEsMjQtODMuM1YwSC00Mjd2MTcwLjFMLTQyNi45LDE2OS44TC00MjYuOSwxNjkuOHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTU1LjA0NTI5NiwgNTYuODM3MTA0KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuNTYyNDUzLCAxLjc5OTg0MikiPgogICAgICAgIDxwYXRoIGQ9Ik0tMzEyLDE0OGMwLDIxLDAsMzkuNSwxLjcsNTUuNGgtMzEuOGwtMi4xLTMzLjNoLTAuOGMtNi43LDExLjYtMTYuNCwyMS4zLTI4LDI3LjkgYy0xMS42LDYuNi0yNC44LDEwLTM4LjIsOS44Yy0zMS40LDAtNjktMTcuNy02OS04OVYwaDM2LjR2MTEyLjdjMCwzOC43LDExLjYsNjQuNyw0NC42LDY0LjdjMTAuMy0wLjIsMjAuNC0zLjUsMjguOS05LjQgYzguNS01LjksMTUuMS0xNC4zLDE4LjktMjMuOWMyLjItNi4xLDMuMy0xMi41LDMuMy0xOC45VjAuMmgzNi40VjE0OEgtMzEyTC0zMTIsMTQ4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTAuMDEzMzIyLCA1My40Nzk2MzgpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS43MDY0NTgsIDAuMjMxNDI1KSI+CiAgICAgICAgPHBhdGggZD0iTS00NzguNiw3MS40YzAtMjYtMC44LTQ3LTEuNy02Ni43aDMyLjdsMS43LDM0LjhoMC44YzcuMS0xMi41LDE3LjUtMjIuOCwzMC4xLTI5LjcgYzEyLjUtNywyNi43LTEwLjMsNDEtOS44YzQ4LjMsMCw4NC43LDQxLjcsODQuNywxMDMuM2MwLDczLjEtNDMuNywxMDkuMi05MSwxMDkuMmMtMTIuMSwwLjUtMjQuMi0yLjItMzUtNy44IGMtMTAuOC01LjYtMTkuOS0xMy45LTI2LjYtMjQuMmgtMC44VjI5MWgtMzZ2LTIyMEwtNDc4LjYsNzEuNEwtNDc4LjYsNzEuNHogTS00NDIuNiwxMjUuNmMwLjEsNS4xLDAuNiwxMC4xLDEuNywxNS4xIGMzLDEyLjMsOS45LDIzLjMsMTkuOCwzMS4xYzkuOSw3LjgsMjIuMSwxMi4xLDM0LjcsMTIuMWMzOC41LDAsNjAuNy0zMS45LDYwLjctNzguNWMwLTQwLjctMjEuMS03NS42LTU5LjUtNzUuNiBjLTEyLjksMC40LTI1LjMsNS4xLTM1LjMsMTMuNGMtOS45LDguMy0xNi45LDE5LjctMTkuNiwzMi40Yy0xLjUsNC45LTIuMywxMC0yLjUsMTUuMVYxMjUuNkwtNDQyLjYsMTI1LjZMLTQ0Mi42LDEyNS42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2MDYuNzQwNzI2LCA1Ni44MzcxMDQpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC43NTEyMjYsIDEuOTg5Mjk5KSI+CiAgICAgICAgPHBhdGggZD0iTS00NDAuOCwwbDQzLjcsMTIwLjFjNC41LDEzLjQsOS41LDI5LjQsMTIuOCw0MS43aDAuOGMzLjctMTIuMiw3LjktMjcuNywxMi44LTQyLjQgbDM5LjctMTE5LjJoMzguNUwtMzQ2LjksMTQ1Yy0yNiw2OS43LTQzLjcsMTA1LjQtNjguNiwxMjcuMmMtMTIuNSwxMS43LTI3LjksMjAtNDQuNiwyMy45bC05LjEtMzEuMSBjMTEuNy0zLjksMjIuNS0xMC4xLDMxLjgtMTguMWMxMy4yLTExLjEsMjMuNy0yNS4yLDMwLjYtNDEuMmMxLjUtMi44LDIuNS01LjcsMi45LTguOGMtMC4zLTMuMy0xLjItNi42LTIuNS05LjdMLTQ4MC4yLDAuMSBoMzkuN0wtNDQwLjgsMEwtNDQwLjgsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODIyLjc0ODEwNCwgMC4wMDAwMDApIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS40NjQwNTAsIDAuMzc4OTE0KSI+CiAgICAgICAgPHBhdGggZD0iTS00MTMuNywwdjU4LjNoNTJ2MjguMmgtNTJWMTk2YzAsMjUsNywzOS41LDI3LjMsMzkuNWM3LjEsMC4xLDE0LjItMC43LDIxLjEtMi41IGwxLjcsMjcuN2MtMTAuMywzLjctMjEuMyw1LjQtMzIuMiw1Yy03LjMsMC40LTE0LjYtMC43LTIxLjMtMy40Yy02LjgtMi43LTEyLjktNi44LTE3LjktMTIuMWMtMTAuMy0xMC45LTE0LjEtMjktMTQuMS01Mi45IFY4Ni41aC0zMVY1OC4zaDMxVjkuNkwtNDEzLjcsMEwtNDEzLjcsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTc0LjQzMzI4NiwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAuOTkwMDM0LCAwLjYxMDMzOSkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDQ1LjgsMTEzYzAuOCw1MCwzMi4yLDcwLjYsNjguNiw3MC42YzE5LDAuNiwzNy45LTMsNTUuMy0xMC41bDYuMiwyNi40IGMtMjAuOSw4LjktNDMuNSwxMy4xLTY2LjIsMTIuNmMtNjEuNSwwLTk4LjMtNDEuMi05OC4zLTEwMi41Qy00ODAuMiw0OC4yLTQ0NC43LDAtMzg2LjUsMGM2NS4yLDAsODIuNyw1OC4zLDgyLjcsOTUuNyBjLTAuMSw1LjgtMC41LDExLjUtMS4yLDE3LjJoLTE0MC42SC00NDUuOEwtNDQ1LjgsMTEzeiBNLTMzOS4yLDg2LjZjMC40LTIzLjUtOS41LTYwLjEtNTAuNC02MC4xIGMtMzYuOCwwLTUyLjgsMzQuNC01NS43LDYwLjFILTMzOS4yTC0zMzkuMiw4Ni42TC0zMzkuMiw4Ni42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjAxLjk2MTA1OCwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuMTc5NjQwLCAwLjcwNTA2OCkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDc4LjYsNjhjMC0yMy45LTAuNC00NC41LTEuNy02My40aDMxLjhsMS4yLDM5LjloMS43YzkuMS0yNy4zLDMxLTQ0LjUsNTUuMy00NC41IGMzLjUtMC4xLDcsMC40LDEwLjMsMS4ydjM0LjhjLTQuMS0wLjktOC4yLTEuMy0xMi40LTEuMmMtMjUuNiwwLTQzLjcsMTkuNy00OC43LDQ3LjRjLTEsNS43LTEuNiwxMS41LTEuNywxNy4ydjEwOC4zaC0zNlY2OCBMLTQ3OC42LDY4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi13YXJuMCIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCBkPSJNMTM1Mi4zLDMyNi4yaDM3VjI4aC0zN1YzMjYuMnogTTE2MDQuOCwzMjYuMmMtMi41LTEzLjktMy40LTMxLjEtMy40LTQ4Ljd2LTc2IGMwLTQwLjctMTUuMS04My4xLTc3LjMtODMuMWMtMjUuNiwwLTUwLDcuMS02Ni44LDE4LjFsOC40LDI0LjRjMTQuMy05LjIsMzQtMTUuMSw1My0xNS4xYzQxLjYsMCw0Ni4yLDMwLjIsNDYuMiw0N3Y0LjIgYy03OC42LTAuNC0xMjIuMywyNi41LTEyMi4zLDc1LjZjMCwyOS40LDIxLDU4LjQsNjIuMiw1OC40YzI5LDAsNTAuOS0xNC4zLDYyLjItMzAuMmgxLjNsMi45LDI1LjZIMTYwNC44eiBNMTU2NS43LDI1Ny43IGMwLDMuOC0wLjgsOC0yLjEsMTEuOGMtNS45LDE3LjItMjIuNywzNC00OS4yLDM0Yy0xOC45LDAtMzQuOS0xMS4zLTM0LjktMzUuM2MwLTM5LjUsNDUuOC00Ni42LDg2LjItNDUuOFYyNTcuN3ogTTE2OTguNSwzMjYuMiBsMS43LTMzLjZoMS4zYzE1LjEsMjYuOSwzOC43LDM4LjIsNjguMSwzOC4yYzQ1LjQsMCw5MS4yLTM2LjEsOTEuMi0xMDguOGMwLjQtNjEuNy0zNS4zLTEwMy43LTg1LjctMTAzLjcgYy0zMi44LDAtNTYuMywxNC43LTY5LjMsMzcuNGgtMC44VjI4aC0zNi42djI0NS43YzAsMTguMS0wLjgsMzguNi0xLjcsNTIuNUgxNjk4LjV6IE0xNzA0LjgsMjA4LjJjMC01LjksMS4zLTEwLjksMi4xLTE1LjEgYzcuNi0yOC4xLDMxLjEtNDUuNCw1Ni4zLTQ1LjRjMzkuNSwwLDYwLjUsMzQuOSw2MC41LDc1LjZjMCw0Ni42LTIzLjEsNzguMS02MS44LDc4LjFjLTI2LjksMC00OC4zLTE3LjYtNTUuNS00My4zIGMtMC44LTQuMi0xLjctOC44LTEuNy0xMy40VjIwOC4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgZmlsbD0iIzYxNjE2MSIgZD0iTTE1IDlIOXY2aDZWOXptLTIgNGgtMnYtMmgydjJ6bTgtMlY5aC0yVjdjMC0xLjEtLjktMi0yLTJoLTJWM2gtMnYyaC0yVjNIOXYySDdjLTEuMSAwLTIgLjktMiAydjJIM3YyaDJ2MkgzdjJoMnYyYzAgMS4xLjkgMiAyIDJoMnYyaDJ2LTJoMnYyaDJ2LTJoMmMxLjEgMCAyLS45IDItMnYtMmgydi0yaC0ydi0yaDJ6bS00IDZIN1Y3aDEwdjEweiIvPgo8L3N2Zz4K);--jp-icon-keyboard: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMTdjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY3YzAtMS4xLS45LTItMi0yem0tOSAzaDJ2MmgtMlY4em0wIDNoMnYyaC0ydi0yek04IDhoMnYySDhWOHptMCAzaDJ2Mkg4di0yem0tMSAySDV2LTJoMnYyem0wLTNINVY4aDJ2MnptOSA3SDh2LTJoOHYyem0wLTRoLTJ2LTJoMnYyem0wLTNoLTJWOGgydjJ6bTMgM2gtMnYtMmgydjJ6bTAtM2gtMlY4aDJ2MnoiLz4KPC9zdmc+Cg==);--jp-icon-launch: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzIgMzIiIHdpZHRoPSIzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yNiwyOEg2YTIuMDAyNywyLjAwMjcsMCwwLDEtMi0yVjZBMi4wMDI3LDIuMDAyNywwLDAsMSw2LDRIMTZWNkg2VjI2SDI2VjE2aDJWMjZBMi4wMDI3LDIuMDAyNywwLDAsMSwyNiwyOFoiLz4KICAgIDxwb2x5Z29uIHBvaW50cz0iMjAgMiAyMCA0IDI2LjU4NiA0IDE4IDEyLjU4NiAxOS40MTQgMTQgMjggNS40MTQgMjggMTIgMzAgMTIgMzAgMiAyMCAyIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-launcher: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkgMTlINVY1aDdWM0g1YTIgMiAwIDAwLTIgMnYxNGEyIDIgMCAwMDIgMmgxNGMxLjEgMCAyLS45IDItMnYtN2gtMnY3ek0xNCAzdjJoMy41OWwtOS44MyA5LjgzIDEuNDEgMS40MUwxOSA2LjQxVjEwaDJWM2gtN3oiLz4KPC9zdmc+Cg==);--jp-icon-line-form: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGZpbGw9IndoaXRlIiBkPSJNNS44OCA0LjEyTDEzLjc2IDEybC03Ljg4IDcuODhMOCAyMmwxMC0xMEw4IDJ6Ii8+Cjwvc3ZnPgo=);--jp-icon-link: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMuOSAxMmMwLTEuNzEgMS4zOS0zLjEgMy4xLTMuMWg0VjdIN2MtMi43NiAwLTUgMi4yNC01IDVzMi4yNCA1IDUgNWg0di0xLjlIN2MtMS43MSAwLTMuMS0xLjM5LTMuMS0zLjF6TTggMTNoOHYtMkg4djJ6bTktNmgtNHYxLjloNGMxLjcxIDAgMy4xIDEuMzkgMy4xIDMuMXMtMS4zOSAzLjEtMy4xIDMuMWgtNFYxN2g0YzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xOSA1djE0SDVWNWgxNG0xLjEtMkgzLjljLS41IDAtLjkuNC0uOS45djE2LjJjMCAuNC40LjkuOS45aDE2LjJjLjQgMCAuOS0uNS45LS45VjMuOWMwLS41LS41LS45LS45LS45ek0xMSA3aDZ2MmgtNlY3em0wIDRoNnYyaC02di0yem0wIDRoNnYyaC02ek03IDdoMnYySDd6bTAgNGgydjJIN3ptMCA0aDJ2Mkg3eiIvPgo8L3N2Zz4=);--jp-icon-listings-info: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MC45NzggNTAuOTc4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MC45NzggNTAuOTc4OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+Cgk8Zz4KCQk8cGF0aCBzdHlsZT0iZmlsbDojMDEwMDAyOyIgZD0iTTQzLjUyLDcuNDU4QzM4LjcxMSwyLjY0OCwzMi4zMDcsMCwyNS40ODksMEMxOC42NywwLDEyLjI2NiwyLjY0OCw3LjQ1OCw3LjQ1OAoJCQljLTkuOTQzLDkuOTQxLTkuOTQzLDI2LjExOSwwLDM2LjA2MmM0LjgwOSw0LjgwOSwxMS4yMTIsNy40NTYsMTguMDMxLDcuNDU4YzAsMCwwLjAwMSwwLDAuMDAyLDAKCQkJYzYuODE2LDAsMTMuMjIxLTIuNjQ4LDE4LjAyOS03LjQ1OGM0LjgwOS00LjgwOSw3LjQ1Ny0xMS4yMTIsNy40NTctMTguMDNDNTAuOTc3LDE4LjY3LDQ4LjMyOCwxMi4yNjYsNDMuNTIsNy40NTh6CgkJCSBNNDIuMTA2LDQyLjEwNWMtNC40MzIsNC40MzEtMTAuMzMyLDYuODcyLTE2LjYxNSw2Ljg3MmgtMC4wMDJjLTYuMjg1LTAuMDAxLTEyLjE4Ny0yLjQ0MS0xNi42MTctNi44NzIKCQkJYy05LjE2Mi05LjE2My05LjE2Mi0yNC4wNzEsMC0zMy4yMzNDMTMuMzAzLDQuNDQsMTkuMjA0LDIsMjUuNDg5LDJjNi4yODQsMCwxMi4xODYsMi40NCwxNi42MTcsNi44NzIKCQkJYzQuNDMxLDQuNDMxLDYuODcxLDEwLjMzMiw2Ljg3MSwxNi42MTdDNDguOTc3LDMxLjc3Miw0Ni41MzYsMzcuNjc1LDQyLjEwNiw0Mi4xMDV6Ii8+CgkJPHBhdGggc3R5bGU9ImZpbGw6IzAxMDAwMjsiIGQ9Ik0yMy41NzgsMzIuMjE4Yy0wLjAyMy0xLjczNCwwLjE0My0zLjA1OSwwLjQ5Ni0zLjk3MmMwLjM1My0wLjkxMywxLjExLTEuOTk3LDIuMjcyLTMuMjUzCgkJCWMwLjQ2OC0wLjUzNiwwLjkyMy0xLjA2MiwxLjM2Ny0xLjU3NWMwLjYyNi0wLjc1MywxLjEwNC0xLjQ3OCwxLjQzNi0yLjE3NWMwLjMzMS0wLjcwNywwLjQ5NS0xLjU0MSwwLjQ5NS0yLjUKCQkJYzAtMS4wOTYtMC4yNi0yLjA4OC0wLjc3OS0yLjk3OWMtMC41NjUtMC44NzktMS41MDEtMS4zMzYtMi44MDYtMS4zNjljLTEuODAyLDAuMDU3LTIuOTg1LDAuNjY3LTMuNTUsMS44MzIKCQkJYy0wLjMwMSwwLjUzNS0wLjUwMywxLjE0MS0wLjYwNywxLjgxNGMtMC4xMzksMC43MDctMC4yMDcsMS40MzItMC4yMDcsMi4xNzRoLTIuOTM3Yy0wLjA5MS0yLjIwOCwwLjQwNy00LjExNCwxLjQ5My01LjcxOQoJCQljMS4wNjItMS42NCwyLjg1NS0yLjQ4MSw1LjM3OC0yLjUyN2MyLjE2LDAuMDIzLDMuODc0LDAuNjA4LDUuMTQxLDEuNzU4YzEuMjc4LDEuMTYsMS45MjksMi43NjQsMS45NSw0LjgxMQoJCQljMCwxLjE0Mi0wLjEzNywyLjExMS0wLjQxLDIuOTExYy0wLjMwOSwwLjg0NS0wLjczMSwxLjU5My0xLjI2OCwyLjI0M2MtMC40OTIsMC42NS0xLjA2OCwxLjMxOC0xLjczLDIuMDAyCgkJCWMtMC42NSwwLjY5Ny0xLjMxMywxLjQ3OS0xLjk4NywyLjM0NmMtMC4yMzksMC4zNzctMC40MjksMC43NzctMC41NjUsMS4xOTljLTAuMTYsMC45NTktMC4yMTcsMS45NTEtMC4xNzEsMi45NzkKCQkJQzI2LjU4OSwzMi4yMTgsMjMuNTc4LDMyLjIxOCwyMy41NzgsMzIuMjE4eiBNMjMuNTc4LDM4LjIydi0zLjQ4NGgzLjA3NnYzLjQ4NEgyMy41Nzh6Ii8+Cgk8L2c+Cjwvc3ZnPgo=);--jp-icon-markdown: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjN0IxRkEyIiBkPSJNNSAxNC45aDEybC02LjEgNnptOS40LTYuOGMwLTEuMy0uMS0yLjktLjEtNC41LS40IDEuNC0uOSAyLjktMS4zIDQuM2wtMS4zIDQuM2gtMkw4LjUgNy45Yy0uNC0xLjMtLjctMi45LTEtNC4zLS4xIDEuNi0uMSAzLjItLjIgNC42TDcgMTIuNEg0LjhsLjctMTFoMy4zTDEwIDVjLjQgMS4yLjcgMi43IDEgMy45LjMtMS4yLjctMi42IDEtMy45bDEuMi0zLjdoMy4zbC42IDExaC0yLjRsLS4zLTQuMnoiLz4KPC9zdmc+Cg==);--jp-icon-move-down: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMTIuNDcxIDcuNTI4OTlDMTIuNzYzMiA3LjIzNjg0IDEyLjc2MzIgNi43NjMxNiAxMi40NzEgNi40NzEwMVY2LjQ3MTAxQzEyLjE3OSA2LjE3OTA1IDExLjcwNTcgNi4xNzg4NCAxMS40MTM1IDYuNDcwNTRMNy43NSAxMC4xMjc1VjEuNzVDNy43NSAxLjMzNTc5IDcuNDE0MjEgMSA3IDFWMUM2LjU4NTc5IDEgNi4yNSAxLjMzNTc5IDYuMjUgMS43NVYxMC4xMjc1TDIuNTk3MjYgNi40NjgyMkMyLjMwMzM4IDYuMTczODEgMS44MjY0MSA2LjE3MzU5IDEuNTMyMjYgNi40Njc3NFY2LjQ2Nzc0QzEuMjM4MyA2Ljc2MTcgMS4yMzgzIDcuMjM4MyAxLjUzMjI2IDcuNTMyMjZMNi4yOTI4OSAxMi4yOTI5QzYuNjgzNDIgMTIuNjgzNCA3LjMxNjU4IDEyLjY4MzQgNy43MDcxMSAxMi4yOTI5TDEyLjQ3MSA3LjUyODk5WiIgZmlsbD0iIzYxNjE2MSIvPgo8L3N2Zz4K);--jp-icon-move-up: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMS41Mjg5OSA2LjQ3MTAxQzEuMjM2ODQgNi43NjMxNiAxLjIzNjg0IDcuMjM2ODQgMS41Mjg5OSA3LjUyODk5VjcuNTI4OTlDMS44MjA5NSA3LjgyMDk1IDIuMjk0MjYgNy44MjExNiAyLjU4NjQ5IDcuNTI5NDZMNi4yNSAzLjg3MjVWMTIuMjVDNi4yNSAxMi42NjQyIDYuNTg1NzkgMTMgNyAxM1YxM0M3LjQxNDIxIDEzIDcuNzUgMTIuNjY0MiA3Ljc1IDEyLjI1VjMuODcyNUwxMS40MDI3IDcuNTMxNzhDMTEuNjk2NiA3LjgyNjE5IDEyLjE3MzYgNy44MjY0MSAxMi40Njc3IDcuNTMyMjZWNy41MzIyNkMxMi43NjE3IDcuMjM4MyAxMi43NjE3IDYuNzYxNyAxMi40Njc3IDYuNDY3NzRMNy43MDcxMSAxLjcwNzExQzcuMzE2NTggMS4zMTY1OCA2LjY4MzQyIDEuMzE2NTggNi4yOTI4OSAxLjcwNzExTDEuNTI4OTkgNi40NzEwMVoiIGZpbGw9IiM2MTYxNjEiLz4KPC9zdmc+Cg==);--jp-icon-new-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwIDZoLThsLTItMkg0Yy0xLjExIDAtMS45OS44OS0xLjk5IDJMMiAxOGMwIDEuMTEuODkgMiAyIDJoMTZjMS4xMSAwIDItLjg5IDItMlY4YzAtMS4xMS0uODktMi0yLTJ6bS0xIDhoLTN2M2gtMnYtM2gtM3YtMmgzVjloMnYzaDN2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-not-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI1IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMTkgMTcuMTg0NCAyLjk2OTY4IDE0LjMwMzIgMS44NjA5NCAxMS40NDA5WiIvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24yIiBzdHJva2U9IiMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4zMTU5MiA5LjMyMDMxKSIgZD0iTTcuMzY4NDIgMEwwIDcuMzY0NzkiLz4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMzE1OTIgMTYuNjgzNikgc2NhbGUoMSAtMSkiIGQ9Ik03LjM2ODQyIDBMMCA3LjM2NDc5Ii8+Cjwvc3ZnPgo=);--jp-icon-notebook: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtbm90ZWJvb2staWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNFRjZDMDAiPgogICAgPHBhdGggZD0iTTE4LjcgMy4zdjE1LjRIMy4zVjMuM2gxNS40bTEuNS0xLjVIMS44djE4LjNoMTguM2wuMS0xOC4zeiIvPgogICAgPHBhdGggZD0iTTE2LjUgMTYuNWwtNS40LTQuMy01LjYgNC4zdi0xMWgxMXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-numbering: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTQgMTlINlYxOS41SDVWMjAuNUg2VjIxSDRWMjJIN1YxOEg0VjE5Wk01IDEwSDZWNkg0VjdINVYxMFpNNCAxM0g1LjhMNCAxNS4xVjE2SDdWMTVINS4yTDcgMTIuOVYxMkg0VjEzWk05IDdWOUgyM1Y3SDlaTTkgMjFIMjNWMTlIOVYyMVpNOSAxNUgyM1YxM0g5VjE1WiIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-offline-bolt: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDIuMDJjLTUuNTEgMC05Ljk4IDQuNDctOS45OCA5Ljk4czQuNDcgOS45OCA5Ljk4IDkuOTggOS45OC00LjQ3IDkuOTgtOS45OFMxNy41MSAyLjAyIDEyIDIuMDJ6TTExLjQ4IDIwdi02LjI2SDhMMTMgNHY2LjI2aDMuMzVMMTEuNDggMjB6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-palette: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE4IDEzVjIwSDRWNkg5LjAyQzkuMDcgNS4yOSA5LjI0IDQuNjIgOS41IDRINEMyLjkgNCAyIDQuOSAyIDZWMjBDMiAyMS4xIDIuOSAyMiA0IDIySDE4QzE5LjEgMjIgMjAgMjEuMSAyMCAyMFYxNUwxOCAxM1pNMTkuMyA4Ljg5QzE5Ljc0IDguMTkgMjAgNy4zOCAyMCA2LjVDMjAgNC4wMSAxNy45OSAyIDE1LjUgMkMxMy4wMSAyIDExIDQuMDEgMTEgNi41QzExIDguOTkgMTMuMDEgMTEgMTUuNDkgMTFDMTYuMzcgMTEgMTcuMTkgMTAuNzQgMTcuODggMTAuM0wyMSAxMy40MkwyMi40MiAxMkwxOS4zIDguODlaTTE1LjUgOUMxNC4xMiA5IDEzIDcuODggMTMgNi41QzEzIDUuMTIgMTQuMTIgNCAxNS41IDRDMTYuODggNCAxOCA1LjEyIDE4IDYuNUMxOCA3Ljg4IDE2Ljg4IDkgMTUuNSA5WiIvPgogICAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDZIOS4wMTg5NEM5LjAwNjM5IDYuMTY1MDIgOSA2LjMzMTc2IDkgNi41QzkgOC44MTU3NyAxMC4yMTEgMTAuODQ4NyAxMi4wMzQzIDEySDlWMTRIMTZWMTIuOTgxMUMxNi41NzAzIDEyLjkzNzcgMTcuMTIgMTIuODIwNyAxNy42Mzk2IDEyLjYzOTZMMTggMTNWMjBINFY2Wk04IDhINlYxMEg4VjhaTTYgMTJIOFYxNEg2VjEyWk04IDE2SDZWMThIOFYxNlpNOSAxNkgxNlYxOEg5VjE2WiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-paste: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE5IDJoLTQuMThDMTQuNC44NCAxMy4zIDAgMTIgMGMtMS4zIDAtMi40Ljg0LTIuODIgMkg1Yy0xLjEgMC0yIC45LTIgMnYxNmMwIDEuMS45IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6bS03IDBjLjU1IDAgMSAuNDUgMSAxcy0uNDUgMS0xIDEtMS0uNDUtMS0xIC40NS0xIDEtMXptNyAxOEg1VjRoMnYzaDEwVjRoMnYxNnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);--jp-icon-pdf: url(data:image/svg+xml;base64,PHN2ZwogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMiAyMiIgd2lkdGg9IjE2Ij4KICAgIDxwYXRoIHRyYW5zZm9ybT0icm90YXRlKDQ1KSIgY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0ZGMkEyQSIKICAgICAgIGQ9Im0gMjIuMzQ0MzY5LC0zLjAxNjM2NDIgaCA1LjYzODYwNCB2IDEuNTc5MjQzMyBoIC0zLjU0OTIyNyB2IDEuNTA4NjkyOTkgaCAzLjMzNzU3NiBWIDEuNjUwODE1NCBoIC0zLjMzNzU3NiB2IDMuNDM1MjYxMyBoIC0yLjA4OTM3NyB6IG0gLTcuMTM2NDQ0LDEuNTc5MjQzMyB2IDQuOTQzOTU0MyBoIDAuNzQ4OTIgcSAxLjI4MDc2MSwwIDEuOTUzNzAzLC0wLjYzNDk1MzUgMC42NzgzNjksLTAuNjM0OTUzNSAwLjY3ODM2OSwtMS44NDUxNjQxIDAsLTEuMjA0NzgzNTUgLTAuNjcyOTQyLC0xLjgzNDMxMDExIC0wLjY3Mjk0MiwtMC42Mjk1MjY1OSAtMS45NTkxMywtMC42Mjk1MjY1OSB6IG0gLTIuMDg5Mzc3LC0xLjU3OTI0MzMgaCAyLjIwMzM0MyBxIDEuODQ1MTY0LDAgMi43NDYwMzksMC4yNjU5MjA3IDAuOTA2MzAxLDAuMjYwNDkzNyAxLjU1MjEwOCwwLjg5MDAyMDMgMC41Njk4MywwLjU0ODEyMjMgMC44NDY2MDUsMS4yNjQ0ODAwNiAwLjI3Njc3NCwwLjcxNjM1NzgxIDAuMjc2Nzc0LDEuNjIyNjU4OTQgMCwwLjkxNzE1NTEgLTAuMjc2Nzc0LDEuNjM4OTM5OSAtMC4yNzY3NzUsMC43MTYzNTc4IC0wLjg0NjYwNSwxLjI2NDQ4IC0wLjY1MTIzNCwwLjYyOTUyNjYgLTEuNTYyOTYyLDAuODk1NDQ3MyAtMC45MTE3MjgsMC4yNjA0OTM3IC0yLjczNTE4NSwwLjI2MDQ5MzcgaCAtMi4yMDMzNDMgeiBtIC04LjE0NTg1NjUsMCBoIDMuNDY3ODIzIHEgMS41NDY2ODE2LDAgMi4zNzE1Nzg1LDAuNjg5MjIzIDAuODMwMzI0LDAuNjgzNzk2MSAwLjgzMDMyNCwxLjk1MzcwMzE0IDAsMS4yNzUzMzM5NyAtMC44MzAzMjQsMS45NjQ1NTcwNiBRIDkuOTg3MTk2MSwyLjI3NDkxNSA4LjQ0MDUxNDUsMi4yNzQ5MTUgSCA3LjA2MjA2ODQgViA1LjA4NjA3NjcgSCA0Ljk3MjY5MTUgWiBtIDIuMDg5Mzc2OSwxLjUxNDExOTkgdiAyLjI2MzAzOTQzIGggMS4xNTU5NDEgcSAwLjYwNzgxODgsMCAwLjkzODg2MjksLTAuMjkzMDU1NDcgMC4zMzEwNDQxLC0wLjI5ODQ4MjQxIDAuMzMxMDQ0MSwtMC44NDExNzc3MiAwLC0wLjU0MjY5NTMxIC0wLjMzMTA0NDEsLTAuODM1NzUwNzQgLTAuMzMxMDQ0MSwtMC4yOTMwNTU1IC0wLjkzODg2MjksLTAuMjkzMDU1NSB6IgovPgo8L3N2Zz4K);--jp-icon-python: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iLTEwIC0xMCAxMzEuMTYxMzYxNjk0MzM1OTQgMTMyLjM4ODk5OTkzODk2NDg0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzA2OTk4IiBkPSJNIDU0LjkxODc4NSw5LjE5Mjc0MjFlLTQgQyA1MC4zMzUxMzIsMC4wMjIyMTcyNyA0NS45NTc4NDYsMC40MTMxMzY5NyA0Mi4xMDYyODUsMS4wOTQ2NjkzIDMwLjc2MDA2OSwzLjA5OTE3MzEgMjguNzAwMDM2LDcuMjk0NzcxNCAyOC43MDAwMzUsMTUuMDMyMTY5IHYgMTAuMjE4NzUgaCAyNi44MTI1IHYgMy40MDYyNSBoIC0yNi44MTI1IC0xMC4wNjI1IGMgLTcuNzkyNDU5LDAgLTE0LjYxNTc1ODgsNC42ODM3MTcgLTE2Ljc0OTk5OTgsMTMuNTkzNzUgLTIuNDYxODE5OTgsMTAuMjEyOTY2IC0yLjU3MTAxNTA4LDE2LjU4NjAyMyAwLDI3LjI1IDEuOTA1OTI4Myw3LjkzNzg1MiA2LjQ1NzU0MzIsMTMuNTkzNzQ4IDE0LjI0OTk5OTgsMTMuNTkzNzUgaCA5LjIxODc1IHYgLTEyLjI1IGMgMCwtOC44NDk5MDIgNy42NTcxNDQsLTE2LjY1NjI0OCAxNi43NSwtMTYuNjU2MjUgaCAyNi43ODEyNSBjIDcuNDU0OTUxLDAgMTMuNDA2MjUzLC02LjEzODE2NCAxMy40MDYyNSwtMTMuNjI1IHYgLTI1LjUzMTI1IGMgMCwtNy4yNjYzMzg2IC02LjEyOTk4LC0xMi43MjQ3NzcxIC0xMy40MDYyNSwtMTMuOTM3NDk5NyBDIDY0LjI4MTU0OCwwLjMyNzk0Mzk3IDU5LjUwMjQzOCwtMC4wMjAzNzkwMyA1NC45MTg3ODUsOS4xOTI3NDIxZS00IFogbSAtMTQuNSw4LjIxODc1MDEyNTc5IGMgMi43Njk1NDcsMCA1LjAzMTI1LDIuMjk4NjQ1NiA1LjAzMTI1LDUuMTI0OTk5NiAtMmUtNiwyLjgxNjMzNiAtMi4yNjE3MDMsNS4wOTM3NSAtNS4wMzEyNSw1LjA5Mzc1IC0yLjc3OTQ3NiwtMWUtNiAtNS4wMzEyNSwtMi4yNzc0MTUgLTUuMDMxMjUsLTUuMDkzNzUgLTEwZS03LC0yLjgyNjM1MyAyLjI1MTc3NCwtNS4xMjQ5OTk2IDUuMDMxMjUsLTUuMTI0OTk5NiB6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2ZmZDQzYiIgZD0ibSA4NS42Mzc1MzUsMjguNjU3MTY5IHYgMTEuOTA2MjUgYyAwLDkuMjMwNzU1IC03LjgyNTg5NSwxNi45OTk5OTkgLTE2Ljc1LDE3IGggLTI2Ljc4MTI1IGMgLTcuMzM1ODMzLDAgLTEzLjQwNjI0OSw2LjI3ODQ4MyAtMTMuNDA2MjUsMTMuNjI1IHYgMjUuNTMxMjQ3IGMgMCw3LjI2NjM0NCA2LjMxODU4OCwxMS41NDAzMjQgMTMuNDA2MjUsMTMuNjI1MDA0IDguNDg3MzMxLDIuNDk1NjEgMTYuNjI2MjM3LDIuOTQ2NjMgMjYuNzgxMjUsMCA2Ljc1MDE1NSwtMS45NTQzOSAxMy40MDYyNTMsLTUuODg3NjEgMTMuNDA2MjUsLTEzLjYyNTAwNCBWIDg2LjUwMDkxOSBoIC0yNi43ODEyNSB2IC0zLjQwNjI1IGggMjYuNzgxMjUgMTMuNDA2MjU0IGMgNy43OTI0NjEsMCAxMC42OTYyNTEsLTUuNDM1NDA4IDEzLjQwNjI0MSwtMTMuNTkzNzUgMi43OTkzMywtOC4zOTg4ODYgMi42ODAyMiwtMTYuNDc1Nzc2IDAsLTI3LjI1IC0xLjkyNTc4LC03Ljc1NzQ0MSAtNS42MDM4NywtMTMuNTkzNzUgLTEzLjQwNjI0MSwtMTMuNTkzNzUgeiBtIC0xNS4wNjI1LDY0LjY1NjI1IGMgMi43Nzk0NzgsM2UtNiA1LjAzMTI1LDIuMjc3NDE3IDUuMDMxMjUsNS4wOTM3NDcgLTJlLTYsMi44MjYzNTQgLTIuMjUxNzc1LDUuMTI1MDA0IC01LjAzMTI1LDUuMTI1MDA0IC0yLjc2OTU1LDAgLTUuMDMxMjUsLTIuMjk4NjUgLTUuMDMxMjUsLTUuMTI1MDA0IDJlLTYsLTIuODE2MzMgMi4yNjE2OTcsLTUuMDkzNzQ3IDUuMDMxMjUsLTUuMDkzNzQ3IHoiLz4KPC9zdmc+Cg==);--jp-icon-r-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjE5NkYzIiBkPSJNNC40IDIuNWMxLjItLjEgMi45LS4zIDQuOS0uMyAyLjUgMCA0LjEuNCA1LjIgMS4zIDEgLjcgMS41IDEuOSAxLjUgMy41IDAgMi0xLjQgMy41LTIuOSA0LjEgMS4yLjQgMS43IDEuNiAyLjIgMyAuNiAxLjkgMSAzLjkgMS4zIDQuNmgtMy44Yy0uMy0uNC0uOC0xLjctMS4yLTMuN3MtMS4yLTIuNi0yLjYtMi42aC0uOXY2LjRINC40VjIuNXptMy43IDYuOWgxLjRjMS45IDAgMi45LS45IDIuOS0yLjNzLTEtMi4zLTIuOC0yLjNjLS43IDAtMS4zIDAtMS42LjJ2NC41aC4xdi0uMXoiLz4KPC9zdmc+Cg==);--jp-icon-react: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMTUwIDE1MCA1NDEuOSAyOTUuMyI+CiAgPGcgY2xhc3M9ImpwLWljb24tYnJhbmQyIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxREFGQiI+CiAgICA8cGF0aCBkPSJNNjY2LjMgMjk2LjVjMC0zMi41LTQwLjctNjMuMy0xMDMuMS04Mi40IDE0LjQtNjMuNiA4LTExNC4yLTIwLjItMTMwLjQtNi41LTMuOC0xNC4xLTUuNi0yMi40LTUuNnYyMi4zYzQuNiAwIDguMy45IDExLjQgMi42IDEzLjYgNy44IDE5LjUgMzcuNSAxNC45IDc1LjctMS4xIDkuNC0yLjkgMTkuMy01LjEgMjkuNC0xOS42LTQuOC00MS04LjUtNjMuNS0xMC45LTEzLjUtMTguNS0yNy41LTM1LjMtNDEuNi01MCAzMi42LTMwLjMgNjMuMi00Ni45IDg0LTQ2LjlWNzhjLTI3LjUgMC02My41IDE5LjYtOTkuOSA1My42LTM2LjQtMzMuOC03Mi40LTUzLjItOTkuOS01My4ydjIyLjNjMjAuNyAwIDUxLjQgMTYuNSA4NCA0Ni42LTE0IDE0LjctMjggMzEuNC00MS4zIDQ5LjktMjIuNiAyLjQtNDQgNi4xLTYzLjYgMTEtMi4zLTEwLTQtMTkuNy01LjItMjktNC43LTM4LjIgMS4xLTY3LjkgMTQuNi03NS44IDMtMS44IDYuOS0yLjYgMTEuNS0yLjZWNzguNWMtOC40IDAtMTYgMS44LTIyLjYgNS42LTI4LjEgMTYuMi0zNC40IDY2LjctMTkuOSAxMzAuMS02Mi4yIDE5LjItMTAyLjcgNDkuOS0xMDIuNyA4Mi4zIDAgMzIuNSA0MC43IDYzLjMgMTAzLjEgODIuNC0xNC40IDYzLjYtOCAxMTQuMiAyMC4yIDEzMC40IDYuNSAzLjggMTQuMSA1LjYgMjIuNSA1LjYgMjcuNSAwIDYzLjUtMTkuNiA5OS45LTUzLjYgMzYuNCAzMy44IDcyLjQgNTMuMiA5OS45IDUzLjIgOC40IDAgMTYtMS44IDIyLjYtNS42IDI4LjEtMTYuMiAzNC40LTY2LjcgMTkuOS0xMzAuMSA2Mi0xOS4xIDEwMi41LTQ5LjkgMTAyLjUtODIuM3ptLTEzMC4yLTY2LjdjLTMuNyAxMi45LTguMyAyNi4yLTEzLjUgMzkuNS00LjEtOC04LjQtMTYtMTMuMS0yNC00LjYtOC05LjUtMTUuOC0xNC40LTIzLjQgMTQuMiAyLjEgMjcuOSA0LjcgNDEgNy45em0tNDUuOCAxMDYuNWMtNy44IDEzLjUtMTUuOCAyNi4zLTI0LjEgMzguMi0xNC45IDEuMy0zMCAyLTQ1LjIgMi0xNS4xIDAtMzAuMi0uNy00NS0xLjktOC4zLTExLjktMTYuNC0yNC42LTI0LjItMzgtNy42LTEzLjEtMTQuNS0yNi40LTIwLjgtMzkuOCA2LjItMTMuNCAxMy4yLTI2LjggMjAuNy0zOS45IDcuOC0xMy41IDE1LjgtMjYuMyAyNC4xLTM4LjIgMTQuOS0xLjMgMzAtMiA0NS4yLTIgMTUuMSAwIDMwLjIuNyA0NSAxLjkgOC4zIDExLjkgMTYuNCAyNC42IDI0LjIgMzggNy42IDEzLjEgMTQuNSAyNi40IDIwLjggMzkuOC02LjMgMTMuNC0xMy4yIDI2LjgtMjAuNyAzOS45em0zMi4zLTEzYzUuNCAxMy40IDEwIDI2LjggMTMuOCAzOS44LTEzLjEgMy4yLTI2LjkgNS45LTQxLjIgOCA0LjktNy43IDkuOC0xNS42IDE0LjQtMjMuNyA0LjYtOCA4LjktMTYuMSAxMy0yNC4xek00MjEuMiA0MzBjLTkuMy05LjYtMTguNi0yMC4zLTI3LjgtMzIgOSAuNCAxOC4yLjcgMjcuNS43IDkuNCAwIDE4LjctLjIgMjcuOC0uNy05IDExLjctMTguMyAyMi40LTI3LjUgMzJ6bS03NC40LTU4LjljLTE0LjItMi4xLTI3LjktNC43LTQxLTcuOSAzLjctMTIuOSA4LjMtMjYuMiAxMy41LTM5LjUgNC4xIDggOC40IDE2IDEzLjEgMjQgNC43IDggOS41IDE1LjggMTQuNCAyMy40ek00MjAuNyAxNjNjOS4zIDkuNiAxOC42IDIwLjMgMjcuOCAzMi05LS40LTE4LjItLjctMjcuNS0uNy05LjQgMC0xOC43LjItMjcuOC43IDktMTEuNyAxOC4zLTIyLjQgMjcuNS0zMnptLTc0IDU4LjljLTQuOSA3LjctOS44IDE1LjYtMTQuNCAyMy43LTQuNiA4LTguOSAxNi0xMyAyNC01LjQtMTMuNC0xMC0yNi44LTEzLjgtMzkuOCAxMy4xLTMuMSAyNi45LTUuOCA0MS4yLTcuOXptLTkwLjUgMTI1LjJjLTM1LjQtMTUuMS01OC4zLTM0LjktNTguMy01MC42IDAtMTUuNyAyMi45LTM1LjYgNTguMy01MC42IDguNi0zLjcgMTgtNyAyNy43LTEwLjEgNS43IDE5LjYgMTMuMiA0MCAyMi41IDYwLjktOS4yIDIwLjgtMTYuNiA0MS4xLTIyLjIgNjAuNi05LjktMy4xLTE5LjMtNi41LTI4LTEwLjJ6TTMxMCA0OTBjLTEzLjYtNy44LTE5LjUtMzcuNS0xNC45LTc1LjcgMS4xLTkuNCAyLjktMTkuMyA1LjEtMjkuNCAxOS42IDQuOCA0MSA4LjUgNjMuNSAxMC45IDEzLjUgMTguNSAyNy41IDM1LjMgNDEuNiA1MC0zMi42IDMwLjMtNjMuMiA0Ni45LTg0IDQ2LjktNC41LS4xLTguMy0xLTExLjMtMi43em0yMzcuMi03Ni4yYzQuNyAzOC4yLTEuMSA2Ny45LTE0LjYgNzUuOC0zIDEuOC02LjkgMi42LTExLjUgMi42LTIwLjcgMC01MS40LTE2LjUtODQtNDYuNiAxNC0xNC43IDI4LTMxLjQgNDEuMy00OS45IDIyLjYtMi40IDQ0LTYuMSA2My42LTExIDIuMyAxMC4xIDQuMSAxOS44IDUuMiAyOS4xem0zOC41LTY2LjdjLTguNiAzLjctMTggNy0yNy43IDEwLjEtNS43LTE5LjYtMTMuMi00MC0yMi41LTYwLjkgOS4yLTIwLjggMTYuNi00MS4xIDIyLjItNjAuNiA5LjkgMy4xIDE5LjMgNi41IDI4LjEgMTAuMiAzNS40IDE1LjEgNTguMyAzNC45IDU4LjMgNTAuNi0uMSAxNS43LTIzIDM1LjYtNTguNCA1MC42ek0zMjAuOCA3OC40eiIvPgogICAgPGNpcmNsZSBjeD0iNDIwLjkiIGN5PSIyOTYuNSIgcj0iNDUuNyIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-redo: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTE4LjQgMTAuNkMxNi41NSA4Ljk5IDE0LjE1IDggMTEuNSA4Yy00LjY1IDAtOC41OCAzLjAzLTkuOTYgNy4yMkwzLjkgMTZjMS4wNS0zLjE5IDQuMDUtNS41IDcuNi01LjUgMS45NSAwIDMuNzMuNzIgNS4xMiAxLjg4TDEzIDE2aDlWN2wtMy42IDMuNnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-refresh: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTkgMTMuNWMtMi40OSAwLTQuNS0yLjAxLTQuNS00LjVTNi41MSA0LjUgOSA0LjVjMS4yNCAwIDIuMzYuNTIgMy4xNyAxLjMzTDEwIDhoNVYzbC0xLjc2IDEuNzZDMTIuMTUgMy42OCAxMC42NiAzIDkgMyA1LjY5IDMgMy4wMSA1LjY5IDMuMDEgOVM1LjY5IDE1IDkgMTVjMi45NyAwIDUuNDMtMi4xNiA1LjktNWgtMS41MmMtLjQ2IDItMi4yNCAzLjUtNC4zOCAzLjV6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-regex: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi1hY2NlbnQyIiBmaWxsPSIjRkZGIj4KICAgIDxjaXJjbGUgY2xhc3M9InN0MiIgY3g9IjUuNSIgY3k9IjE0LjUiIHI9IjEuNSIvPgogICAgPHJlY3QgeD0iMTIiIHk9IjQiIGNsYXNzPSJzdDIiIHdpZHRoPSIxIiBoZWlnaHQ9IjgiLz4KICAgIDxyZWN0IHg9IjguNSIgeT0iNy41IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjg2NiAtMC41IDAuNSAwLjg2NiAtMi4zMjU1IDcuMzIxOSkiIGNsYXNzPSJzdDIiIHdpZHRoPSI4IiBoZWlnaHQ9IjEiLz4KICAgIDxyZWN0IHg9IjEyIiB5PSI0IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjUgLTAuODY2IDAuODY2IDAuNSAtMC42Nzc5IDE0LjgyNTIpIiBjbGFzcz0ic3QyIiB3aWR0aD0iMSIgaGVpZ2h0PSI4Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-run: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTggNXYxNGwxMS03eiIvPgogICAgPC9nPgo8L3N2Zz4K);--jp-icon-running: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMjU2IDhDMTE5IDggOCAxMTkgOCAyNTZzMTExIDI0OCAyNDggMjQ4IDI0OC0xMTEgMjQ4LTI0OFMzOTMgOCAyNTYgOHptOTYgMzI4YzAgOC44LTcuMiAxNi0xNiAxNkgxNzZjLTguOCAwLTE2LTcuMi0xNi0xNlYxNzZjMC04LjggNy4yLTE2IDE2LTE2aDE2MGM4LjggMCAxNiA3LjIgMTYgMTZ2MTYweiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-save: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE3IDNINWMtMS4xMSAwLTIgLjktMiAydjE0YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjdsLTQtNHptLTUgMTZjLTEuNjYgMC0zLTEuMzQtMy0zczEuMzQtMyAzLTMgMyAxLjM0IDMgMy0xLjM0IDMtMyAzem0zLTEwSDVWNWgxMHY0eiIvPgogICAgPC9nPgo8L3N2Zz4K);--jp-icon-search: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjEsMTAuOWgtMC43bC0wLjItMC4yYzAuOC0wLjksMS4zLTIuMiwxLjMtMy41YzAtMy0yLjQtNS40LTUuNC01LjRTMS44LDQuMiwxLjgsNy4xczIuNCw1LjQsNS40LDUuNCBjMS4zLDAsMi41LTAuNSwzLjUtMS4zbDAuMiwwLjJ2MC43bDQuMSw0LjFsMS4yLTEuMkwxMi4xLDEwLjl6IE03LjEsMTAuOWMtMi4xLDAtMy43LTEuNy0zLjctMy43czEuNy0zLjcsMy43LTMuN3MzLjcsMS43LDMuNywzLjcgUzkuMiwxMC45LDcuMSwxMC45eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-settings: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuNDMgMTIuOThjLjA0LS4zMi4wNy0uNjQuMDctLjk4cy0uMDMtLjY2LS4wNy0uOThsMi4xMS0xLjY1Yy4xOS0uMTUuMjQtLjQyLjEyLS42NGwtMi0zLjQ2Yy0uMTItLjIyLS4zOS0uMy0uNjEtLjIybC0yLjQ5IDFjLS41Mi0uNC0xLjA4LS43My0xLjY5LS45OGwtLjM4LTIuNjVBLjQ4OC40ODggMCAwMDE0IDJoLTRjLS4yNSAwLS40Ni4xOC0uNDkuNDJsLS4zOCAyLjY1Yy0uNjEuMjUtMS4xNy41OS0xLjY5Ljk4bC0yLjQ5LTFjLS4yMy0uMDktLjQ5IDAtLjYxLjIybC0yIDMuNDZjLS4xMy4yMi0uMDcuNDkuMTIuNjRsMi4xMSAxLjY1Yy0uMDQuMzItLjA3LjY1LS4wNy45OHMuMDMuNjYuMDcuOThsLTIuMTEgMS42NWMtLjE5LjE1LS4yNC40Mi0uMTIuNjRsMiAzLjQ2Yy4xMi4yMi4zOS4zLjYxLjIybDIuNDktMWMuNTIuNCAxLjA4LjczIDEuNjkuOThsLjM4IDIuNjVjLjAzLjI0LjI0LjQyLjQ5LjQyaDRjLjI1IDAgLjQ2LS4xOC40OS0uNDJsLjM4LTIuNjVjLjYxLS4yNSAxLjE3LS41OSAxLjY5LS45OGwyLjQ5IDFjLjIzLjA5LjQ5IDAgLjYxLS4yMmwyLTMuNDZjLjEyLS4yMi4wNy0uNDktLjEyLS42NGwtMi4xMS0xLjY1ek0xMiAxNS41Yy0xLjkzIDAtMy41LTEuNTctMy41LTMuNXMxLjU3LTMuNSAzLjUtMy41IDMuNSAxLjU3IDMuNSAzLjUtMS41NyAzLjUtMy41IDMuNXoiLz4KPC9zdmc+Cg==);--jp-icon-share: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTSAxOCAyIEMgMTYuMzU0OTkgMiAxNSAzLjM1NDk5MDQgMTUgNSBDIDE1IDUuMTkwOTUyOSAxNS4wMjE3OTEgNS4zNzcxMjI0IDE1LjA1NjY0MSA1LjU1ODU5MzggTCA3LjkyMTg3NSA5LjcyMDcwMzEgQyA3LjM5ODUzOTkgOS4yNzc4NTM5IDYuNzMyMDc3MSA5IDYgOSBDIDQuMzU0OTkwNCA5IDMgMTAuMzU0OTkgMyAxMiBDIDMgMTMuNjQ1MDEgNC4zNTQ5OTA0IDE1IDYgMTUgQyA2LjczMjA3NzEgMTUgNy4zOTg1Mzk5IDE0LjcyMjE0NiA3LjkyMTg3NSAxNC4yNzkyOTcgTCAxNS4wNTY2NDEgMTguNDM5NDUzIEMgMTUuMDIxNTU1IDE4LjYyMTUxNCAxNSAxOC44MDgzODYgMTUgMTkgQyAxNSAyMC42NDUwMSAxNi4zNTQ5OSAyMiAxOCAyMiBDIDE5LjY0NTAxIDIyIDIxIDIwLjY0NTAxIDIxIDE5IEMgMjEgMTcuMzU0OTkgMTkuNjQ1MDEgMTYgMTggMTYgQyAxNy4yNjc0OCAxNiAxNi42MDE1OTMgMTYuMjc5MzI4IDE2LjA3ODEyNSAxNi43MjI2NTYgTCA4Ljk0MzM1OTQgMTIuNTU4NTk0IEMgOC45NzgyMDk1IDEyLjM3NzEyMiA5IDEyLjE5MDk1MyA5IDEyIEMgOSAxMS44MDkwNDcgOC45NzgyMDk1IDExLjYyMjg3OCA4Ljk0MzM1OTQgMTEuNDQxNDA2IEwgMTYuMDc4MTI1IDcuMjc5Mjk2OSBDIDE2LjYwMTQ2IDcuNzIyMTQ2MSAxNy4yNjc5MjMgOCAxOCA4IEMgMTkuNjQ1MDEgOCAyMSA2LjY0NTAwOTYgMjEgNSBDIDIxIDMuMzU0OTkwNCAxOS42NDUwMSAyIDE4IDIgeiBNIDE4IDQgQyAxOC41NjQxMjkgNCAxOSA0LjQzNTg3MDYgMTkgNSBDIDE5IDUuNTY0MTI5NCAxOC41NjQxMjkgNiAxOCA2IEMgMTcuNDM1ODcxIDYgMTcgNS41NjQxMjk0IDE3IDUgQyAxNyA0LjQzNTg3MDYgMTcuNDM1ODcxIDQgMTggNCB6IE0gNiAxMSBDIDYuNTY0MTI5NCAxMSA3IDExLjQzNTg3MSA3IDEyIEMgNyAxMi41NjQxMjkgNi41NjQxMjk0IDEzIDYgMTMgQyA1LjQzNTg3MDYgMTMgNSAxMi41NjQxMjkgNSAxMiBDIDUgMTEuNDM1ODcxIDUuNDM1ODcwNiAxMSA2IDExIHogTSAxOCAxOCBDIDE4LjU2NDEyOSAxOCAxOSAxOC40MzU4NzEgMTkgMTkgQyAxOSAxOS41NjQxMjkgMTguNTY0MTI5IDIwIDE4IDIwIEMgMTcuNDM1ODcxIDIwIDE3IDE5LjU2NDEyOSAxNyAxOSBDIDE3IDE4LjQzNTg3MSAxNy40MzU4NzEgMTggMTggMTggeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-spreadsheet: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNENBRjUwIiBkPSJNMi4yIDIuMnYxNy42aDE3LjZWMi4ySDIuMnptMTUuNCA3LjdoLTUuNVY0LjRoNS41djUuNXpNOS45IDQuNHY1LjVINC40VjQuNGg1LjV6bS01LjUgNy43aDUuNXY1LjVINC40di01LjV6bTcuNyA1LjV2LTUuNWg1LjV2NS41aC01LjV6Ii8+Cjwvc3ZnPgo=);--jp-icon-stop: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik02IDZoMTJ2MTJINnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);--jp-icon-tab: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIxIDNIM2MtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxOGMxLjEgMCAyLS45IDItMlY1YzAtMS4xLS45LTItMi0yem0wIDE2SDNWNWgxMHY0aDh2MTB6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-table-rows: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMSw4SDNWNGgxOFY4eiBNMjEsMTBIM3Y0aDE4VjEweiBNMjEsMTZIM3Y0aDE4VjE2eiIvPgogICAgPC9nPgo8L3N2Zz4=);--jp-icon-tag: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCA0MyAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTI4LjgzMzIgMTIuMzM0TDMyLjk5OTggMTYuNTAwN0wzNy4xNjY1IDEyLjMzNEgyOC44MzMyWiIvPgoJCTxwYXRoIGQ9Ik0xNi4yMDk1IDIxLjYxMDRDMTUuNjg3MyAyMi4xMjk5IDE0Ljg0NDMgMjIuMTI5OSAxNC4zMjQ4IDIxLjYxMDRMNi45ODI5IDE0LjcyNDVDNi41NzI0IDE0LjMzOTQgNi4wODMxMyAxMy42MDk4IDYuMDQ3ODYgMTMuMDQ4MkM1Ljk1MzQ3IDExLjUyODggNi4wMjAwMiA4LjYxOTQ0IDYuMDY2MjEgNy4wNzY5NUM2LjA4MjgxIDYuNTE0NzcgNi41NTU0OCA2LjA0MzQ3IDcuMTE4MDQgNi4wMzA1NUM5LjA4ODYzIDUuOTg0NzMgMTMuMjYzOCA1LjkzNTc5IDEzLjY1MTggNi4zMjQyNUwyMS43MzY5IDEzLjYzOUMyMi4yNTYgMTQuMTU4NSAyMS43ODUxIDE1LjQ3MjQgMjEuMjYyIDE1Ljk5NDZMMTYuMjA5NSAyMS42MTA0Wk05Ljc3NTg1IDguMjY1QzkuMzM1NTEgNy44MjU2NiA4LjYyMzUxIDcuODI1NjYgOC4xODI4IDguMjY1QzcuNzQzNDYgOC43MDU3MSA3Ljc0MzQ2IDkuNDE3MzMgOC4xODI4IDkuODU2NjdDOC42MjM4MiAxMC4yOTY0IDkuMzM1ODIgMTAuMjk2NCA5Ljc3NTg1IDkuODU2NjdDMTAuMjE1NiA5LjQxNzMzIDEwLjIxNTYgOC43MDUzMyA5Ljc3NTg1IDguMjY1WiIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-terminal: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiA+CiAgICA8cmVjdCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1iYWNrZ3JvdW5kLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyIDIpIiBmaWxsPSIjMzMzMzMzIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUtaW52ZXJzZSIgZD0iTTUuMDU2NjQgOC43NjE3MkM1LjA1NjY0IDguNTk3NjYgNS4wMzEyNSA4LjQ1MzEyIDQuOTgwNDcgOC4zMjgxMkM0LjkzMzU5IDguMTk5MjIgNC44NTU0NyA4LjA4MjAzIDQuNzQ2MDkgNy45NzY1NkM0LjY0MDYyIDcuODcxMDkgNC41IDcuNzc1MzkgNC4zMjQyMiA3LjY4OTQ1QzQuMTUyMzQgNy41OTk2MSAzLjk0MzM2IDcuNTExNzIgMy42OTcyNyA3LjQyNTc4QzMuMzAyNzMgNy4yODUxNiAyLjk0MzM2IDcuMTM2NzIgMi42MTkxNCA2Ljk4MDQ3QzIuMjk0OTIgNi44MjQyMiAyLjAxNzU4IDYuNjQyNTggMS43ODcxMSA2LjQzNTU1QzEuNTYwNTUgNi4yMjg1MiAxLjM4NDc3IDUuOTg4MjggMS4yNTk3NyA1LjcxNDg0QzEuMTM0NzcgNS40Mzc1IDEuMDcyMjcgNS4xMDkzOCAxLjA3MjI3IDQuNzMwNDdDMS4wNzIyNyA0LjM5ODQ0IDEuMTI4OTEgNC4wOTU3IDEuMjQyMTkgMy44MjIyN0MxLjM1NTQ3IDMuNTQ0OTIgMS41MTU2MiAzLjMwNDY5IDEuNzIyNjYgMy4xMDE1NkMxLjkyOTY5IDIuODk4NDQgMi4xNzk2OSAyLjczNDM3IDIuNDcyNjYgMi42MDkzOEMyLjc2NTYyIDIuNDg0MzggMy4wOTE4IDIuNDA0MyAzLjQ1MTE3IDIuMzY5MTRWMS4xMDkzOEg0LjM4ODY3VjIuMzgwODZDNC43NDAyMyAyLjQyNzczIDUuMDU2NjQgMi41MjM0NCA1LjMzNzg5IDIuNjY3OTdDNS42MTkxNCAyLjgxMjUgNS44NTc0MiAzLjAwMTk1IDYuMDUyNzMgMy4yMzYzM0M2LjI1MTk1IDMuNDY2OCA2LjQwNDMgMy43NDAyMyA2LjUwOTc3IDQuMDU2NjRDNi42MTkxNCA0LjM2OTE0IDYuNjczODMgNC43MjA3IDYuNjczODMgNS4xMTEzM0g1LjA0NDkyQzUuMDQ0OTIgNC42Mzg2NyA0LjkzNzUgNC4yODEyNSA0LjcyMjY2IDQuMDM5MDZDNC41MDc4MSAzLjc5Mjk3IDQuMjE2OCAzLjY2OTkyIDMuODQ5NjEgMy42Njk5MkMzLjY1MDM5IDMuNjY5OTIgMy40NzY1NiAzLjY5NzI3IDMuMzI4MTIgMy43NTE5NUMzLjE4MzU5IDMuODAyNzMgMy4wNjQ0NSAzLjg3Njk1IDIuOTcwNyAzLjk3NDYxQzIuODc2OTUgNC4wNjgzNiAyLjgwNjY0IDQuMTc5NjkgMi43NTk3NyA0LjMwODU5QzIuNzE2OCA0LjQzNzUgMi42OTUzMSA0LjU3ODEyIDIuNjk1MzEgNC43MzA0N0MyLjY5NTMxIDQuODgyODEgMi43MTY4IDUuMDE5NTMgMi43NTk3NyA1LjE0MDYyQzIuODA2NjQgNS4yNTc4MSAyLjg4MjgxIDUuMzY3MTkgMi45ODgyOCA1LjQ2ODc1QzMuMDk3NjYgNS41NzAzMSAzLjI0MDIzIDUuNjY3OTcgMy40MTYwMiA1Ljc2MTcyQzMuNTkxOCA1Ljg1MTU2IDMuODEwNTUgNS45NDMzNiA0LjA3MjI3IDYuMDM3MTFDNC40NjY4IDYuMTg1NTUgNC44MjQyMiA2LjMzOTg0IDUuMTQ0NTMgNi41QzUuNDY0ODQgNi42NTYyNSA1LjczODI4IDYuODM5ODQgNS45NjQ4NCA3LjA1MDc4QzYuMTk1MzEgNy4yNTc4MSA2LjM3MTA5IDcuNSA2LjQ5MjE5IDcuNzc3MzRDNi42MTcxOSA4LjA1MDc4IDYuNjc5NjkgOC4zNzUgNi42Nzk2OSA4Ljc1QzYuNjc5NjkgOS4wOTM3NSA2LjYyMzA1IDkuNDA0MyA2LjUwOTc3IDkuNjgxNjRDNi4zOTY0OCA5Ljk1NTA4IDYuMjM0MzggMTAuMTkxNCA2LjAyMzQ0IDEwLjM5MDZDNS44MTI1IDEwLjU4OTggNS41NTg1OSAxMC43NSA1LjI2MTcyIDEwLjg3MTFDNC45NjQ4NCAxMC45ODgzIDQuNjMyODEgMTEuMDY0NSA0LjI2NTYyIDExLjA5OTZWMTIuMjQ4SDMuMzMzOThWMTEuMDk5NkMzLjAwMTk1IDExLjA2ODQgMi42Nzk2OSAxMC45OTYxIDIuMzY3MTkgMTAuODgyOEMyLjA1NDY5IDEwLjc2NTYgMS43NzczNCAxMC41OTc3IDEuNTM1MTYgMTAuMzc4OUMxLjI5Njg4IDEwLjE2MDIgMS4xMDU0NyA5Ljg4NDc3IDAuOTYwOTM4IDkuNTUyNzNDMC44MTY0MDYgOS4yMTY4IDAuNzQ0MTQxIDguODE0NDUgMC43NDQxNDEgOC4zNDU3SDIuMzc4OTFDMi4zNzg5MSA4LjYyNjk1IDIuNDE5OTIgOC44NjMyOCAyLjUwMTk1IDkuMDU0NjlDMi41ODM5OCA5LjI0MjE5IDIuNjg5NDUgOS4zOTI1OCAyLjgxODM2IDkuNTA1ODZDMi45NTExNyA5LjYxNTIzIDMuMTAxNTYgOS42OTMzNiAzLjI2OTUzIDkuNzQwMjNDMy40Mzc1IDkuNzg3MTEgMy42MDkzOCA5LjgxMDU1IDMuNzg1MTYgOS44MTA1NUM0LjIwMzEyIDkuODEwNTUgNC41MTk1MyA5LjcxMjg5IDQuNzM0MzggOS41MTc1OEM0Ljk0OTIyIDkuMzIyMjcgNS4wNTY2NCA5LjA3MDMxIDUuMDU2NjQgOC43NjE3MlpNMTMuNDE4IDEyLjI3MTVIOC4wNzQyMlYxMUgxMy40MThWMTIuMjcxNVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMuOTUyNjQgNikiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=);--jp-icon-text-editor: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtdGV4dC1lZGl0b3ItaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xNSAxNUgzdjJoMTJ2LTJ6bTAtOEgzdjJoMTJWN3pNMyAxM2gxOHYtMkgzdjJ6bTAgOGgxOHYtMkgzdjJ6TTMgM3YyaDE4VjNIM3oiLz4KPC9zdmc+Cg==);--jp-icon-toc: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik03LDVIMjFWN0g3VjVNNywxM1YxMUgyMVYxM0g3TTQsNC41QTEuNSwxLjUgMCAwLDEgNS41LDZBMS41LDEuNSAwIDAsMSA0LDcuNUExLjUsMS41IDAgMCwxIDIuNSw2QTEuNSwxLjUgMCAwLDEgNCw0LjVNNCwxMC41QTEuNSwxLjUgMCAwLDEgNS41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMy41QTEuNSwxLjUgMCAwLDEgMi41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMC41TTcsMTlWMTdIMjFWMTlIN000LDE2LjVBMS41LDEuNSAwIDAsMSA1LjUsMThBMS41LDEuNSAwIDAsMSA0LDE5LjVBMS41LDEuNSAwIDAsMSAyLjUsMThBMS41LDEuNSAwIDAsMSA0LDE2LjVaIiAvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-tree-view: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMiAxMVYzaC03djNIOVYzSDJ2OGg3VjhoMnYxMGg0djNoN3YtOGgtN3YzaC0yVjhoMnYzeiIvPgogICAgPC9nPgo8L3N2Zz4=);--jp-icon-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMiAxNy4xODQ0IDIuOTY5NjggMTQuMzAzMiAxLjg2MDk0IDExLjQ0MDlaIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiMzMzMzMzMiIHN0cm9rZT0iIzMzMzMzMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOCA5Ljg2NzE5KSIgZD0iTTIuODYwMTUgNC44NjUzNUwwLjcyNjU0OSAyLjk5OTU5TDAgMy42MzA0NUwyLjg2MDE1IDYuMTMxNTdMOCAwLjYzMDg3Mkw3LjI3ODU3IDBMMi44NjAxNSA0Ljg2NTM1WiIvPgo8L3N2Zz4K);--jp-icon-undo: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjUgOGMtMi42NSAwLTUuMDUuOTktNi45IDIuNkwyIDd2OWg5bC0zLjYyLTMuNjJjMS4zOS0xLjE2IDMuMTYtMS44OCA1LjEyLTEuODggMy41NCAwIDYuNTUgMi4zMSA3LjYgNS41bDIuMzctLjc4QzIxLjA4IDExLjAzIDE3LjE1IDggMTIuNSA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-user: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE2IDdhNCA0IDAgMTEtOCAwIDQgNCAwIDAxOCAwek0xMiAxNGE3IDcgMCAwMC03IDdoMTRhNyA3IDAgMDAtNy03eiIvPgogIDwvZz4KPC9zdmc+);--jp-icon-users: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDM2IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogPGcgY2xhc3M9ImpwLWljb24zIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjczMjcgMCAwIDEuNzMyNyAtMy42MjgyIC4wOTk1NzcpIiBmaWxsPSIjNjE2MTYxIj4KICA8cGF0aCB0cmFuc2Zvcm09Im1hdHJpeCgxLjUsMCwwLDEuNSwwLC02KSIgZD0ibTEyLjE4NiA3LjUwOThjLTEuMDUzNSAwLTEuOTc1NyAwLjU2NjUtMi40Nzg1IDEuNDEwMiAwLjc1MDYxIDAuMzEyNzcgMS4zOTc0IDAuODI2NDggMS44NzMgMS40NzI3aDMuNDg2M2MwLTEuNTkyLTEuMjg4OS0yLjg4MjgtMi44ODA5LTIuODgyOHoiLz4KICA8cGF0aCBkPSJtMjAuNDY1IDIuMzg5NWEyLjE4ODUgMi4xODg1IDAgMCAxLTIuMTg4NCAyLjE4ODUgMi4xODg1IDIuMTg4NSAwIDAgMS0yLjE4ODUtMi4xODg1IDIuMTg4NSAyLjE4ODUgMCAwIDEgMi4xODg1LTIuMTg4NSAyLjE4ODUgMi4xODg1IDAgMCAxIDIuMTg4NCAyLjE4ODV6Ii8+CiAgPHBhdGggdHJhbnNmb3JtPSJtYXRyaXgoMS41LDAsMCwxLjUsMCwtNikiIGQ9Im0zLjU4OTggOC40MjE5Yy0xLjExMjYgMC0yLjAxMzcgMC45MDExMS0yLjAxMzcgMi4wMTM3aDIuODE0NWMwLjI2Nzk3LTAuMzczMDkgMC41OTA3LTAuNzA0MzUgMC45NTg5OC0wLjk3ODUyLTAuMzQ0MzMtMC42MTY4OC0xLjAwMzEtMS4wMzUyLTEuNzU5OC0xLjAzNTJ6Ii8+CiAgPHBhdGggZD0ibTYuOTE1NCA0LjYyM2ExLjUyOTQgMS41Mjk0IDAgMCAxLTEuNTI5NCAxLjUyOTQgMS41Mjk0IDEuNTI5NCAwIDAgMS0xLjUyOTQtMS41Mjk0IDEuNTI5NCAxLjUyOTQgMCAwIDEgMS41Mjk0LTEuNTI5NCAxLjUyOTQgMS41Mjk0IDAgMCAxIDEuNTI5NCAxLjUyOTR6Ii8+CiAgPHBhdGggZD0ibTYuMTM1IDEzLjUzNWMwLTMuMjM5MiAyLjYyNTktNS44NjUgNS44NjUtNS44NjUgMy4yMzkyIDAgNS44NjUgMi42MjU5IDUuODY1IDUuODY1eiIvPgogIDxjaXJjbGUgY3g9IjEyIiBjeT0iMy43Njg1IiByPSIyLjk2ODUiLz4KIDwvZz4KPC9zdmc+Cg==);--jp-icon-vega: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbjEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjEyMTIxIj4KICAgIDxwYXRoIGQ9Ik0xMC42IDUuNGwyLjItMy4ySDIuMnY3LjNsNC02LjZ6Ii8+CiAgICA8cGF0aCBkPSJNMTUuOCAyLjJsLTQuNCA2LjZMNyA2LjNsLTQuOCA4djUuNWgxNy42VjIuMmgtNHptLTcgMTUuNEg1LjV2LTQuNGgzLjN2NC40em00LjQgMEg5LjhWOS44aDMuNHY3Ljh6bTQuNCAwaC0zLjRWNi41aDMuNHYxMS4xeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-yaml: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1jb250cmFzdDIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjRDgxQjYwIj4KICAgIDxwYXRoIGQ9Ik03LjIgMTguNnYtNS40TDMgNS42aDMuM2wxLjQgMy4xYy4zLjkuNiAxLjYgMSAyLjUuMy0uOC42LTEuNiAxLTIuNWwxLjQtMy4xaDMuNGwtNC40IDcuNnY1LjVsLTIuOS0uMXoiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxNi41IiByPSIyLjEiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxMSIgcj0iMi4xIi8+CiAgPC9nPgo8L3N2Zz4K)}.jupyter-wrapper .jp-AddAboveIcon{background-image:var(--jp-icon-add-above)}.jupyter-wrapper .jp-AddBelowIcon{background-image:var(--jp-icon-add-below)}.jupyter-wrapper .jp-AddIcon{background-image:var(--jp-icon-add)}.jupyter-wrapper .jp-BellIcon{background-image:var(--jp-icon-bell)}.jupyter-wrapper .jp-BugDotIcon{background-image:var(--jp-icon-bug-dot)}.jupyter-wrapper .jp-BugIcon{background-image:var(--jp-icon-bug)}.jupyter-wrapper .jp-BuildIcon{background-image:var(--jp-icon-build)}.jupyter-wrapper .jp-CaretDownEmptyIcon{background-image:var(--jp-icon-caret-down-empty)}.jupyter-wrapper .jp-CaretDownEmptyThinIcon{background-image:var(--jp-icon-caret-down-empty-thin)}.jupyter-wrapper .jp-CaretDownIcon{background-image:var(--jp-icon-caret-down)}.jupyter-wrapper .jp-CaretLeftIcon{background-image:var(--jp-icon-caret-left)}.jupyter-wrapper .jp-CaretRightIcon{background-image:var(--jp-icon-caret-right)}.jupyter-wrapper .jp-CaretUpEmptyThinIcon{background-image:var(--jp-icon-caret-up-empty-thin)}.jupyter-wrapper .jp-CaretUpIcon{background-image:var(--jp-icon-caret-up)}.jupyter-wrapper .jp-CaseSensitiveIcon{background-image:var(--jp-icon-case-sensitive)}.jupyter-wrapper .jp-CheckIcon{background-image:var(--jp-icon-check)}.jupyter-wrapper .jp-CircleEmptyIcon{background-image:var(--jp-icon-circle-empty)}.jupyter-wrapper .jp-CircleIcon{background-image:var(--jp-icon-circle)}.jupyter-wrapper .jp-ClearIcon{background-image:var(--jp-icon-clear)}.jupyter-wrapper .jp-CloseIcon{background-image:var(--jp-icon-close)}.jupyter-wrapper .jp-CodeIcon{background-image:var(--jp-icon-code)}.jupyter-wrapper .jp-ConsoleIcon{background-image:var(--jp-icon-console)}.jupyter-wrapper .jp-CopyIcon{background-image:var(--jp-icon-copy)}.jupyter-wrapper .jp-CopyrightIcon{background-image:var(--jp-icon-copyright)}.jupyter-wrapper .jp-CutIcon{background-image:var(--jp-icon-cut)}.jupyter-wrapper .jp-DeleteIcon{background-image:var(--jp-icon-delete)}.jupyter-wrapper .jp-DownloadIcon{background-image:var(--jp-icon-download)}.jupyter-wrapper .jp-DuplicateIcon{background-image:var(--jp-icon-duplicate)}.jupyter-wrapper .jp-EditIcon{background-image:var(--jp-icon-edit)}.jupyter-wrapper .jp-EllipsesIcon{background-image:var(--jp-icon-ellipses)}.jupyter-wrapper .jp-ExtensionIcon{background-image:var(--jp-icon-extension)}.jupyter-wrapper .jp-FastForwardIcon{background-image:var(--jp-icon-fast-forward)}.jupyter-wrapper .jp-FileIcon{background-image:var(--jp-icon-file)}.jupyter-wrapper .jp-FileUploadIcon{background-image:var(--jp-icon-file-upload)}.jupyter-wrapper .jp-FilterListIcon{background-image:var(--jp-icon-filter-list)}.jupyter-wrapper .jp-FolderFavoriteIcon{background-image:var(--jp-icon-folder-favorite)}.jupyter-wrapper .jp-FolderIcon{background-image:var(--jp-icon-folder)}.jupyter-wrapper .jp-HomeIcon{background-image:var(--jp-icon-home)}.jupyter-wrapper .jp-Html5Icon{background-image:var(--jp-icon-html5)}.jupyter-wrapper .jp-ImageIcon{background-image:var(--jp-icon-image)}.jupyter-wrapper .jp-InspectorIcon{background-image:var(--jp-icon-inspector)}.jupyter-wrapper .jp-JsonIcon{background-image:var(--jp-icon-json)}.jupyter-wrapper .jp-JuliaIcon{background-image:var(--jp-icon-julia)}.jupyter-wrapper .jp-JupyterFaviconIcon{background-image:var(--jp-icon-jupyter-favicon)}.jupyter-wrapper .jp-JupyterIcon{background-image:var(--jp-icon-jupyter)}.jupyter-wrapper .jp-JupyterlabWordmarkIcon{background-image:var(--jp-icon-jupyterlab-wordmark)}.jupyter-wrapper .jp-KernelIcon{background-image:var(--jp-icon-kernel)}.jupyter-wrapper .jp-KeyboardIcon{background-image:var(--jp-icon-keyboard)}.jupyter-wrapper .jp-LaunchIcon{background-image:var(--jp-icon-launch)}.jupyter-wrapper .jp-LauncherIcon{background-image:var(--jp-icon-launcher)}.jupyter-wrapper .jp-LineFormIcon{background-image:var(--jp-icon-line-form)}.jupyter-wrapper .jp-LinkIcon{background-image:var(--jp-icon-link)}.jupyter-wrapper .jp-ListIcon{background-image:var(--jp-icon-list)}.jupyter-wrapper .jp-ListingsInfoIcon{background-image:var(--jp-icon-listings-info)}.jupyter-wrapper .jp-MarkdownIcon{background-image:var(--jp-icon-markdown)}.jupyter-wrapper .jp-MoveDownIcon{background-image:var(--jp-icon-move-down)}.jupyter-wrapper .jp-MoveUpIcon{background-image:var(--jp-icon-move-up)}.jupyter-wrapper .jp-NewFolderIcon{background-image:var(--jp-icon-new-folder)}.jupyter-wrapper .jp-NotTrustedIcon{background-image:var(--jp-icon-not-trusted)}.jupyter-wrapper .jp-NotebookIcon{background-image:var(--jp-icon-notebook)}.jupyter-wrapper .jp-NumberingIcon{background-image:var(--jp-icon-numbering)}.jupyter-wrapper .jp-OfflineBoltIcon{background-image:var(--jp-icon-offline-bolt)}.jupyter-wrapper .jp-PaletteIcon{background-image:var(--jp-icon-palette)}.jupyter-wrapper .jp-PasteIcon{background-image:var(--jp-icon-paste)}.jupyter-wrapper .jp-PdfIcon{background-image:var(--jp-icon-pdf)}.jupyter-wrapper .jp-PythonIcon{background-image:var(--jp-icon-python)}.jupyter-wrapper .jp-RKernelIcon{background-image:var(--jp-icon-r-kernel)}.jupyter-wrapper .jp-ReactIcon{background-image:var(--jp-icon-react)}.jupyter-wrapper .jp-RedoIcon{background-image:var(--jp-icon-redo)}.jupyter-wrapper .jp-RefreshIcon{background-image:var(--jp-icon-refresh)}.jupyter-wrapper .jp-RegexIcon{background-image:var(--jp-icon-regex)}.jupyter-wrapper .jp-RunIcon{background-image:var(--jp-icon-run)}.jupyter-wrapper .jp-RunningIcon{background-image:var(--jp-icon-running)}.jupyter-wrapper .jp-SaveIcon{background-image:var(--jp-icon-save)}.jupyter-wrapper .jp-SearchIcon{background-image:var(--jp-icon-search)}.jupyter-wrapper .jp-SettingsIcon{background-image:var(--jp-icon-settings)}.jupyter-wrapper .jp-ShareIcon{background-image:var(--jp-icon-share)}.jupyter-wrapper .jp-SpreadsheetIcon{background-image:var(--jp-icon-spreadsheet)}.jupyter-wrapper .jp-StopIcon{background-image:var(--jp-icon-stop)}.jupyter-wrapper .jp-TabIcon{background-image:var(--jp-icon-tab)}.jupyter-wrapper .jp-TableRowsIcon{background-image:var(--jp-icon-table-rows)}.jupyter-wrapper .jp-TagIcon{background-image:var(--jp-icon-tag)}.jupyter-wrapper .jp-TerminalIcon{background-image:var(--jp-icon-terminal)}.jupyter-wrapper .jp-TextEditorIcon{background-image:var(--jp-icon-text-editor)}.jupyter-wrapper .jp-TocIcon{background-image:var(--jp-icon-toc)}.jupyter-wrapper .jp-TreeViewIcon{background-image:var(--jp-icon-tree-view)}.jupyter-wrapper .jp-TrustedIcon{background-image:var(--jp-icon-trusted)}.jupyter-wrapper .jp-UndoIcon{background-image:var(--jp-icon-undo)}.jupyter-wrapper .jp-UserIcon{background-image:var(--jp-icon-user)}.jupyter-wrapper .jp-UsersIcon{background-image:var(--jp-icon-users)}.jupyter-wrapper .jp-VegaIcon{background-image:var(--jp-icon-vega)}.jupyter-wrapper .jp-YamlIcon{background-image:var(--jp-icon-yaml)}.jupyter-wrapper .jp-Icon,.jupyter-wrapper .jp-MaterialIcon{background-position:center;background-repeat:no-repeat;background-size:16px;min-width:16px;min-height:16px}.jupyter-wrapper .jp-Icon-cover{background-position:center;background-repeat:no-repeat;background-size:cover}.jupyter-wrapper .jp-Icon-16{background-size:16px;min-width:16px;min-height:16px}.jupyter-wrapper .jp-Icon-18{background-size:18px;min-width:18px;min-height:18px}.jupyter-wrapper .jp-Icon-20{background-size:20px;min-width:20px;min-height:20px}.jupyter-wrapper .lm-TabBar .lm-TabBar-addButton{align-items:center;display:flex;padding:4px 4px 5px;margin-right:1px;background-color:var(--jp-layout-color2)}.jupyter-wrapper .lm-TabBar .lm-TabBar-addButton:hover{background-color:var(--jp-layout-color1)}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab{width:var(--jp-private-horizontal-tab-width)}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-content{flex:unset}.jupyter-wrapper .lm-DockPanel-tabBar[data-orientation=horizontal]{flex:1 1 auto}.jupyter-wrapper .jp-icon0[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon1[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon2[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon3[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon4[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon0[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon1[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon2[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon3[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon4[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-accent0[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-accent1[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-accent2[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-accent3[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-accent4[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-accent0[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-accent1[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-accent2[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-accent3[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-accent4[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-none[fill]{fill:none}.jupyter-wrapper .jp-icon-none[stroke]{stroke:none}.jupyter-wrapper .jp-icon-brand0[fill]{fill:var(--jp-brand-color0)}.jupyter-wrapper .jp-icon-brand1[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper .jp-icon-brand2[fill]{fill:var(--jp-brand-color2)}.jupyter-wrapper .jp-icon-brand3[fill]{fill:var(--jp-brand-color3)}.jupyter-wrapper .jp-icon-brand4[fill]{fill:var(--jp-brand-color4)}.jupyter-wrapper .jp-icon-brand0[stroke]{stroke:var(--jp-brand-color0)}.jupyter-wrapper .jp-icon-brand1[stroke]{stroke:var(--jp-brand-color1)}.jupyter-wrapper .jp-icon-brand2[stroke]{stroke:var(--jp-brand-color2)}.jupyter-wrapper .jp-icon-brand3[stroke]{stroke:var(--jp-brand-color3)}.jupyter-wrapper .jp-icon-brand4[stroke]{stroke:var(--jp-brand-color4)}.jupyter-wrapper .jp-icon-warn0[fill]{fill:var(--jp-warn-color0)}.jupyter-wrapper .jp-icon-warn1[fill]{fill:var(--jp-warn-color1)}.jupyter-wrapper .jp-icon-warn2[fill]{fill:var(--jp-warn-color2)}.jupyter-wrapper .jp-icon-warn3[fill]{fill:var(--jp-warn-color3)}.jupyter-wrapper .jp-icon-warn0[stroke]{stroke:var(--jp-warn-color0)}.jupyter-wrapper .jp-icon-warn1[stroke]{stroke:var(--jp-warn-color1)}.jupyter-wrapper .jp-icon-warn2[stroke]{stroke:var(--jp-warn-color2)}.jupyter-wrapper .jp-icon-warn3[stroke]{stroke:var(--jp-warn-color3)}.jupyter-wrapper .jp-icon-contrast0[fill]{fill:var(--jp-icon-contrast-color0)}.jupyter-wrapper .jp-icon-contrast1[fill]{fill:var(--jp-icon-contrast-color1)}.jupyter-wrapper .jp-icon-contrast2[fill]{fill:var(--jp-icon-contrast-color2)}.jupyter-wrapper .jp-icon-contrast3[fill]{fill:var(--jp-icon-contrast-color3)}.jupyter-wrapper .jp-icon-contrast0[stroke]{stroke:var(--jp-icon-contrast-color0)}.jupyter-wrapper .jp-icon-contrast1[stroke]{stroke:var(--jp-icon-contrast-color1)}.jupyter-wrapper .jp-icon-contrast2[stroke]{stroke:var(--jp-icon-contrast-color2)}.jupyter-wrapper .jp-icon-contrast3[stroke]{stroke:var(--jp-icon-contrast-color3)}.jupyter-wrapper .jp-jupyter-icon-color[fill]{fill:var(--jp-jupyter-icon-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-notebook-icon-color[fill]{fill:var(--jp-notebook-icon-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-json-icon-color[fill]{fill:var(--jp-json-icon-color, var(--jp-warn-color1))}.jupyter-wrapper .jp-console-icon-color[fill]{fill:var(--jp-console-icon-color, white)}.jupyter-wrapper .jp-console-icon-background-color[fill]{fill:var(--jp-console-icon-background-color, var(--jp-brand-color1))}.jupyter-wrapper .jp-terminal-icon-color[fill]{fill:var(--jp-terminal-icon-color, var(--jp-layout-color2))}.jupyter-wrapper .jp-terminal-icon-background-color[fill]{fill:var(--jp-terminal-icon-background-color, var(--jp-inverse-layout2))}.jupyter-wrapper .jp-text-editor-icon-color[fill]{fill:var(--jp-text-editor-icon-color, var(--jp-inverse-layout3))}.jupyter-wrapper .jp-inspector-icon-color[fill]{fill:var(--jp-inspector-icon-color, var(--jp-inverse-layout3))}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected .jp-icon-selectable-inverse[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-selectable-inverse[fill],.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-hover :hover .jp-icon-selectable[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-hover :hover .jp-icon-selectable-inverse[fill]{fill:#fff}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon3[fill]{fill:none}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty.jp-mod-active>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:#fff}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon3[fill]{fill:none}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper #jp-main-statusbar .jp-mod-selected .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper #jp-main-statusbar .jp-mod-selected .jp-icon-selectable-inverse[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper :root{--jp-warn-color0: var(--md-orange-700)}.jupyter-wrapper .jp-DragIcon{margin-right:4px}.jupyter-wrapper .jp-icon-alt .jp-icon0[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon1[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon2[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon3[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon4[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon0[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon1[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon2[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon3[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon4[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent0[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent1[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent2[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent3[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent4[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent0[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent1[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent2[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent3[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent4[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hoverShow:not(:hover) .jp-icon-hoverShow-content{display:none!important}.jupyter-wrapper .jp-icon-hover :hover .jp-icon0-hover[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon1-hover[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon2-hover[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon3-hover[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon4-hover[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon0-hover[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon1-hover[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon2-hover[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon3-hover[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon4-hover[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent0-hover[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent1-hover[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent2-hover[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent3-hover[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent4-hover[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent0-hover[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent1-hover[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent2-hover[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent3-hover[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent4-hover[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-none-hover[fill]{fill:none}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-none-hover[stroke]{stroke:none}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-switch{display:flex;align-items:center;padding-left:4px;padding-right:4px;font-size:var(--jp-ui-font-size1);background-color:transparent;color:var(--jp-ui-font-color1);border:none;height:20px}.jupyter-wrapper .jp-switch:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-switch-label{margin-right:5px}.jupyter-wrapper .jp-switch-track{cursor:pointer;background-color:var(--jp-switch-color, var(--jp-border-color1));-webkit-transition:.4s;transition:.4s;border-radius:34px;height:16px;width:35px;position:relative}.jupyter-wrapper .jp-switch-track:before{content:\"\";position:absolute;height:10px;width:10px;margin:3px;left:0;background-color:var(--jp-ui-inverse-font-color1);-webkit-transition:.4s;transition:.4s;border-radius:50%}.jupyter-wrapper .jp-switch[aria-checked=true] .jp-switch-track{background-color:var(--jp-switch-true-position-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-switch[aria-checked=true] .jp-switch-track:before{left:19px}.jupyter-wrapper html{box-sizing:unset}.jupyter-wrapper *,.jupyter-wrapper *:before,.jupyter-wrapper *:after{box-sizing:unset}.jupyter-wrapper body{color:unset;font-family:var(--jp-ui-font-family)}.jupyter-wrapper :focus{outline:unset;outline-offset:unset;-moz-outline-radius:unset}.jupyter-wrapper .jp-Button{border-radius:var(--jp-border-radius);padding:0 12px;font-size:var(--jp-ui-font-size1)}.jupyter-wrapper button.jp-Button.bp3-button.bp3-minimal:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-Button.minimal{color:unset!important}.jupyter-wrapper .jp-Button.jp-ToolbarButtonComponent{text-transform:none}.jupyter-wrapper .jp-InputGroup input{box-sizing:border-box;border-radius:0;background-color:transparent;color:var(--jp-ui-font-color0);box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color)}.jupyter-wrapper .jp-InputGroup input:focus{box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-active-box-shadow-color),inset 0 0 0 3px var(--jp-input-active-box-shadow-color)}.jupyter-wrapper .jp-InputGroup input::placeholder,.jupyter-wrapper input::placeholder{color:var(--jp-ui-font-color3)}.jupyter-wrapper .jp-BPIcon{display:inline-block;vertical-align:middle;margin:auto}.jupyter-wrapper .bp3-icon.jp-BPIcon>svg:not([fill]){fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-InputGroupAction{padding:6px}.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select{background-color:initial;border:none;border-radius:0;box-shadow:none;color:var(--jp-ui-font-color0);display:block;font-size:var(--jp-ui-font-size1);height:24px;line-height:14px;padding:0 25px 0 10px;text-align:left;-moz-appearance:none;-webkit-appearance:none}.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select:hover,.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select>option{background-color:var(--jp-layout-color2);color:var(--jp-ui-font-color0)}.jupyter-wrapper select{box-sizing:border-box}.jupyter-wrapper .jp-Collapse{display:flex;flex-direction:column;align-items:stretch;border-top:1px solid var(--jp-border-color2);border-bottom:1px solid var(--jp-border-color2)}.jupyter-wrapper .jp-Collapse-header{padding:1px 12px;color:var(--jp-ui-font-color1);background-color:var(--jp-layout-color1);font-size:var(--jp-ui-font-size2)}.jupyter-wrapper .jp-Collapse-header:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-Collapse-contents{padding:0 12px;background-color:var(--jp-layout-color1);color:var(--jp-ui-font-color1);overflow:auto}.jupyter-wrapper :root{--jp-private-commandpalette-search-height: 28px}.jupyter-wrapper .lm-CommandPalette{padding-bottom:0;color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .jp-ModalCommandPalette{position:absolute;z-index:10000;top:38px;left:30%;margin:0;padding:4px;width:40%;box-shadow:var(--jp-elevation-z4);border-radius:4px;background:var(--jp-layout-color0)}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette{max-height:40vh}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-close-icon:after{display:none}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-header{display:none}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item{margin-left:4px;margin-right:4px}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item.lm-mod-disabled{display:none}.jupyter-wrapper .lm-CommandPalette-search{padding:4px;background-color:var(--jp-layout-color1);z-index:2}.jupyter-wrapper .lm-CommandPalette-wrapper{overflow:overlay;padding:0 9px;background-color:var(--jp-input-active-background);height:30px;box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color)}.jupyter-wrapper .lm-CommandPalette.lm-mod-focused .lm-CommandPalette-wrapper{box-shadow:inset 0 0 0 1px var(--jp-input-active-box-shadow-color),inset 0 0 0 3px var(--jp-input-active-box-shadow-color)}.jupyter-wrapper .jp-SearchIconGroup{color:#fff;background-color:var(--jp-brand-color1);position:absolute;top:4px;right:4px;padding:5px 5px 1px}.jupyter-wrapper .jp-SearchIconGroup svg{height:20px;width:20px}.jupyter-wrapper .jp-SearchIconGroup .jp-icon3[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .lm-CommandPalette-input{background:transparent;width:calc(100% - 18px);float:left;border:none;outline:none;font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);line-height:var(--jp-private-commandpalette-search-height)}.jupyter-wrapper .lm-CommandPalette-input::-webkit-input-placeholder,.jupyter-wrapper .lm-CommandPalette-input::-moz-placeholder,.jupyter-wrapper .lm-CommandPalette-input:-ms-input-placeholder{color:var(--jp-ui-font-color2);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .lm-CommandPalette-header:first-child{margin-top:0}.jupyter-wrapper .lm-CommandPalette-header{border-bottom:solid var(--jp-border-width) var(--jp-border-color2);color:var(--jp-ui-font-color1);cursor:pointer;display:flex;font-size:var(--jp-ui-font-size0);font-weight:600;letter-spacing:1px;margin-top:8px;padding:8px 0 8px 12px;text-transform:uppercase}.jupyter-wrapper .lm-CommandPalette-header.lm-mod-active{background:var(--jp-layout-color2)}.jupyter-wrapper .lm-CommandPalette-header>mark{background-color:transparent;font-weight:700;color:var(--jp-ui-font-color1)}.jupyter-wrapper .lm-CommandPalette-item{padding:4px 12px 4px 4px;color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);font-weight:400;display:flex}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled{color:var(--jp-ui-font-color2)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active{color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active .jp-icon-selectable[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active .lm-CommandPalette-itemLabel>mark{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active:hover:not(.lm-mod-disabled){color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .lm-CommandPalette-item:hover:not(.lm-mod-active):not(.lm-mod-disabled){background:var(--jp-layout-color2)}.jupyter-wrapper .lm-CommandPalette-itemContent{overflow:hidden}.jupyter-wrapper .lm-CommandPalette-itemLabel>mark{color:var(--jp-ui-font-color0);background-color:transparent;font-weight:700}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled mark{color:var(--jp-ui-font-color2)}.jupyter-wrapper .lm-CommandPalette-item .lm-CommandPalette-itemIcon{margin:0 4px 0 0;position:relative;width:16px;top:2px;flex:0 0 auto}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled .lm-CommandPalette-itemIcon{opacity:.6}.jupyter-wrapper .lm-CommandPalette-item .lm-CommandPalette-itemShortcut{flex:0 0 auto}.jupyter-wrapper .lm-CommandPalette-itemCaption{display:none}.jupyter-wrapper .lm-CommandPalette-content{background-color:var(--jp-layout-color1)}.jupyter-wrapper .lm-CommandPalette-content:empty:after{content:\"No results\";margin:20px auto auto;width:100px;display:block;font-size:var(--jp-ui-font-size2);font-family:var(--jp-ui-font-family);font-weight:lighter}.jupyter-wrapper .lm-CommandPalette-emptyMessage{text-align:center;margin-top:24px;line-height:1.32;padding:0 8px;color:var(--jp-content-font-color3)}.jupyter-wrapper .jp-Dialog{position:absolute;z-index:10000;display:flex;flex-direction:column;align-items:center;justify-content:center;top:0;left:0;margin:0;padding:0;width:100%;height:100%;background:var(--jp-dialog-background)}.jupyter-wrapper .jp-Dialog-content{display:flex;flex-direction:column;margin-left:auto;margin-right:auto;background:var(--jp-layout-color1);padding:24px 24px 12px;min-width:300px;min-height:150px;max-width:1000px;max-height:500px;box-sizing:border-box;box-shadow:var(--jp-elevation-z20);word-wrap:break-word;border-radius:var(--jp-border-radius);font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color1);resize:both}.jupyter-wrapper .jp-Dialog-content.jp-Dialog-content-small{max-width:500px}.jupyter-wrapper .jp-Dialog-button{overflow:visible}.jupyter-wrapper button.jp-Dialog-button:focus{outline:1px solid var(--jp-brand-color1);outline-offset:4px;-moz-outline-radius:0px}.jupyter-wrapper button.jp-Dialog-button:focus::-moz-focus-inner{border:0}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus,.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus,.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus{outline-offset:4px;-moz-outline-radius:0px}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus{outline:1px solid var(--md-blue-700)}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus{outline:1px solid var(--md-red-600)}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus{outline:1px solid var(--md-grey-700)}.jupyter-wrapper button.jp-Dialog-close-button{padding:0;height:100%;min-width:unset;min-height:unset}.jupyter-wrapper .jp-Dialog-header{display:flex;justify-content:space-between;flex:0 0 auto;padding-bottom:12px;font-size:var(--jp-ui-font-size3);font-weight:400;color:var(--jp-ui-font-color0)}.jupyter-wrapper .jp-Dialog-body{display:flex;flex-direction:column;flex:1 1 auto;font-size:var(--jp-ui-font-size1);background:var(--jp-layout-color1);overflow:auto}.jupyter-wrapper .jp-Dialog-footer{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;flex:0 0 auto;margin-left:-12px;margin-right:-12px;padding:12px}.jupyter-wrapper .jp-Dialog-checkbox{padding-right:5px}.jupyter-wrapper .jp-Dialog-checkbox>input:focus-visible{outline:1px solid var(--jp-input-active-border-color);outline-offset:1px}.jupyter-wrapper .jp-Dialog-spacer{flex:1 1 auto}.jupyter-wrapper .jp-Dialog-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .jp-Dialog-body>.jp-select-wrapper{width:100%}.jupyter-wrapper .jp-Dialog-body>button{padding:0 16px}.jupyter-wrapper .jp-Dialog-body>label{line-height:1.4;color:var(--jp-ui-font-color0)}.jupyter-wrapper .jp-Dialog-button.jp-mod-styled:not(:last-child){margin-right:12px}.jupyter-wrapper .jp-HoverBox{position:fixed}.jupyter-wrapper .jp-HoverBox.jp-mod-outofview{display:none}.jupyter-wrapper .jp-IFrame{width:100%;height:100%}.jupyter-wrapper .jp-IFrame>iframe{border:none}.jupyter-wrapper body.lm-mod-override-cursor .jp-IFrame{position:relative}.jupyter-wrapper body.lm-mod-override-cursor .jp-IFrame:before{content:\"\";position:absolute;top:0;left:0;right:0;bottom:0;background:transparent}.jupyter-wrapper .jp-Input-Boolean-Dialog{flex-direction:row-reverse;align-items:end;width:100%}.jupyter-wrapper .jp-Input-Boolean-Dialog>label{flex:1 1 auto}.jupyter-wrapper .jp-MainAreaWidget>:focus{outline:none}.jupyter-wrapper .jp-MainAreaWidget .jp-MainAreaWidget-error{padding:6px}.jupyter-wrapper .jp-MainAreaWidget .jp-MainAreaWidget-error>pre{width:auto;padding:10px;background:var(--jp-error-color3);border:var(--jp-border-width) solid var(--jp-error-color1);border-radius:var(--jp-border-radius);color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);white-space:pre-wrap;word-wrap:break-word}.jupyter-wrapper .jp-MainAreaWidget{contain:strict}.jupyter-wrapper :root{--md-red-50: #ffebee;--md-red-100: #ffcdd2;--md-red-200: #ef9a9a;--md-red-300: #e57373;--md-red-400: #ef5350;--md-red-500: #f44336;--md-red-600: #e53935;--md-red-700: #d32f2f;--md-red-800: #c62828;--md-red-900: #b71c1c;--md-red-A100: #ff8a80;--md-red-A200: #ff5252;--md-red-A400: #ff1744;--md-red-A700: #d50000;--md-pink-50: #fce4ec;--md-pink-100: #f8bbd0;--md-pink-200: #f48fb1;--md-pink-300: #f06292;--md-pink-400: #ec407a;--md-pink-500: #e91e63;--md-pink-600: #d81b60;--md-pink-700: #c2185b;--md-pink-800: #ad1457;--md-pink-900: #880e4f;--md-pink-A100: #ff80ab;--md-pink-A200: #ff4081;--md-pink-A400: #f50057;--md-pink-A700: #c51162;--md-purple-50: #f3e5f5;--md-purple-100: #e1bee7;--md-purple-200: #ce93d8;--md-purple-300: #ba68c8;--md-purple-400: #ab47bc;--md-purple-500: #9c27b0;--md-purple-600: #8e24aa;--md-purple-700: #7b1fa2;--md-purple-800: #6a1b9a;--md-purple-900: #4a148c;--md-purple-A100: #ea80fc;--md-purple-A200: #e040fb;--md-purple-A400: #d500f9;--md-purple-A700: #aa00ff;--md-deep-purple-50: #ede7f6;--md-deep-purple-100: #d1c4e9;--md-deep-purple-200: #b39ddb;--md-deep-purple-300: #9575cd;--md-deep-purple-400: #7e57c2;--md-deep-purple-500: #673ab7;--md-deep-purple-600: #5e35b1;--md-deep-purple-700: #512da8;--md-deep-purple-800: #4527a0;--md-deep-purple-900: #311b92;--md-deep-purple-A100: #b388ff;--md-deep-purple-A200: #7c4dff;--md-deep-purple-A400: #651fff;--md-deep-purple-A700: #6200ea;--md-indigo-50: #e8eaf6;--md-indigo-100: #c5cae9;--md-indigo-200: #9fa8da;--md-indigo-300: #7986cb;--md-indigo-400: #5c6bc0;--md-indigo-500: #3f51b5;--md-indigo-600: #3949ab;--md-indigo-700: #303f9f;--md-indigo-800: #283593;--md-indigo-900: #1a237e;--md-indigo-A100: #8c9eff;--md-indigo-A200: #536dfe;--md-indigo-A400: #3d5afe;--md-indigo-A700: #304ffe;--md-blue-50: #e3f2fd;--md-blue-100: #bbdefb;--md-blue-200: #90caf9;--md-blue-300: #64b5f6;--md-blue-400: #42a5f5;--md-blue-500: #2196f3;--md-blue-600: #1e88e5;--md-blue-700: #1976d2;--md-blue-800: #1565c0;--md-blue-900: #0d47a1;--md-blue-A100: #82b1ff;--md-blue-A200: #448aff;--md-blue-A400: #2979ff;--md-blue-A700: #2962ff;--md-light-blue-50: #e1f5fe;--md-light-blue-100: #b3e5fc;--md-light-blue-200: #81d4fa;--md-light-blue-300: #4fc3f7;--md-light-blue-400: #29b6f6;--md-light-blue-500: #03a9f4;--md-light-blue-600: #039be5;--md-light-blue-700: #0288d1;--md-light-blue-800: #0277bd;--md-light-blue-900: #01579b;--md-light-blue-A100: #80d8ff;--md-light-blue-A200: #40c4ff;--md-light-blue-A400: #00b0ff;--md-light-blue-A700: #0091ea;--md-cyan-50: #e0f7fa;--md-cyan-100: #b2ebf2;--md-cyan-200: #80deea;--md-cyan-300: #4dd0e1;--md-cyan-400: #26c6da;--md-cyan-500: #00bcd4;--md-cyan-600: #00acc1;--md-cyan-700: #0097a7;--md-cyan-800: #00838f;--md-cyan-900: #006064;--md-cyan-A100: #84ffff;--md-cyan-A200: #18ffff;--md-cyan-A400: #00e5ff;--md-cyan-A700: #00b8d4;--md-teal-50: #e0f2f1;--md-teal-100: #b2dfdb;--md-teal-200: #80cbc4;--md-teal-300: #4db6ac;--md-teal-400: #26a69a;--md-teal-500: #009688;--md-teal-600: #00897b;--md-teal-700: #00796b;--md-teal-800: #00695c;--md-teal-900: #004d40;--md-teal-A100: #a7ffeb;--md-teal-A200: #64ffda;--md-teal-A400: #1de9b6;--md-teal-A700: #00bfa5;--md-green-50: #e8f5e9;--md-green-100: #c8e6c9;--md-green-200: #a5d6a7;--md-green-300: #81c784;--md-green-400: #66bb6a;--md-green-500: #4caf50;--md-green-600: #43a047;--md-green-700: #388e3c;--md-green-800: #2e7d32;--md-green-900: #1b5e20;--md-green-A100: #b9f6ca;--md-green-A200: #69f0ae;--md-green-A400: #00e676;--md-green-A700: #00c853;--md-light-green-50: #f1f8e9;--md-light-green-100: #dcedc8;--md-light-green-200: #c5e1a5;--md-light-green-300: #aed581;--md-light-green-400: #9ccc65;--md-light-green-500: #8bc34a;--md-light-green-600: #7cb342;--md-light-green-700: #689f38;--md-light-green-800: #558b2f;--md-light-green-900: #33691e;--md-light-green-A100: #ccff90;--md-light-green-A200: #b2ff59;--md-light-green-A400: #76ff03;--md-light-green-A700: #64dd17;--md-lime-50: #f9fbe7;--md-lime-100: #f0f4c3;--md-lime-200: #e6ee9c;--md-lime-300: #dce775;--md-lime-400: #d4e157;--md-lime-500: #cddc39;--md-lime-600: #c0ca33;--md-lime-700: #afb42b;--md-lime-800: #9e9d24;--md-lime-900: #827717;--md-lime-A100: #f4ff81;--md-lime-A200: #eeff41;--md-lime-A400: #c6ff00;--md-lime-A700: #aeea00;--md-yellow-50: #fffde7;--md-yellow-100: #fff9c4;--md-yellow-200: #fff59d;--md-yellow-300: #fff176;--md-yellow-400: #ffee58;--md-yellow-500: #ffeb3b;--md-yellow-600: #fdd835;--md-yellow-700: #fbc02d;--md-yellow-800: #f9a825;--md-yellow-900: #f57f17;--md-yellow-A100: #ffff8d;--md-yellow-A200: #ffff00;--md-yellow-A400: #ffea00;--md-yellow-A700: #ffd600;--md-amber-50: #fff8e1;--md-amber-100: #ffecb3;--md-amber-200: #ffe082;--md-amber-300: #ffd54f;--md-amber-400: #ffca28;--md-amber-500: #ffc107;--md-amber-600: #ffb300;--md-amber-700: #ffa000;--md-amber-800: #ff8f00;--md-amber-900: #ff6f00;--md-amber-A100: #ffe57f;--md-amber-A200: #ffd740;--md-amber-A400: #ffc400;--md-amber-A700: #ffab00;--md-orange-50: #fff3e0;--md-orange-100: #ffe0b2;--md-orange-200: #ffcc80;--md-orange-300: #ffb74d;--md-orange-400: #ffa726;--md-orange-500: #ff9800;--md-orange-600: #fb8c00;--md-orange-700: #f57c00;--md-orange-800: #ef6c00;--md-orange-900: #e65100;--md-orange-A100: #ffd180;--md-orange-A200: #ffab40;--md-orange-A400: #ff9100;--md-orange-A700: #ff6d00;--md-deep-orange-50: #fbe9e7;--md-deep-orange-100: #ffccbc;--md-deep-orange-200: #ffab91;--md-deep-orange-300: #ff8a65;--md-deep-orange-400: #ff7043;--md-deep-orange-500: #ff5722;--md-deep-orange-600: #f4511e;--md-deep-orange-700: #e64a19;--md-deep-orange-800: #d84315;--md-deep-orange-900: #bf360c;--md-deep-orange-A100: #ff9e80;--md-deep-orange-A200: #ff6e40;--md-deep-orange-A400: #ff3d00;--md-deep-orange-A700: #dd2c00;--md-brown-50: #efebe9;--md-brown-100: #d7ccc8;--md-brown-200: #bcaaa4;--md-brown-300: #a1887f;--md-brown-400: #8d6e63;--md-brown-500: #795548;--md-brown-600: #6d4c41;--md-brown-700: #5d4037;--md-brown-800: #4e342e;--md-brown-900: #3e2723;--md-grey-50: #fafafa;--md-grey-100: #f5f5f5;--md-grey-200: #eeeeee;--md-grey-300: #e0e0e0;--md-grey-400: #bdbdbd;--md-grey-500: #9e9e9e;--md-grey-600: #757575;--md-grey-700: #616161;--md-grey-800: #424242;--md-grey-900: #212121;--md-blue-grey-50: #eceff1;--md-blue-grey-100: #cfd8dc;--md-blue-grey-200: #b0bec5;--md-blue-grey-300: #90a4ae;--md-blue-grey-400: #78909c;--md-blue-grey-500: #607d8b;--md-blue-grey-600: #546e7a;--md-blue-grey-700: #455a64;--md-blue-grey-800: #37474f;--md-blue-grey-900: #263238}.jupyter-wrapper .jp-Spinner{position:absolute;display:flex;justify-content:center;align-items:center;z-index:10;left:0;top:0;width:100%;height:100%;background:var(--jp-layout-color0);outline:none}.jupyter-wrapper .jp-SpinnerContent{font-size:10px;margin:50px auto;text-indent:-9999em;width:3em;height:3em;border-radius:50%;background:var(--jp-brand-color3);background:linear-gradient(to right,#f37626 10%,rgba(255,255,255,0) 42%);position:relative;animation:load3 1s infinite linear,fadeIn 1s}.jupyter-wrapper .jp-SpinnerContent:before{width:50%;height:50%;background:#f37626;border-radius:100% 0 0;position:absolute;top:0;left:0;content:\"\"}.jupyter-wrapper .jp-SpinnerContent:after{background:var(--jp-layout-color0);width:75%;height:75%;border-radius:50%;content:\"\";margin:auto;position:absolute;top:0;left:0;bottom:0;right:0}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes load3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.jupyter-wrapper button.jp-mod-styled{font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);border:none;box-sizing:border-box;text-align:center;line-height:32px;height:32px;padding:0 12px;letter-spacing:.8px;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper input.jp-mod-styled{background:var(--jp-input-background);height:28px;box-sizing:border-box;border:var(--jp-border-width) solid var(--jp-border-color1);padding-left:7px;padding-right:7px;font-size:var(--jp-ui-font-size2);color:var(--jp-ui-font-color0);outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper input[type=checkbox].jp-mod-styled{appearance:checkbox;-webkit-appearance:checkbox;-moz-appearance:checkbox;height:auto}.jupyter-wrapper input.jp-mod-styled:focus{border:var(--jp-border-width) solid var(--md-blue-500);box-shadow:inset 0 0 4px var(--md-blue-300)}.jupyter-wrapper .jp-FileDialog-Checkbox{margin-top:35px;display:flex;flex-direction:row;align-items:end;width:100%}.jupyter-wrapper .jp-FileDialog-Checkbox>label{flex:1 1 auto}.jupyter-wrapper .jp-select-wrapper{display:flex;position:relative;flex-direction:column;padding:1px;background-color:var(--jp-layout-color1);height:28px;box-sizing:border-box;margin-bottom:12px}.jupyter-wrapper .jp-select-wrapper.jp-mod-focused select.jp-mod-styled{border:var(--jp-border-width) solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow);background-color:var(--jp-input-active-background)}.jupyter-wrapper select.jp-mod-styled:hover{background-color:var(--jp-layout-color1);cursor:pointer;color:var(--jp-ui-font-color0);background-color:var(--jp-input-hover-background);box-shadow:inset 0 0 1px #00000080}.jupyter-wrapper select.jp-mod-styled{flex:1 1 auto;height:32px;width:100%;font-size:var(--jp-ui-font-size2);background:var(--jp-input-background);color:var(--jp-ui-font-color0);padding:0 25px 0 8px;border:var(--jp-border-width) solid var(--jp-input-border-color);border-radius:0;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper :root{--jp-private-toolbar-height: calc( 28px + var(--jp-border-width) )}.jupyter-wrapper .jp-Toolbar{color:var(--jp-ui-font-color1);flex:0 0 auto;display:flex;flex-direction:row;border-bottom:var(--jp-border-width) solid var(--jp-toolbar-border-color);box-shadow:var(--jp-toolbar-box-shadow);background:var(--jp-toolbar-background);min-height:var(--jp-toolbar-micro-height);padding:2px;z-index:8;overflow-x:hidden}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-item.jp-Toolbar-spacer{flex-grow:1;flex-shrink:1}.jupyter-wrapper .jp-Toolbar-item.jp-Toolbar-kernelStatus{display:inline-block;width:32px;background-repeat:no-repeat;background-position:center;background-size:16px}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-item{flex:0 0 auto;display:flex;padding-left:1px;padding-right:1px;font-size:var(--jp-ui-font-size1);line-height:var(--jp-private-toolbar-height);height:100%}.jupyter-wrapper div.jp-ToolbarButton{color:transparent;border:none;box-sizing:border-box;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none;padding:0;margin:0}.jupyter-wrapper button.jp-ToolbarButtonComponent{background:var(--jp-layout-color1);border:none;box-sizing:border-box;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none;padding:0 6px;margin:0;height:24px;border-radius:var(--jp-border-radius);display:flex;align-items:center;text-align:center;font-size:14px;min-width:unset;min-height:unset}.jupyter-wrapper button.jp-ToolbarButtonComponent:disabled{opacity:.4}.jupyter-wrapper button.jp-ToolbarButtonComponent span{padding:0;flex:0 0 auto}.jupyter-wrapper button.jp-ToolbarButtonComponent .jp-ToolbarButtonComponent-label{font-size:var(--jp-ui-font-size1);line-height:100%;padding-left:2px;color:var(--jp-ui-font-color1)}.jupyter-wrapper #jp-main-dock-panel[data-mode=single-document] .jp-MainAreaWidget>.jp-Toolbar.jp-Toolbar-micro{padding:0;min-height:0}.jupyter-wrapper #jp-main-dock-panel[data-mode=single-document] .jp-MainAreaWidget>.jp-Toolbar{border:none;box-shadow:none}.jupyter-wrapper body.p-mod-override-cursor *,.jupyter-wrapper body.lm-mod-override-cursor *{cursor:inherit!important}.jupyter-wrapper .jp-JSONEditor{display:flex;flex-direction:column;width:100%}.jupyter-wrapper .jp-JSONEditor-host{flex:1 1 auto;border:var(--jp-border-width) solid var(--jp-input-border-color);border-radius:0;background:var(--jp-layout-color0);min-height:50px;padding:1px}.jupyter-wrapper .jp-JSONEditor.jp-mod-error .jp-JSONEditor-host{border-color:red;outline-color:red}.jupyter-wrapper .jp-JSONEditor-header{display:flex;flex:1 0 auto;padding:0 0 0 12px}.jupyter-wrapper .jp-JSONEditor-header label{flex:0 0 auto}.jupyter-wrapper .jp-JSONEditor-commitButton{height:16px;width:16px;background-size:18px;background-repeat:no-repeat;background-position:center}.jupyter-wrapper .jp-JSONEditor-host.jp-mod-focused{background-color:var(--jp-input-active-background);border:1px solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow)}.jupyter-wrapper .jp-Editor.jp-mod-dropTarget{border:var(--jp-border-width) solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow)}.jupyter-wrapper .jp-Statusbar-ProgressCircle svg{display:block;margin:0 auto;width:16px;height:24px;align-self:normal}.jupyter-wrapper .jp-Statusbar-ProgressCircle path{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar{height:10px;width:100px;border:solid .25px var(--jp-brand-color2);border-radius:3px;overflow:hidden;align-self:center}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar>div{background-color:var(--jp-brand-color2);background-image:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%,transparent);background-size:40px 40px;float:left;width:0%;height:100%;font-size:12px;line-height:14px;color:#fff;text-align:center;animation:jp-Statusbar-ExecutionTime-progress-bar 2s linear infinite}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar p{color:var(--jp-ui-font-color1);font-family:var(--jp-ui-font-family);font-size:var(--jp-ui-font-size1);line-height:10px;width:100px}@keyframes jp-Statusbar-ExecutionTime-progress-bar{0%{background-position:0 0}to{background-position:40px 40px}}.jupyter-wrapper .CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.jupyter-wrapper .CodeMirror-lines{padding:4px 0}.jupyter-wrapper .CodeMirror pre.CodeMirror-line,.jupyter-wrapper .CodeMirror pre.CodeMirror-line-like{padding:0 4px}.jupyter-wrapper .CodeMirror-scrollbar-filler,.jupyter-wrapper .CodeMirror-gutter-filler{background-color:#fff}.jupyter-wrapper .CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.jupyter-wrapper .CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.jupyter-wrapper .CodeMirror-guttermarker{color:#000}.jupyter-wrapper .CodeMirror-guttermarker-subtle{color:#999}.jupyter-wrapper .CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.jupyter-wrapper .CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.jupyter-wrapper .cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.jupyter-wrapper .cm-fat-cursor div.CodeMirror-cursors{z-index:1}.jupyter-wrapper .cm-fat-cursor-mark{background-color:#14ff1480;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.jupyter-wrapper .cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.jupyter-wrapper .cm-tab{display:inline-block;text-decoration:inherit}.jupyter-wrapper .CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.jupyter-wrapper .CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.jupyter-wrapper .cm-s-default .cm-header{color:#00f}.jupyter-wrapper .cm-s-default .cm-quote{color:#090}.jupyter-wrapper .cm-negative{color:#d44}.jupyter-wrapper .cm-positive{color:#292}.jupyter-wrapper .cm-header,.jupyter-wrapper .cm-strong{font-weight:700}.jupyter-wrapper .cm-em{font-style:italic}.jupyter-wrapper .cm-link{text-decoration:underline}.jupyter-wrapper .cm-strikethrough{text-decoration:line-through}.jupyter-wrapper .cm-s-default .cm-keyword{color:#708}.jupyter-wrapper .cm-s-default .cm-atom{color:#219}.jupyter-wrapper .cm-s-default .cm-number{color:#164}.jupyter-wrapper .cm-s-default .cm-def{color:#00f}.jupyter-wrapper .cm-s-default .cm-variable-2{color:#05a}.jupyter-wrapper .cm-s-default .cm-variable-3,.jupyter-wrapper .cm-s-default .cm-type{color:#085}.jupyter-wrapper .cm-s-default .cm-comment{color:#a50}.jupyter-wrapper .cm-s-default .cm-string{color:#a11}.jupyter-wrapper .cm-s-default .cm-string-2{color:#f50}.jupyter-wrapper .cm-s-default .cm-meta,.jupyter-wrapper .cm-s-default .cm-qualifier{color:#555}.jupyter-wrapper .cm-s-default .cm-builtin{color:#30a}.jupyter-wrapper .cm-s-default .cm-bracket{color:#997}.jupyter-wrapper .cm-s-default .cm-tag{color:#170}.jupyter-wrapper .cm-s-default .cm-attribute{color:#00c}.jupyter-wrapper .cm-s-default .cm-hr{color:#999}.jupyter-wrapper .cm-s-default .cm-link{color:#00c}.jupyter-wrapper .cm-s-default .cm-error,.jupyter-wrapper .cm-invalidchar{color:red}.jupyter-wrapper .CodeMirror-composing{border-bottom:2px solid}.jupyter-wrapper div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}.jupyter-wrapper div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.jupyter-wrapper .CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.jupyter-wrapper .CodeMirror-activeline-background{background:#e8f2ff}.jupyter-wrapper .CodeMirror{position:relative;overflow:hidden;background:white}.jupyter-wrapper .CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative}.jupyter-wrapper .CodeMirror-sizer{position:relative;border-right:50px solid transparent}.jupyter-wrapper .CodeMirror-vscrollbar,.jupyter-wrapper .CodeMirror-hscrollbar,.jupyter-wrapper .CodeMirror-scrollbar-filler,.jupyter-wrapper .CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.jupyter-wrapper .CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.jupyter-wrapper .CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.jupyter-wrapper .CodeMirror-scrollbar-filler{right:0;bottom:0}.jupyter-wrapper .CodeMirror-gutter-filler{left:0;bottom:0}.jupyter-wrapper .CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.jupyter-wrapper .CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.jupyter-wrapper .CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.jupyter-wrapper .CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.jupyter-wrapper .CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.jupyter-wrapper .CodeMirror-gutter-wrapper ::selection{background-color:transparent}.jupyter-wrapper .CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.jupyter-wrapper .CodeMirror-lines{cursor:text;min-height:1px}.jupyter-wrapper .CodeMirror pre.CodeMirror-line,.jupyter-wrapper .CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.jupyter-wrapper .CodeMirror-wrap pre.CodeMirror-line,.jupyter-wrapper .CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.jupyter-wrapper .CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.jupyter-wrapper .CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.jupyter-wrapper .CodeMirror-rtl pre{direction:rtl}.jupyter-wrapper .CodeMirror-code{outline:none}.jupyter-wrapper .CodeMirror-scroll,.jupyter-wrapper .CodeMirror-sizer,.jupyter-wrapper .CodeMirror-gutter,.jupyter-wrapper .CodeMirror-gutters,.jupyter-wrapper .CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.jupyter-wrapper .CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.jupyter-wrapper .CodeMirror-cursor{position:absolute;pointer-events:none}.jupyter-wrapper .CodeMirror-measure pre{position:static}.jupyter-wrapper div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.jupyter-wrapper div.CodeMirror-dragcursors,.jupyter-wrapper .CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.jupyter-wrapper .CodeMirror-selected{background:#d9d9d9}.jupyter-wrapper .CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.jupyter-wrapper .CodeMirror-crosshair{cursor:crosshair}.jupyter-wrapper .CodeMirror-line::selection,.jupyter-wrapper .CodeMirror-line>span::selection,.jupyter-wrapper .CodeMirror-line>span>span::selection{background:#d7d4f0}.jupyter-wrapper .CodeMirror-line::-moz-selection,.jupyter-wrapper .CodeMirror-line>span::-moz-selection,.jupyter-wrapper .CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.jupyter-wrapper .cm-searching{background-color:#ffa;background-color:#ff06}.jupyter-wrapper .cm-force-border{padding-right:.1px}@media print{.jupyter-wrapper .CodeMirror div.CodeMirror-cursors{visibility:hidden}}.jupyter-wrapper .cm-tab-wrap-hack:after{content:\"\"}.jupyter-wrapper span.CodeMirror-selectedtext{background:none}.jupyter-wrapper .CodeMirror-dialog{position:absolute;left:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.jupyter-wrapper .CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.jupyter-wrapper .CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.jupyter-wrapper .CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.jupyter-wrapper .CodeMirror-dialog button{font-size:70%}.jupyter-wrapper .CodeMirror-foldmarker{color:#00f;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.jupyter-wrapper .CodeMirror-foldgutter{width:.7em}.jupyter-wrapper .CodeMirror-foldgutter-open,.jupyter-wrapper .CodeMirror-foldgutter-folded{cursor:pointer}.jupyter-wrapper .CodeMirror-foldgutter-open:after{content:\"\u25be\"}.jupyter-wrapper .CodeMirror-foldgutter-folded:after{content:\"\u25b8\"}.jupyter-wrapper .CodeMirror{line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);font-family:var(--jp-code-font-family);border:0;border-radius:0;height:auto}.jupyter-wrapper .CodeMirror pre{padding:0 var(--jp-code-padding)}.jupyter-wrapper .CodeMirror.cm-fat-cursor .cm-overlay.cm-searching{opacity:.5}.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-dialog{background-color:var(--jp-layout-color0);color:var(--jp-content-font-color1)}.jupyter-wrapper .CodeMirror-lines{padding:var(--jp-code-padding) 0}.jupyter-wrapper .CodeMirror-linenumber{padding:0 8px}.jupyter-wrapper .jp-CodeMirrorEditor{cursor:text}.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)}@media screen and (min-width: 2138px) and (max-width: 4319px){.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width1) solid var(--jp-editor-cursor-color)}}@media screen and (min-width: 4320px){.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width2) solid var(--jp-editor-cursor-color)}}.jupyter-wrapper .CodeMirror.jp-mod-readOnly .CodeMirror-cursor{display:none}.jupyter-wrapper .CodeMirror-gutters{border-right:1px solid var(--jp-border-color2);background-color:var(--jp-layout-color0)}.jupyter-wrapper .jp-CollaboratorCursor{border-left:5px solid transparent;border-right:5px solid transparent;border-top:none;border-bottom:3px solid;background-clip:content-box;margin-left:-5px;margin-right:-5px}.jupyter-wrapper .CodeMirror-selectedtext.cm-searching{background-color:var(--jp-search-selected-match-background-color)!important;color:var(--jp-search-selected-match-color)!important}.jupyter-wrapper .cm-searching{background-color:var(--jp-search-unselected-match-background-color)!important;color:var(--jp-search-unselected-match-color)!important}.jupyter-wrapper .cm-trailingspace{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAsElEQVQIHQGlAFr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7+r3zKmT0/+pk9P/7+r3zAAAAAAAAAAABAAAAAAAAAAA6OPzM+/q9wAAAAAA6OPzMwAAAAAAAAAAAgAAAAAAAAAAGR8NiRQaCgAZIA0AGR8NiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQyoYJ/SY80UAAAAASUVORK5CYII=);background-position:center left;background-repeat:repeat-x}.jupyter-wrapper .CodeMirror-focused .CodeMirror-selected{background-color:var(--jp-editor-selected-focused-background)}.jupyter-wrapper .CodeMirror-selected{background-color:var(--jp-editor-selected-background)}.jupyter-wrapper .jp-CollaboratorCursor-hover{position:absolute;z-index:1;transform:translate(-50%);color:#fff;border-radius:3px;padding:1px 4px;text-align:center;font-size:var(--jp-ui-font-size1);white-space:nowrap}.jupyter-wrapper .jp-CodeMirror-ruler{border-left:1px dashed var(--jp-border-color2)}.jupyter-wrapper .CodeMirror.cm-s-jupyter{background:var(--jp-layout-color0);color:var(--jp-content-font-color1)}.jupyter-wrapper .jp-CodeConsole .CodeMirror.cm-s-jupyter,.jupyter-wrapper .jp-Notebook .CodeMirror.cm-s-jupyter{background:transparent}.jupyter-wrapper .cm-s-jupyter .CodeMirror-cursor{border-left:var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)}.jupyter-wrapper .cm-s-jupyter span.cm-keyword{color:var(--jp-mirror-editor-keyword-color);font-weight:700}.jupyter-wrapper .cm-s-jupyter span.cm-atom{color:var(--jp-mirror-editor-atom-color)}.jupyter-wrapper .cm-s-jupyter span.cm-number{color:var(--jp-mirror-editor-number-color)}.jupyter-wrapper .cm-s-jupyter span.cm-def{color:var(--jp-mirror-editor-def-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable{color:var(--jp-mirror-editor-variable-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable-2{color:var(--jp-mirror-editor-variable-2-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable-3{color:var(--jp-mirror-editor-variable-3-color)}.jupyter-wrapper .cm-s-jupyter span.cm-punctuation{color:var(--jp-mirror-editor-punctuation-color)}.jupyter-wrapper .cm-s-jupyter span.cm-property{color:var(--jp-mirror-editor-property-color)}.jupyter-wrapper .cm-s-jupyter span.cm-operator{color:var(--jp-mirror-editor-operator-color);font-weight:700}.jupyter-wrapper .cm-s-jupyter span.cm-comment{color:var(--jp-mirror-editor-comment-color);font-style:italic}.jupyter-wrapper .cm-s-jupyter span.cm-string{color:var(--jp-mirror-editor-string-color)}.jupyter-wrapper .cm-s-jupyter span.cm-string-2{color:var(--jp-mirror-editor-string-2-color)}.jupyter-wrapper .cm-s-jupyter span.cm-meta{color:var(--jp-mirror-editor-meta-color)}.jupyter-wrapper .cm-s-jupyter span.cm-qualifier{color:var(--jp-mirror-editor-qualifier-color)}.jupyter-wrapper .cm-s-jupyter span.cm-builtin{color:var(--jp-mirror-editor-builtin-color)}.jupyter-wrapper .cm-s-jupyter span.cm-bracket{color:var(--jp-mirror-editor-bracket-color)}.jupyter-wrapper .cm-s-jupyter span.cm-tag{color:var(--jp-mirror-editor-tag-color)}.jupyter-wrapper .cm-s-jupyter span.cm-attribute{color:var(--jp-mirror-editor-attribute-color)}.jupyter-wrapper .cm-s-jupyter span.cm-header{color:var(--jp-mirror-editor-header-color)}.jupyter-wrapper .cm-s-jupyter span.cm-quote{color:var(--jp-mirror-editor-quote-color)}.jupyter-wrapper .cm-s-jupyter span.cm-link{color:var(--jp-mirror-editor-link-color)}.jupyter-wrapper .cm-s-jupyter span.cm-error{color:var(--jp-mirror-editor-error-color)}.jupyter-wrapper .cm-s-jupyter span.cm-hr{color:#999}.jupyter-wrapper .cm-s-jupyter span.cm-tab{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);background-position:right;background-repeat:no-repeat}.jupyter-wrapper .cm-s-jupyter .CodeMirror-activeline-background,.jupyter-wrapper .cm-s-jupyter .CodeMirror-gutter{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret{position:relative;border-left:2px solid black;margin-left:-1px;margin-right:-1px;box-sizing:border-box}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret>div{white-space:nowrap;position:absolute;top:-1.15em;padding-bottom:.05em;left:-2px;font-size:.95em;background-color:#fa8100;font-family:var(--jp-ui-font-family);font-weight:700;line-height:normal;-webkit-user-select:none;user-select:none;color:#fff;padding-left:2px;padding-right:2px;z-index:3;transition:opacity .3s ease-in-out}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret.hide-name>div{transition-delay:.7s;opacity:0}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret:hover>div[style]{opacity:1;transition-delay:0s}.jupyter-wrapper :root{--jp-private-code-span-padding: calc( (var(--jp-code-line-height) - 1) * var(--jp-code-font-size) / 2 )}.jupyter-wrapper .jp-RenderedText{text-align:left;padding-left:var(--jp-code-padding);line-height:var(--jp-code-line-height);font-family:var(--jp-code-font-family)}.jupyter-wrapper .jp-RenderedText pre,.jupyter-wrapper .jp-RenderedJavaScript pre,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore pre{color:var(--jp-content-font-color1);font-size:var(--jp-code-font-size);border:none;margin:0;padding:0}.jupyter-wrapper .jp-RenderedText pre a:link{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre a:hover{text-decoration:underline;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre a:visited{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre .ansi-black-fg{color:#3e424d}.jupyter-wrapper .jp-RenderedText pre .ansi-red-fg{color:#e75c58}.jupyter-wrapper .jp-RenderedText pre .ansi-green-fg{color:#00a250}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-fg{color:#ddb62b}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-fg{color:#208ffb}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-fg{color:#d160c4}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-fg{color:#60c6c8}.jupyter-wrapper .jp-RenderedText pre .ansi-white-fg{color:#c5c1b4}.jupyter-wrapper .jp-RenderedText pre .ansi-black-bg{background-color:#3e424d;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-red-bg{background-color:#e75c58;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-green-bg{background-color:#00a250;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-bg{background-color:#ddb62b;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-bg{background-color:#208ffb;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-bg{background-color:#d160c4;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-bg{background-color:#60c6c8;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-white-bg{background-color:#c5c1b4;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-black-intense-fg{color:#282c36}.jupyter-wrapper .jp-RenderedText pre .ansi-red-intense-fg{color:#b22b31}.jupyter-wrapper .jp-RenderedText pre .ansi-green-intense-fg{color:#007427}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-intense-fg{color:#b27d12}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-intense-fg{color:#0065ca}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-intense-fg{color:#a03196}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-intense-fg{color:#258f8f}.jupyter-wrapper .jp-RenderedText pre .ansi-white-intense-fg{color:#a1a6b2}.jupyter-wrapper .jp-RenderedText pre .ansi-black-intense-bg{background-color:#282c36;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-red-intense-bg{background-color:#b22b31;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-green-intense-bg{background-color:#007427;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-intense-bg{background-color:#b27d12;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-intense-bg{background-color:#0065ca;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-intense-bg{background-color:#a03196;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-intense-bg{background-color:#258f8f;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-white-intense-bg{background-color:#a1a6b2;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-default-inverse-fg{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .jp-RenderedText pre .ansi-default-inverse-bg{background-color:var(--jp-inverse-layout-color0);padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-bold{font-weight:700}.jupyter-wrapper .jp-RenderedText pre .ansi-underline{text-decoration:underline}.jupyter-wrapper .jp-RenderedText[data-mime-type=\"application/vnd.jupyter.stderr\"]{background:var(--jp-rendermime-error-background);padding-top:var(--jp-code-padding)}.jupyter-wrapper .jp-RenderedLatex{color:var(--jp-content-font-color1);font-size:var(--jp-content-font-size1);line-height:var(--jp-content-line-height)}.jupyter-wrapper .jp-OutputArea-output.jp-RenderedLatex{padding:var(--jp-code-padding);text-align:left}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore{color:var(--jp-content-font-color1);font-family:var(--jp-content-font-family);font-size:var(--jp-content-font-size1);line-height:var(--jp-content-line-height);padding-right:20px}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore em{font-style:italic}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore strong{font-weight:700}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore u{text-decoration:underline}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:link{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:hover{text-decoration:underline;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:visited{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6{line-height:var(--jp-content-heading-line-height);font-weight:var(--jp-content-heading-font-weight);font-style:normal;margin:var(--jp-content-heading-margin-top) 0 var(--jp-content-heading-margin-bottom) 0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6:first-child{margin-top:calc(.5 * var(--jp-content-heading-margin-top))}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6:last-child{margin-bottom:calc(.5 * var(--jp-content-heading-margin-bottom))}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1{font-size:var(--jp-content-font-size5)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2{font-size:var(--jp-content-font-size4)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3{font-size:var(--jp-content-font-size3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4{font-size:var(--jp-content-font-size2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5{font-size:var(--jp-content-font-size1)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6{font-size:var(--jp-content-font-size0)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul:not(.list-inline),.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol:not(.list-inline){padding-left:2em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul{list-style:disc}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul{list-style:square}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul ul{list-style:circle}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol{list-style:decimal}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol{list-style:upper-alpha}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol{list-style:lower-alpha}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol ol{list-style:lower-roman}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol ol ol{list-style:decimal}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ol,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ul,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore hr{color:var(--jp-border-color2);background-color:var(--jp-border-color1);margin-top:1em;margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>pre{margin:1.5em 2em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore pre,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore code{border:0;background-color:var(--jp-layout-color0);color:var(--jp-content-font-color1);font-family:var(--jp-code-font-family);font-size:inherit;line-height:var(--jp-code-line-height);padding:0;white-space:pre-wrap}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore :not(pre)>code{background-color:var(--jp-layout-color2);padding:1px 5px}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore table{border-collapse:collapse;border-spacing:0;border:none;color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);table-layout:fixed;margin-left:auto;margin-right:auto}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore thead{border-bottom:var(--jp-border-width) solid var(--jp-border-color1);vertical-align:bottom}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore th,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tr{vertical-align:middle;padding:.5em;line-height:normal;white-space:normal;max-width:none;border:none}.jupyter-wrapper .jp-RenderedMarkdown.jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper .jp-RenderedMarkdown.jp-RenderedHTMLCommon-ignore th{max-width:none}.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore th,.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore tr{text-align:right}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore th{font-weight:700}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:nth-child(odd){background:var(--jp-layout-color0)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:nth-child(2n){background:var(--jp-rendermime-table-row-background)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:hover{background:var(--jp-rendermime-table-row-hover-background)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore table{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore p{text-align:left;margin:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore p{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img{-moz-force-broken-image-icon:1}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>img{display:block;margin-left:0;margin-right:0;margin-bottom:1em}.jupyter-wrapper [data-jp-theme-light=false] .jp-RenderedImage img.jp-needs-light-background,.jupyter-wrapper [data-jp-theme-light=true] .jp-RenderedImage img.jp-needs-dark-background{background-color:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img,.jupyter-wrapper .jp-RenderedImage img,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore svg,.jupyter-wrapper .jp-RenderedSVG svg{max-width:100%;height:auto}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedImage img.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore svg.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedSVG svg.jp-mod-unconfined{max-width:none}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert{padding:var(--jp-notebook-padding);border:var(--jp-border-width) solid transparent;border-radius:var(--jp-border-radius);margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info{color:var(--jp-info-color0);background-color:var(--jp-info-color3);border-color:var(--jp-info-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info hr{border-color:var(--jp-info-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning{color:var(--jp-warn-color0);background-color:var(--jp-warn-color3);border-color:var(--jp-warn-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning hr{border-color:var(--jp-warn-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success{color:var(--jp-success-color0);background-color:var(--jp-success-color3);border-color:var(--jp-success-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success hr{border-color:var(--jp-success-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger{color:var(--jp-error-color0);background-color:var(--jp-error-color3);border-color:var(--jp-error-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger hr{border-color:var(--jp-error-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore blockquote{margin:1em 2em;padding:0 1em;border-left:5px solid var(--jp-border-color2)}.jupyter-wrapper a.jp-InternalAnchorLink{visibility:hidden;margin-left:8px;color:var(--md-blue-800)}.jupyter-wrapper h1:hover .jp-InternalAnchorLink,.jupyter-wrapper h2:hover .jp-InternalAnchorLink,.jupyter-wrapper h3:hover .jp-InternalAnchorLink,.jupyter-wrapper h4:hover .jp-InternalAnchorLink,.jupyter-wrapper h5:hover .jp-InternalAnchorLink,.jupyter-wrapper h6:hover .jp-InternalAnchorLink{visibility:visible}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore kbd{background-color:var(--jp-rendermime-table-row-background);border:1px solid var(--jp-border-color0);border-bottom-color:var(--jp-border-color2);border-radius:3px;box-shadow:inset 0 -1px #00000040;display:inline-block;font-size:var(--jp-ui-font-size0);line-height:1em;padding:.2em .5em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>*:last-child{margin-bottom:.5em}.jupyter-wrapper .jp-MimeDocument{outline:none}.jupyter-wrapper :root{--jp-private-filebrowser-button-height: 28px;--jp-private-filebrowser-button-width: 48px}.jupyter-wrapper .jp-FileBrowser{display:flex;flex-direction:column;color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .jp-FileBrowser-toolbar.jp-Toolbar{border-bottom:none;height:auto;margin:8px 12px 0;padding:0;box-shadow:none;justify-content:flex-start}.jupyter-wrapper .jp-BreadCrumbs{flex:0 0 auto;margin:8px 12px}.jupyter-wrapper .jp-BreadCrumbs-item{margin:0 2px;padding:0 2px;border-radius:var(--jp-border-radius);cursor:pointer}.jupyter-wrapper .jp-BreadCrumbs-item:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-BreadCrumbs-item:first-child{margin-left:0}.jupyter-wrapper .jp-BreadCrumbs-item.jp-mod-dropTarget{background-color:var(--jp-brand-color2);opacity:.7}.jupyter-wrapper .jp-FileBrowser-toolbar>.jp-Toolbar-item{flex:0 0 auto;padding-left:0;padding-right:2px}.jupyter-wrapper .jp-FileBrowser-toolbar>.jp-Toolbar-item .jp-ToolbarButtonComponent{width:40px}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]{width:72px;background:var(--jp-brand-color1)}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]:hover,.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]:focus-visible{background-color:var(--jp-brand-color0)!important}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"] .jp-icon3{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-FileDialog.jp-mod-conflict input{color:var(--jp-error-color1)}.jupyter-wrapper .jp-FileDialog .jp-new-name-title{margin-top:12px}.jupyter-wrapper .jp-LastModified-hidden{display:none}.jupyter-wrapper .jp-FileBrowser-filterBox{padding:0;flex:0 0 auto;margin:8px 12px 0}.jupyter-wrapper .jp-DirListing{flex:1 1 auto;display:flex;flex-direction:column;outline:0}.jupyter-wrapper .jp-DirListing:focus-visible{outline:1px solid var(--jp-brand-color1);outline-offset:-2px}.jupyter-wrapper .jp-DirListing-header{flex:0 0 auto;display:flex;flex-direction:row;overflow:hidden;border-top:var(--jp-border-width) solid var(--jp-border-color2);border-bottom:var(--jp-border-width) solid var(--jp-border-color1);box-shadow:var(--jp-toolbar-box-shadow);z-index:2}.jupyter-wrapper .jp-DirListing-headerItem{padding:4px 12px 2px;font-weight:500}.jupyter-wrapper .jp-DirListing-headerItem:hover{background:var(--jp-layout-color2)}.jupyter-wrapper .jp-DirListing-headerItem.jp-id-name{flex:1 0 84px}.jupyter-wrapper .jp-DirListing-headerItem.jp-id-modified{flex:0 0 112px;border-left:var(--jp-border-width) solid var(--jp-border-color2);text-align:right}.jupyter-wrapper .jp-id-narrow{display:none;flex:0 0 5px;padding:4px;border-left:var(--jp-border-width) solid var(--jp-border-color2);text-align:right;color:var(--jp-border-color2)}.jupyter-wrapper .jp-DirListing-narrow .jp-id-narrow{display:block}.jupyter-wrapper .jp-DirListing-narrow .jp-id-modified,.jupyter-wrapper .jp-DirListing-narrow .jp-DirListing-itemModified{display:none}.jupyter-wrapper .jp-DirListing-headerItem.jp-mod-selected{font-weight:600}.jupyter-wrapper .jp-DirListing-content{flex:1 1 auto;margin:0;padding:0;list-style-type:none;overflow:auto;background-color:var(--jp-layout-color1)}.jupyter-wrapper .jp-DirListing-content mark{color:var(--jp-ui-font-color0);background-color:transparent;font-weight:700}.jupyter-wrapper .jp-DirListing-content .jp-DirListing-item.jp-mod-selected mark{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .jp-DirListing.jp-mod-native-drop .jp-DirListing-content{outline:5px dashed rgba(128,128,128,.5);outline-offset:-10px;cursor:copy}.jupyter-wrapper .jp-DirListing-item{display:flex;flex-direction:row;padding:4px 12px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .jp-DirListing-item[data-is-dot]{opacity:75%}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected{color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .jp-DirListing-item.jp-mod-dropTarget{background:var(--jp-brand-color3)}.jupyter-wrapper .jp-DirListing-item:hover:not(.jp-mod-selected){background:var(--jp-layout-color2)}.jupyter-wrapper .jp-DirListing-itemIcon{flex:0 0 20px;margin-right:4px}.jupyter-wrapper .jp-DirListing-itemText{flex:1 0 64px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;user-select:none}.jupyter-wrapper .jp-DirListing-itemModified{flex:0 0 125px;text-align:right}.jupyter-wrapper .jp-DirListing-editor{flex:1 0 64px;outline:none;border:none;color:var(--jp-ui-font-color1);background-color:var(--jp-layout-color1)}.jupyter-wrapper .jp-DirListing-item.jp-mod-running .jp-DirListing-itemIcon:before{color:var(--jp-success-color1);content:\"\u25cf\";font-size:8px;position:absolute;left:-8px}.jupyter-wrapper .jp-DirListing-item.jp-mod-running.jp-mod-selected .jp-DirListing-itemIcon:before{color:var(--jp-ui-inverse-font-color1)}.jupyter-wrapper .jp-DirListing-item.lm-mod-drag-image,.jupyter-wrapper .jp-DirListing-item.jp-mod-selected.lm-mod-drag-image{font-size:var(--jp-ui-font-size1);padding-left:4px;margin-left:4px;width:160px;background-color:var(--jp-ui-inverse-font-color2);box-shadow:var(--jp-elevation-z2);border-radius:0;color:var(--jp-ui-font-color1);transform:translate(-40%) translateY(-58%)}.jupyter-wrapper .jp-Document{min-width:120px;min-height:120px;outline:none}.jupyter-wrapper .jp-OutputArea{overflow-y:auto}.jupyter-wrapper .jp-OutputArea-child{display:flex;flex-direction:row}.jupyter-wrapper body[data-format=mobile] .jp-OutputArea-child{flex-direction:column}.jupyter-wrapper .jp-OutputPrompt{flex:0 0 var(--jp-cell-prompt-width);color:var(--jp-cell-outprompt-font-color);font-family:var(--jp-cell-prompt-font-family);padding:var(--jp-code-padding);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent;opacity:var(--jp-cell-prompt-opacity);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper body[data-format=mobile] .jp-OutputPrompt{flex:0 0 auto;text-align:left}.jupyter-wrapper .jp-OutputArea-output{height:auto;overflow:auto;user-select:text;-moz-user-select:text;-webkit-user-select:text;-ms-user-select:text}.jupyter-wrapper .jp-OutputArea-child .jp-OutputArea-output{flex-grow:1;flex-shrink:1}.jupyter-wrapper body[data-format=mobile] .jp-OutputArea-child .jp-OutputArea-output{margin-left:var(--jp-notebook-padding)}.jupyter-wrapper .jp-OutputArea-output.jp-mod-isolated{width:100%;display:block}.jupyter-wrapper body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated{position:relative}.jupyter-wrapper body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated:before{content:\"\";position:absolute;top:0;left:0;right:0;bottom:0;background:transparent}.jupyter-wrapper .jp-OutputArea-output pre{border:none;margin:0;padding:0;overflow-x:auto;overflow-y:auto;word-break:break-all;word-wrap:break-word;white-space:pre-wrap}.jupyter-wrapper .jp-OutputArea-output.jp-RenderedHTMLCommon-ignore table{margin-left:0;margin-right:0}.jupyter-wrapper .jp-OutputArea-output dl,.jupyter-wrapper .jp-OutputArea-output dt,.jupyter-wrapper .jp-OutputArea-output dd{display:block}.jupyter-wrapper .jp-OutputArea-output dl{width:100%;overflow:hidden;padding:0;margin:0}.jupyter-wrapper .jp-OutputArea-output dt{font-weight:700;float:left;width:20%;padding:0;margin:0}.jupyter-wrapper .jp-OutputArea-output dd{float:left;width:80%;padding:0;margin:0}.jupyter-wrapper .jp-TrimmedOutputs a{margin:10px;text-decoration:none;cursor:pointer}.jupyter-wrapper .jp-OutputArea .jp-OutputArea .jp-OutputArea-prompt{display:none}.jupyter-wrapper .jp-OutputArea-prompt:empty{padding:0;border:0}.jupyter-wrapper .jp-OutputArea-output.jp-OutputArea-executeResult{margin-left:0;flex:1 1 auto}.jupyter-wrapper .jp-OutputArea-executeResult .jp-RenderedText.jp-OutputArea-output{padding-top:var(--jp-code-padding);border-top:var(--jp-border-width) solid transparent}.jupyter-wrapper .jp-Stdin-prompt{color:var(--jp-content-font-color0);padding-right:var(--jp-code-padding);vertical-align:baseline;flex:0 0 auto}.jupyter-wrapper .jp-Stdin-input{font-family:var(--jp-code-font-family);font-size:inherit;color:inherit;background-color:inherit;width:42%;min-width:200px;vertical-align:baseline;padding:0 .25em;margin:0 .25em;flex:0 0 70%}.jupyter-wrapper .jp-Stdin-input::placeholder{opacity:0}.jupyter-wrapper .jp-Stdin-input:focus{box-shadow:none}.jupyter-wrapper .jp-Stdin-input:focus::placeholder{opacity:1}.jupyter-wrapper .jp-LinkedOutputView .jp-OutputArea{height:100%;display:block}.jupyter-wrapper .jp-LinkedOutputView .jp-OutputArea-output:only-child{height:100%}.jupyter-wrapper .jp-Collapser{flex:0 0 var(--jp-cell-collapser-width);padding:0;margin:0;border:none;outline:none;background:transparent;border-radius:var(--jp-border-radius);opacity:1}.jupyter-wrapper .jp-Collapser-child{display:block;width:100%;box-sizing:border-box;position:absolute;top:0;bottom:0}.jupyter-wrapper .jp-CellHeader,.jupyter-wrapper .jp-CellFooter{height:0px;width:100%;padding:0;margin:0;border:none;outline:none;background:transparent}.jupyter-wrapper .jp-InputArea{display:flex;flex-direction:row;overflow:hidden}.jupyter-wrapper body[data-format=mobile] .jp-InputArea{flex-direction:column}.jupyter-wrapper .jp-InputArea-editor{flex:1 1 auto;overflow:hidden}.jupyter-wrapper .jp-InputArea-editor{border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);border-radius:0;background:var(--jp-cell-editor-background)}.jupyter-wrapper body[data-format=mobile] .jp-InputArea-editor{margin-left:var(--jp-notebook-padding)}.jupyter-wrapper .jp-InputPrompt{flex:0 0 var(--jp-cell-prompt-width);color:var(--jp-cell-inprompt-font-color);font-family:var(--jp-cell-prompt-font-family);padding:var(--jp-code-padding);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent;opacity:var(--jp-cell-prompt-opacity);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper body[data-format=mobile] .jp-InputPrompt{flex:0 0 auto;text-align:left}.jupyter-wrapper .jp-Placeholder{display:flex;flex-direction:row;flex:1 1 auto}.jupyter-wrapper .jp-Placeholder-prompt{box-sizing:border-box}.jupyter-wrapper .jp-Placeholder-content{flex:1 1 auto;border:none;background:transparent;height:20px;box-sizing:border-box}.jupyter-wrapper .jp-Placeholder-content .jp-MoreHorizIcon{width:32px;height:16px;border:1px solid transparent;border-radius:var(--jp-border-radius)}.jupyter-wrapper .jp-Placeholder-content .jp-MoreHorizIcon:hover{border:1px solid var(--jp-border-color1);box-shadow:0 0 2px #00000040;background-color:var(--jp-layout-color0)}.jupyter-wrapper :root{--jp-private-cell-scrolling-output-offset: 5px}.jupyter-wrapper .jp-Cell{padding:var(--jp-cell-padding);margin:0;border:none;outline:none;background:transparent}.jupyter-wrapper .jp-Cell-inputWrapper,.jupyter-wrapper .jp-Cell-outputWrapper{display:flex;flex-direction:row;padding:0;margin:0;overflow:visible}.jupyter-wrapper .jp-Cell-inputArea,.jupyter-wrapper .jp-Cell-outputArea{flex:1 1 auto}.jupyter-wrapper .jp-Cell.jp-mod-noOutputs .jp-Cell-outputCollapser{border:none!important;background:transparent!important}.jupyter-wrapper .jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputCollapser{min-height:var(--jp-cell-collapser-min-height)}.jupyter-wrapper .jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputWrapper{margin-top:5px}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea{overflow-y:auto;max-height:24em;margin-left:var(--jp-private-cell-scrolling-output-offset)}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea:after{content:\" \";box-shadow:inset 0 0 6px 2px #0000004d;width:100%;height:100%;position:sticky;bottom:0;top:0;margin-top:-50%;float:left;display:block;pointer-events:none}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-child{padding-top:6px}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-prompt{flex:0 0 calc(var(--jp-cell-prompt-width) - var(--jp-private-cell-scrolling-output-offset))}.jupyter-wrapper .jp-MarkdownOutput{flex:1 1 auto;margin-top:0;margin-bottom:0;padding-left:var(--jp-code-padding)}.jupyter-wrapper .jp-MarkdownOutput.jp-RenderedHTMLCommon-ignore{overflow:auto}.jupyter-wrapper .jp-collapseHeadingButton{display:none;min-height:var(--jp-cell-collapser-min-height);font-size:var(--jp-code-font-size);position:absolute;right:0;top:0;bottom:0;background-color:transparent;background-size:25px;background-repeat:no-repeat;background-position-x:center;background-position-y:top;background-image:var(--jp-icon-caret-down);border:none;cursor:pointer}.jupyter-wrapper .jp-collapseHeadingButton:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-collapseHeadingButton.jp-mod-collapsed{background-image:var(--jp-icon-caret-right)}.jupyter-wrapper :is(.jp-MarkdownCell:hover,.jp-mod-active) .jp-collapseHeadingButton{display:flex}.jupyter-wrapper .jp-MarkdownCell .jp-InputPrompt{font-size:var(--jp-content-font-size1)}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"1\"]{font-size:var(--jp-content-font-size5);background-position-y:calc(.3 * var(--jp-content-font-size5))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"2\"]{font-size:var(--jp-content-font-size4);background-position-y:calc(.3 * var(--jp-content-font-size4))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"3\"]{font-size:var(--jp-content-font-size3);background-position-y:calc(.3 * var(--jp-content-font-size3))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"4\"]{font-size:var(--jp-content-font-size2);background-position-y:calc(.3 * var(--jp-content-font-size2))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"5\"]{font-size:var(--jp-content-font-size1);background-position-y:top}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"6\"]{font-size:var(--jp-content-font-size0);background-position-y:top}.jupyter-wrapper .jp-showHiddenCellsButton{margin-left:calc(var(--jp-cell-prompt-width) + 2 * var(--jp-code-padding));margin-top:var(--jp-code-padding);border:1px solid var(--jp-border-color2);background-color:var(--jp-border-color3)!important;color:var(--jp-content-font-color0)!important}.jupyter-wrapper .jp-showHiddenCellsButton:hover{background-color:var(--jp-border-color2)!important}.jupyter-wrapper :root{--jp-notebook-toolbar-padding: 2px 5px 2px 2px}.jupyter-wrapper .jp-NotebookPanel-toolbar{padding:var(--jp-notebook-toolbar-padding)}.jupyter-wrapper .jp-Toolbar-item.jp-Notebook-toolbarCellType .jp-select-wrapper.jp-mod-focused{border:none;box-shadow:none}.jupyter-wrapper .jp-Notebook-toolbarCellTypeDropdown select{height:24px;font-size:var(--jp-ui-font-size1);line-height:14px;border-radius:0;display:block}.jupyter-wrapper .jp-Notebook-toolbarCellTypeDropdown span{top:5px!important}.jupyter-wrapper .jp-Toolbar-responsive-popup{position:absolute;height:fit-content;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-end;border-bottom:var(--jp-border-width) solid var(--jp-toolbar-border-color);box-shadow:var(--jp-toolbar-box-shadow);background:var(--jp-toolbar-background);min-height:var(--jp-toolbar-micro-height);padding:var(--jp-notebook-toolbar-padding);z-index:1;right:0;top:0}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-responsive-opener{margin-left:auto}.jupyter-wrapper .jp-Notebook-ExecutionIndicator{position:relative;display:inline-block;height:100%;z-index:9997}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip{visibility:hidden;height:auto;width:max-content;width:-moz-max-content;background-color:var(--jp-layout-color2);color:var(--jp-ui-font-color1);text-align:justify;border-radius:6px;padding:0 5px;position:fixed;display:table}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.up{transform:translate(-50%) translateY(-100%) translateY(-32px)}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.down{transform:translate(calc(-100% + 16px)) translateY(5px)}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.hidden{display:none}.jupyter-wrapper .jp-Notebook-ExecutionIndicator:hover .jp-Notebook-ExecutionIndicator-tooltip{visibility:visible}.jupyter-wrapper .jp-Notebook-ExecutionIndicator span{font-size:var(--jp-ui-font-size1);font-family:var(--jp-ui-font-family);color:var(--jp-ui-font-color1);line-height:24px;display:block}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-progress-bar{display:flex;justify-content:center;height:100%}.jupyter-wrapper :root{--jp-private-notebook-dragImage-width: 304px;--jp-private-notebook-dragImage-height: 36px;--jp-private-notebook-selected-color: var(--md-blue-400);--jp-private-notebook-active-color: var(--md-green-400)}.jupyter-wrapper .jp-NotebookPanel{display:block;height:100%}.jupyter-wrapper .jp-NotebookPanel.jp-Document{min-width:240px;min-height:120px}.jupyter-wrapper .jp-Notebook{padding:var(--jp-notebook-padding);outline:none;overflow:auto}.jupyter-wrapper .jp-Notebook.jp-mod-scrollPastEnd:after{display:block;content:\"\";min-height:var(--jp-notebook-scroll-padding)}.jupyter-wrapper .jp-MainAreaWidget-ContainStrict .jp-Notebook *{contain:strict}.jupyter-wrapper .jp-Notebook .jp-Cell{overflow:visible}.jupyter-wrapper .jp-Notebook .jp-Cell .jp-InputPrompt{cursor:move;float:left}.jupyter-wrapper .jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-InputPrompt{opacity:var(--jp-cell-prompt-not-active-opacity);color:var(--jp-cell-prompt-not-active-font-color)}.jupyter-wrapper .jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-OutputPrompt{opacity:var(--jp-cell-prompt-not-active-opacity);color:var(--jp-cell-prompt-not-active-font-color)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser{background:var(--jp-brand-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt{color:var(--jp-warn-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt:before{color:var(--jp-warn-color1);content:\"\u2022\"}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active.jp-mod-dirty .jp-Collapser{background:var(--jp-warn-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell .jp-Collapser:hover{box-shadow:var(--jp-elevation-z2);background:var(--jp-brand-color1);opacity:var(--jp-cell-collapser-not-active-hover-opacity)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover{background:var(--jp-brand-color0);opacity:1}.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-selected{background:var(--jp-notebook-multiselected-color)}.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-active.jp-mod-selected:not(.jp-mod-multiSelected){background:transparent}.jupyter-wrapper .jp-Notebook.jp-mod-editMode .jp-Cell.jp-mod-active .jp-InputArea-editor{border:var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);box-shadow:var(--jp-input-box-shadow);background-color:var(--jp-cell-editor-active-background)}.jupyter-wrapper .jp-Notebook-cell.jp-mod-dropSource{opacity:.5}.jupyter-wrapper .jp-Notebook-cell.jp-mod-dropTarget,.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Notebook-cell.jp-mod-active.jp-mod-selected.jp-mod-dropTarget{border-top-color:var(--jp-private-notebook-selected-color);border-top-style:solid;border-top-width:2px}.jupyter-wrapper .jp-dragImage{display:block;flex-direction:row;width:var(--jp-private-notebook-dragImage-width);height:var(--jp-private-notebook-dragImage-height);border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);background:var(--jp-cell-editor-background);overflow:visible}.jupyter-wrapper .jp-dragImage-singlePrompt{box-shadow:2px 2px 4px #0000001f}.jupyter-wrapper .jp-dragImage .jp-dragImage-content{flex:1 1 auto;z-index:2;font-size:var(--jp-code-font-size);font-family:var(--jp-code-font-family);line-height:var(--jp-code-line-height);padding:var(--jp-code-padding);border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);background:var(--jp-cell-editor-background-color);color:var(--jp-content-font-color3);text-align:left;margin:4px 4px 4px 0}.jupyter-wrapper .jp-dragImage .jp-dragImage-prompt{flex:0 0 auto;min-width:36px;color:var(--jp-cell-inprompt-font-color);padding:var(--jp-code-padding);padding-left:12px;font-family:var(--jp-cell-prompt-font-family);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:1.9;font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent}.jupyter-wrapper .jp-dragImage-multipleBack{z-index:-1;position:absolute;height:32px;width:300px;top:8px;left:8px;background:var(--jp-layout-color2);border:var(--jp-border-width) solid var(--jp-input-border-color);box-shadow:2px 2px 4px #0000001f}.jupyter-wrapper .jp-NotebookTools{display:block;min-width:var(--jp-sidebar-min-width);color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1);overflow:auto}.jupyter-wrapper .jp-NotebookTools-tool{padding:0 12px}.jupyter-wrapper .jp-ActiveCellTool{padding:12px;background-color:var(--jp-layout-color1);border-top:none!important}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-prompt{flex:0 0 auto;padding-left:0}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-editor{flex:1 1 auto;background:var(--jp-cell-editor-background);border-color:var(--jp-cell-editor-border-color)}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-editor .CodeMirror{background:transparent}.jupyter-wrapper .jp-MetadataEditorTool{flex-direction:column;padding:12px 0}.jupyter-wrapper .jp-RankedPanel>:not(:first-child){margin-top:12px}.jupyter-wrapper .jp-KeySelector select.jp-mod-styled{font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);border:var(--jp-border-width) solid var(--jp-border-color1)}.jupyter-wrapper .jp-KeySelector label,.jupyter-wrapper .jp-MetadataEditorTool label{line-height:1.4}.jupyter-wrapper .jp-NotebookTools .jp-select-wrapper{margin-top:4px;margin-bottom:0}.jupyter-wrapper .jp-NotebookTools .jp-Collapse{margin-top:16px}.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook{--jp-content-font-size1: var(--jp-content-presentation-font-size1);--jp-code-font-size: var(--jp-code-presentation-font-size)}.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-InputPrompt,.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-OutputPrompt{flex:0 0 110px}.jupyter-wrapper :root{--jp-side-by-side-output-size: 1fr;--jp-side-by-side-resized-cell: var(--jp-side-by-side-output-size)}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-Notebook-cell{margin:3em 5%}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell{display:grid;grid-template-columns:minmax(0,1fr) min-content minmax(0,var(--jp-side-by-side-output-size));grid-template-rows:auto minmax(0,1fr) auto;grid-template-areas:\"header header header\" \"input handle output\" \"footer footer footer\"}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell{grid-template-columns:minmax(0,1fr) min-content minmax(0,var(--jp-side-by-side-resized-cell))}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellHeader{grid-area:header}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-inputWrapper{grid-area:input}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-outputWrapper{margin-top:0;grid-area:output}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellFooter{grid-area:footer}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle{grid-area:handle;-webkit-user-select:none;user-select:none;display:block;height:100%;cursor:ew-resize;padding:0 var(--jp-cell-padding)}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle:after{content:\"\";display:block;background:var(--jp-border-color2);height:100%;width:5px}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell .jp-CellResizeHandle:after{background:var(--jp-border-color0)}.jupyter-wrapper .jp-CellResizeHandle{display:none}.jupyter-wrapper .jp-Cell-Placeholder{padding-left:55px}.jupyter-wrapper .jp-Cell-Placeholder-wrapper{background:#fff;border:1px solid;border-color:#e5e6e9 #dfe0e4 #d0d1d5;border-radius:4px;-webkit-border-radius:4px;margin:10px 15px}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-inner{padding:15px;position:relative}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body{background-repeat:repeat;background-size:50% auto}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body div{background:#f6f7f8;background-image:-webkit-linear-gradient(left,#f6f7f8 0%,#edeef1 20%,#f6f7f8 40%,#f6f7f8 100%);background-repeat:no-repeat;background-size:800px 104px;height:104px;position:relative}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body div{position:absolute;right:15px;left:15px;top:15px}.jupyter-wrapper div.jp-Cell-Placeholder-h1{top:20px;height:20px;left:15px;width:150px}.jupyter-wrapper div.jp-Cell-Placeholder-h2{left:15px;top:50px;height:10px;width:100px}.jupyter-wrapper div.jp-Cell-Placeholder-content-1,.jupyter-wrapper div.jp-Cell-Placeholder-content-2,.jupyter-wrapper div.jp-Cell-Placeholder-content-3{left:15px;right:15px;height:10px}.jupyter-wrapper div.jp-Cell-Placeholder-content-1{top:100px}.jupyter-wrapper div.jp-Cell-Placeholder-content-2{top:120px}.jupyter-wrapper div.jp-Cell-Placeholder-content-3{top:140px}.jupyter-wrapper table.dataframe{table-layout:auto!important}.jupyter-wrapper .md-typeset__scrollwrap{margin:0}.jupyter-wrapper .jp-MarkdownOutput{padding:0}.jupyter-wrapper h1 .anchor-link,.jupyter-wrapper h2 .anchor-link,.jupyter-wrapper h3 .anchor-link,.jupyter-wrapper h4 .anchor-link,.jupyter-wrapper h5 .anchor-link,.jupyter-wrapper h6 .anchor-link{display:none;margin-left:.5rem;color:var(--md-default-fg-color--lighter)}.jupyter-wrapper h1 .anchor-link:hover,.jupyter-wrapper h2 .anchor-link:hover,.jupyter-wrapper h3 .anchor-link:hover,.jupyter-wrapper h4 .anchor-link:hover,.jupyter-wrapper h5 .anchor-link:hover,.jupyter-wrapper h6 .anchor-link:hover{text-decoration:none;color:var(--md-accent-fg-color)}.jupyter-wrapper h1:hover .anchor-link,.jupyter-wrapper h2:hover .anchor-link,.jupyter-wrapper h3:hover .anchor-link,.jupyter-wrapper h4:hover .anchor-link,.jupyter-wrapper h5:hover .anchor-link,.jupyter-wrapper h6:hover .anchor-link{display:inline-block}.jupyter-wrapper .jp-InputArea,.jupyter-wrapper .jp-Cell-inputArea,.jupyter-wrapper .jp-RenderedHTMLCommon{width:100%}.jupyter-wrapper .jp-Cell-inputWrapper .jp-InputPrompt{display:none}.jupyter-wrapper .jp-CodeCell .jp-Cell-inputWrapper .jp-InputPrompt{display:block}.jupyter-wrapper .jp-Cell .jp-InputPrompt{cursor:normal}.jupyter-wrapper .highlight pre{background-color:#f5f5f5;padding:10px;overflow:auto}.jupyter-wrapper .celltoolbar{border:none;background:#eee;border-radius:2px 2px 0 0;width:100%;height:29px;padding-right:4px;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;box-pack:end;justify-content:flex-start;display:-webkit-flex}.jupyter-wrapper .celltoolbar .tags_button_container{display:flex}.jupyter-wrapper .celltoolbar .tags_button_container .tag-container{display:flex;flex-direction:row;flex-grow:1;overflow:hidden;position:relative}.jupyter-wrapper .celltoolbar .tags_button_container .tag-container .cell-tag{display:inline-flex;align-items:center;background-color:#fff;white-space:nowrap;margin:3px 4px;padding:0 4px;border-radius:1px;border:1px solid #ccc;box-shadow:none;width:inherit;font-size:11px;font-family:Roboto Mono,SFMono-Regular,Consolas,Menlo,monospace;height:17px}.jupyter-wrapper .jp-InputArea-editor{width:1px}.jupyter-wrapper .jp-InputPrompt,.jupyter-wrapper .jp-OutputPrompt{overflow:unset}.jupyter-wrapper .jp-RenderedText{font-size:var(--jp-code-font-size)}.jupyter-wrapper .highlight-ipynb{overflow:auto}.jupyter-wrapper .highlight-ipynb pre{margin:0;padding:5px 10px}.jupyter-wrapper table{width:max-content}.jupyter-wrapper table.dataframe{margin-left:auto;margin-right:auto;border:none;border-collapse:collapse;border-spacing:0;color:#000;font-size:12px;table-layout:fixed}.jupyter-wrapper table.dataframe thead{border-bottom:1px solid black;vertical-align:bottom}.jupyter-wrapper table.dataframe tr,.jupyter-wrapper table.dataframe th,.jupyter-wrapper table.dataframe td{text-align:right;vertical-align:middle;padding:.5em;line-height:normal;white-space:normal;max-width:none;border:none}.jupyter-wrapper table.dataframe th{font-weight:700}.jupyter-wrapper table.dataframe tbody tr:nth-child(odd){background:#f5f5f5}.jupyter-wrapper table.dataframe tbody tr:hover{background:rgba(66,165,245,.2)}.jupyter-wrapper *+table{margin-top:1em}.jupyter-wrapper .jp-InputArea-editor{position:relative}.jupyter-wrapper .zeroclipboard-container{position:absolute;top:-3px;right:0;z-index:1}.jupyter-wrapper .zeroclipboard-container clipboard-copy{-webkit-appearance:button;-moz-appearance:button;padding:7px 5px;font:11px system-ui,sans-serif;display:inline-block;cursor:default}.jupyter-wrapper .zeroclipboard-container clipboard-copy:hover{cursor:pointer}.jupyter-wrapper .zeroclipboard-container .clipboard-copy-icon{width:15px;padding:2px 0;color:#57606a;vertical-align:text-bottom}.jupyter-wrapper .clipboard-copy-txt{display:none}[data-md-color-scheme=slate] .highlight pre{background-color:#21222c;padding:10px;overflow:auto}[data-md-color-scheme=slate] .clipboard-copy-icon{color:#555!important}[data-md-color-scheme=slate] .celltoolbar{background:#333!important}[data-md-color-scheme=slate] .celltoolbar .tags_button_container .tag-container .cell-tag{background-color:transparent!important;border:1px solid #666!important}[data-md-color-scheme=slate] table.dataframe{color:#e9ebfc}[data-md-color-scheme=slate] table.dataframe thead{border-bottom:1px solid rgba(233,235,252,.12)}[data-md-color-scheme=slate] table.dataframe tbody tr:nth-child(odd){background:#222}[data-md-color-scheme=slate] table.dataframe tbody tr:hover{background:rgba(66,165,245,.2)}table{width:max-content} .jupyter-wrapper{--jp-shadow-base-lightness: 0;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-400);--jp-border-color1: var(--md-grey-400);--jp-border-color2: var(--md-grey-300);--jp-border-color3: var(--md-grey-200);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(0, 0, 0, 1);--jp-ui-font-color1: rgba(0, 0, 0, .87);--jp-ui-font-color2: rgba(0, 0, 0, .54);--jp-ui-font-color3: rgba(0, 0, 0, .38);--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color2: rgba(255, 255, 255, .7);--jp-ui-inverse-font-color3: rgba(255, 255, 255, .5);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(0, 0, 0, 1);--jp-content-font-color1: rgba(0, 0, 0, .87);--jp-content-font-color2: rgba(0, 0, 0, .54);--jp-content-font-color3: rgba(0, 0, 0, .38);--jp-content-link-color: var(--md-blue-700);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: white;--jp-layout-color1: white;--jp-layout-color2: var(--md-grey-200);--jp-layout-color3: var(--md-grey-400);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: #111111;--jp-inverse-layout-color1: var(--md-grey-900);--jp-inverse-layout-color2: var(--md-grey-800);--jp-inverse-layout-color3: var(--md-grey-700);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-900);--jp-brand-color1: var(--md-blue-700);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-900);--jp-accent-color1: var(--md-green-700);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-900);--jp-warn-color1: var(--md-orange-700);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-900);--jp-error-color1: var(--md-red-700);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-900);--jp-success-color1: var(--md-green-700);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-900);--jp-info-color1: var(--md-cyan-700);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--md-grey-100);--jp-cell-editor-border-color: var(--md-grey-300);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: .5;--jp-cell-prompt-not-active-font-color: var(--md-grey-700);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: var(--md-blue-50);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: #fdd;--jp-rendermime-table-row-background: var(--md-grey-100);--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);--jp-dialog-background: rgba(0, 0, 0, .25);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color1);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .24);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--md-grey-300);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color1);--jp-input-hover-background: var(--jp-layout-color1);--jp-input-background: var(--md-grey-100);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: #d9d9d9;--jp-editor-selected-focused-background: #d7d4f0;--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: #008000;--jp-mirror-editor-atom-color: #88f;--jp-mirror-editor-number-color: #080;--jp-mirror-editor-def-color: #00f;--jp-mirror-editor-variable-color: var(--md-grey-900);--jp-mirror-editor-variable-2-color: #05a;--jp-mirror-editor-variable-3-color: #085;--jp-mirror-editor-punctuation-color: #05a;--jp-mirror-editor-property-color: #05a;--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ba2121;--jp-mirror-editor-string-2-color: #708;--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: #008000;--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: #170;--jp-mirror-editor-attribute-color: #00c;--jp-mirror-editor-header-color: blue;--jp-mirror-editor-quote-color: #090;--jp-mirror-editor-link-color: #00c;--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ffad8e;--jp-collaborator-color2: #dac83d;--jp-collaborator-color3: #72dd76;--jp-collaborator-color4: #00e4d0;--jp-collaborator-color5: #45d4ff;--jp-collaborator-color6: #e2b1ff;--jp-collaborator-color7: #ff9de6;--jp-vega-background: white;--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .5;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(245, 200, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-700);--jp-console-icon-background-color: var(--md-blue-700);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-800);--jp-terminal-icon-color: var(--md-grey-200);--jp-text-editor-icon-color: var(--md-grey-700);--jp-inspector-icon-color: var(--md-grey-700);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-900)} init_mathjax = function() { if (window.MathJax) { // MathJax loaded MathJax.Hub.Config({ TeX: { equationNumbers: { autoNumber: \"AMS\", useLabelIds: true } }, tex2jax: { inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ], displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ], processEscapes: true, processEnvironments: true }, displayAlign: 'center', CommonHTML: { linebreaks: { automatic: true } } }); MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]); } } init_mathjax(); document.addEventListener(\"DOMContentLoaded\", async () => { const diagrams = document.querySelectorAll(\".jp-Mermaid > pre.mermaid\"); // do not load mermaidjs if not needed if (!diagrams.length) { return; } const mermaid = (await import(\"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs\")).default; const parser = new DOMParser(); mermaid.initialize({ maxTextSize: 100000, maxEdges: 100000, startOnLoad: false, fontFamily: window .getComputedStyle(document.body) .getPropertyValue(\"--jp-ui-font-family\"), theme: document.querySelector(\"body[data-jp-theme-light='true']\") ? \"default\" : \"dark\", }); let _nextMermaidId = 0; function makeMermaidImage(svg) { const img = document.createElement(\"img\"); const doc = parser.parseFromString(svg, \"image/svg+xml\"); const svgEl = doc.querySelector(\"svg\"); const { maxWidth } = svgEl?.style || {}; const firstTitle = doc.querySelector(\"title\"); const firstDesc = doc.querySelector(\"desc\"); img.setAttribute(\"src\", `data:image/svg+xml,${encodeURIComponent(svg)}`); if (maxWidth) { img.width = parseInt(maxWidth); } if (firstTitle) { img.setAttribute(\"alt\", firstTitle.textContent); } if (firstDesc) { const caption = document.createElement(\"figcaption\"); caption.className = \"sr-only\"; caption.textContent = firstDesc.textContent; return [img, caption]; } return [img]; } async function makeMermaidError(text) { let errorMessage = \"\"; try { await mermaid.parse(text); } catch (err) { errorMessage = `${err}`; } const result = document.createElement(\"details\"); result.className = 'jp-RenderedMermaid-Details'; const summary = document.createElement(\"summary\"); summary.className = 'jp-RenderedMermaid-Summary'; const pre = document.createElement(\"pre\"); const code = document.createElement(\"code\"); code.innerText = text; pre.appendChild(code); summary.appendChild(pre); result.appendChild(summary); const warning = document.createElement(\"pre\"); warning.innerText = errorMessage; result.appendChild(warning); return [result]; } async function renderOneMarmaid(src) { const id = `jp-mermaid-${_nextMermaidId++}`; const parent = src.parentNode; let raw = src.textContent.trim(); const el = document.createElement(\"div\"); el.style.visibility = \"hidden\"; document.body.appendChild(el); let results = null; let output = null; try { let { svg } = await mermaid.render(id, raw, el); svg = cleanMermaidSvg(svg); results = makeMermaidImage(svg); output = document.createElement(\"figure\"); results.map(output.appendChild, output); } catch (err) { parent.classList.add(\"jp-mod-warning\"); results = await makeMermaidError(raw); output = results[0]; } finally { el.remove(); } parent.classList.add(\"jp-RenderedMermaid\"); parent.appendChild(output); } /** * Post-process to ensure mermaid diagrams contain only valid SVG and XHTML. */ function cleanMermaidSvg(svg) { return svg.replace(RE_VOID_ELEMENT, replaceVoidElement); } /** * A regular expression for all void elements, which may include attributes and * a slash. * * @see https://developer.mozilla.org/en-US/docs/Glossary/Void_element * * Of these, only `
    ` is generated by Mermaid in place of `\\n`, * but _any_ \"malformed\" tag will break the SVG rendering entirely. */ const RE_VOID_ELEMENT = /<\\s*(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\\s*([^>]*?)\\s*>/gi; /** * Ensure a void element is closed with a slash, preserving any attributes. */ function replaceVoidElement(match, tag, rest) { rest = rest.trim(); if (!rest.endsWith('/')) { rest = `${rest} /`; } return `<${tag} ${rest}>`; } void Promise.all([...diagrams].map(renderOneMarmaid)); }); .jp-Mermaid:not(.jp-RenderedMermaid) { display: none; } .jp-RenderedMermaid { overflow: auto; display: flex; } .jp-RenderedMermaid.jp-mod-warning { width: auto; padding: 0.5em; margin-top: 0.5em; border: var(--jp-border-width) solid var(--jp-warn-color2); border-radius: var(--jp-border-radius); color: var(--jp-ui-font-color1); font-size: var(--jp-ui-font-size1); white-space: pre-wrap; word-wrap: break-word; } .jp-RenderedMermaid figure { margin: 0; overflow: auto; max-width: 100%; } .jp-RenderedMermaid img { max-width: 100%; } .jp-RenderedMermaid-Details > pre { margin-top: 1em; } .jp-RenderedMermaid-Summary { color: var(--jp-warn-color2); } .jp-RenderedMermaid:not(.jp-mod-warning) pre { display: none; } .jp-RenderedMermaid-Summary > pre { display: inline-block; white-space: normal; } scPRINT use case on BPH (part 2, GN analysis) \u00b6 In this use-case, which some of the results are presented in Figure 5 of our manuscript , we perform an extensive analysis of gene networks generated by scPRINT in our previous notebook for fibroblasts of the prostate in both normal and benign prostatic hyperplasia states. We can look at many patterns from the gene networks such as hub genes, gene modules, and gene-gene interactions. Some of them are related to highly variable and differentially expressed genes while others can only be infered by using the gene networks. Table of content: Hub genes Network similarity Network communities Cancer version Normal version Differential Gene - Gene connections Using classification In [1]: Copied! from bengrn import BenGRN import scanpy as sc from bengrn.base import train_classifier from anndata.utils import make_index_unique from grnndata import utils as grnutils from grnndata import read_h5ad from matplotlib import pyplot as plt from scdataloader import utils as data_utils import numpy as np from pyvis import network as pnx import networkx as nx import scipy.sparse import pandas as pd import gseapy as gp from gseapy import dotplot % load_ext autoreload % autoreload 2 from bengrn import BenGRN import scanpy as sc from bengrn.base import train_classifier from anndata.utils import make_index_unique from grnndata import utils as grnutils from grnndata import read_h5ad from matplotlib import pyplot as plt from scdataloader import utils as data_utils import numpy as np from pyvis import network as pnx import networkx as nx import scipy.sparse import pandas as pd import gseapy as gp from gseapy import dotplot %load_ext autoreload %autoreload 2 \ud83d\udca1 connected lamindb: jkobject/scprint In [ ]: Copied! prostate_combined = sc . read_h5ad ( \"../data/prostate_combined_o2uniqsx.h5ad\" ) prostate_combined = sc.read_h5ad(\"../data/prostate_combined_o2uniqsx.h5ad\") In [2]: Copied! # load the generated gene networks from the previous notebook grn = read_h5ad ( \"../../data/prostate_fibro_grn.h5ad\" ) grn_c = read_h5ad ( \"../../data/prostate_cancer_fibro_grn.h5ad\" ) #remove duplicates grn . var . symbol = make_index_unique ( grn . var . symbol . astype ( str )) grn_c . var . symbol = make_index_unique ( grn_c . var . symbol . astype ( str )) # convert gene ids to symbols grn . var [ 'ensembl_id' ] = grn . var . index grn . var . index = grn . var . symbol grn_c . var [ 'ensembl_id' ] = grn_c . var . index grn_c . var . index = grn_c . var . symbol grn . obs . cleaned_pred_disease_ontology_term_id . value_counts (), grn_c . obs . cleaned_pred_disease_ontology_term_id . value_counts () # load the generated gene networks from the previous notebook grn = read_h5ad(\"../../data/prostate_fibro_grn.h5ad\") grn_c = read_h5ad(\"../../data/prostate_cancer_fibro_grn.h5ad\") #remove duplicates grn.var.symbol = make_index_unique(grn.var.symbol.astype(str)) grn_c.var.symbol = make_index_unique(grn_c.var.symbol.astype(str)) # convert gene ids to symbols grn.var['ensembl_id'] = grn.var.index grn.var.index = grn.var.symbol grn_c.var['ensembl_id'] = grn_c.var.index grn_c.var.index = grn_c.var.symbol grn.obs.cleaned_pred_disease_ontology_term_id.value_counts(),grn_c.obs.cleaned_pred_disease_ontology_term_id.value_counts() Out[2]: (cleaned_pred_disease_ontology_term_id normal 300 Name: count, dtype: int64, cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 300 Name: count, dtype: int64) 1. Hub genes \u00b6 We will use 2 different definition of centrality to compare the hubs of the networks in both states. The first one is the degree centrality, which is the number of connections of a node. The second one is the eigenvector centrality, which is the sum of the centrality of the neighbors of a node. For each gene we mostly interogate their meaning with genecards, e.g. https://www.genecards.org/cgi-bin/carddisp.pl?gene=CD99 In [7]: Copied! # between the two networks we have ~3000 genes in common over their 4000 genes common = set ( grn_c . var . symbol ) & set ( grn . var . symbol ) len ( common ) # between the two networks we have ~3000 genes in common over their 4000 genes common = set(grn_c.var.symbol) & set(grn.var.symbol) len(common) Out[7]: 2881 In [8]: Copied! # hub genes based on edge centrality (number of connections / strength of connections) grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 20 ) # hub genes based on edge centrality (number of connections / strength of connections) grn.grn.sum(0).sort_values(ascending=False).head(20) Out[8]: symbol S100A6 58.131020 TGIF2-RAB5IF 51.177635 MIF 44.534096 DNAJB9 40.953262 IGFBP7 38.629910 APOD 38.003906 BRME1 37.598698 SPARCL1 37.160854 TIMP1 36.671650 DCN 34.621376 C1S 32.746254 MGP 30.496748 nan-270 29.884596 SLC25A6 29.308729 BLOC1S5-TXNDC5 28.986681 CETN1 28.746281 FTL 28.266533 AKR1C1 27.641245 FBLN1 26.828733 MT2A 25.590197 dtype: float32 In [7]: Copied! # without taking in account genes that are not present in the cancer network grn . grn . sum ( 0 ) . loc [ list ( common )] . sort_values ( ascending = False ) . head ( 20 ) # without taking in account genes that are not present in the cancer network grn.grn.sum(0).loc[list(common)].sort_values(ascending=False).head(20) Out[7]: symbol TGIF2-RAB5IF 51.177635 IGFBP7 38.629910 APOD 38.003906 BRME1 37.598698 SPARCL1 37.160854 TIMP1 36.671650 DCN 34.621376 C1S 32.746254 MGP 30.496748 BLOC1S5-TXNDC5 28.986681 AKR1C1 27.641245 FBLN1 26.828733 MT2A 25.590197 MYOC 25.428144 FAM205A 25.296257 YBX3 24.937267 CST3 24.676405 C11orf96 18.731924 TFPI 18.429214 ATP6V0C 17.695705 dtype: float32 In [11]: Copied! # cancer hub genes grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 20 ) # cancer hub genes grn_c.grn.sum(0).sort_values(ascending=False).head(20) Out[11]: symbol HSPA1A 75.300415 MT2A 57.938267 CREM 42.478115 TGIF2-RAB5IF 39.980556 HSPE1 38.607624 CALD1 36.512047 SPOCK3 35.564945 HLA-A 33.446110 SPARCL1 33.403152 RBP1 32.482758 C1S 32.037743 BRME1-1 31.879770 FABP4 31.604069 nan-99 31.555256 LUM 30.523245 EIF4A1 29.690474 ATP6V0C 29.475002 PDZD2 27.333025 DEFA1 26.979454 CTSG 25.070097 dtype: float32 In [10]: Copied! # without taking in account genes not present in the normal network grn_c . grn . sum ( 0 ) . loc [ list ( common )] . sort_values ( ascending = False ) . head ( 20 ) # without taking in account genes not present in the normal network grn_c.grn.sum(0).loc[list(common)].sort_values(ascending=False).head(20) Out[10]: symbol HSPA1A 75.300415 MT2A 57.938267 TGIF2-RAB5IF 39.980556 SPOCK3 35.564945 HLA-A 33.446110 SPARCL1 33.403152 C1S 32.037743 nan-99 31.555256 LUM 30.523245 EIF4A1 29.690474 ATP6V0C 29.475002 DEFA1 26.979454 IGFBP7 23.982243 DCN 23.304916 MGP 22.596451 CD99 21.624668 BLOC1S5-TXNDC5 20.914230 SERPING1 20.824636 COL6A2 18.076559 THBS1 17.826540 dtype: float32 In [12]: Copied! # top differential hubs TOP = 10 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) # top differential hubs TOP = 10 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[12]: {'HLA-A', 'HSPA1A', 'MT2A', 'SPOCK3'} In [13]: Copied! TOP = 20 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 20 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[13]: {'ATP6V0C', 'DEFA1', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LUM', 'SPOCK3', 'nan-99'} In [14]: Copied! TOP = 50 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 50 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[14]: {'CD99', 'CPE', 'DEFA1', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LGALS1', 'LUM', 'PYDC2', 'SERPING1', 'SPOCK3', 'THBS1', 'nan-191', 'nan-99'} overall we see that both are somewhat similar in the way the networks classifies main nodes but at least around half of the top 200 nodes are different between the two datasets and half of those are not due to diffent gene being used by the networks (50) genes preferentially given as top elements in the tumor version only: CD99 CPE DEFA1 EIF4A1 HLA-A HSPA1A LGALS1 LUM PYDC2 SERPING1 SPOCK3 THBS1 In [3]: Copied! # we now compute eigen centrality creating a sparse network by only keeping the top 20 neighbors for each gene in the network TOP = 20 grnutils . get_centrality ( grn , TOP , top_k_to_disp = 0 ) grnutils . get_centrality ( grn_c , TOP , top_k_to_disp = 0 ) # we now compute eigen centrality creating a sparse network by only keeping the top 20 neighbors for each gene in the network TOP = 20 grnutils.get_centrality(grn, TOP, top_k_to_disp=0) grnutils.get_centrality(grn_c, TOP, top_k_to_disp=0) Top central genes: [] Top central genes: [] Out[3]: [] In [12]: Copied! grn_c . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn_c.var.centrality.sort_values(ascending=False).head(10) Out[12]: symbol HSPA1A 0.271584 MT2A 0.271584 CREM 0.271574 CD99 0.271517 NR4A3 0.271385 RBP1 0.271130 SOX4 0.264214 ATP6V0C 0.263235 HLA-A 0.232913 LUM 0.202007 Name: centrality, dtype: float64 In [9]: Copied! grn_c . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn_c.var.centrality.sort_values(ascending=False).head(10) Out[9]: symbol HSPA1A 0.271584 MT2A 0.271584 CREM 0.271574 CD99 0.271517 NR4A3 0.271385 RBP1 0.271130 SOX4 0.264214 ATP6V0C 0.263235 HLA-A 0.232913 LUM 0.202007 Name: centrality, dtype: float64 In [10]: Copied! grn . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn.var.centrality.sort_values(ascending=False).head(10) Out[10]: symbol MT2A 0.276470 SLC25A6 0.276183 CXCL8 0.275859 FTH1 0.275757 MIF 0.267968 DNAJB9 0.265635 SOX4 0.241950 RELB 0.234482 YBX3 0.216567 CST3 0.213585 Name: centrality, dtype: float64 In [13]: Copied! TOP = 10 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 10 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[13]: {'ATP6V0C', 'CD99', 'HLA-A', 'HSPA1A', 'LUM'} In [12]: Copied! TOP = 20 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 20 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[12]: {'ATP6V0C', 'CD99', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LUM', 'PAGE4', 'RYR2', 'SERPINF1'} In [11]: Copied! TOP = 50 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 50 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[11]: {'C1R', 'CD99', 'COL6A2', 'HLA-A', 'HNRNPA0', 'HSPA1A', 'LUM', 'PAGE4', 'SERPINA3', 'SERPING1', 'SPOCK3', 'THBS1'} it seems the networks are even more similar when comparing them at the level of the centrality of their nodes. this means that some are highly central while maybe not 2. Network similarity \u00b6 We now look at the similarity of the two networks based on general overlap of their top K edges across their common nodes In [41]: Copied! grn . var . index = grn . var . ensembl_id grn_c . var . index = grn_c . var . ensembl_id overlap = list ( set ( grn . var . index ) & set ( grn_c . var . index )) grn.var.index = grn.var.ensembl_id grn_c.var.index = grn_c.var.ensembl_id overlap = list(set(grn.var.index) & set(grn_c.var.index)) In [43]: Copied! K = 20 subgrn_c = grn_c . get ( overlap ) . grn subgrn_c = subgrn_c . apply ( lambda row : row >= row . nlargest ( K ) . min (), axis = 1 ) subgrn = grn . get ( overlap ) . grn subgrn = subgrn . apply ( lambda row : row >= row . nlargest ( K ) . min (), axis = 1 ) ( subgrn & subgrn_c ) . sum ( 1 ) . mean () / K K = 20 subgrn_c = grn_c.get(overlap).grn subgrn_c = subgrn_c.apply(lambda row: row >= row.nlargest(K).min(), axis=1) subgrn = grn.get(overlap).grn subgrn = subgrn.apply(lambda row: row >= row.nlargest(K).min(), axis=1) (subgrn & subgrn_c).sum(1).mean() / K Out[43]: 0.5055735930735931 when looking at the top 20 connection for each genes in the network we see that on average only 50% of them agree between the two networks 3. Network communities \u00b6 Again looking at the top 20 connections for each gene in the network we use the leiden (or louvain) algorithm to find communities in both networks. We then study the hub of these communities as well as their enrichment using enrichr and ontology databases. We will only look at communities between 20 and 200 genes In [33]: Copied! TOP = 20 grnutils . get_centrality ( grn , TOP , top_k_to_disp = 0 ) grnutils . get_centrality ( grn_c , TOP , top_k_to_disp = 0 ) TOP = 20 grnutils.get_centrality(grn, TOP, top_k_to_disp=0) grnutils.get_centrality(grn_c, TOP, top_k_to_disp=0) Top central genes: [] Top central genes: [] Out[33]: [] In [17]: Copied! grn_c = grnutils . compute_cluster ( grn_c , 1.5 , use = \"leiden\" , n_iterations = 10 , max_comm_size = 100 ) grn_c = grnutils.compute_cluster(grn_c, 1.5, use=\"leiden\", n_iterations=10, max_comm_size=100) In [4]: Copied! grn = grnutils . compute_cluster ( grn , 1.5 ) grn_c = grnutils . compute_cluster ( grn_c , 1.5 ) grn = grnutils.compute_cluster(grn, 1.5) grn_c = grnutils.compute_cluster(grn_c, 1.5) 3.1 Cancer version \u00b6 In [30]: Copied! # our communities grn . var [ 'cluster_1.5' ] . value_counts () . head ( 10 ) # our communities grn.var['cluster_1.5'].value_counts().head(10) Out[30]: cluster_1.5 0 1620 1 1483 2 732 3 111 4 23 5 9 6 4 16 1 23 1 22 1 Name: count, dtype: int64 In [31]: Copied! G = grn_c . plot_subgraph ( grn_c . var [ grn_c . var [ 'cluster_1.5' ] == '4' ] . index . tolist (), only = 200 , interactive = False ) # G = grn_c.plot_subgraph(grn_c.var[grn_c.var['cluster_1.5']=='4'].index.tolist(), only=200, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['PRDM6', 'MSANTD3', 'STAG3', 'TRHDE', 'TBX5', 'HEPH', 'GALNT16', 'NFATC4', 'SYNDIG1', 'HSF4', 'ZNF423', 'PLA2G4C', 'PLPPR2', 'SCN1B', 'ASPA', 'SNX15', 'BAG2', 'PTK7', 'HRH2', 'PLCL1', 'PTCH2', 'TGFB3', 'RASL11A', 'TOX2', 'CPNE5', 'GLIS2', 'HIVEP3', 'FGF13', 'ACAP3', 'DUSP26', 'CTIF', 'CAMK1', 'SLC9A5', 'FBN2', 'LRIG1', 'LIMD1', 'TRPC1', 'SLC2A13', 'ADAMTS12', 'FZD7', 'AFF2', 'CACNA1D', 'MRAS', 'ST6GALNAC6', 'FGFR4', 'PTGER1', 'PKDCC', 'SLC9B2', 'NPY1R', 'ANKRD33B', 'DCLK2', 'PURG', 'GXYLT2', 'LRRN4CL', 'CA8', 'EXOC3L1', 'BHLHE22', 'AATK', 'CMC4', 'BOLA2', 'CCR10', 'TCEAL2', 'SLC24A3', 'ROR1', 'SLC51B', 'EMID1', 'AGMO', 'CENPP', 'OPTC', 'SPOCK3', 'COL27A1', 'DACT3', 'STMN3', 'DLL1', 'SMOC1', 'COLGALT2', 'ZDBF2', 'DOK6', 'HNRNPUL2-BSCL2', 'C3orf84', 'C2orf74', 'ARHGEF25', 'NPIPB5', 'TNFSF12-TNFSF13', 'ZFP91-CNTF', 'nan-41', 'nan-81', 'nan-96', 'nan-98', 'HERC3', 'nan-116', 'nan-117'], dtype='object', name='symbol_2') In [26]: Copied! # if you want to draw better looking networks pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_4.html\" ) # if you want to draw better looking networks pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_4.html\") In [32]: Copied! # Assuming 'node_names' contains the list of gene names. # Note: it seems with enrichr, one can only use one gene set at a time, choose accordingly enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn_c . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names. # Note: it seems with enrichr, one can only use one gene set at a time, choose accordingly enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn_c.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:31:53,534 [WARNING] Input library not found: Reactome. Skip Out[32]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Solute:Potassium Antiporter Activity (GO:0022821) 0.000523 0.050652 0 0 inf inf SLC24A3;SLC9A5 1 GO_Molecular_Function_2023 Coreceptor Activity Involved In Wnt Signaling ... 0.001547 0.050652 0 0 86.822222 561.890021 PTK7;ROR1 2 GO_Molecular_Function_2023 Sodium Ion Transmembrane Transporter Activity ... 0.001547 0.050652 0 0 86.822222 561.890021 SLC9A5;SLC9B2 3 GO_Molecular_Function_2023 Calcium Ion Transmembrane Transporter Activity... 0.001700 0.050652 0 0 16.432584 104.795452 SLC24A3;TRPC1;CACNA1D 4 GO_Molecular_Function_2023 Calcium-Dependent Phospholipid Binding (GO:000... 0.003047 0.050652 0 0 43.400000 251.445478 CPNE5;PLA2G4C 5 GO_Molecular_Function_2023 Coreceptor Activity Involved In Wnt Signaling ... 0.003047 0.050652 0 0 43.400000 251.445478 PTK7;ROR1 6 GO_Molecular_Function_2023 Metal Cation:Proton Antiporter Activity (GO:00... 0.003047 0.050652 0 0 43.400000 251.445478 SLC9A5;SLC9B2 7 GO_Molecular_Function_2023 Sodium:Proton Antiporter Activity (GO:0015385) 0.003047 0.050652 0 0 43.400000 251.445478 SLC9A5;SLC9B2 8 GO_Molecular_Function_2023 Iron Ion Binding (GO:0005506) 0.005002 0.070586 0 0 28.925926 153.247105 HEPH;AGMO 9 GO_Molecular_Function_2023 Calcium Channel Activity (GO:0005262) 0.005307 0.070586 0 0 10.099395 52.907606 SLC24A3;TRPC1;CACNA1D 10 GO_Molecular_Function_2023 Wnt Receptor Activity (GO:0042813) 0.007391 0.089364 0 0 21.688889 106.438022 FZD7;ROR1 11 GO_Molecular_Function_2023 RNA Polymerase II-specific DNA-binding Transcr... 0.010110 0.104284 0 0 7.715135 35.445265 TBX5;DUSP26;DLL1 12 GO_Molecular_Function_2023 Phospholipase Activity (GO:0004620) 0.010193 0.104284 0 0 17.346667 79.552387 PLCL1;PLA2G4C 13 GO_Molecular_Function_2023 Monoatomic Cation Channel Activity (GO:0005261) 0.011601 0.110210 0 0 7.284644 32.465172 SLC24A3;TRPC1;CACNA1D 14 GO_Molecular_Function_2023 Sodium Channel Regulator Activity (GO:0017080) 0.013389 0.118714 0 0 14.451852 62.335739 FGF13;SCN1B 15 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.022992 0.139045 0 0 2.668376 10.066740 HSF4;HIVEP3;BHLHE22;TBX5;ZNF423;NFATC4;GLIS2 16 GO_Molecular_Function_2023 Calcium:Sodium Antiporter Activity (GO:0005432) 0.023000 0.139045 0 0 inf inf SLC24A3 17 GO_Molecular_Function_2023 Potassium:Proton Antiporter Activity (GO:0015386) 0.023000 0.139045 0 0 inf inf SLC9A5 18 GO_Molecular_Function_2023 Xylosyltransferase Activity (GO:0042285) 0.023000 0.139045 0 0 inf inf GXYLT2 19 GO_Molecular_Function_2023 Tat Protein Binding (GO:0030957) 0.023000 0.139045 0 0 inf inf DLL1 In [33]: Copied! # we make a plot of the enrichment enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) # we make a plot of the enrichment enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [34]: Copied! G = grn_c . plot_subgraph ( grn_c . var [ grn_c . var [ 'cluster_1.5' ] == '5' ] . index . tolist (), only = 80 , interactive = False ) # G = grn_c.plot_subgraph(grn_c.var[grn_c.var['cluster_1.5']=='5'].index.tolist(), only=80, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['ABCF2', 'ITIH4', 'OLFM2', 'ICAM4', 'RIGI', 'KAZALD1', 'BST1', 'PANX1', 'C9', 'FBXO2', 'ZNF410', 'ACVR1C', 'VAMP7', 'TOP2A', 'TAF4B', 'KIAA1755', 'EDA', 'YPEL4', 'ENTPD3', 'GP9', 'NLGN2', 'CLCF1', 'RPRM', 'ODF3B', 'MSC', 'NTF3', 'COL13A1', 'GP1BB', 'HSPA1A', 'TMEM158', 'nan-82', 'NBPF19', 'SCO2', 'SMIM41'], dtype='object', name='symbol_2') In [87]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_5.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_5.html\") In [44]: Copied! grn_c . var . loc [ 'nan-82' ] # par of the Glycoside Hydrolase Family grn_c.var.loc['nan-82'] # par of the Glycoside Hydrolase Family Out[44]: uid 4giyQrh7tkXI symbol nan-82 ncbi_gene_ids biotype protein_coding description novel protein synonyms organism_id 2 public_source_id 9.0 created_by_id 1 mt False ribo False hb False organism NCBITaxon:9606 TFs False ensembl_id ENSG00000269590 centrality 0.0 cluster_1.5 5 Name: nan-82, dtype: object In [35]: Copied! enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn_c . var . symbol . tolist (), ) enr . res2d . head ( 20 ) enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn_c.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:33:16,565 [WARNING] Input library not found: Reactome. Skip Out[35]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Death Receptor Binding (GO:0005123) 0.000416 0.028729 0 0 123.875000 964.236668 EDA;NTF3 1 GO_Molecular_Function_2023 Purine Ribonucleoside Triphosphate Binding (GO... 0.007050 0.073312 0 0 8.626100 42.739637 ABCF2;RIGI;HSPA1A 2 GO_Molecular_Function_2023 Receptor Ligand Activity (GO:0048018) 0.007732 0.073312 0 0 5.742222 27.920829 EDA;CLCF1;NTF3;HSPA1A 3 GO_Molecular_Function_2023 Activin Receptor Activity (GO:0017002) 0.008500 0.073312 0 0 inf inf ACVR1C 4 GO_Molecular_Function_2023 Gap Junction Hemi-Channel Activity (GO:0055077) 0.008500 0.073312 0 0 inf inf PANX1 5 GO_Molecular_Function_2023 NF-kappaB Binding (GO:0051059) 0.008500 0.073312 0 0 inf inf TAF4B 6 GO_Molecular_Function_2023 Hydrolase Activity, Hydrolyzing N-glycosyl Com... 0.008500 0.073312 0 0 inf inf BST1 7 GO_Molecular_Function_2023 Ubiquitin-Protein Transferase Activator Activi... 0.008500 0.073312 0 0 inf inf RIGI 8 GO_Molecular_Function_2023 DNA Binding, Bending (GO:0008301) 0.016930 0.083096 0 0 120.151515 490.060134 TOP2A 9 GO_Molecular_Function_2023 Disordered Domain Specific Binding (GO:0097718) 0.016930 0.083096 0 0 120.151515 490.060134 HSPA1A 10 GO_Molecular_Function_2023 UDP Phosphatase Activity (GO:0045134) 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 11 GO_Molecular_Function_2023 GDP Phosphatase Activity (GO:0004382) 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 12 GO_Molecular_Function_2023 Nucleoside Diphosphate Phosphatase Activity (G... 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 13 GO_Molecular_Function_2023 ATP Binding (GO:0005524) 0.017220 0.083096 0 0 11.204545 45.509349 ABCF2;HSPA1A 14 GO_Molecular_Function_2023 Ubiquitin Protein Ligase Binding (GO:0031625) 0.020064 0.083096 0 0 10.265625 40.126707 RIGI;HSPA1A 15 GO_Molecular_Function_2023 Ubiquitin-Like Protein Ligase Binding (GO:0044... 0.021555 0.083096 0 0 9.852500 37.805688 RIGI;HSPA1A 16 GO_Molecular_Function_2023 Growth Factor Activity (GO:0008083) 0.023090 0.083096 0 0 9.471154 35.690549 CLCF1;NTF3 17 GO_Molecular_Function_2023 Adenyl Ribonucleotide Binding (GO:0032559) 0.024670 0.083096 0 0 9.118056 33.756535 ABCF2;HSPA1A 18 GO_Molecular_Function_2023 C3HC4-type RING Finger Domain Binding (GO:0055... 0.025290 0.083096 0 0 60.060606 220.863728 HSPA1A 19 GO_Molecular_Function_2023 Ubiquitin Binding (GO:0043130) 0.025290 0.083096 0 0 60.060606 220.863728 TOP2A In [36]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( similar story to cluster above. this time with PTN often found in the litterature with 6 other m Studies on the role of STEAP1, OR51E2, PTN, ABCC4, NDRG2 have been relatively in-depth. For instance, STEAP1 is all-called six-transmembrane epithelial antigen of the prostate 1, which belongs to a family of metalloproteinases involved in iron and copper homeostasis and other cellular processes has been listed with 8 other members as predictors of CAF-related gene prognostic index (CRGPI) in prostate cancer. https://www.nature.com/articles/s41598-023-36125-0#Sec11 (NDRG2, TSPAN1, PTN, APOE, OR51E2, P4HB, STEAP1 and ABCC4 were used to construct molecular subtypes and) https://www.genecards.org/cgi-bin/carddisp.pl?gene=GSN 3.2 Normal version \u00b6 In [9]: Copied! grn . var [ 'cluster_1.5' ] . value_counts () . head ( 10 ) grn.var['cluster_1.5'].value_counts().head(10) Out[9]: cluster_1.5 0 1620 1 1483 2 732 3 111 4 23 5 9 6 4 16 1 23 1 22 1 Name: count, dtype: int64 https://www.genecards.org/cgi-bin/carddisp.pl?gene=MYOC In [37]: Copied! G = grn . plot_subgraph ( grn . var [ grn . var [ 'cluster_1.5' ] == '3' ] . index . tolist (), only = 200 , interactive = False ) G = grn.plot_subgraph(grn.var[grn.var['cluster_1.5']=='3'].index.tolist(), only=200, interactive=False) ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['TMEM132A', 'ADGRA2', 'AGPAT4', 'THAP3', 'DNAJC25', 'TRAM2', 'NTN1', 'STAG3', 'COL4A4', 'HSD17B14', ... 'nan-75', 'TRABD2B', 'nan-77', 'PCGF2', 'nan-107', 'nan-182', 'nan-192', 'nan-195', 'nan-239', 'nan-259'], dtype='object', name='symbol_2', length=111) In [26]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_3.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_3.html\") In [27]: Copied! grn . var . loc [ 'nan-259' ] # par of the Glycoside Hydrolase Family grn.var.loc['nan-259'] # par of the Glycoside Hydrolase Family Out[27]: uid 62JAXxQNqtOd symbol nan-259 ncbi_gene_ids 83737 biotype protein_coding description novel protein synonyms organism_id 2 public_source_id 9.0 created_by_id 1 mt False ribo False hb False organism NCBITaxon:9606 TFs False ensembl_id ENSG00000289720 centrality 0.0 cluster_1.5 3 Name: nan-259, dtype: object In [12]: Copied! grn . get ( grn . var [ grn . var [ 'cluster_1.5' ] == '3' ] . index . tolist ()) . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 3 ) ##.grn # selenom grn.get(grn.var[grn.var['cluster_1.5']=='3'].index.tolist()).grn.sum(0).sort_values(ascending=False).head(3)##.grn # selenom Out[12]: symbol RNASEK 0.942102 SELENOM 0.292933 nan-259 0.256140 dtype: float32 RNASEK acidifying the internal vesicle important in endocytosis# https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10547866/ RNA phosphodiester bond hydrolysis --> hydrolisis pathway in the model and RNA transcription regulation In [38]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:33:49,291 [WARNING] Input library not found: Reactome. Skip /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/enrichr.py:643: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation. self.results = pd.concat(self.results, ignore_index=True) Out[38]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Sulfotransferase Activity (GO:0008146) 0.007252 0.123369 0 0 20.138462 99.212171 CHST7;SULT1C4 1 GO_Molecular_Function_2023 RNA Polymerase II Transcription Regulatory Reg... 0.007713 0.123369 0 0 3.386005 16.472449 ZNF483;HAND2;NTN1;NFATC4;GLIS2;PURG;ZNF286A 2 GO_Molecular_Function_2023 ATPase Binding (GO:0051117) 0.013790 0.123369 0 0 13.415385 57.468682 SLC2A13;NKD2 3 GO_Molecular_Function_2023 Chondroitin Sulfotransferase Activity (GO:0034... 0.016750 0.123369 0 0 inf inf CHST7 4 GO_Molecular_Function_2023 Peptidyl-Proline 4-Dioxygenase Activity (GO:00... 0.016750 0.123369 0 0 inf inf P4HA3 5 GO_Molecular_Function_2023 Aryl Sulfotransferase Activity (GO:0004062) 0.016750 0.123369 0 0 inf inf SULT1C4 6 GO_Molecular_Function_2023 Histone Reader Activity (GO:0140566) 0.016750 0.123369 0 0 inf inf TONSL 7 GO_Molecular_Function_2023 Hydrolase Activity, Hydrolyzing N-glycosyl Com... 0.016750 0.123369 0 0 inf inf BST1 8 GO_Molecular_Function_2023 Tat Protein Binding (GO:0030957) 0.016750 0.123369 0 0 inf inf DLL1 9 GO_Molecular_Function_2023 WW Domain Binding (GO:0050699) 0.016750 0.123369 0 0 inf inf ENTREP3 10 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.016754 0.123369 0 0 3.180050 13.003634 ZNF483;HAND2;NTN1;NFATC4;GLIS2;ZNF286A 11 GO_Molecular_Function_2023 DNA-binding Transcription Activator Activity, ... 0.026719 0.134555 0 0 5.074219 18.380719 HAND2;INSL3;GLIS2 12 GO_Molecular_Function_2023 Procollagen-Proline Dioxygenase Activity (GO:0... 0.033223 0.134555 0 0 59.575758 202.825781 P4HA3 13 GO_Molecular_Function_2023 N-acetylglucosamine 6-O-sulfotransferase Activ... 0.033223 0.134555 0 0 59.575758 202.825781 CHST7 14 GO_Molecular_Function_2023 ABC-type Xenobiotic Transporter Activity (GO:0... 0.033223 0.134555 0 0 59.575758 202.825781 ABCC1 15 GO_Molecular_Function_2023 alpha-N-acetylgalactosaminide Alpha-2,6-Sialyl... 0.033223 0.134555 0 0 59.575758 202.825781 ST6GALNAC6 16 GO_Molecular_Function_2023 miRNA Binding (GO:0035198) 0.033223 0.134555 0 0 59.575758 202.825781 DND1 17 GO_Molecular_Function_2023 Myosin Heavy Chain Binding (GO:0032036) 0.033223 0.134555 0 0 59.575758 202.825781 NKD2 18 GO_Molecular_Function_2023 Estradiol 17-Beta-Dehydrogenase [NAD(P)] Activ... 0.033223 0.134555 0 0 59.575758 202.825781 HSD17B14 19 GO_Molecular_Function_2023 Solute:Proton Symporter Activity (GO:0015295) 0.033223 0.134555 0 0 59.575758 202.825781 SLC2A13 In [39]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( https://www.genecards.org/cgi-bin/carddisp.pl?gene=PTN In [40]: Copied! G = grn . plot_subgraph ( grn . var [ grn . var [ 'cluster_1.5' ] == '4' ] . index . tolist (), only = 80 , interactive = False ) # G = grn.plot_subgraph(grn.var[grn.var['cluster_1.5']=='4'].index.tolist(), only=80, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['TRHDE', 'PGR', 'ESR1', 'RASD2', 'SYNDIG1', 'OLFM2', 'FZD10', 'BHMT2', 'DUSP26', 'FOXF2', 'ADAM33', 'ADAMTS12', 'HS3ST3A1', 'CHODL', 'FTCD', 'FNDC1', 'HSPB3', 'FOXL1', 'AGMO', 'ADAMTSL2', 'S100A6', 'AKR1B10', 'SCGB1C2'], dtype='object', name='symbol_2') In [29]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_4.html\") In [41]: Copied! enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'GO_Molecular_Function_2023' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['GO_Molecular_Function_2023', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:34:27,578 [WARNING] Input library not found: Reactome. Skip Out[41]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 RNA Polymerase II General Transcription Initia... 0.000032 0.000933 0 0 inf inf FOXF2;ESR1 1 GO_Molecular_Function_2023 Estrogen Response Element Binding (GO:0034056) 0.000032 0.000933 0 0 inf inf PGR;ESR1 2 GO_Molecular_Function_2023 General Transcription Initiation Factor Bindin... 0.000095 0.001860 0 0 378.666667 3508.819727 FOXF2;ESR1 3 GO_Molecular_Function_2023 Transcription Coactivator Binding (GO:0001223) 0.000188 0.002780 0 0 189.285714 1623.428489 PGR;ESR1 4 GO_Molecular_Function_2023 Transition Metal Ion Binding (GO:0046914) 0.000446 0.005263 0 0 13.515099 104.272240 BHMT2;AGMO;ADAM33;TRHDE 5 GO_Molecular_Function_2023 Metalloendopeptidase Activity (GO:0004222) 0.000551 0.005414 0 0 22.794231 171.058857 ADAMTSL2;ADAM33;ADAMTS12 6 GO_Molecular_Function_2023 Metallopeptidase Activity (GO:0008237) 0.000672 0.005666 0 0 21.155357 154.536591 ADAMTSL2;ADAM33;ADAMTS12 7 GO_Molecular_Function_2023 Transcription Coregulator Binding (GO:0001221) 0.001111 0.008195 0 0 54.013605 367.419603 PGR;ESR1 8 GO_Molecular_Function_2023 DNA-binding Transcription Activator Activity, ... 0.001429 0.009365 0 0 15.972973 104.640056 FOXF2;PGR;ESR1 9 GO_Molecular_Function_2023 ATPase Binding (GO:0051117) 0.002016 0.011893 0 0 37.780952 234.495632 PGR;ESR1 10 GO_Molecular_Function_2023 Zinc Ion Binding (GO:0008270) 0.002284 0.012250 0 0 13.407955 81.545835 BHMT2;ADAM33;TRHDE 11 GO_Molecular_Function_2023 Cis-Regulatory Region Sequence-Specific DNA Bi... 0.004517 0.021203 0 0 6.945569 37.504924 FOXF2;PGR;FOXL1;ESR1 12 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.005523 0.021203 0 0 6.541596 34.009122 FOXF2;PGR;FOXL1;ESR1 13 GO_Molecular_Function_2023 DNA Binding, Bending (GO:0008301) 0.005750 0.021203 0 0 inf inf FOXL1 14 GO_Molecular_Function_2023 TBP-class Protein Binding (GO:0017025) 0.005750 0.021203 0 0 inf inf ESR1 15 GO_Molecular_Function_2023 [Heparan Sulfate]-Glucosamine 3-Sulfotransfera... 0.005750 0.021203 0 0 inf inf HS3ST3A1 16 GO_Molecular_Function_2023 RNA Polymerase II Transcription Regulatory Reg... 0.008164 0.028333 0 0 5.812950 27.949028 FOXF2;PGR;FOXL1;ESR1 17 GO_Molecular_Function_2023 Endopeptidase Activity (GO:0004175) 0.008882 0.028593 0 0 8.021918 37.893119 ADAMTSL2;ADAM33;ADAMTS12 18 GO_Molecular_Function_2023 DNA Binding (GO:0003677) 0.009208 0.028593 0 0 7.911486 37.086673 FOXF2;PGR;FOXL1 19 GO_Molecular_Function_2023 Heparan Sulfate Sulfotransferase Activity (GO:... 0.011468 0.030756 0 0 180.727273 807.520606 HS3ST3A1 In [42]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( 4. Differential Gene - Gene connections \u00b6 look at the connections of some key TFs in here do GSEA over these connections compare the connections of these same TFs for both conditions In [5]: Copied! G = grn_c . plot_subgraph ( \"PAGE4\" , only = 100 , max_genes = 40 , interactive = False ) # G = grn_c.plot_subgraph(\"PAGE4\", only=100, max_genes=40, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#ff7f0e'] Index(['MT2A', 'HSPA1A', 'CREM', 'PTN', 'HLA-A', 'SPARCL1', 'SPOCK3', 'NR4A3', 'APOD', 'CALD1', 'MGP', 'HSPE1', 'EIF4A1', 'CD99', 'EMP1', 'FABP4', 'NAMPT', 'NNMT', 'RBP1', 'LUM', 'IGFBP7', 'THBS1', 'YBX3', 'NAF1', 'DCN', 'A2M', 'CPE', 'C1R', 'ATP6V0C', 'MATN2', 'COL6A2', 'UBE2S', 'CST3', 'RHOQ', 'UBE2C', 'C1S', 'H2AZ1', 'GPRC5A', 'HLA-C', 'LGALS1', 'PAGE4'], dtype='object', name='symbol_2') In [96]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) first_node = list ( G . nodes )[ - 1 ] pnet . get_node ( first_node )[ 'color' ] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_PAGE4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) first_node = list(G.nodes)[-1] pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_PAGE4.html\") In [22]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ #'KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', 'WikiPathway_2023_Human' , #'TF_Perturbations_Followed_by_Expression', #'PPI_Hub_Proteins', #'OMIM_Disease', #'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 10 ) enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( 'R-HSA' ) . str [ 0 ] . str . split ( ' WP' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=[ #'KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', 'WikiPathway_2023_Human', #'TF_Perturbations_Followed_by_Expression', #'PPI_Hub_Proteins', #'OMIM_Disease', #'GO_Molecular_Function_2023' ], organism='Human', # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(10) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split('R-HSA').str[0].str.split(' WP').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [139]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size figsize = ( 4 , 5 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size figsize=(4,5), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [17]: Copied! G = grn . plot_subgraph ( \"PAGE4\" , only = 100 , max_genes = 40 , interactive = False ) G = grn.plot_subgraph(\"PAGE4\", only=100, max_genes=40, interactive=False) ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#ff7f0e'] Index(['nan-270', 'S100A6', 'MT2A', 'SPARCL1', 'MIF', 'SLC25A6', 'IGFBP7', 'APOD', 'MGP', 'DCN', 'A2M', 'PTN', 'RELB', 'DNAJB9', 'AKR1C1', 'C1S', 'CST3', 'CXCL8', 'FTH1', 'BRME1', 'FAM205A', 'TIMP1', 'YBX3', 'NPPB', 'TGIF2-RAB5IF', 'FBLN1', 'MTDH', 'IGFBP5', 'TFPI', 'MAP1B', 'COL6A2', 'HNRNPA0', 'EIF4A1', 'CCL21', 'FTL', 'CETN1', 'NME2', 'LSAMP', 'ACR', 'ATP6V0C', 'PAGE4'], dtype='object', name='symbol_2') In [98]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) first_node = list ( G . nodes )[ - 1 ] pnet . get_node ( first_node )[ 'color' ] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_PAGE4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) first_node = list(G.nodes)[-1] pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_PAGE4.html\") In [24]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', #'WikiPathway_2023_Human', # 'TF_Perturbations_Followed_by_Expression', # 'Reactome', #'PPI_Hub_Proteins', #'OMIM_Disease', 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', #'WikiPathway_2023_Human', # 'TF_Perturbations_Followed_by_Expression', # 'Reactome', #'PPI_Hub_Proteins', #'OMIM_Disease', 'GO_Molecular_Function_2023' ], organism='Human', # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) Out[24]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Peptidase Inhibitor Activity (GO:0030414) 0.000020 0.001566 0 0 104.105263 1128.623016 CST3;TIMP1;TFPI 1 GO_Molecular_Function_2023 Transition Metal Ion Binding (GO:0046914) 0.000463 0.016191 0 0 9.025463 69.301557 ACR;MT2A;FTH1;TIMP1;FTL 2 GO_Molecular_Function_2023 Double-Stranded RNA Binding (GO:0003725) 0.000607 0.016191 0 0 101.461538 751.496153 EIF4A1;MTDH 3 GO_Molecular_Function_2023 Endopeptidase Inhibitor Activity (GO:0004866) 0.001010 0.019977 0 0 18.306502 126.278211 CST3;TIMP1;TFPI 4 GO_Molecular_Function_2023 Endopeptidase Regulator Activity (GO:0061135) 0.001498 0.019977 0 0 50.705128 329.757829 CST3;TFPI 5 GO_Molecular_Function_2023 Ferrous Iron Binding (GO:0008198) 0.001498 0.019977 0 0 50.705128 329.757829 FTH1;FTL 6 GO_Molecular_Function_2023 Protease Binding (GO:0002020) 0.002465 0.027606 0 0 12.944079 77.736001 CST3;ACR;TIMP1 7 GO_Molecular_Function_2023 Iron Ion Binding (GO:0005506) 0.002761 0.027606 0 0 33.786325 199.079000 FTH1;FTL 8 GO_Molecular_Function_2023 Calcium Ion Binding (GO:0005509) 0.003252 0.028910 0 0 7.400664 42.393777 CETN1;S100A6;SPARCL1;FBLN1 9 GO_Molecular_Function_2023 Kinase Binding (GO:0019900) 0.005211 0.038377 0 0 9.688322 50.930509 PTN;RELB;HNRNPA0 10 GO_Molecular_Function_2023 RNA Binding (GO:0003723) 0.005277 0.038377 0 0 5.000000 26.222182 EIF4A1;YBX3;DCN;MTDH;HNRNPA0 11 GO_Molecular_Function_2023 Chemokine Activity (GO:0008009) 0.007445 0.039047 0 0 18.405594 90.191859 CXCL8;CCL21 12 GO_Molecular_Function_2023 Chemokine Receptor Binding (GO:0042379) 0.007445 0.039047 0 0 18.405594 90.191859 CXCL8;CCL21 13 GO_Molecular_Function_2023 Metal Ion Binding (GO:0046872) 0.008569 0.039047 0 0 5.523471 26.289761 CETN1;S100A6;SPARCL1;FBLN1 14 GO_Molecular_Function_2023 Protein Kinase Binding (GO:0019901) 0.009285 0.039047 0 0 7.734868 36.193807 PTN;RELB;HNRNPA0 15 GO_Molecular_Function_2023 mRNA 3'-UTR Binding (GO:0003730) 0.009893 0.039047 0 0 15.566075 71.852090 YBX3;HNRNPA0 16 GO_Molecular_Function_2023 NF-kappaB Binding (GO:0051059) 0.010250 0.039047 0 0 inf inf MTDH 17 GO_Molecular_Function_2023 Phosphatase Inhibitor Activity (GO:0019212) 0.010250 0.039047 0 0 inf inf PTN 18 GO_Molecular_Function_2023 Phosphotransferase Activity, Phosphate Group A... 0.010250 0.039047 0 0 inf inf NME2 19 GO_Molecular_Function_2023 Nucleobase-Containing Compound Kinase Activity... 0.010250 0.039047 0 0 inf inf NME2 In [30]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size figsize = ( 4 , 5 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size figsize=(4,5), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( 5. Using classification \u00b6 Here we used the network given by the mean of all heads in our scPRINT model. We could also use other scPRINT versions to see if the results are consistent. but we could also use the classification mechanism presented in our manuscript and other notebooks to get to possibly more specialized networks. In [ ]: Copied! grn_normal = grn_inferer ( layer = list ( range ( model . nlayers ))[:], cell_type = \"naive B cell\" ) grn_normal , m , omni_cls = train_classifier ( grn_normal , C = 0.5 , train_size = 0.9 , class_weight = { 1 : 200 , 0 : 1 }, shuffle = True ) grn_normal = grn_inferer(layer=list(range(model.nlayers))[:], cell_type=\"naive B cell\") grn_normal, m, omni_cls = train_classifier(grn_normal, C=0.5, train_size=0.9, class_weight={ 1: 200, 0: 1}, shuffle=True) number of expressed genes in this cell type: 16801 LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0] Predicting: 0it [00:00, ?it/s] true elem 2115 ... doing regression.... metrics {'used_heads': 25, 'precision': 0.0, 'random_precision': 0.0006433550820644942, 'recall': 0.0, 'predicted_true': 177.0, 'number_of_true': 219.0, 'epr': 0.0} In [ ]: Copied! # highlight differential links on genes that are expressed in both grn_normal . varp [ 'all' ] = grn_normal . varp [ 'GRN' ] . copy () grn_normal . varp [ 'GRN' ] = grn_normal . varp [ 'classified' ] # highlight differential links on genes that are expressed in both grn_normal.varp['all'] = grn_normal.varp['GRN'].copy() grn_normal.varp['GRN'] = grn_normal.varp['classified'] Notes on findings and their relation to the literature \u00b6 CAV1-expressing CAFs contribute to invasion and metastasis in breast cancer24 loss of caveolin1 (CAV1) is found in metabolically reprogrammed CAFs that promote tumorigenesis discoidin domain-containing receptor 2 (DDR2)21 and integrin \u03b111\u03b2122, have emerged to identify CAFs in the context of a specific TME https://www.nature.com/articles/s12276-023-01013-0 normal fibroblast populations marked by the expression of Gli1 and Hoxb6 CAFs, remain perpetually activated with a high capacity for ECM synthesis and microenvironmental remodeling, leading to stromal desmoplasia, a phenomenon characterized by increased deposition of ECM components in tumors. In this regard, CAFs share many basic characteristics, such as a secretory phenotype and capacity to synthesize ECM components, with fibroblasts found in nonmalignant tissue fibrosis. Therefore, the classic markers found to be expressed in fibroblasts, including \u03b1-SMA, vimentin, desmin, fibroblast-specific protein 1 (FSP1; also known as S100A4) Fibrogenesis is part of a normal protective response to tissue injury that can become irreversible and progressive, leading to fatal diseases. Senescent cells are a main driver of fibrotic diseases through their secretome, known as senescence-associated secretory phenotype (SASP) CAFs (vCAFs), cycling CAFs (cCAFs), and developmental CAFs (dCAFs) The stem-like \u2018universal\u2019 type of fibroblast cell, marked by expression of peptidase inhibitor 16 (Pi16) and Col15a, found in the steady state across tissues, activated fibroblasts, as observed by the development of LRRC15+ CAFs in PDAC. . SOCS1: Suppressor of cytokine signaling; STAT3: Signal transducer and activator of transcription 3; LDH: Lactate dehydrogenase; PYCR1: pyrroline-5-carboxylate reductase senescence, and multiple types of fibrotic diseases in mice and humans are characterized by the accumulation of iron. https://www.nature.com/articles/s42255-023-00928-2 Current evidence indicate that cancer-associated fibroblasts (CAFs) play an important role in prostate cancer (PCa) development and progression. playing a role in invasion. NDRG2, TSPAN1, PTN, APOE, OR51E2, P4HB, STEAP1 and ABCC4 were used to construct molecular subtypes and CAF-related gene prognostic index (CRGPI) Studies on the role of STEAP1, OR51E2, PTN, ABCC4, NDRG2 have been relatively in-depth. For instance, STEAP1 is all-called six-transmembrane epithelial antigen of the prostate 1, which belongs to a family of metalloproteinases involved in iron and copper homeostasis and other cellular processes37. STEAP1 is overexpressed on the plasma membrane of PCa cells and is associated with PCa invasiveness and metastasis50. The possible mechanism of STEAP1 promoting tumor proliferation and metastasis is by acting as a channel for small molecules that are involved in intercellular communication OR51E2 perhaps could be used as one of the biomarkers for PCa53,54,55,56 https://www.nature.com/articles/s41598-023-36125-0#Sec11 The protein encoded by ABCC4 is a member of the superfamily of ATP-binding cassette (ABC) transporters, which is also called multidrug resistance protein 4 (MRP4)64. MRP4 was reported to be associated with drug resistance of PCa in many studies65,66,67 PRRX1, OSR1, FOXD1, HOXC4,LHX9, TBX3 and TWIST2, targeted five or more TFs inthe fibroblast TRN. This influential-set explained 62.5% ofthe total number of regulatory edges and they collectivelytargeted 15 out of 18 TFs represented in the network. Upona closer examination of the fibroblastic network, the inter-actions among OSR1\u2013PRRX1\u2013TWIST2 were notably co-ordinated, regulating one another in both directions https://www.researchgate.net/publication/264633205_A_transient_disruption_of_fibroblastic_transcriptional_regulatory_network_facilitates_trans-differentiation FGF receptors are important in PCa initiation and progression. These endocrine FGFs require alpha-Klotho (KL) and/or beta-Klotho (KLB), two related single-pass transmembrane proteins restricted in their tissue distribution. FGF19 is expressed in primary and metastatic PCa tissues where it functions as an autocrine growth factor. https://www.e-cancer.fr/Professionnels-de-sante/Veille-bibliographique/Nota-Bene-Cancer/NBC-174/The-endocrine-fibroblast-growth-factor-FGF19-promotes-prostate-cancer-progression \u2022 Prostate cancer stroma contains diverse populations of fibroblasts. \u2022 Carcinoma associated fibroblasts can promote prostate carcinogenesis. \u2022 Interaction among fibroblast subsets modulate stromal-epithelial paracrine signaling. The stroma in the normal prostate is predominantly composed of smooth muscle cells while in cancer this is partially replaced by fibroblasts and myofibroblasts6. These fibroblastic cells are responsible for collagen and extracellular matrix (ECM) deposition, changing local organ stiffness iCAF, myCAF, apCAF It has been shown that SDF-1/CXCL12, secreted by CAF, acts via TGF\u03b2\u2013mediated upregulation of CXCR4 in epithelial cells to activate Akt signaling associated with tumorigenesis. Overexpression of SDF-1/CXCL12 and TGF\u03b21 in benign human prostate fibroblasts has been shown to induce malignant transformation of benign prostate epithelial cells and formation of highly invasive tumors in vivo increased cadherin 2 (CDH2) mRNA expression in LNCaP cells Upregulation of DNA methyltransferases (DNMT) consistent with aberrant promoter hypermethylation of tumor-suppressor genes in multiple cancer types including PCa has been reported https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8788937/#:~:text=The%20stroma%20in%20the%20normal,deposition%2C%20changing%20local%20organ%20stiffness . CD10 and GPR77 can define a human CAF subset that sustains cancer stemness Fibroblasts are also fundamental for inducing angiogenesis by secreting angiogenic factors such as vascular endothelial growth factor (VEGF) and matrix proteins Epithelial cells release TGF\u03b2 ligands, Kallikrein-related peptidase-4 (KLK4), CAFs are characterized by molecular markers that are upregulated compared to normal fibroblasts, such as fibroblast activation protein (FAP), PDGFR-\u03b2, fibroblast-specific protein-1 (FSP-1) (also known as S100A4) ACTA2 \u03b1-smooth actin (\u03b1-SMA) Upregulated RT-qPCR, IHC on tissue microarrays [42,43] ASPN Asporin Upregulated Tag-based RNA profiling, microarray profiling, IHC, RT-qPCR [38,44,45] CAV1 Caveolin-1 Downregulated Tag profiling, IHC, RT-qPCR [38] COL1A1 Collagen Type-I Upregulated RT-qPCR, IHC [42,43] CXCL12 Stromal cell-derived factor 1 (SDF1)/ (C-X-C motif chemokine ligand 12 (CXCL12) Upregulated Tag-profiling, RT-qPCR, ELISA [38,46] FAP Fibroblast activation protein Upregulated IHC [42] FGF2, FGF7, FGF10 Fibroblast growth factor-2/-7/-10 Upregulated RT-qPCR, Western Blot, IHC [43,47,48] FN1 Fibronectin Upregulated Tag profiling, IHC, RT-qPCR [38] ITGA1 Integrin-\u03b11 (CD49a) Upregulated IHC [49] OGN Osteoglycin Upregulated Tag-profiling, IHC, RT-qPCR [38] PDGFRB Platelet-derived growth factor receptor \u03b2 Upregulated Microarray profiling [44,50] POSTN Periostin Upregulated Microarray profiling, IHC [44] S100A4 Fibroblast-specific protein 1 (FSP1)/S100 Calcium Binding Protein A4 (S100A4) Upregulated Immunofluorescence, RT-qPCR, Western Blot [51,52,53] S100A6 S100 Calcium Binding Protein A6 Downregulated Tag profiling, IHC, RT-qPCR [38] SPARC Secreted Protein Acidic and Cysteine Rich Up/downregulated Microarray profiling, Tag-profiling [38,44] STC1 Stanniocalcin 1 Downregulated Tag profiling, IHC, RT-qPCR [38] THY1 Cluster of differentiation 90 (CD90) antigen Upregulated IHC [54] TNC Tenascin C Upregulated RT-qPCR, IHC [42,43] VIM Vimentin Upregulated IHC Benign prostatic hyperplasia (BPH) is a non-malignant growth of the prostate, typically occurring in older men with an occurrence of 80\u201390% of men in their 70s BPH develops in the transition zone differently from PCa foci, which usually develop in the peripheral zone ESR1= . Here we studied the role of CAF estrogen receptor alpha (ER\u03b1) and found that it could protect against PCa invasion. ER\u03b1 could function through a CAF\u2013epithelial interaction via selectively upregulating thrombospondin 2 (Thbs2) and downregulating matrix metalloproteinase 3 (MMP3) at the protein and messenger RNA levels https://academic.oup.com/carcin/article/35/6/1301/449417 ACTA2: we found that \u201creactive CAFs\u201d induce shear resistance to prostate tumor cells via intercellular contact and soluble derived factors. The reactive CAFs showed higher expression of \u03b1-smooth muscle actin (\u03b1-SMA) and fibroblast activation protein (FAP) compared to differentiated CAFs https://www.oncotarget.com/article/27510/ Proteins that exhibited a significant increase in CAF versus NPF were enriched for the functional categories \u201ccell adhesion\u201d and the \u201cextracellular matrix.\u201d The CAF phosphoproteome exhibited enhanced phosphorylation of proteins associated with the \u201cspliceosome\u201d and \u201cactin binding.\u201d COL1A1/2 and COL5A1; the receptor tyrosine kinase discoidin domain-containing receptor 2 (DDR2), a receptor for fibrillar collagens; and lysyl oxidase-like 2 (LOXL2) https://www.mcponline.org/article/S1535-9476(20)31548-6/fulltext \u2022Cancer-associated fibroblasts (CAFs) exhibit a highly aligned cytoskeleton and extracellular matrix. \u2022CAFs are stiffer than normal fibroblasts from the prostate. \u2022Benign prostate epithelial cells are more compliant after co-culture with CAFs. \u2022Benign epithelial cells are more invasive and proliferative in presence of CAFs. https://www.sciencedirect.com/science/article/pii/S2590006420300338 These findings suggest that CAFs exosomes drive PCa metastasis via the miR-500a-3p/FBXW7/HSF1 axis in a hypoxic microenvironmen https://www.nature.com/articles/s41417-024-00742-2 https://www.genecards.org/cgi-bin/carddisp.pl?gene=CCT8L2 CCT8L2 (Chaperonin Containing TCP1 Subunit 8 Like 2) is a Protein Coding gene. Gene Ontology (GO) annotations related to this gene include calcium-activated potassium channel activity and monoatomic anion channel activity. An important paralog of this gene is CCT8. related to the meta transmembrane activity via Possible molecular chaperone; assists the folding of proteins upon ATP hydrolysis. The TRiC complex mediates the folding of WRAP53/TCAB1, thereby regulating telomere maintenance (PubMed:25467444). As part of the TRiC complex may play a role in the assembly of BBSome, a complex involved in ciliogenesis regulating transports vesicles to the cilia https://www.genecards.org/cgi-bin/carddisp.pl?gene=TIMP1 TIMP Metallopeptidase Inhibitor 1 inhibitors of the matrix metalloproteinases (MMPs), a group of peptidases involved in degradation of the extracellular matrix. In addition to its inhibitory role against most of the known MMPs, the encoded protein is able to promote cell proliferation connected to TLL2: zinc-dependent metalloprotease part of the metzincin protein complex which also is Among its related pathways are Collagen chain trimerization and Extracellular matrix organization. PDXP, SEPTIN5 cytoskeletal organization and regulation PRAME inhibits the signaling of retinoic acid and mediates the regulation of selenoproteins many genes involved in cancer. indeed, it is known that 80% adult male above 70 years old will have such hyperplastic prostate. This is due to scenesence. and that Iron accumulation drives fibrosis, senescence and the senescence-associated secretory phenotype. (of which we have some proteins present here.) A mechanism that this clustered is one of genes that strongly regulates each other in this fibroblasts from pre-cancerous lesions via fibrotic iron accumulation and a secretory mechanism GJC1 (exchange of things between cells (here likely metals?)) Unknown genes like SMIM40. integral membrane protein could be linked to this phenotype ['pre { line-height: 125%; }\\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n.highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) }\\n.highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\\n.highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\\n.highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */\\n.highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\\n.highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\\n.highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\\n.highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\\n.highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\\n.highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\\n.highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\\n.highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\\n.highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\\n.highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\\n.highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\\n.highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\\n.highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\\n.highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\\n.highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\\n.highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\\n.highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\\n.highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\\n.highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\\n.highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\\n.highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\\n.highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\\n.highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\\n.highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\\n.highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\\n.highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\\n.highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\\n.highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\\n.highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\\n.highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\\n.highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\\n.highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\\n.highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\\n.highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\\n.highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\\n.highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\\n.highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\\n.highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\\n.highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */']","title":"scPRINT use case on BPH (part 2, GN analysis)"},{"location":"notebooks/cancer_usecase_part2/#scprint-use-case-on-bph-part-2-gn-analysis","text":"In this use-case, which some of the results are presented in Figure 5 of our manuscript , we perform an extensive analysis of gene networks generated by scPRINT in our previous notebook for fibroblasts of the prostate in both normal and benign prostatic hyperplasia states. We can look at many patterns from the gene networks such as hub genes, gene modules, and gene-gene interactions. Some of them are related to highly variable and differentially expressed genes while others can only be infered by using the gene networks. Table of content: Hub genes Network similarity Network communities Cancer version Normal version Differential Gene - Gene connections Using classification In [1]: Copied! from bengrn import BenGRN import scanpy as sc from bengrn.base import train_classifier from anndata.utils import make_index_unique from grnndata import utils as grnutils from grnndata import read_h5ad from matplotlib import pyplot as plt from scdataloader import utils as data_utils import numpy as np from pyvis import network as pnx import networkx as nx import scipy.sparse import pandas as pd import gseapy as gp from gseapy import dotplot % load_ext autoreload % autoreload 2 from bengrn import BenGRN import scanpy as sc from bengrn.base import train_classifier from anndata.utils import make_index_unique from grnndata import utils as grnutils from grnndata import read_h5ad from matplotlib import pyplot as plt from scdataloader import utils as data_utils import numpy as np from pyvis import network as pnx import networkx as nx import scipy.sparse import pandas as pd import gseapy as gp from gseapy import dotplot %load_ext autoreload %autoreload 2 \ud83d\udca1 connected lamindb: jkobject/scprint In [ ]: Copied! prostate_combined = sc . read_h5ad ( \"../data/prostate_combined_o2uniqsx.h5ad\" ) prostate_combined = sc.read_h5ad(\"../data/prostate_combined_o2uniqsx.h5ad\") In [2]: Copied! # load the generated gene networks from the previous notebook grn = read_h5ad ( \"../../data/prostate_fibro_grn.h5ad\" ) grn_c = read_h5ad ( \"../../data/prostate_cancer_fibro_grn.h5ad\" ) #remove duplicates grn . var . symbol = make_index_unique ( grn . var . symbol . astype ( str )) grn_c . var . symbol = make_index_unique ( grn_c . var . symbol . astype ( str )) # convert gene ids to symbols grn . var [ 'ensembl_id' ] = grn . var . index grn . var . index = grn . var . symbol grn_c . var [ 'ensembl_id' ] = grn_c . var . index grn_c . var . index = grn_c . var . symbol grn . obs . cleaned_pred_disease_ontology_term_id . value_counts (), grn_c . obs . cleaned_pred_disease_ontology_term_id . value_counts () # load the generated gene networks from the previous notebook grn = read_h5ad(\"../../data/prostate_fibro_grn.h5ad\") grn_c = read_h5ad(\"../../data/prostate_cancer_fibro_grn.h5ad\") #remove duplicates grn.var.symbol = make_index_unique(grn.var.symbol.astype(str)) grn_c.var.symbol = make_index_unique(grn_c.var.symbol.astype(str)) # convert gene ids to symbols grn.var['ensembl_id'] = grn.var.index grn.var.index = grn.var.symbol grn_c.var['ensembl_id'] = grn_c.var.index grn_c.var.index = grn_c.var.symbol grn.obs.cleaned_pred_disease_ontology_term_id.value_counts(),grn_c.obs.cleaned_pred_disease_ontology_term_id.value_counts() Out[2]: (cleaned_pred_disease_ontology_term_id normal 300 Name: count, dtype: int64, cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 300 Name: count, dtype: int64)","title":"scPRINT use case on BPH (part 2, GN analysis)"},{"location":"notebooks/cancer_usecase_part2/#1-hub-genes","text":"We will use 2 different definition of centrality to compare the hubs of the networks in both states. The first one is the degree centrality, which is the number of connections of a node. The second one is the eigenvector centrality, which is the sum of the centrality of the neighbors of a node. For each gene we mostly interogate their meaning with genecards, e.g. https://www.genecards.org/cgi-bin/carddisp.pl?gene=CD99 In [7]: Copied! # between the two networks we have ~3000 genes in common over their 4000 genes common = set ( grn_c . var . symbol ) & set ( grn . var . symbol ) len ( common ) # between the two networks we have ~3000 genes in common over their 4000 genes common = set(grn_c.var.symbol) & set(grn.var.symbol) len(common) Out[7]: 2881 In [8]: Copied! # hub genes based on edge centrality (number of connections / strength of connections) grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 20 ) # hub genes based on edge centrality (number of connections / strength of connections) grn.grn.sum(0).sort_values(ascending=False).head(20) Out[8]: symbol S100A6 58.131020 TGIF2-RAB5IF 51.177635 MIF 44.534096 DNAJB9 40.953262 IGFBP7 38.629910 APOD 38.003906 BRME1 37.598698 SPARCL1 37.160854 TIMP1 36.671650 DCN 34.621376 C1S 32.746254 MGP 30.496748 nan-270 29.884596 SLC25A6 29.308729 BLOC1S5-TXNDC5 28.986681 CETN1 28.746281 FTL 28.266533 AKR1C1 27.641245 FBLN1 26.828733 MT2A 25.590197 dtype: float32 In [7]: Copied! # without taking in account genes that are not present in the cancer network grn . grn . sum ( 0 ) . loc [ list ( common )] . sort_values ( ascending = False ) . head ( 20 ) # without taking in account genes that are not present in the cancer network grn.grn.sum(0).loc[list(common)].sort_values(ascending=False).head(20) Out[7]: symbol TGIF2-RAB5IF 51.177635 IGFBP7 38.629910 APOD 38.003906 BRME1 37.598698 SPARCL1 37.160854 TIMP1 36.671650 DCN 34.621376 C1S 32.746254 MGP 30.496748 BLOC1S5-TXNDC5 28.986681 AKR1C1 27.641245 FBLN1 26.828733 MT2A 25.590197 MYOC 25.428144 FAM205A 25.296257 YBX3 24.937267 CST3 24.676405 C11orf96 18.731924 TFPI 18.429214 ATP6V0C 17.695705 dtype: float32 In [11]: Copied! # cancer hub genes grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 20 ) # cancer hub genes grn_c.grn.sum(0).sort_values(ascending=False).head(20) Out[11]: symbol HSPA1A 75.300415 MT2A 57.938267 CREM 42.478115 TGIF2-RAB5IF 39.980556 HSPE1 38.607624 CALD1 36.512047 SPOCK3 35.564945 HLA-A 33.446110 SPARCL1 33.403152 RBP1 32.482758 C1S 32.037743 BRME1-1 31.879770 FABP4 31.604069 nan-99 31.555256 LUM 30.523245 EIF4A1 29.690474 ATP6V0C 29.475002 PDZD2 27.333025 DEFA1 26.979454 CTSG 25.070097 dtype: float32 In [10]: Copied! # without taking in account genes not present in the normal network grn_c . grn . sum ( 0 ) . loc [ list ( common )] . sort_values ( ascending = False ) . head ( 20 ) # without taking in account genes not present in the normal network grn_c.grn.sum(0).loc[list(common)].sort_values(ascending=False).head(20) Out[10]: symbol HSPA1A 75.300415 MT2A 57.938267 TGIF2-RAB5IF 39.980556 SPOCK3 35.564945 HLA-A 33.446110 SPARCL1 33.403152 C1S 32.037743 nan-99 31.555256 LUM 30.523245 EIF4A1 29.690474 ATP6V0C 29.475002 DEFA1 26.979454 IGFBP7 23.982243 DCN 23.304916 MGP 22.596451 CD99 21.624668 BLOC1S5-TXNDC5 20.914230 SERPING1 20.824636 COL6A2 18.076559 THBS1 17.826540 dtype: float32 In [12]: Copied! # top differential hubs TOP = 10 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) # top differential hubs TOP = 10 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[12]: {'HLA-A', 'HSPA1A', 'MT2A', 'SPOCK3'} In [13]: Copied! TOP = 20 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 20 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[13]: {'ATP6V0C', 'DEFA1', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LUM', 'SPOCK3', 'nan-99'} In [14]: Copied! TOP = 50 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 50 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[14]: {'CD99', 'CPE', 'DEFA1', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LGALS1', 'LUM', 'PYDC2', 'SERPING1', 'SPOCK3', 'THBS1', 'nan-191', 'nan-99'} overall we see that both are somewhat similar in the way the networks classifies main nodes but at least around half of the top 200 nodes are different between the two datasets and half of those are not due to diffent gene being used by the networks (50) genes preferentially given as top elements in the tumor version only: CD99 CPE DEFA1 EIF4A1 HLA-A HSPA1A LGALS1 LUM PYDC2 SERPING1 SPOCK3 THBS1 In [3]: Copied! # we now compute eigen centrality creating a sparse network by only keeping the top 20 neighbors for each gene in the network TOP = 20 grnutils . get_centrality ( grn , TOP , top_k_to_disp = 0 ) grnutils . get_centrality ( grn_c , TOP , top_k_to_disp = 0 ) # we now compute eigen centrality creating a sparse network by only keeping the top 20 neighbors for each gene in the network TOP = 20 grnutils.get_centrality(grn, TOP, top_k_to_disp=0) grnutils.get_centrality(grn_c, TOP, top_k_to_disp=0) Top central genes: [] Top central genes: [] Out[3]: [] In [12]: Copied! grn_c . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn_c.var.centrality.sort_values(ascending=False).head(10) Out[12]: symbol HSPA1A 0.271584 MT2A 0.271584 CREM 0.271574 CD99 0.271517 NR4A3 0.271385 RBP1 0.271130 SOX4 0.264214 ATP6V0C 0.263235 HLA-A 0.232913 LUM 0.202007 Name: centrality, dtype: float64 In [9]: Copied! grn_c . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn_c.var.centrality.sort_values(ascending=False).head(10) Out[9]: symbol HSPA1A 0.271584 MT2A 0.271584 CREM 0.271574 CD99 0.271517 NR4A3 0.271385 RBP1 0.271130 SOX4 0.264214 ATP6V0C 0.263235 HLA-A 0.232913 LUM 0.202007 Name: centrality, dtype: float64 In [10]: Copied! grn . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn.var.centrality.sort_values(ascending=False).head(10) Out[10]: symbol MT2A 0.276470 SLC25A6 0.276183 CXCL8 0.275859 FTH1 0.275757 MIF 0.267968 DNAJB9 0.265635 SOX4 0.241950 RELB 0.234482 YBX3 0.216567 CST3 0.213585 Name: centrality, dtype: float64 In [13]: Copied! TOP = 10 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 10 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[13]: {'ATP6V0C', 'CD99', 'HLA-A', 'HSPA1A', 'LUM'} In [12]: Copied! TOP = 20 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 20 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[12]: {'ATP6V0C', 'CD99', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LUM', 'PAGE4', 'RYR2', 'SERPINF1'} In [11]: Copied! TOP = 50 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 50 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[11]: {'C1R', 'CD99', 'COL6A2', 'HLA-A', 'HNRNPA0', 'HSPA1A', 'LUM', 'PAGE4', 'SERPINA3', 'SERPING1', 'SPOCK3', 'THBS1'} it seems the networks are even more similar when comparing them at the level of the centrality of their nodes. this means that some are highly central while maybe not","title":"1. Hub genes"},{"location":"notebooks/cancer_usecase_part2/#2-network-similarity","text":"We now look at the similarity of the two networks based on general overlap of their top K edges across their common nodes In [41]: Copied! grn . var . index = grn . var . ensembl_id grn_c . var . index = grn_c . var . ensembl_id overlap = list ( set ( grn . var . index ) & set ( grn_c . var . index )) grn.var.index = grn.var.ensembl_id grn_c.var.index = grn_c.var.ensembl_id overlap = list(set(grn.var.index) & set(grn_c.var.index)) In [43]: Copied! K = 20 subgrn_c = grn_c . get ( overlap ) . grn subgrn_c = subgrn_c . apply ( lambda row : row >= row . nlargest ( K ) . min (), axis = 1 ) subgrn = grn . get ( overlap ) . grn subgrn = subgrn . apply ( lambda row : row >= row . nlargest ( K ) . min (), axis = 1 ) ( subgrn & subgrn_c ) . sum ( 1 ) . mean () / K K = 20 subgrn_c = grn_c.get(overlap).grn subgrn_c = subgrn_c.apply(lambda row: row >= row.nlargest(K).min(), axis=1) subgrn = grn.get(overlap).grn subgrn = subgrn.apply(lambda row: row >= row.nlargest(K).min(), axis=1) (subgrn & subgrn_c).sum(1).mean() / K Out[43]: 0.5055735930735931 when looking at the top 20 connection for each genes in the network we see that on average only 50% of them agree between the two networks","title":"2. Network similarity"},{"location":"notebooks/cancer_usecase_part2/#3-network-communities","text":"Again looking at the top 20 connections for each gene in the network we use the leiden (or louvain) algorithm to find communities in both networks. We then study the hub of these communities as well as their enrichment using enrichr and ontology databases. We will only look at communities between 20 and 200 genes In [33]: Copied! TOP = 20 grnutils . get_centrality ( grn , TOP , top_k_to_disp = 0 ) grnutils . get_centrality ( grn_c , TOP , top_k_to_disp = 0 ) TOP = 20 grnutils.get_centrality(grn, TOP, top_k_to_disp=0) grnutils.get_centrality(grn_c, TOP, top_k_to_disp=0) Top central genes: [] Top central genes: [] Out[33]: [] In [17]: Copied! grn_c = grnutils . compute_cluster ( grn_c , 1.5 , use = \"leiden\" , n_iterations = 10 , max_comm_size = 100 ) grn_c = grnutils.compute_cluster(grn_c, 1.5, use=\"leiden\", n_iterations=10, max_comm_size=100) In [4]: Copied! grn = grnutils . compute_cluster ( grn , 1.5 ) grn_c = grnutils . compute_cluster ( grn_c , 1.5 ) grn = grnutils.compute_cluster(grn, 1.5) grn_c = grnutils.compute_cluster(grn_c, 1.5)","title":"3. Network communities"},{"location":"notebooks/cancer_usecase_part2/#31-cancer-version","text":"In [30]: Copied! # our communities grn . var [ 'cluster_1.5' ] . value_counts () . head ( 10 ) # our communities grn.var['cluster_1.5'].value_counts().head(10) Out[30]: cluster_1.5 0 1620 1 1483 2 732 3 111 4 23 5 9 6 4 16 1 23 1 22 1 Name: count, dtype: int64 In [31]: Copied! G = grn_c . plot_subgraph ( grn_c . var [ grn_c . var [ 'cluster_1.5' ] == '4' ] . index . tolist (), only = 200 , interactive = False ) # G = grn_c.plot_subgraph(grn_c.var[grn_c.var['cluster_1.5']=='4'].index.tolist(), only=200, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['PRDM6', 'MSANTD3', 'STAG3', 'TRHDE', 'TBX5', 'HEPH', 'GALNT16', 'NFATC4', 'SYNDIG1', 'HSF4', 'ZNF423', 'PLA2G4C', 'PLPPR2', 'SCN1B', 'ASPA', 'SNX15', 'BAG2', 'PTK7', 'HRH2', 'PLCL1', 'PTCH2', 'TGFB3', 'RASL11A', 'TOX2', 'CPNE5', 'GLIS2', 'HIVEP3', 'FGF13', 'ACAP3', 'DUSP26', 'CTIF', 'CAMK1', 'SLC9A5', 'FBN2', 'LRIG1', 'LIMD1', 'TRPC1', 'SLC2A13', 'ADAMTS12', 'FZD7', 'AFF2', 'CACNA1D', 'MRAS', 'ST6GALNAC6', 'FGFR4', 'PTGER1', 'PKDCC', 'SLC9B2', 'NPY1R', 'ANKRD33B', 'DCLK2', 'PURG', 'GXYLT2', 'LRRN4CL', 'CA8', 'EXOC3L1', 'BHLHE22', 'AATK', 'CMC4', 'BOLA2', 'CCR10', 'TCEAL2', 'SLC24A3', 'ROR1', 'SLC51B', 'EMID1', 'AGMO', 'CENPP', 'OPTC', 'SPOCK3', 'COL27A1', 'DACT3', 'STMN3', 'DLL1', 'SMOC1', 'COLGALT2', 'ZDBF2', 'DOK6', 'HNRNPUL2-BSCL2', 'C3orf84', 'C2orf74', 'ARHGEF25', 'NPIPB5', 'TNFSF12-TNFSF13', 'ZFP91-CNTF', 'nan-41', 'nan-81', 'nan-96', 'nan-98', 'HERC3', 'nan-116', 'nan-117'], dtype='object', name='symbol_2') In [26]: Copied! # if you want to draw better looking networks pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_4.html\" ) # if you want to draw better looking networks pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_4.html\") In [32]: Copied! # Assuming 'node_names' contains the list of gene names. # Note: it seems with enrichr, one can only use one gene set at a time, choose accordingly enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn_c . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names. # Note: it seems with enrichr, one can only use one gene set at a time, choose accordingly enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn_c.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:31:53,534 [WARNING] Input library not found: Reactome. Skip Out[32]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Solute:Potassium Antiporter Activity (GO:0022821) 0.000523 0.050652 0 0 inf inf SLC24A3;SLC9A5 1 GO_Molecular_Function_2023 Coreceptor Activity Involved In Wnt Signaling ... 0.001547 0.050652 0 0 86.822222 561.890021 PTK7;ROR1 2 GO_Molecular_Function_2023 Sodium Ion Transmembrane Transporter Activity ... 0.001547 0.050652 0 0 86.822222 561.890021 SLC9A5;SLC9B2 3 GO_Molecular_Function_2023 Calcium Ion Transmembrane Transporter Activity... 0.001700 0.050652 0 0 16.432584 104.795452 SLC24A3;TRPC1;CACNA1D 4 GO_Molecular_Function_2023 Calcium-Dependent Phospholipid Binding (GO:000... 0.003047 0.050652 0 0 43.400000 251.445478 CPNE5;PLA2G4C 5 GO_Molecular_Function_2023 Coreceptor Activity Involved In Wnt Signaling ... 0.003047 0.050652 0 0 43.400000 251.445478 PTK7;ROR1 6 GO_Molecular_Function_2023 Metal Cation:Proton Antiporter Activity (GO:00... 0.003047 0.050652 0 0 43.400000 251.445478 SLC9A5;SLC9B2 7 GO_Molecular_Function_2023 Sodium:Proton Antiporter Activity (GO:0015385) 0.003047 0.050652 0 0 43.400000 251.445478 SLC9A5;SLC9B2 8 GO_Molecular_Function_2023 Iron Ion Binding (GO:0005506) 0.005002 0.070586 0 0 28.925926 153.247105 HEPH;AGMO 9 GO_Molecular_Function_2023 Calcium Channel Activity (GO:0005262) 0.005307 0.070586 0 0 10.099395 52.907606 SLC24A3;TRPC1;CACNA1D 10 GO_Molecular_Function_2023 Wnt Receptor Activity (GO:0042813) 0.007391 0.089364 0 0 21.688889 106.438022 FZD7;ROR1 11 GO_Molecular_Function_2023 RNA Polymerase II-specific DNA-binding Transcr... 0.010110 0.104284 0 0 7.715135 35.445265 TBX5;DUSP26;DLL1 12 GO_Molecular_Function_2023 Phospholipase Activity (GO:0004620) 0.010193 0.104284 0 0 17.346667 79.552387 PLCL1;PLA2G4C 13 GO_Molecular_Function_2023 Monoatomic Cation Channel Activity (GO:0005261) 0.011601 0.110210 0 0 7.284644 32.465172 SLC24A3;TRPC1;CACNA1D 14 GO_Molecular_Function_2023 Sodium Channel Regulator Activity (GO:0017080) 0.013389 0.118714 0 0 14.451852 62.335739 FGF13;SCN1B 15 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.022992 0.139045 0 0 2.668376 10.066740 HSF4;HIVEP3;BHLHE22;TBX5;ZNF423;NFATC4;GLIS2 16 GO_Molecular_Function_2023 Calcium:Sodium Antiporter Activity (GO:0005432) 0.023000 0.139045 0 0 inf inf SLC24A3 17 GO_Molecular_Function_2023 Potassium:Proton Antiporter Activity (GO:0015386) 0.023000 0.139045 0 0 inf inf SLC9A5 18 GO_Molecular_Function_2023 Xylosyltransferase Activity (GO:0042285) 0.023000 0.139045 0 0 inf inf GXYLT2 19 GO_Molecular_Function_2023 Tat Protein Binding (GO:0030957) 0.023000 0.139045 0 0 inf inf DLL1 In [33]: Copied! # we make a plot of the enrichment enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) # we make a plot of the enrichment enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [34]: Copied! G = grn_c . plot_subgraph ( grn_c . var [ grn_c . var [ 'cluster_1.5' ] == '5' ] . index . tolist (), only = 80 , interactive = False ) # G = grn_c.plot_subgraph(grn_c.var[grn_c.var['cluster_1.5']=='5'].index.tolist(), only=80, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['ABCF2', 'ITIH4', 'OLFM2', 'ICAM4', 'RIGI', 'KAZALD1', 'BST1', 'PANX1', 'C9', 'FBXO2', 'ZNF410', 'ACVR1C', 'VAMP7', 'TOP2A', 'TAF4B', 'KIAA1755', 'EDA', 'YPEL4', 'ENTPD3', 'GP9', 'NLGN2', 'CLCF1', 'RPRM', 'ODF3B', 'MSC', 'NTF3', 'COL13A1', 'GP1BB', 'HSPA1A', 'TMEM158', 'nan-82', 'NBPF19', 'SCO2', 'SMIM41'], dtype='object', name='symbol_2') In [87]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_5.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_5.html\") In [44]: Copied! grn_c . var . loc [ 'nan-82' ] # par of the Glycoside Hydrolase Family grn_c.var.loc['nan-82'] # par of the Glycoside Hydrolase Family Out[44]: uid 4giyQrh7tkXI symbol nan-82 ncbi_gene_ids biotype protein_coding description novel protein synonyms organism_id 2 public_source_id 9.0 created_by_id 1 mt False ribo False hb False organism NCBITaxon:9606 TFs False ensembl_id ENSG00000269590 centrality 0.0 cluster_1.5 5 Name: nan-82, dtype: object In [35]: Copied! enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn_c . var . symbol . tolist (), ) enr . res2d . head ( 20 ) enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn_c.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:33:16,565 [WARNING] Input library not found: Reactome. Skip Out[35]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Death Receptor Binding (GO:0005123) 0.000416 0.028729 0 0 123.875000 964.236668 EDA;NTF3 1 GO_Molecular_Function_2023 Purine Ribonucleoside Triphosphate Binding (GO... 0.007050 0.073312 0 0 8.626100 42.739637 ABCF2;RIGI;HSPA1A 2 GO_Molecular_Function_2023 Receptor Ligand Activity (GO:0048018) 0.007732 0.073312 0 0 5.742222 27.920829 EDA;CLCF1;NTF3;HSPA1A 3 GO_Molecular_Function_2023 Activin Receptor Activity (GO:0017002) 0.008500 0.073312 0 0 inf inf ACVR1C 4 GO_Molecular_Function_2023 Gap Junction Hemi-Channel Activity (GO:0055077) 0.008500 0.073312 0 0 inf inf PANX1 5 GO_Molecular_Function_2023 NF-kappaB Binding (GO:0051059) 0.008500 0.073312 0 0 inf inf TAF4B 6 GO_Molecular_Function_2023 Hydrolase Activity, Hydrolyzing N-glycosyl Com... 0.008500 0.073312 0 0 inf inf BST1 7 GO_Molecular_Function_2023 Ubiquitin-Protein Transferase Activator Activi... 0.008500 0.073312 0 0 inf inf RIGI 8 GO_Molecular_Function_2023 DNA Binding, Bending (GO:0008301) 0.016930 0.083096 0 0 120.151515 490.060134 TOP2A 9 GO_Molecular_Function_2023 Disordered Domain Specific Binding (GO:0097718) 0.016930 0.083096 0 0 120.151515 490.060134 HSPA1A 10 GO_Molecular_Function_2023 UDP Phosphatase Activity (GO:0045134) 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 11 GO_Molecular_Function_2023 GDP Phosphatase Activity (GO:0004382) 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 12 GO_Molecular_Function_2023 Nucleoside Diphosphate Phosphatase Activity (G... 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 13 GO_Molecular_Function_2023 ATP Binding (GO:0005524) 0.017220 0.083096 0 0 11.204545 45.509349 ABCF2;HSPA1A 14 GO_Molecular_Function_2023 Ubiquitin Protein Ligase Binding (GO:0031625) 0.020064 0.083096 0 0 10.265625 40.126707 RIGI;HSPA1A 15 GO_Molecular_Function_2023 Ubiquitin-Like Protein Ligase Binding (GO:0044... 0.021555 0.083096 0 0 9.852500 37.805688 RIGI;HSPA1A 16 GO_Molecular_Function_2023 Growth Factor Activity (GO:0008083) 0.023090 0.083096 0 0 9.471154 35.690549 CLCF1;NTF3 17 GO_Molecular_Function_2023 Adenyl Ribonucleotide Binding (GO:0032559) 0.024670 0.083096 0 0 9.118056 33.756535 ABCF2;HSPA1A 18 GO_Molecular_Function_2023 C3HC4-type RING Finger Domain Binding (GO:0055... 0.025290 0.083096 0 0 60.060606 220.863728 HSPA1A 19 GO_Molecular_Function_2023 Ubiquitin Binding (GO:0043130) 0.025290 0.083096 0 0 60.060606 220.863728 TOP2A In [36]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( similar story to cluster above. this time with PTN often found in the litterature with 6 other m Studies on the role of STEAP1, OR51E2, PTN, ABCC4, NDRG2 have been relatively in-depth. For instance, STEAP1 is all-called six-transmembrane epithelial antigen of the prostate 1, which belongs to a family of metalloproteinases involved in iron and copper homeostasis and other cellular processes has been listed with 8 other members as predictors of CAF-related gene prognostic index (CRGPI) in prostate cancer. https://www.nature.com/articles/s41598-023-36125-0#Sec11 (NDRG2, TSPAN1, PTN, APOE, OR51E2, P4HB, STEAP1 and ABCC4 were used to construct molecular subtypes and) https://www.genecards.org/cgi-bin/carddisp.pl?gene=GSN","title":"3.1 Cancer version"},{"location":"notebooks/cancer_usecase_part2/#32-normal-version","text":"In [9]: Copied! grn . var [ 'cluster_1.5' ] . value_counts () . head ( 10 ) grn.var['cluster_1.5'].value_counts().head(10) Out[9]: cluster_1.5 0 1620 1 1483 2 732 3 111 4 23 5 9 6 4 16 1 23 1 22 1 Name: count, dtype: int64 https://www.genecards.org/cgi-bin/carddisp.pl?gene=MYOC In [37]: Copied! G = grn . plot_subgraph ( grn . var [ grn . var [ 'cluster_1.5' ] == '3' ] . index . tolist (), only = 200 , interactive = False ) G = grn.plot_subgraph(grn.var[grn.var['cluster_1.5']=='3'].index.tolist(), only=200, interactive=False) ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['TMEM132A', 'ADGRA2', 'AGPAT4', 'THAP3', 'DNAJC25', 'TRAM2', 'NTN1', 'STAG3', 'COL4A4', 'HSD17B14', ... 'nan-75', 'TRABD2B', 'nan-77', 'PCGF2', 'nan-107', 'nan-182', 'nan-192', 'nan-195', 'nan-239', 'nan-259'], dtype='object', name='symbol_2', length=111) In [26]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_3.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_3.html\") In [27]: Copied! grn . var . loc [ 'nan-259' ] # par of the Glycoside Hydrolase Family grn.var.loc['nan-259'] # par of the Glycoside Hydrolase Family Out[27]: uid 62JAXxQNqtOd symbol nan-259 ncbi_gene_ids 83737 biotype protein_coding description novel protein synonyms organism_id 2 public_source_id 9.0 created_by_id 1 mt False ribo False hb False organism NCBITaxon:9606 TFs False ensembl_id ENSG00000289720 centrality 0.0 cluster_1.5 3 Name: nan-259, dtype: object In [12]: Copied! grn . get ( grn . var [ grn . var [ 'cluster_1.5' ] == '3' ] . index . tolist ()) . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 3 ) ##.grn # selenom grn.get(grn.var[grn.var['cluster_1.5']=='3'].index.tolist()).grn.sum(0).sort_values(ascending=False).head(3)##.grn # selenom Out[12]: symbol RNASEK 0.942102 SELENOM 0.292933 nan-259 0.256140 dtype: float32 RNASEK acidifying the internal vesicle important in endocytosis# https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10547866/ RNA phosphodiester bond hydrolysis --> hydrolisis pathway in the model and RNA transcription regulation In [38]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:33:49,291 [WARNING] Input library not found: Reactome. Skip /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/enrichr.py:643: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation. self.results = pd.concat(self.results, ignore_index=True) Out[38]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Sulfotransferase Activity (GO:0008146) 0.007252 0.123369 0 0 20.138462 99.212171 CHST7;SULT1C4 1 GO_Molecular_Function_2023 RNA Polymerase II Transcription Regulatory Reg... 0.007713 0.123369 0 0 3.386005 16.472449 ZNF483;HAND2;NTN1;NFATC4;GLIS2;PURG;ZNF286A 2 GO_Molecular_Function_2023 ATPase Binding (GO:0051117) 0.013790 0.123369 0 0 13.415385 57.468682 SLC2A13;NKD2 3 GO_Molecular_Function_2023 Chondroitin Sulfotransferase Activity (GO:0034... 0.016750 0.123369 0 0 inf inf CHST7 4 GO_Molecular_Function_2023 Peptidyl-Proline 4-Dioxygenase Activity (GO:00... 0.016750 0.123369 0 0 inf inf P4HA3 5 GO_Molecular_Function_2023 Aryl Sulfotransferase Activity (GO:0004062) 0.016750 0.123369 0 0 inf inf SULT1C4 6 GO_Molecular_Function_2023 Histone Reader Activity (GO:0140566) 0.016750 0.123369 0 0 inf inf TONSL 7 GO_Molecular_Function_2023 Hydrolase Activity, Hydrolyzing N-glycosyl Com... 0.016750 0.123369 0 0 inf inf BST1 8 GO_Molecular_Function_2023 Tat Protein Binding (GO:0030957) 0.016750 0.123369 0 0 inf inf DLL1 9 GO_Molecular_Function_2023 WW Domain Binding (GO:0050699) 0.016750 0.123369 0 0 inf inf ENTREP3 10 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.016754 0.123369 0 0 3.180050 13.003634 ZNF483;HAND2;NTN1;NFATC4;GLIS2;ZNF286A 11 GO_Molecular_Function_2023 DNA-binding Transcription Activator Activity, ... 0.026719 0.134555 0 0 5.074219 18.380719 HAND2;INSL3;GLIS2 12 GO_Molecular_Function_2023 Procollagen-Proline Dioxygenase Activity (GO:0... 0.033223 0.134555 0 0 59.575758 202.825781 P4HA3 13 GO_Molecular_Function_2023 N-acetylglucosamine 6-O-sulfotransferase Activ... 0.033223 0.134555 0 0 59.575758 202.825781 CHST7 14 GO_Molecular_Function_2023 ABC-type Xenobiotic Transporter Activity (GO:0... 0.033223 0.134555 0 0 59.575758 202.825781 ABCC1 15 GO_Molecular_Function_2023 alpha-N-acetylgalactosaminide Alpha-2,6-Sialyl... 0.033223 0.134555 0 0 59.575758 202.825781 ST6GALNAC6 16 GO_Molecular_Function_2023 miRNA Binding (GO:0035198) 0.033223 0.134555 0 0 59.575758 202.825781 DND1 17 GO_Molecular_Function_2023 Myosin Heavy Chain Binding (GO:0032036) 0.033223 0.134555 0 0 59.575758 202.825781 NKD2 18 GO_Molecular_Function_2023 Estradiol 17-Beta-Dehydrogenase [NAD(P)] Activ... 0.033223 0.134555 0 0 59.575758 202.825781 HSD17B14 19 GO_Molecular_Function_2023 Solute:Proton Symporter Activity (GO:0015295) 0.033223 0.134555 0 0 59.575758 202.825781 SLC2A13 In [39]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( https://www.genecards.org/cgi-bin/carddisp.pl?gene=PTN In [40]: Copied! G = grn . plot_subgraph ( grn . var [ grn . var [ 'cluster_1.5' ] == '4' ] . index . tolist (), only = 80 , interactive = False ) # G = grn.plot_subgraph(grn.var[grn.var['cluster_1.5']=='4'].index.tolist(), only=80, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['TRHDE', 'PGR', 'ESR1', 'RASD2', 'SYNDIG1', 'OLFM2', 'FZD10', 'BHMT2', 'DUSP26', 'FOXF2', 'ADAM33', 'ADAMTS12', 'HS3ST3A1', 'CHODL', 'FTCD', 'FNDC1', 'HSPB3', 'FOXL1', 'AGMO', 'ADAMTSL2', 'S100A6', 'AKR1B10', 'SCGB1C2'], dtype='object', name='symbol_2') In [29]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_4.html\") In [41]: Copied! enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'GO_Molecular_Function_2023' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['GO_Molecular_Function_2023', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:34:27,578 [WARNING] Input library not found: Reactome. Skip Out[41]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 RNA Polymerase II General Transcription Initia... 0.000032 0.000933 0 0 inf inf FOXF2;ESR1 1 GO_Molecular_Function_2023 Estrogen Response Element Binding (GO:0034056) 0.000032 0.000933 0 0 inf inf PGR;ESR1 2 GO_Molecular_Function_2023 General Transcription Initiation Factor Bindin... 0.000095 0.001860 0 0 378.666667 3508.819727 FOXF2;ESR1 3 GO_Molecular_Function_2023 Transcription Coactivator Binding (GO:0001223) 0.000188 0.002780 0 0 189.285714 1623.428489 PGR;ESR1 4 GO_Molecular_Function_2023 Transition Metal Ion Binding (GO:0046914) 0.000446 0.005263 0 0 13.515099 104.272240 BHMT2;AGMO;ADAM33;TRHDE 5 GO_Molecular_Function_2023 Metalloendopeptidase Activity (GO:0004222) 0.000551 0.005414 0 0 22.794231 171.058857 ADAMTSL2;ADAM33;ADAMTS12 6 GO_Molecular_Function_2023 Metallopeptidase Activity (GO:0008237) 0.000672 0.005666 0 0 21.155357 154.536591 ADAMTSL2;ADAM33;ADAMTS12 7 GO_Molecular_Function_2023 Transcription Coregulator Binding (GO:0001221) 0.001111 0.008195 0 0 54.013605 367.419603 PGR;ESR1 8 GO_Molecular_Function_2023 DNA-binding Transcription Activator Activity, ... 0.001429 0.009365 0 0 15.972973 104.640056 FOXF2;PGR;ESR1 9 GO_Molecular_Function_2023 ATPase Binding (GO:0051117) 0.002016 0.011893 0 0 37.780952 234.495632 PGR;ESR1 10 GO_Molecular_Function_2023 Zinc Ion Binding (GO:0008270) 0.002284 0.012250 0 0 13.407955 81.545835 BHMT2;ADAM33;TRHDE 11 GO_Molecular_Function_2023 Cis-Regulatory Region Sequence-Specific DNA Bi... 0.004517 0.021203 0 0 6.945569 37.504924 FOXF2;PGR;FOXL1;ESR1 12 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.005523 0.021203 0 0 6.541596 34.009122 FOXF2;PGR;FOXL1;ESR1 13 GO_Molecular_Function_2023 DNA Binding, Bending (GO:0008301) 0.005750 0.021203 0 0 inf inf FOXL1 14 GO_Molecular_Function_2023 TBP-class Protein Binding (GO:0017025) 0.005750 0.021203 0 0 inf inf ESR1 15 GO_Molecular_Function_2023 [Heparan Sulfate]-Glucosamine 3-Sulfotransfera... 0.005750 0.021203 0 0 inf inf HS3ST3A1 16 GO_Molecular_Function_2023 RNA Polymerase II Transcription Regulatory Reg... 0.008164 0.028333 0 0 5.812950 27.949028 FOXF2;PGR;FOXL1;ESR1 17 GO_Molecular_Function_2023 Endopeptidase Activity (GO:0004175) 0.008882 0.028593 0 0 8.021918 37.893119 ADAMTSL2;ADAM33;ADAMTS12 18 GO_Molecular_Function_2023 DNA Binding (GO:0003677) 0.009208 0.028593 0 0 7.911486 37.086673 FOXF2;PGR;FOXL1 19 GO_Molecular_Function_2023 Heparan Sulfate Sulfotransferase Activity (GO:... 0.011468 0.030756 0 0 180.727273 807.520606 HS3ST3A1 In [42]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace(","title":"3.2 Normal version"},{"location":"notebooks/cancer_usecase_part2/#4-differential-gene-gene-connections","text":"look at the connections of some key TFs in here do GSEA over these connections compare the connections of these same TFs for both conditions In [5]: Copied! G = grn_c . plot_subgraph ( \"PAGE4\" , only = 100 , max_genes = 40 , interactive = False ) # G = grn_c.plot_subgraph(\"PAGE4\", only=100, max_genes=40, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#ff7f0e'] Index(['MT2A', 'HSPA1A', 'CREM', 'PTN', 'HLA-A', 'SPARCL1', 'SPOCK3', 'NR4A3', 'APOD', 'CALD1', 'MGP', 'HSPE1', 'EIF4A1', 'CD99', 'EMP1', 'FABP4', 'NAMPT', 'NNMT', 'RBP1', 'LUM', 'IGFBP7', 'THBS1', 'YBX3', 'NAF1', 'DCN', 'A2M', 'CPE', 'C1R', 'ATP6V0C', 'MATN2', 'COL6A2', 'UBE2S', 'CST3', 'RHOQ', 'UBE2C', 'C1S', 'H2AZ1', 'GPRC5A', 'HLA-C', 'LGALS1', 'PAGE4'], dtype='object', name='symbol_2') In [96]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) first_node = list ( G . nodes )[ - 1 ] pnet . get_node ( first_node )[ 'color' ] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_PAGE4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) first_node = list(G.nodes)[-1] pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_PAGE4.html\") In [22]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ #'KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', 'WikiPathway_2023_Human' , #'TF_Perturbations_Followed_by_Expression', #'PPI_Hub_Proteins', #'OMIM_Disease', #'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 10 ) enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( 'R-HSA' ) . str [ 0 ] . str . split ( ' WP' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=[ #'KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', 'WikiPathway_2023_Human', #'TF_Perturbations_Followed_by_Expression', #'PPI_Hub_Proteins', #'OMIM_Disease', #'GO_Molecular_Function_2023' ], organism='Human', # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(10) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split('R-HSA').str[0].str.split(' WP').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [139]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size figsize = ( 4 , 5 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size figsize=(4,5), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [17]: Copied! G = grn . plot_subgraph ( \"PAGE4\" , only = 100 , max_genes = 40 , interactive = False ) G = grn.plot_subgraph(\"PAGE4\", only=100, max_genes=40, interactive=False) ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#ff7f0e'] Index(['nan-270', 'S100A6', 'MT2A', 'SPARCL1', 'MIF', 'SLC25A6', 'IGFBP7', 'APOD', 'MGP', 'DCN', 'A2M', 'PTN', 'RELB', 'DNAJB9', 'AKR1C1', 'C1S', 'CST3', 'CXCL8', 'FTH1', 'BRME1', 'FAM205A', 'TIMP1', 'YBX3', 'NPPB', 'TGIF2-RAB5IF', 'FBLN1', 'MTDH', 'IGFBP5', 'TFPI', 'MAP1B', 'COL6A2', 'HNRNPA0', 'EIF4A1', 'CCL21', 'FTL', 'CETN1', 'NME2', 'LSAMP', 'ACR', 'ATP6V0C', 'PAGE4'], dtype='object', name='symbol_2') In [98]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) first_node = list ( G . nodes )[ - 1 ] pnet . get_node ( first_node )[ 'color' ] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_PAGE4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) first_node = list(G.nodes)[-1] pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_PAGE4.html\") In [24]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', #'WikiPathway_2023_Human', # 'TF_Perturbations_Followed_by_Expression', # 'Reactome', #'PPI_Hub_Proteins', #'OMIM_Disease', 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', #'WikiPathway_2023_Human', # 'TF_Perturbations_Followed_by_Expression', # 'Reactome', #'PPI_Hub_Proteins', #'OMIM_Disease', 'GO_Molecular_Function_2023' ], organism='Human', # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) Out[24]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Peptidase Inhibitor Activity (GO:0030414) 0.000020 0.001566 0 0 104.105263 1128.623016 CST3;TIMP1;TFPI 1 GO_Molecular_Function_2023 Transition Metal Ion Binding (GO:0046914) 0.000463 0.016191 0 0 9.025463 69.301557 ACR;MT2A;FTH1;TIMP1;FTL 2 GO_Molecular_Function_2023 Double-Stranded RNA Binding (GO:0003725) 0.000607 0.016191 0 0 101.461538 751.496153 EIF4A1;MTDH 3 GO_Molecular_Function_2023 Endopeptidase Inhibitor Activity (GO:0004866) 0.001010 0.019977 0 0 18.306502 126.278211 CST3;TIMP1;TFPI 4 GO_Molecular_Function_2023 Endopeptidase Regulator Activity (GO:0061135) 0.001498 0.019977 0 0 50.705128 329.757829 CST3;TFPI 5 GO_Molecular_Function_2023 Ferrous Iron Binding (GO:0008198) 0.001498 0.019977 0 0 50.705128 329.757829 FTH1;FTL 6 GO_Molecular_Function_2023 Protease Binding (GO:0002020) 0.002465 0.027606 0 0 12.944079 77.736001 CST3;ACR;TIMP1 7 GO_Molecular_Function_2023 Iron Ion Binding (GO:0005506) 0.002761 0.027606 0 0 33.786325 199.079000 FTH1;FTL 8 GO_Molecular_Function_2023 Calcium Ion Binding (GO:0005509) 0.003252 0.028910 0 0 7.400664 42.393777 CETN1;S100A6;SPARCL1;FBLN1 9 GO_Molecular_Function_2023 Kinase Binding (GO:0019900) 0.005211 0.038377 0 0 9.688322 50.930509 PTN;RELB;HNRNPA0 10 GO_Molecular_Function_2023 RNA Binding (GO:0003723) 0.005277 0.038377 0 0 5.000000 26.222182 EIF4A1;YBX3;DCN;MTDH;HNRNPA0 11 GO_Molecular_Function_2023 Chemokine Activity (GO:0008009) 0.007445 0.039047 0 0 18.405594 90.191859 CXCL8;CCL21 12 GO_Molecular_Function_2023 Chemokine Receptor Binding (GO:0042379) 0.007445 0.039047 0 0 18.405594 90.191859 CXCL8;CCL21 13 GO_Molecular_Function_2023 Metal Ion Binding (GO:0046872) 0.008569 0.039047 0 0 5.523471 26.289761 CETN1;S100A6;SPARCL1;FBLN1 14 GO_Molecular_Function_2023 Protein Kinase Binding (GO:0019901) 0.009285 0.039047 0 0 7.734868 36.193807 PTN;RELB;HNRNPA0 15 GO_Molecular_Function_2023 mRNA 3'-UTR Binding (GO:0003730) 0.009893 0.039047 0 0 15.566075 71.852090 YBX3;HNRNPA0 16 GO_Molecular_Function_2023 NF-kappaB Binding (GO:0051059) 0.010250 0.039047 0 0 inf inf MTDH 17 GO_Molecular_Function_2023 Phosphatase Inhibitor Activity (GO:0019212) 0.010250 0.039047 0 0 inf inf PTN 18 GO_Molecular_Function_2023 Phosphotransferase Activity, Phosphate Group A... 0.010250 0.039047 0 0 inf inf NME2 19 GO_Molecular_Function_2023 Nucleobase-Containing Compound Kinase Activity... 0.010250 0.039047 0 0 inf inf NME2 In [30]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size figsize = ( 4 , 5 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size figsize=(4,5), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace(","title":"4. Differential Gene - Gene connections"},{"location":"notebooks/cancer_usecase_part2/#5-using-classification","text":"Here we used the network given by the mean of all heads in our scPRINT model. We could also use other scPRINT versions to see if the results are consistent. but we could also use the classification mechanism presented in our manuscript and other notebooks to get to possibly more specialized networks. In [ ]: Copied! grn_normal = grn_inferer ( layer = list ( range ( model . nlayers ))[:], cell_type = \"naive B cell\" ) grn_normal , m , omni_cls = train_classifier ( grn_normal , C = 0.5 , train_size = 0.9 , class_weight = { 1 : 200 , 0 : 1 }, shuffle = True ) grn_normal = grn_inferer(layer=list(range(model.nlayers))[:], cell_type=\"naive B cell\") grn_normal, m, omni_cls = train_classifier(grn_normal, C=0.5, train_size=0.9, class_weight={ 1: 200, 0: 1}, shuffle=True) number of expressed genes in this cell type: 16801 LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0] Predicting: 0it [00:00, ?it/s] true elem 2115 ... doing regression.... metrics {'used_heads': 25, 'precision': 0.0, 'random_precision': 0.0006433550820644942, 'recall': 0.0, 'predicted_true': 177.0, 'number_of_true': 219.0, 'epr': 0.0} In [ ]: Copied! # highlight differential links on genes that are expressed in both grn_normal . varp [ 'all' ] = grn_normal . varp [ 'GRN' ] . copy () grn_normal . varp [ 'GRN' ] = grn_normal . varp [ 'classified' ] # highlight differential links on genes that are expressed in both grn_normal.varp['all'] = grn_normal.varp['GRN'].copy() grn_normal.varp['GRN'] = grn_normal.varp['classified']","title":"5. Using classification"},{"location":"notebooks/cancer_usecase_part2/#notes-on-findings-and-their-relation-to-the-literature","text":"CAV1-expressing CAFs contribute to invasion and metastasis in breast cancer24 loss of caveolin1 (CAV1) is found in metabolically reprogrammed CAFs that promote tumorigenesis discoidin domain-containing receptor 2 (DDR2)21 and integrin \u03b111\u03b2122, have emerged to identify CAFs in the context of a specific TME https://www.nature.com/articles/s12276-023-01013-0 normal fibroblast populations marked by the expression of Gli1 and Hoxb6 CAFs, remain perpetually activated with a high capacity for ECM synthesis and microenvironmental remodeling, leading to stromal desmoplasia, a phenomenon characterized by increased deposition of ECM components in tumors. In this regard, CAFs share many basic characteristics, such as a secretory phenotype and capacity to synthesize ECM components, with fibroblasts found in nonmalignant tissue fibrosis. Therefore, the classic markers found to be expressed in fibroblasts, including \u03b1-SMA, vimentin, desmin, fibroblast-specific protein 1 (FSP1; also known as S100A4) Fibrogenesis is part of a normal protective response to tissue injury that can become irreversible and progressive, leading to fatal diseases. Senescent cells are a main driver of fibrotic diseases through their secretome, known as senescence-associated secretory phenotype (SASP) CAFs (vCAFs), cycling CAFs (cCAFs), and developmental CAFs (dCAFs) The stem-like \u2018universal\u2019 type of fibroblast cell, marked by expression of peptidase inhibitor 16 (Pi16) and Col15a, found in the steady state across tissues, activated fibroblasts, as observed by the development of LRRC15+ CAFs in PDAC. . SOCS1: Suppressor of cytokine signaling; STAT3: Signal transducer and activator of transcription 3; LDH: Lactate dehydrogenase; PYCR1: pyrroline-5-carboxylate reductase senescence, and multiple types of fibrotic diseases in mice and humans are characterized by the accumulation of iron. https://www.nature.com/articles/s42255-023-00928-2 Current evidence indicate that cancer-associated fibroblasts (CAFs) play an important role in prostate cancer (PCa) development and progression. playing a role in invasion. NDRG2, TSPAN1, PTN, APOE, OR51E2, P4HB, STEAP1 and ABCC4 were used to construct molecular subtypes and CAF-related gene prognostic index (CRGPI) Studies on the role of STEAP1, OR51E2, PTN, ABCC4, NDRG2 have been relatively in-depth. For instance, STEAP1 is all-called six-transmembrane epithelial antigen of the prostate 1, which belongs to a family of metalloproteinases involved in iron and copper homeostasis and other cellular processes37. STEAP1 is overexpressed on the plasma membrane of PCa cells and is associated with PCa invasiveness and metastasis50. The possible mechanism of STEAP1 promoting tumor proliferation and metastasis is by acting as a channel for small molecules that are involved in intercellular communication OR51E2 perhaps could be used as one of the biomarkers for PCa53,54,55,56 https://www.nature.com/articles/s41598-023-36125-0#Sec11 The protein encoded by ABCC4 is a member of the superfamily of ATP-binding cassette (ABC) transporters, which is also called multidrug resistance protein 4 (MRP4)64. MRP4 was reported to be associated with drug resistance of PCa in many studies65,66,67 PRRX1, OSR1, FOXD1, HOXC4,LHX9, TBX3 and TWIST2, targeted five or more TFs inthe fibroblast TRN. This influential-set explained 62.5% ofthe total number of regulatory edges and they collectivelytargeted 15 out of 18 TFs represented in the network. Upona closer examination of the fibroblastic network, the inter-actions among OSR1\u2013PRRX1\u2013TWIST2 were notably co-ordinated, regulating one another in both directions https://www.researchgate.net/publication/264633205_A_transient_disruption_of_fibroblastic_transcriptional_regulatory_network_facilitates_trans-differentiation FGF receptors are important in PCa initiation and progression. These endocrine FGFs require alpha-Klotho (KL) and/or beta-Klotho (KLB), two related single-pass transmembrane proteins restricted in their tissue distribution. FGF19 is expressed in primary and metastatic PCa tissues where it functions as an autocrine growth factor. https://www.e-cancer.fr/Professionnels-de-sante/Veille-bibliographique/Nota-Bene-Cancer/NBC-174/The-endocrine-fibroblast-growth-factor-FGF19-promotes-prostate-cancer-progression \u2022 Prostate cancer stroma contains diverse populations of fibroblasts. \u2022 Carcinoma associated fibroblasts can promote prostate carcinogenesis. \u2022 Interaction among fibroblast subsets modulate stromal-epithelial paracrine signaling. The stroma in the normal prostate is predominantly composed of smooth muscle cells while in cancer this is partially replaced by fibroblasts and myofibroblasts6. These fibroblastic cells are responsible for collagen and extracellular matrix (ECM) deposition, changing local organ stiffness iCAF, myCAF, apCAF It has been shown that SDF-1/CXCL12, secreted by CAF, acts via TGF\u03b2\u2013mediated upregulation of CXCR4 in epithelial cells to activate Akt signaling associated with tumorigenesis. Overexpression of SDF-1/CXCL12 and TGF\u03b21 in benign human prostate fibroblasts has been shown to induce malignant transformation of benign prostate epithelial cells and formation of highly invasive tumors in vivo increased cadherin 2 (CDH2) mRNA expression in LNCaP cells Upregulation of DNA methyltransferases (DNMT) consistent with aberrant promoter hypermethylation of tumor-suppressor genes in multiple cancer types including PCa has been reported https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8788937/#:~:text=The%20stroma%20in%20the%20normal,deposition%2C%20changing%20local%20organ%20stiffness . CD10 and GPR77 can define a human CAF subset that sustains cancer stemness Fibroblasts are also fundamental for inducing angiogenesis by secreting angiogenic factors such as vascular endothelial growth factor (VEGF) and matrix proteins Epithelial cells release TGF\u03b2 ligands, Kallikrein-related peptidase-4 (KLK4), CAFs are characterized by molecular markers that are upregulated compared to normal fibroblasts, such as fibroblast activation protein (FAP), PDGFR-\u03b2, fibroblast-specific protein-1 (FSP-1) (also known as S100A4) ACTA2 \u03b1-smooth actin (\u03b1-SMA) Upregulated RT-qPCR, IHC on tissue microarrays [42,43] ASPN Asporin Upregulated Tag-based RNA profiling, microarray profiling, IHC, RT-qPCR [38,44,45] CAV1 Caveolin-1 Downregulated Tag profiling, IHC, RT-qPCR [38] COL1A1 Collagen Type-I Upregulated RT-qPCR, IHC [42,43] CXCL12 Stromal cell-derived factor 1 (SDF1)/ (C-X-C motif chemokine ligand 12 (CXCL12) Upregulated Tag-profiling, RT-qPCR, ELISA [38,46] FAP Fibroblast activation protein Upregulated IHC [42] FGF2, FGF7, FGF10 Fibroblast growth factor-2/-7/-10 Upregulated RT-qPCR, Western Blot, IHC [43,47,48] FN1 Fibronectin Upregulated Tag profiling, IHC, RT-qPCR [38] ITGA1 Integrin-\u03b11 (CD49a) Upregulated IHC [49] OGN Osteoglycin Upregulated Tag-profiling, IHC, RT-qPCR [38] PDGFRB Platelet-derived growth factor receptor \u03b2 Upregulated Microarray profiling [44,50] POSTN Periostin Upregulated Microarray profiling, IHC [44] S100A4 Fibroblast-specific protein 1 (FSP1)/S100 Calcium Binding Protein A4 (S100A4) Upregulated Immunofluorescence, RT-qPCR, Western Blot [51,52,53] S100A6 S100 Calcium Binding Protein A6 Downregulated Tag profiling, IHC, RT-qPCR [38] SPARC Secreted Protein Acidic and Cysteine Rich Up/downregulated Microarray profiling, Tag-profiling [38,44] STC1 Stanniocalcin 1 Downregulated Tag profiling, IHC, RT-qPCR [38] THY1 Cluster of differentiation 90 (CD90) antigen Upregulated IHC [54] TNC Tenascin C Upregulated RT-qPCR, IHC [42,43] VIM Vimentin Upregulated IHC Benign prostatic hyperplasia (BPH) is a non-malignant growth of the prostate, typically occurring in older men with an occurrence of 80\u201390% of men in their 70s BPH develops in the transition zone differently from PCa foci, which usually develop in the peripheral zone ESR1= . Here we studied the role of CAF estrogen receptor alpha (ER\u03b1) and found that it could protect against PCa invasion. ER\u03b1 could function through a CAF\u2013epithelial interaction via selectively upregulating thrombospondin 2 (Thbs2) and downregulating matrix metalloproteinase 3 (MMP3) at the protein and messenger RNA levels https://academic.oup.com/carcin/article/35/6/1301/449417 ACTA2: we found that \u201creactive CAFs\u201d induce shear resistance to prostate tumor cells via intercellular contact and soluble derived factors. The reactive CAFs showed higher expression of \u03b1-smooth muscle actin (\u03b1-SMA) and fibroblast activation protein (FAP) compared to differentiated CAFs https://www.oncotarget.com/article/27510/ Proteins that exhibited a significant increase in CAF versus NPF were enriched for the functional categories \u201ccell adhesion\u201d and the \u201cextracellular matrix.\u201d The CAF phosphoproteome exhibited enhanced phosphorylation of proteins associated with the \u201cspliceosome\u201d and \u201cactin binding.\u201d COL1A1/2 and COL5A1; the receptor tyrosine kinase discoidin domain-containing receptor 2 (DDR2), a receptor for fibrillar collagens; and lysyl oxidase-like 2 (LOXL2) https://www.mcponline.org/article/S1535-9476(20)31548-6/fulltext \u2022Cancer-associated fibroblasts (CAFs) exhibit a highly aligned cytoskeleton and extracellular matrix. \u2022CAFs are stiffer than normal fibroblasts from the prostate. \u2022Benign prostate epithelial cells are more compliant after co-culture with CAFs. \u2022Benign epithelial cells are more invasive and proliferative in presence of CAFs. https://www.sciencedirect.com/science/article/pii/S2590006420300338 These findings suggest that CAFs exosomes drive PCa metastasis via the miR-500a-3p/FBXW7/HSF1 axis in a hypoxic microenvironmen https://www.nature.com/articles/s41417-024-00742-2 https://www.genecards.org/cgi-bin/carddisp.pl?gene=CCT8L2 CCT8L2 (Chaperonin Containing TCP1 Subunit 8 Like 2) is a Protein Coding gene. Gene Ontology (GO) annotations related to this gene include calcium-activated potassium channel activity and monoatomic anion channel activity. An important paralog of this gene is CCT8. related to the meta transmembrane activity via Possible molecular chaperone; assists the folding of proteins upon ATP hydrolysis. The TRiC complex mediates the folding of WRAP53/TCAB1, thereby regulating telomere maintenance (PubMed:25467444). As part of the TRiC complex may play a role in the assembly of BBSome, a complex involved in ciliogenesis regulating transports vesicles to the cilia https://www.genecards.org/cgi-bin/carddisp.pl?gene=TIMP1 TIMP Metallopeptidase Inhibitor 1 inhibitors of the matrix metalloproteinases (MMPs), a group of peptidases involved in degradation of the extracellular matrix. In addition to its inhibitory role against most of the known MMPs, the encoded protein is able to promote cell proliferation connected to TLL2: zinc-dependent metalloprotease part of the metzincin protein complex which also is Among its related pathways are Collagen chain trimerization and Extracellular matrix organization. PDXP, SEPTIN5 cytoskeletal organization and regulation PRAME inhibits the signaling of retinoic acid and mediates the regulation of selenoproteins many genes involved in cancer. indeed, it is known that 80% adult male above 70 years old will have such hyperplastic prostate. This is due to scenesence. and that Iron accumulation drives fibrosis, senescence and the senescence-associated secretory phenotype. (of which we have some proteins present here.) A mechanism that this clustered is one of genes that strongly regulates each other in this fibroblasts from pre-cancerous lesions via fibrotic iron accumulation and a secretory mechanism GJC1 (exchange of things between cells (here likely metals?)) Unknown genes like SMIM40. integral membrane protein could be linked to this phenotype ['pre { line-height: 125%; }\\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n.highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) }\\n.highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\\n.highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\\n.highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */\\n.highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\\n.highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\\n.highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\\n.highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\\n.highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\\n.highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\\n.highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\\n.highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\\n.highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\\n.highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\\n.highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\\n.highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\\n.highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\\n.highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\\n.highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\\n.highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\\n.highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\\n.highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\\n.highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\\n.highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\\n.highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\\n.highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\\n.highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\\n.highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\\n.highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\\n.highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\\n.highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\\n.highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\\n.highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\\n.highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\\n.highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\\n.highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\\n.highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\\n.highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\\n.highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\\n.highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\\n.highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\\n.highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\\n.highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */']","title":"Notes on findings and their relation to the literature"}]} \ No newline at end of file +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"","text":"scPRINT: Large Cell Model for scRNAseq data scPRINT is a large transformer model built for the inference of gene networks (connections between genes explaining the cell's expression profile) from scRNAseq data. It uses novel encoding and decoding of the cell expression profile and new pre-training methodologies to learn a cell model. scPRINT can be used to perform the following analyses: expression denoising : increase the resolution of your scRNAseq data cell embedding : generate a low-dimensional representation of your dataset label prediction : predict the cell type, disease, sequencer, sex, and ethnicity of your cells gene network inference : generate a gene network from any cell or cell cluster in your scRNAseq dataset Read the manuscript! if you would like to know more about scPRINT. Have a look at some of my X-plainers . Table of Contents scPRINT: Large Cell Model for scRNAseq data Table of Contents Install scPRINT lamin.ai install pytorch and GPUs dev install Usage scPRINT's basic commands Notes on GPU/CPU usage with triton Simple tests: FAQ I want to generate gene networks from scRNAseq data: I want to generate cell embeddings and cell label predictions from scRNAseq data: I want to denoise my scRNAseq dataset: I want to generate an atlas-level embedding I need to generate gene tokens using pLLMs I want to pre-train scPRINT from scratch on my own data how can I find if scPRINT was trained on my data? can I use scPRINT on other organisms rather than human? how long does scPRINT takes? what kind of resources do I need? (or in alternative: can i run scPRINT locally?) I have different scRNASeq batches. Should I integrate my data before running scPRINT? where to find the gene embeddings? Documentation Model Weights Development Work in progress (PR welcomed): Install scPRINT For the moment scPRINT has been tested on MacOS and Linux (Ubuntu 20.04) with Python 3.10. Its instalation takes on average 10 minutes. If you want to be using flashattention2, know that it only supports triton 2.0 MLIR's version and torch==2.0.0 for now. lamin.ai To use scPRINT, I need you to use lamin.ai. This is needed to load biological informations like genes, cell types, organisms etc... To do so, you will need to connect with google or github to lamin.ai , then be sure to connect before running anything (or before starting a notebook): lamin login --key . Follow the instructions on their website . install To start you will need to do: conda create -n python==3.10 #scprint might work with python >3.10, but it is not tested #one of pip install scprint # OR pip install scprint[dev] # for the dev dependencies (building etc..) OR pip install scprint[flash] # to use flashattention2 with triton: only if you have a compatible gpu (e.g. not available for apple GPUs for now, see https://github.com/triton-lang/triton?tab=readme-ov-file#compatibility) #OR pip install scPRINT[dev,flash] lamin login --key lamin init --storage --schema bionty if you start with lamin and had to do a lamin init , you will also need to populate your ontologies. This is because scPRINT is using ontologies to define its cell types, diseases, sexes, ethnicities, etc. you can do it manually or with our function: from scdataloader.utils import populate_my_ontology populate_my_ontology() #to populate everything (recommended) (can take 2-10mns) populate_my_ontology( #the minimum for scprint to run some inferences (denoising, grn inference) organisms: List[str] = [\"NCBITaxon:10090\", \"NCBITaxon:9606\"], sex: List[str] = [\"PATO:0000384\", \"PATO:0000383\"], celltypes = None, ethnicities = None, assays = None, tissues = None, diseases = None, dev_stages = None, ) We make use of some additional packages we developed alongside scPRint. Please refer to their documentation for more information: scDataLoader : a dataloader for training large cell models. GRnnData : a package to work with gene networks from single cell data. benGRN : a package to benchmark gene network inference methods from single cell data. pytorch and GPUs scPRINT can run on machines without GPUs, but it will be slow. It is highly recommended to use a GPU for inference. Once you have a GPU, and installed the required drivers, you might need to install a specific version of pytorch that is compatible with your drivers (e.g. nvidia 550 drivers will lead to a nvidia toolkit 11.7 or 11.8 which might mean you need to re-install a different flavor of pytorch for things to work. e.g. using the command: pip install torch==2.2.0 torchvision==0.17.0 torchaudio==2.2.0 --index-url https://download.pytorch.org/whl/cu118 on my case on linux ). I was able to test it with nvidia 11.7, 11.8, 12.2. dev install If you want to use the latest version of scPRINT and work on the code yourself use git clone and pip -e instead of pip install . git clone https://github.com/jkobject/scPRINT git clone https://github.com/jkobject/scDataLoader git clone https://github.com/cantinilab/GRnnData git clone https://github.com/jkobject/benGRN pip install -e scPRINT[dev] pip install -e scDataLoader[dev] pip install -e GRnnData[dev] pip install -e benGRN[dev] Usage scPRINT's basic commands This is the most minimal example of how scPRINT works: from lightning.pytorch import Trainer from scprint import scPrint from scdataloader import DataModule datamodule = DataModule(...) model = scPrint(...) # to train / fit / test the model trainer = Trainer(...) trainer.fit(model, datamodule=datamodule) # to do predictions Denoiser, Embedder, GNInfer denoiser = Denoiser(...) adata = sc.read_h5ad(...) denoiser(model, adata=adata) ... or, from a bash command line $ scprint fit/train/predict/test/denoise/embed/gninfer --config config/[medium|large|vlarge] ... find out more about the commands by running scprint --help or scprint [command] --help . more examples of using the command line are available in the docs . Notes on GPU/CPU usage with triton If you do not have triton installed you will not be able to take advantage of GPU acceleration, but you can still use the model on the CPU. In that case, if loading from a checkpoint that was trained with flashattention, you will need to specify transformer=\"normal\" in the load_from_checkpoint function like so: model = scPrint.load_from_checkpoint( '../data/temp/last.ckpt', precpt_gene_emb=None, transformer=\"normal\") Simple tests: An instalation of scPRINT and a simple test of the denoiser is performed during each commit to the main branch with a Github action and pytest workflow . It also provides an expected runtime for the installation and run of scPRINT. We now explore the different usages of scPRINT: FAQ I want to generate gene networks from scRNAseq data: -> Refer to the section . gene network inference in this notebook . -> More examples in this notebook ./notebooks/assessments/bench_omni.ipynb . I want to generate cell embeddings and cell label predictions from scRNAseq data: -> Refer to the embeddings and cell annotations section in this notebook . I want to denoise my scRNAseq dataset: -> Refer to the Denoising of B-cell section in this notebook . -> More example in our benchmark notebook ./notebooks/assessments/bench_denoising.ipynb . I want to generate an atlas-level embedding -> Refer to the notebook nice_umap.ipynb . I need to generate gene tokens using pLLMs To run scPRINT, you can use the option to define the gene tokens using protein language model embeddings of genes. This is done by providing the path to a parquet file of the precomputed set of embeddings for each gene name to scPRINT via \"precpt_gene_emb\" -> To generate this file please refer to the notebook generate_gene_embeddings . I want to pre-train scPRINT from scratch on my own data -> Refer to the documentation page pretrain scprint how can I find if scPRINT was trained on my data? If your data is available in cellxgene, scPRINT was likely trained on it. However some cells, datasets were dropped due to low quality data and some were randomly removed to be part of the validation / test sets. can I use scPRINT on other organisms rather than human? scPRINT has been pretrained on both humans and mouse, and can be used on any organism with a similar gene set. If you want to use scPRINT on very different organisms, you will need to generate gene embeddings for that organism and re-train scPRINT how long does scPRINT takes? what kind of resources do I need? (or in alternative: can i run scPRINT locally?) please look at our supplementary tables in the manuscript I have different scRNASeq batches. Should I integrate my data before running scPRINT? scPRINT takes raw count as inputs, so please don't use integrated data. Just give the raw counts to scPRINT and it will take care of the rest. where to find the gene embeddings? If you think you need the gene embeddings file for loading the model from a checkpoint, you don't, as the embeddings are also stored in the model weights. You just need to load the weights like this: model = scPrint.load_from_checkpoint( '../../data/temp/last.ckpt', precpt_gene_emb=None, ) You can also recreate the gene embedding file through this notebook . Just call the functions, and it should recreate the file itself. the file itself is also available on hugging face Documentation For more information on usage please see the documentation in https://www.jkobject.com/scPRINT/ Model Weights Model weights are available on hugging face . Development Read the CONTRIBUTING.md file. Read the training runs document to know more about how pre-training was performed and the its behavior. code coverage is not right as I am using the command line interface for now. >50% of the code is covered by my current unit test. Acknowledgement: python template laminDB lightning Work in progress (PR welcomed): remove the triton dependencies add version with additional labels (tissues, age) and organisms (mouse, zebrafish) and more datasets from cellxgene version with separate transformer blocks for the encoding part of the bottleneck learning and for the cell embeddings improve classifier to output uncertainties and topK predictions when unsure setup latest lamindb version Awesome Large Cell Model created by Jeremie Kalfon.","title":"Home"},{"location":"#scprint-large-cell-model-for-scrnaseq-data","text":"scPRINT is a large transformer model built for the inference of gene networks (connections between genes explaining the cell's expression profile) from scRNAseq data. It uses novel encoding and decoding of the cell expression profile and new pre-training methodologies to learn a cell model. scPRINT can be used to perform the following analyses: expression denoising : increase the resolution of your scRNAseq data cell embedding : generate a low-dimensional representation of your dataset label prediction : predict the cell type, disease, sequencer, sex, and ethnicity of your cells gene network inference : generate a gene network from any cell or cell cluster in your scRNAseq dataset Read the manuscript! if you would like to know more about scPRINT. Have a look at some of my X-plainers .","title":"scPRINT: Large Cell Model for scRNAseq data"},{"location":"#table-of-contents","text":"scPRINT: Large Cell Model for scRNAseq data Table of Contents Install scPRINT lamin.ai install pytorch and GPUs dev install Usage scPRINT's basic commands Notes on GPU/CPU usage with triton Simple tests: FAQ I want to generate gene networks from scRNAseq data: I want to generate cell embeddings and cell label predictions from scRNAseq data: I want to denoise my scRNAseq dataset: I want to generate an atlas-level embedding I need to generate gene tokens using pLLMs I want to pre-train scPRINT from scratch on my own data how can I find if scPRINT was trained on my data? can I use scPRINT on other organisms rather than human? how long does scPRINT takes? what kind of resources do I need? (or in alternative: can i run scPRINT locally?) I have different scRNASeq batches. Should I integrate my data before running scPRINT? where to find the gene embeddings? Documentation Model Weights Development Work in progress (PR welcomed):","title":"Table of Contents"},{"location":"#install-scprint","text":"For the moment scPRINT has been tested on MacOS and Linux (Ubuntu 20.04) with Python 3.10. Its instalation takes on average 10 minutes. If you want to be using flashattention2, know that it only supports triton 2.0 MLIR's version and torch==2.0.0 for now.","title":"Install scPRINT"},{"location":"#laminai","text":"To use scPRINT, I need you to use lamin.ai. This is needed to load biological informations like genes, cell types, organisms etc... To do so, you will need to connect with google or github to lamin.ai , then be sure to connect before running anything (or before starting a notebook): lamin login --key . Follow the instructions on their website .","title":"lamin.ai"},{"location":"#install","text":"To start you will need to do: conda create -n python==3.10 #scprint might work with python >3.10, but it is not tested #one of pip install scprint # OR pip install scprint[dev] # for the dev dependencies (building etc..) OR pip install scprint[flash] # to use flashattention2 with triton: only if you have a compatible gpu (e.g. not available for apple GPUs for now, see https://github.com/triton-lang/triton?tab=readme-ov-file#compatibility) #OR pip install scPRINT[dev,flash] lamin login --key lamin init --storage --schema bionty if you start with lamin and had to do a lamin init , you will also need to populate your ontologies. This is because scPRINT is using ontologies to define its cell types, diseases, sexes, ethnicities, etc. you can do it manually or with our function: from scdataloader.utils import populate_my_ontology populate_my_ontology() #to populate everything (recommended) (can take 2-10mns) populate_my_ontology( #the minimum for scprint to run some inferences (denoising, grn inference) organisms: List[str] = [\"NCBITaxon:10090\", \"NCBITaxon:9606\"], sex: List[str] = [\"PATO:0000384\", \"PATO:0000383\"], celltypes = None, ethnicities = None, assays = None, tissues = None, diseases = None, dev_stages = None, ) We make use of some additional packages we developed alongside scPRint. Please refer to their documentation for more information: scDataLoader : a dataloader for training large cell models. GRnnData : a package to work with gene networks from single cell data. benGRN : a package to benchmark gene network inference methods from single cell data.","title":"install"},{"location":"#pytorch-and-gpus","text":"scPRINT can run on machines without GPUs, but it will be slow. It is highly recommended to use a GPU for inference. Once you have a GPU, and installed the required drivers, you might need to install a specific version of pytorch that is compatible with your drivers (e.g. nvidia 550 drivers will lead to a nvidia toolkit 11.7 or 11.8 which might mean you need to re-install a different flavor of pytorch for things to work. e.g. using the command: pip install torch==2.2.0 torchvision==0.17.0 torchaudio==2.2.0 --index-url https://download.pytorch.org/whl/cu118 on my case on linux ). I was able to test it with nvidia 11.7, 11.8, 12.2.","title":"pytorch and GPUs"},{"location":"#dev-install","text":"If you want to use the latest version of scPRINT and work on the code yourself use git clone and pip -e instead of pip install . git clone https://github.com/jkobject/scPRINT git clone https://github.com/jkobject/scDataLoader git clone https://github.com/cantinilab/GRnnData git clone https://github.com/jkobject/benGRN pip install -e scPRINT[dev] pip install -e scDataLoader[dev] pip install -e GRnnData[dev] pip install -e benGRN[dev]","title":"dev install"},{"location":"#usage","text":"","title":"Usage"},{"location":"#scprints-basic-commands","text":"This is the most minimal example of how scPRINT works: from lightning.pytorch import Trainer from scprint import scPrint from scdataloader import DataModule datamodule = DataModule(...) model = scPrint(...) # to train / fit / test the model trainer = Trainer(...) trainer.fit(model, datamodule=datamodule) # to do predictions Denoiser, Embedder, GNInfer denoiser = Denoiser(...) adata = sc.read_h5ad(...) denoiser(model, adata=adata) ... or, from a bash command line $ scprint fit/train/predict/test/denoise/embed/gninfer --config config/[medium|large|vlarge] ... find out more about the commands by running scprint --help or scprint [command] --help . more examples of using the command line are available in the docs .","title":"scPRINT's basic commands"},{"location":"#notes-on-gpucpu-usage-with-triton","text":"If you do not have triton installed you will not be able to take advantage of GPU acceleration, but you can still use the model on the CPU. In that case, if loading from a checkpoint that was trained with flashattention, you will need to specify transformer=\"normal\" in the load_from_checkpoint function like so: model = scPrint.load_from_checkpoint( '../data/temp/last.ckpt', precpt_gene_emb=None, transformer=\"normal\")","title":"Notes on GPU/CPU usage with triton"},{"location":"#simple-tests","text":"An instalation of scPRINT and a simple test of the denoiser is performed during each commit to the main branch with a Github action and pytest workflow . It also provides an expected runtime for the installation and run of scPRINT. We now explore the different usages of scPRINT:","title":"Simple tests:"},{"location":"#faq","text":"","title":"FAQ"},{"location":"#i-want-to-generate-gene-networks-from-scrnaseq-data","text":"-> Refer to the section . gene network inference in this notebook . -> More examples in this notebook ./notebooks/assessments/bench_omni.ipynb .","title":"I want to generate gene networks from scRNAseq data:"},{"location":"#i-want-to-generate-cell-embeddings-and-cell-label-predictions-from-scrnaseq-data","text":"-> Refer to the embeddings and cell annotations section in this notebook .","title":"I want to generate cell embeddings and cell label predictions from scRNAseq data:"},{"location":"#i-want-to-denoise-my-scrnaseq-dataset","text":"-> Refer to the Denoising of B-cell section in this notebook . -> More example in our benchmark notebook ./notebooks/assessments/bench_denoising.ipynb .","title":"I want to denoise my scRNAseq dataset:"},{"location":"#i-want-to-generate-an-atlas-level-embedding","text":"-> Refer to the notebook nice_umap.ipynb .","title":"I want to generate an atlas-level embedding"},{"location":"#i-need-to-generate-gene-tokens-using-pllms","text":"To run scPRINT, you can use the option to define the gene tokens using protein language model embeddings of genes. This is done by providing the path to a parquet file of the precomputed set of embeddings for each gene name to scPRINT via \"precpt_gene_emb\" -> To generate this file please refer to the notebook generate_gene_embeddings .","title":"I need to generate gene tokens using pLLMs"},{"location":"#i-want-to-pre-train-scprint-from-scratch-on-my-own-data","text":"-> Refer to the documentation page pretrain scprint","title":"I want to pre-train scPRINT from scratch on my own data"},{"location":"#how-can-i-find-if-scprint-was-trained-on-my-data","text":"If your data is available in cellxgene, scPRINT was likely trained on it. However some cells, datasets were dropped due to low quality data and some were randomly removed to be part of the validation / test sets.","title":"how can I find if scPRINT was trained on my data?"},{"location":"#can-i-use-scprint-on-other-organisms-rather-than-human","text":"scPRINT has been pretrained on both humans and mouse, and can be used on any organism with a similar gene set. If you want to use scPRINT on very different organisms, you will need to generate gene embeddings for that organism and re-train scPRINT","title":"can I use scPRINT on other organisms rather than human?"},{"location":"#how-long-does-scprint-takes-what-kind-of-resources-do-i-need-or-in-alternative-can-i-run-scprint-locally","text":"please look at our supplementary tables in the manuscript","title":"how long does scPRINT takes? what kind of resources do I need? (or in alternative: can i run scPRINT locally?)"},{"location":"#i-have-different-scrnaseq-batches-should-i-integrate-my-data-before-running-scprint","text":"scPRINT takes raw count as inputs, so please don't use integrated data. Just give the raw counts to scPRINT and it will take care of the rest.","title":"I have different scRNASeq batches. Should I integrate my data before running scPRINT?"},{"location":"#where-to-find-the-gene-embeddings","text":"If you think you need the gene embeddings file for loading the model from a checkpoint, you don't, as the embeddings are also stored in the model weights. You just need to load the weights like this: model = scPrint.load_from_checkpoint( '../../data/temp/last.ckpt', precpt_gene_emb=None, ) You can also recreate the gene embedding file through this notebook . Just call the functions, and it should recreate the file itself. the file itself is also available on hugging face","title":"where to find the gene embeddings?"},{"location":"#documentation","text":"For more information on usage please see the documentation in https://www.jkobject.com/scPRINT/","title":"Documentation"},{"location":"#model-weights","text":"Model weights are available on hugging face .","title":"Model Weights"},{"location":"#development","text":"Read the CONTRIBUTING.md file. Read the training runs document to know more about how pre-training was performed and the its behavior. code coverage is not right as I am using the command line interface for now. >50% of the code is covered by my current unit test. Acknowledgement: python template laminDB lightning","title":"Development"},{"location":"#work-in-progress-pr-welcomed","text":"remove the triton dependencies add version with additional labels (tissues, age) and organisms (mouse, zebrafish) and more datasets from cellxgene version with separate transformer blocks for the encoding part of the bottleneck learning and for the cell embeddings improve classifier to output uncertainties and topK predictions when unsure setup latest lamindb version Awesome Large Cell Model created by Jeremie Kalfon.","title":"Work in progress (PR welcomed):"},{"location":"cli/","text":"Documentation for the cli modules scprint.__main__ Entry point for scprint. MySaveConfig Bases: SaveConfigCallback MySaveConfig is a subclass of SaveConfigCallback to parametrize the wandb logger further in cli mode scprint.cli MyCLI Bases: LightningCLI MyCLI is a subclass of LightningCLI to add some missing params and create bindings between params of the model and the data. Used to allow calling denoise / embed / gninfer from the command line. Also to add more parameters and link parameters between the scdataloader and the scPRINT model. scprint.trainer.trainer TrainingMode Bases: Callback TrainingMode a callback to set the training specific info to the model. This is because lightning is unfortunately setup this way. the model should be separated from training but at the same time it has training specific methods... so we have to do this. Parameters: do_denoise ( bool , default: True ) \u2013 Whether to apply denoising during training. Defaults to True. noise ( List [ float ] , default: [0.6] ) \u2013 List of noise levels to apply if denoising is enabled. Defaults to [0.6], meaning only one forward path with 60% of the counts being dropped will happen. do_cce ( bool , default: False ) \u2013 Whether to apply the Contrastive Cell Embedding from scGPT during training. Defaults to False. cce_sim ( float , default: 0.5 ) \u2013 Similarity threshold for CCE. Defaults to 0.5. cce_scale ( float , default: 0.002 ) \u2013 Scaling factor for CCE loss. Defaults to 0.002. do_ecs ( bool , default: False ) \u2013 Whether to apply the Elastic Cell Similarity loss from scGPT during training. Defaults to False. ecs_threshold ( float , default: 0.3 ) \u2013 Threshold for ECS. Defaults to 0.3. ecs_scale ( float , default: 0.05 ) \u2013 Scaling factor for ECS loss. Defaults to 0.05. do_mvc ( bool , default: False ) \u2013 Whether to do the cell embedding generation with the scGPT's MVC loss. Defaults to False. mvc_scale ( float , default: 1.0 ) \u2013 Scaling factor for MVC loss. Defaults to 1.0. do_adv_cls ( bool , default: False ) \u2013 Whether to apply adversarial classification during training. Defaults to False. do_generate ( bool , default: True ) \u2013 Whether to do the bottleneck learning task. Defaults to True. class_scale ( float , default: 1.5 ) \u2013 Scaling factor for classification loss. Defaults to 1.5. mask_ratio ( List [ float ] , default: [] ) \u2013 List of mask ratios to apply during training. Defaults to [], meaning no masking is applied during pretraining. warmup_duration ( int , default: 500 ) \u2013 Number of warmup steps for learning rate scheduling. Defaults to 500. fused_adam ( bool , default: False ) \u2013 Whether to use fused Adam optimizer. Defaults to True. adv_class_scale ( float , default: 0.1 ) \u2013 Scaling factor for adversarial classification loss. Defaults to 0.1. lr_reduce_patience ( int , default: 1 ) \u2013 Number of epochs with no improvement after which learning rate will be reduced. Defaults to 1. lr_reduce_factor ( float , default: 0.6 ) \u2013 Factor by which the learning rate will be reduced. Defaults to 0.6. lr_reduce_monitor ( str , default: 'val_loss' ) \u2013 Quantity to be monitored for learning rate reduction. Defaults to \"val_loss\". do_cls ( bool , default: True ) \u2013 Whether to perform classification during training. Defaults to True. do_adv_batch ( bool , default: False ) \u2013 Whether to apply adversarial batch training. Defaults to False. run_full_forward ( bool , default: False ) \u2013 Whether to run a second forward pass without masking or denoising for the bottleneck learning / MVC case. Defaults to False. lr ( float , default: 0.001 ) \u2013 Initial learning rate. Defaults to 0.001. optim ( str , default: 'adamW' ) \u2013 Optimizer to use during training. Defaults to \"adamW\". weight_decay ( float , default: 0.01 ) \u2013 Weight decay to apply during optimization. Defaults to 0.01. name ( str , default: '' ) \u2013 Name of the training mode. Defaults to an empty string. should be an ID for the model Source code in scprint/trainer/trainer.py 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 def __init__ ( self , do_denoise : bool = True , noise : List [ float ] = [ 0.6 ], do_cce : bool = False , cce_sim : float = 0.5 , # .6 cce_scale : float = 0.002 , # .01 do_ecs : bool = False , ecs_threshold : float = 0.3 , ecs_scale : float = 0.05 , # .1 do_mvc : bool = False , mvc_scale : float = 1.0 , do_adv_cls : bool = False , do_next_tp : bool = False , do_generate : bool = True , class_scale : float = 1.5 , mask_ratio : List [ float ] = [], # 0.3 warmup_duration : int = 500 , fused_adam : bool = False , adv_class_scale : float = 0.1 , lr_reduce_patience : int = 1 , lr_reduce_factor : float = 0.6 , lr_reduce_monitor : str = \"val_loss\" , do_cls : bool = True , do_adv_batch : bool = False , run_full_forward : bool = False , lr : float = 0.001 , optim : str = \"adamW\" , weight_decay : float = 0.01 , name = \"\" , ): \"\"\" TrainingMode a callback to set the training specific info to the model. This is because lightning is unfortunately setup this way. the model should be separated from training but at the same time it has training specific methods... so we have to do this. Args: do_denoise (bool): Whether to apply denoising during training. Defaults to True. noise (List[float]): List of noise levels to apply if denoising is enabled. Defaults to [0.6], meaning only one forward path with 60% of the counts being dropped will happen. do_cce (bool): Whether to apply the Contrastive Cell Embedding from scGPT during training. Defaults to False. cce_sim (float): Similarity threshold for CCE. Defaults to 0.5. cce_scale (float): Scaling factor for CCE loss. Defaults to 0.002. do_ecs (bool): Whether to apply the Elastic Cell Similarity loss from scGPT during training. Defaults to False. ecs_threshold (float): Threshold for ECS. Defaults to 0.3. ecs_scale (float): Scaling factor for ECS loss. Defaults to 0.05. do_mvc (bool): Whether to do the cell embedding generation with the scGPT's MVC loss. Defaults to False. mvc_scale (float): Scaling factor for MVC loss. Defaults to 1.0. do_adv_cls (bool): Whether to apply adversarial classification during training. Defaults to False. do_generate (bool): Whether to do the bottleneck learning task. Defaults to True. class_scale (float): Scaling factor for classification loss. Defaults to 1.5. mask_ratio (List[float]): List of mask ratios to apply during training. Defaults to [], meaning no masking is applied during pretraining. warmup_duration (int): Number of warmup steps for learning rate scheduling. Defaults to 500. fused_adam (bool): Whether to use fused Adam optimizer. Defaults to True. adv_class_scale (float): Scaling factor for adversarial classification loss. Defaults to 0.1. lr_reduce_patience (int): Number of epochs with no improvement after which learning rate will be reduced. Defaults to 1. lr_reduce_factor (float): Factor by which the learning rate will be reduced. Defaults to 0.6. lr_reduce_monitor (str): Quantity to be monitored for learning rate reduction. Defaults to \"val_loss\". do_cls (bool): Whether to perform classification during training. Defaults to True. do_adv_batch (bool): Whether to apply adversarial batch training. Defaults to False. run_full_forward (bool): Whether to run a second forward pass without masking or denoising for the bottleneck learning / MVC case. Defaults to False. lr (float): Initial learning rate. Defaults to 0.001. optim (str): Optimizer to use during training. Defaults to \"adamW\". weight_decay (float): Weight decay to apply during optimization. Defaults to 0.01. name (str): Name of the training mode. Defaults to an empty string. should be an ID for the model \"\"\" super () . __init__ () self . do_denoise = do_denoise self . noise = noise self . do_cce = do_cce self . cce_sim = cce_sim self . cce_scale = cce_scale self . do_ecs = do_ecs self . ecs_threshold = ecs_threshold self . ecs_scale = ecs_scale self . do_mvc = do_mvc self . do_adv_cls = do_adv_cls self . do_next_tp = do_next_tp self . do_generate = do_generate self . class_scale = class_scale self . mask_ratio = mask_ratio self . warmup_duration = warmup_duration self . fused_adam = fused_adam self . mvc_scale = mvc_scale self . do_cls = do_cls self . adv_class_scale = adv_class_scale self . lr_reduce_patience = lr_reduce_patience self . lr_reduce_factor = lr_reduce_factor self . lr_reduce_monitor = lr_reduce_monitor self . lr = lr self . optim = optim self . weight_decay = weight_decay self . do_cls = do_cls self . do_adv_batch = do_adv_batch self . run_full_forward = run_full_forward self . name = name","title":"cli"},{"location":"cli/#documentation-for-the-cli-modules","text":"","title":"Documentation for the cli modules"},{"location":"cli/#scprint.__main__","text":"Entry point for scprint.","title":"__main__"},{"location":"cli/#scprint.__main__.MySaveConfig","text":"Bases: SaveConfigCallback MySaveConfig is a subclass of SaveConfigCallback to parametrize the wandb logger further in cli mode","title":"MySaveConfig"},{"location":"cli/#scprint.cli","text":"","title":"cli"},{"location":"cli/#scprint.cli.MyCLI","text":"Bases: LightningCLI MyCLI is a subclass of LightningCLI to add some missing params and create bindings between params of the model and the data. Used to allow calling denoise / embed / gninfer from the command line. Also to add more parameters and link parameters between the scdataloader and the scPRINT model.","title":"MyCLI"},{"location":"cli/#scprint.trainer.trainer","text":"","title":"trainer"},{"location":"cli/#scprint.trainer.trainer.TrainingMode","text":"Bases: Callback TrainingMode a callback to set the training specific info to the model. This is because lightning is unfortunately setup this way. the model should be separated from training but at the same time it has training specific methods... so we have to do this. Parameters: do_denoise ( bool , default: True ) \u2013 Whether to apply denoising during training. Defaults to True. noise ( List [ float ] , default: [0.6] ) \u2013 List of noise levels to apply if denoising is enabled. Defaults to [0.6], meaning only one forward path with 60% of the counts being dropped will happen. do_cce ( bool , default: False ) \u2013 Whether to apply the Contrastive Cell Embedding from scGPT during training. Defaults to False. cce_sim ( float , default: 0.5 ) \u2013 Similarity threshold for CCE. Defaults to 0.5. cce_scale ( float , default: 0.002 ) \u2013 Scaling factor for CCE loss. Defaults to 0.002. do_ecs ( bool , default: False ) \u2013 Whether to apply the Elastic Cell Similarity loss from scGPT during training. Defaults to False. ecs_threshold ( float , default: 0.3 ) \u2013 Threshold for ECS. Defaults to 0.3. ecs_scale ( float , default: 0.05 ) \u2013 Scaling factor for ECS loss. Defaults to 0.05. do_mvc ( bool , default: False ) \u2013 Whether to do the cell embedding generation with the scGPT's MVC loss. Defaults to False. mvc_scale ( float , default: 1.0 ) \u2013 Scaling factor for MVC loss. Defaults to 1.0. do_adv_cls ( bool , default: False ) \u2013 Whether to apply adversarial classification during training. Defaults to False. do_generate ( bool , default: True ) \u2013 Whether to do the bottleneck learning task. Defaults to True. class_scale ( float , default: 1.5 ) \u2013 Scaling factor for classification loss. Defaults to 1.5. mask_ratio ( List [ float ] , default: [] ) \u2013 List of mask ratios to apply during training. Defaults to [], meaning no masking is applied during pretraining. warmup_duration ( int , default: 500 ) \u2013 Number of warmup steps for learning rate scheduling. Defaults to 500. fused_adam ( bool , default: False ) \u2013 Whether to use fused Adam optimizer. Defaults to True. adv_class_scale ( float , default: 0.1 ) \u2013 Scaling factor for adversarial classification loss. Defaults to 0.1. lr_reduce_patience ( int , default: 1 ) \u2013 Number of epochs with no improvement after which learning rate will be reduced. Defaults to 1. lr_reduce_factor ( float , default: 0.6 ) \u2013 Factor by which the learning rate will be reduced. Defaults to 0.6. lr_reduce_monitor ( str , default: 'val_loss' ) \u2013 Quantity to be monitored for learning rate reduction. Defaults to \"val_loss\". do_cls ( bool , default: True ) \u2013 Whether to perform classification during training. Defaults to True. do_adv_batch ( bool , default: False ) \u2013 Whether to apply adversarial batch training. Defaults to False. run_full_forward ( bool , default: False ) \u2013 Whether to run a second forward pass without masking or denoising for the bottleneck learning / MVC case. Defaults to False. lr ( float , default: 0.001 ) \u2013 Initial learning rate. Defaults to 0.001. optim ( str , default: 'adamW' ) \u2013 Optimizer to use during training. Defaults to \"adamW\". weight_decay ( float , default: 0.01 ) \u2013 Weight decay to apply during optimization. Defaults to 0.01. name ( str , default: '' ) \u2013 Name of the training mode. Defaults to an empty string. should be an ID for the model Source code in scprint/trainer/trainer.py 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 def __init__ ( self , do_denoise : bool = True , noise : List [ float ] = [ 0.6 ], do_cce : bool = False , cce_sim : float = 0.5 , # .6 cce_scale : float = 0.002 , # .01 do_ecs : bool = False , ecs_threshold : float = 0.3 , ecs_scale : float = 0.05 , # .1 do_mvc : bool = False , mvc_scale : float = 1.0 , do_adv_cls : bool = False , do_next_tp : bool = False , do_generate : bool = True , class_scale : float = 1.5 , mask_ratio : List [ float ] = [], # 0.3 warmup_duration : int = 500 , fused_adam : bool = False , adv_class_scale : float = 0.1 , lr_reduce_patience : int = 1 , lr_reduce_factor : float = 0.6 , lr_reduce_monitor : str = \"val_loss\" , do_cls : bool = True , do_adv_batch : bool = False , run_full_forward : bool = False , lr : float = 0.001 , optim : str = \"adamW\" , weight_decay : float = 0.01 , name = \"\" , ): \"\"\" TrainingMode a callback to set the training specific info to the model. This is because lightning is unfortunately setup this way. the model should be separated from training but at the same time it has training specific methods... so we have to do this. Args: do_denoise (bool): Whether to apply denoising during training. Defaults to True. noise (List[float]): List of noise levels to apply if denoising is enabled. Defaults to [0.6], meaning only one forward path with 60% of the counts being dropped will happen. do_cce (bool): Whether to apply the Contrastive Cell Embedding from scGPT during training. Defaults to False. cce_sim (float): Similarity threshold for CCE. Defaults to 0.5. cce_scale (float): Scaling factor for CCE loss. Defaults to 0.002. do_ecs (bool): Whether to apply the Elastic Cell Similarity loss from scGPT during training. Defaults to False. ecs_threshold (float): Threshold for ECS. Defaults to 0.3. ecs_scale (float): Scaling factor for ECS loss. Defaults to 0.05. do_mvc (bool): Whether to do the cell embedding generation with the scGPT's MVC loss. Defaults to False. mvc_scale (float): Scaling factor for MVC loss. Defaults to 1.0. do_adv_cls (bool): Whether to apply adversarial classification during training. Defaults to False. do_generate (bool): Whether to do the bottleneck learning task. Defaults to True. class_scale (float): Scaling factor for classification loss. Defaults to 1.5. mask_ratio (List[float]): List of mask ratios to apply during training. Defaults to [], meaning no masking is applied during pretraining. warmup_duration (int): Number of warmup steps for learning rate scheduling. Defaults to 500. fused_adam (bool): Whether to use fused Adam optimizer. Defaults to True. adv_class_scale (float): Scaling factor for adversarial classification loss. Defaults to 0.1. lr_reduce_patience (int): Number of epochs with no improvement after which learning rate will be reduced. Defaults to 1. lr_reduce_factor (float): Factor by which the learning rate will be reduced. Defaults to 0.6. lr_reduce_monitor (str): Quantity to be monitored for learning rate reduction. Defaults to \"val_loss\". do_cls (bool): Whether to perform classification during training. Defaults to True. do_adv_batch (bool): Whether to apply adversarial batch training. Defaults to False. run_full_forward (bool): Whether to run a second forward pass without masking or denoising for the bottleneck learning / MVC case. Defaults to False. lr (float): Initial learning rate. Defaults to 0.001. optim (str): Optimizer to use during training. Defaults to \"adamW\". weight_decay (float): Weight decay to apply during optimization. Defaults to 0.01. name (str): Name of the training mode. Defaults to an empty string. should be an ID for the model \"\"\" super () . __init__ () self . do_denoise = do_denoise self . noise = noise self . do_cce = do_cce self . cce_sim = cce_sim self . cce_scale = cce_scale self . do_ecs = do_ecs self . ecs_threshold = ecs_threshold self . ecs_scale = ecs_scale self . do_mvc = do_mvc self . do_adv_cls = do_adv_cls self . do_next_tp = do_next_tp self . do_generate = do_generate self . class_scale = class_scale self . mask_ratio = mask_ratio self . warmup_duration = warmup_duration self . fused_adam = fused_adam self . mvc_scale = mvc_scale self . do_cls = do_cls self . adv_class_scale = adv_class_scale self . lr_reduce_patience = lr_reduce_patience self . lr_reduce_factor = lr_reduce_factor self . lr_reduce_monitor = lr_reduce_monitor self . lr = lr self . optim = optim self . weight_decay = weight_decay self . do_cls = do_cls self . do_adv_batch = do_adv_batch self . run_full_forward = run_full_forward self . name = name","title":"TrainingMode"},{"location":"embedder/","text":"Documentation for the tokenizers module scprint.tokenizers.protein_embedder PROTBERT PROTBERT a ghost class to call protein LLMs to encode protein sequences. Parameters: config ( str , default: 'esm-extract' ) \u2013 The configuration for the model. Defaults to \"esm-extract\". pretrained_model ( str , default: 'esm2_t33_650M_UR50D' ) \u2013 The pretrained model to be used. Defaults to \"esm2_t33_650M_UR50D\". Source code in scprint/tokenizers/protein_embedder.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def __init__ ( self , config : str = \"esm-extract\" , pretrained_model : str = \"esm2_t33_650M_UR50D\" , ): \"\"\" PROTBERT a ghost class to call protein LLMs to encode protein sequences. Args: config (str, optional): The configuration for the model. Defaults to \"esm-extract\". pretrained_model (str, optional): The pretrained model to be used. Defaults to \"esm2_t33_650M_UR50D\". \"\"\" self . config = config self . pretrained_model = pretrained_model __call__ Call the PROTBERT model on the input file. Parameters: input_file ( str ) \u2013 The input file to be processed. output_folder ( str , default: '/tmp/esm_out/' ) \u2013 The folder where the output will be stored. Defaults to \"/tmp/esm_out/\". cache ( bool , default: True ) \u2013 If True, use cached data if available. Defaults to True. Returns: DataFrame \u2013 pd.DataFrame: The results of the model as a DataFrame. Source code in scprint/tokenizers/protein_embedder.py 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 def __call__ ( self , input_file : str , output_folder : str = \"/tmp/esm_out/\" , cache : bool = True ) -> pd . DataFrame : \"\"\" Call the PROTBERT model on the input file. Args: input_file (str): The input file to be processed. output_folder (str, optional): The folder where the output will be stored. Defaults to \"/tmp/esm_out/\". cache (bool, optional): If True, use cached data if available. Defaults to True. Returns: pd.DataFrame: The results of the model as a DataFrame. \"\"\" if not os . path . exists ( output_folder ) or not cache : os . makedirs ( output_folder , exist_ok = True ) print ( \"running protbert\" ) cmd = ( self . config + \" \" + self . pretrained_model + \" \" + input_file + \" \" + output_folder + \" --include mean\" ) try : run_command ( cmd , shell = True ) except Exception as e : raise RuntimeError ( \"An error occurred while running the esm-extract command: \" + str ( e ) ) return self . read_results ( output_folder ) read_results Read multiple .pt files in a folder and convert them into a DataFrame. Parameters: output_folder ( str ) \u2013 The folder where the .pt files are stored. Returns: \u2013 pd.DataFrame: The results of the model as a DataFrame. Source code in scprint/tokenizers/protein_embedder.py 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 def read_results ( self , output_folder ): \"\"\" Read multiple .pt files in a folder and convert them into a DataFrame. Args: output_folder (str): The folder where the .pt files are stored. Returns: pd.DataFrame: The results of the model as a DataFrame. \"\"\" files = os . listdir ( output_folder ) files = [ i for i in files if i . endswith ( \".pt\" )] results = [] for file in files : results . append ( load ( output_folder + file )[ \"mean_representations\" ][ 33 ] . numpy () . tolist () ) return pd . DataFrame ( data = results , index = [ file . split ( \".\" )[ 0 ] for file in files ]) scprint.tokenizers.embedder protein_embeddings_generator protein_embeddings_generator embed a set of genes using fasta file and LLMs Parameters: genedf ( DataFrame ) \u2013 A DataFrame containing gene information. organism ( str , default: 'homo_sapiens' ) \u2013 The organism to which the genes belong. Defaults to \"homo_sapiens\". cache ( bool , default: True ) \u2013 If True, the function will use cached data if available. Defaults to True. fasta_path ( str , default: '/tmp/data/fasta/' ) \u2013 The path to the directory where the fasta files are stored. Defaults to \"/tmp/data/fasta/\". embedding_size ( int , default: 512 ) \u2013 The size of the embeddings to be generated. Defaults to 512. Returns: \u2013 pd.DataFrame: Returns a DataFrame containing the protein embeddings, and the RNA embeddings. Source code in scprint/tokenizers/embedder.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 def protein_embeddings_generator ( genedf : pd . DataFrame , organism : str = \"homo_sapiens\" , # mus_musculus, cache : bool = True , fasta_path : str = \"/tmp/data/fasta/\" , embedding_size : int = 512 , ): \"\"\" protein_embeddings_generator embed a set of genes using fasta file and LLMs Args: genedf (pd.DataFrame): A DataFrame containing gene information. organism (str, optional): The organism to which the genes belong. Defaults to \"homo_sapiens\". cache (bool, optional): If True, the function will use cached data if available. Defaults to True. fasta_path (str, optional): The path to the directory where the fasta files are stored. Defaults to \"/tmp/data/fasta/\". embedding_size (int, optional): The size of the embeddings to be generated. Defaults to 512. Returns: pd.DataFrame: Returns a DataFrame containing the protein embeddings, and the RNA embeddings. \"\"\" # given a gene file and organism # load the organism fasta if not already done utils . load_fasta_species ( species = organism , output_path = fasta_path , cache = cache ) # subset the fasta fasta_file = next ( file for file in os . listdir ( fasta_path ) if file . endswith ( \".all.fa.gz\" ) ) protgenedf = genedf [ genedf [ \"biotype\" ] == \"protein_coding\" ] utils . utils . run_command ([ \"gunzip\" , fasta_path + fasta_file ]) utils . subset_fasta ( protgenedf . index . tolist (), subfasta_path = fasta_path + \"subset.fa\" , fasta_path = fasta_path + fasta_file [: - 3 ], drop_unknown_seq = True , ) # subset the gene file # embed prot_embedder = PROTBERT () prot_embeddings = prot_embedder ( fasta_path + \"subset.fa\" , output_folder = fasta_path + \"esm_out/\" , cache = cache ) # load the data and erase / zip the rest utils . utils . run_command ([ \"gzip\" , fasta_path + fasta_file [: - 3 ]]) # return the embedding and gene file # TODO: to redebug # do the same for RNA # rnagenedf = genedf[genedf[\"biotype\"] != \"protein_coding\"] # fasta_file = next( # file for file in os.listdir(fasta_path) if file.endswith(\".ncrna.fa.gz\") # ) # utils.utils.run_command([\"gunzip\", fasta_path + fasta_file]) # utils.subset_fasta( # rnagenedf[\"ensembl_gene_id\"].tolist(), # subfasta_path=fasta_path + \"subset.ncrna.fa\", # fasta_path=fasta_path + fasta_file[:-3], # drop_unknown_seq=True, # ) # rna_embedder = RNABERT() # rna_embeddings = rna_embedder(fasta_path + \"subset.ncrna.fa\") ## Check if the sizes of the cembeddings are not the same # utils.utils.run_command([\"gzip\", fasta_path + fasta_file[:-3]]) # m = AdaptiveAvgPool1d ( embedding_size ) prot_embeddings = pd . DataFrame ( data = m ( torch . tensor ( prot_embeddings . values )), index = prot_embeddings . index ) # rna_embeddings = pd.DataFrame( # data=m(torch.tensor(rna_embeddings.values)), index=rna_embeddings.index # ) # Concatenate the embeddings return prot_embeddings # pd.concat([prot_embeddings, rna_embeddings])","title":"embedders"},{"location":"embedder/#documentation-for-the-tokenizers-module","text":"","title":"Documentation for the tokenizers module"},{"location":"embedder/#scprint.tokenizers.protein_embedder","text":"","title":"protein_embedder"},{"location":"embedder/#scprint.tokenizers.protein_embedder.PROTBERT","text":"PROTBERT a ghost class to call protein LLMs to encode protein sequences. Parameters: config ( str , default: 'esm-extract' ) \u2013 The configuration for the model. Defaults to \"esm-extract\". pretrained_model ( str , default: 'esm2_t33_650M_UR50D' ) \u2013 The pretrained model to be used. Defaults to \"esm2_t33_650M_UR50D\". Source code in scprint/tokenizers/protein_embedder.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 def __init__ ( self , config : str = \"esm-extract\" , pretrained_model : str = \"esm2_t33_650M_UR50D\" , ): \"\"\" PROTBERT a ghost class to call protein LLMs to encode protein sequences. Args: config (str, optional): The configuration for the model. Defaults to \"esm-extract\". pretrained_model (str, optional): The pretrained model to be used. Defaults to \"esm2_t33_650M_UR50D\". \"\"\" self . config = config self . pretrained_model = pretrained_model","title":"PROTBERT"},{"location":"embedder/#scprint.tokenizers.protein_embedder.PROTBERT.__call__","text":"Call the PROTBERT model on the input file. Parameters: input_file ( str ) \u2013 The input file to be processed. output_folder ( str , default: '/tmp/esm_out/' ) \u2013 The folder where the output will be stored. Defaults to \"/tmp/esm_out/\". cache ( bool , default: True ) \u2013 If True, use cached data if available. Defaults to True. Returns: DataFrame \u2013 pd.DataFrame: The results of the model as a DataFrame. Source code in scprint/tokenizers/protein_embedder.py 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 def __call__ ( self , input_file : str , output_folder : str = \"/tmp/esm_out/\" , cache : bool = True ) -> pd . DataFrame : \"\"\" Call the PROTBERT model on the input file. Args: input_file (str): The input file to be processed. output_folder (str, optional): The folder where the output will be stored. Defaults to \"/tmp/esm_out/\". cache (bool, optional): If True, use cached data if available. Defaults to True. Returns: pd.DataFrame: The results of the model as a DataFrame. \"\"\" if not os . path . exists ( output_folder ) or not cache : os . makedirs ( output_folder , exist_ok = True ) print ( \"running protbert\" ) cmd = ( self . config + \" \" + self . pretrained_model + \" \" + input_file + \" \" + output_folder + \" --include mean\" ) try : run_command ( cmd , shell = True ) except Exception as e : raise RuntimeError ( \"An error occurred while running the esm-extract command: \" + str ( e ) ) return self . read_results ( output_folder )","title":"__call__"},{"location":"embedder/#scprint.tokenizers.protein_embedder.PROTBERT.read_results","text":"Read multiple .pt files in a folder and convert them into a DataFrame. Parameters: output_folder ( str ) \u2013 The folder where the .pt files are stored. Returns: \u2013 pd.DataFrame: The results of the model as a DataFrame. Source code in scprint/tokenizers/protein_embedder.py 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 def read_results ( self , output_folder ): \"\"\" Read multiple .pt files in a folder and convert them into a DataFrame. Args: output_folder (str): The folder where the .pt files are stored. Returns: pd.DataFrame: The results of the model as a DataFrame. \"\"\" files = os . listdir ( output_folder ) files = [ i for i in files if i . endswith ( \".pt\" )] results = [] for file in files : results . append ( load ( output_folder + file )[ \"mean_representations\" ][ 33 ] . numpy () . tolist () ) return pd . DataFrame ( data = results , index = [ file . split ( \".\" )[ 0 ] for file in files ])","title":"read_results"},{"location":"embedder/#scprint.tokenizers.embedder","text":"","title":"embedder"},{"location":"embedder/#scprint.tokenizers.embedder.protein_embeddings_generator","text":"protein_embeddings_generator embed a set of genes using fasta file and LLMs Parameters: genedf ( DataFrame ) \u2013 A DataFrame containing gene information. organism ( str , default: 'homo_sapiens' ) \u2013 The organism to which the genes belong. Defaults to \"homo_sapiens\". cache ( bool , default: True ) \u2013 If True, the function will use cached data if available. Defaults to True. fasta_path ( str , default: '/tmp/data/fasta/' ) \u2013 The path to the directory where the fasta files are stored. Defaults to \"/tmp/data/fasta/\". embedding_size ( int , default: 512 ) \u2013 The size of the embeddings to be generated. Defaults to 512. Returns: \u2013 pd.DataFrame: Returns a DataFrame containing the protein embeddings, and the RNA embeddings. Source code in scprint/tokenizers/embedder.py 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 def protein_embeddings_generator ( genedf : pd . DataFrame , organism : str = \"homo_sapiens\" , # mus_musculus, cache : bool = True , fasta_path : str = \"/tmp/data/fasta/\" , embedding_size : int = 512 , ): \"\"\" protein_embeddings_generator embed a set of genes using fasta file and LLMs Args: genedf (pd.DataFrame): A DataFrame containing gene information. organism (str, optional): The organism to which the genes belong. Defaults to \"homo_sapiens\". cache (bool, optional): If True, the function will use cached data if available. Defaults to True. fasta_path (str, optional): The path to the directory where the fasta files are stored. Defaults to \"/tmp/data/fasta/\". embedding_size (int, optional): The size of the embeddings to be generated. Defaults to 512. Returns: pd.DataFrame: Returns a DataFrame containing the protein embeddings, and the RNA embeddings. \"\"\" # given a gene file and organism # load the organism fasta if not already done utils . load_fasta_species ( species = organism , output_path = fasta_path , cache = cache ) # subset the fasta fasta_file = next ( file for file in os . listdir ( fasta_path ) if file . endswith ( \".all.fa.gz\" ) ) protgenedf = genedf [ genedf [ \"biotype\" ] == \"protein_coding\" ] utils . utils . run_command ([ \"gunzip\" , fasta_path + fasta_file ]) utils . subset_fasta ( protgenedf . index . tolist (), subfasta_path = fasta_path + \"subset.fa\" , fasta_path = fasta_path + fasta_file [: - 3 ], drop_unknown_seq = True , ) # subset the gene file # embed prot_embedder = PROTBERT () prot_embeddings = prot_embedder ( fasta_path + \"subset.fa\" , output_folder = fasta_path + \"esm_out/\" , cache = cache ) # load the data and erase / zip the rest utils . utils . run_command ([ \"gzip\" , fasta_path + fasta_file [: - 3 ]]) # return the embedding and gene file # TODO: to redebug # do the same for RNA # rnagenedf = genedf[genedf[\"biotype\"] != \"protein_coding\"] # fasta_file = next( # file for file in os.listdir(fasta_path) if file.endswith(\".ncrna.fa.gz\") # ) # utils.utils.run_command([\"gunzip\", fasta_path + fasta_file]) # utils.subset_fasta( # rnagenedf[\"ensembl_gene_id\"].tolist(), # subfasta_path=fasta_path + \"subset.ncrna.fa\", # fasta_path=fasta_path + fasta_file[:-3], # drop_unknown_seq=True, # ) # rna_embedder = RNABERT() # rna_embeddings = rna_embedder(fasta_path + \"subset.ncrna.fa\") ## Check if the sizes of the cembeddings are not the same # utils.utils.run_command([\"gzip\", fasta_path + fasta_file[:-3]]) # m = AdaptiveAvgPool1d ( embedding_size ) prot_embeddings = pd . DataFrame ( data = m ( torch . tensor ( prot_embeddings . values )), index = prot_embeddings . index ) # rna_embeddings = pd.DataFrame( # data=m(torch.tensor(rna_embeddings.values)), index=rna_embeddings.index # ) # Concatenate the embeddings return prot_embeddings # pd.concat([prot_embeddings, rna_embeddings])","title":"protein_embeddings_generator"},{"location":"model/","text":"Documentation for the model model description scprint.model.model scPrint Bases: LightningModule , PyTorchModelHubMixin scPRINT transformer for single cell biology and the inference of Gene Regulatory networks Parameters: genes ( list ) \u2013 List of gene names the model will work with. precpt_gene_emb ( array , default: None ) \u2013 Gene embeddings of size (len(genes), d_model). Should be in the same order as the genes. Defaults to None. gene_pos_enc ( list , default: None ) \u2013 Gene position encoding of the same size as genes. Provides a location value for each gene in genes. Defaults to None. d_model ( int , default: 512 ) \u2013 Dimension of the model. Defaults to 512. nhead ( int , default: 8 ) \u2013 Number of heads in the multihead attention models. Defaults to 8. d_hid ( int , default: 512 ) \u2013 Dimension of the feedforward network model. Defaults to 512. nlayers ( int , default: 6 ) \u2013 Number of layers in the transformer model. Defaults to 6. expr_encoder_layers ( int , default: 2 ) \u2013 Number of layers in the expression encoder. Defaults to 2. layers_cls ( list [ int ] , default: [] ) \u2013 List specifying the number of layers in the classifier. Defaults to []. classes ( Dict [ str , int ] , default: {} ) \u2013 Classes to predict with the number of classes for each. Defaults to {}. labels_hierarchy ( Dict [ str , Dict [ int , list [ int ]]] , default: {} ) \u2013 Class hierarchy for classes with hierarchical classes. Defaults to {}. dropout ( float , default: 0.2 ) \u2013 Dropout value. Defaults to 0.2. transformer ( str , default: 'fast' ) \u2013 Transformer type to use. One of \"linear\", \"flash\", \"flashsparse\", \"scprint\". Defaults to \"fast\". domain_spec_batchnorm ( str , default: 'None' ) \u2013 Whether to apply domain-specific batch normalization. Defaults to \"None\". expr_emb_style ( str , default: 'continuous' ) \u2013 Style of input embedding. One of \"continuous\", \"binned_pos\", \"cont_pos\". Defaults to \"continuous\". mvc_decoder ( str , default: 'None' ) \u2013 Style of MVC decoder. One of \"None\", \"inner product\", \"concat query\", \"sum query\". Defaults to \"None\". pred_embedding ( list [ str ] , default: [] ) \u2013 List of classes to use for plotting embeddings. Defaults to []. cell_emb_style ( str , default: 'cls' ) \u2013 Style of cell embedding. One of \"cls\", \"avg-pool\", \"w-pool\". Defaults to \"cls\". freeze_embeddings ( bool , default: True ) \u2013 Whether to freeze the embeddings during training. Defaults to True. label_decoders ( Optional [ Dict [ str , Dict [ int , str ]]] , default: None ) \u2013 Label decoders to use for plotting the UMAP during validations. Defaults to None. zinb ( bool , default: True ) \u2013 Whether to use Zero-Inflated Negative Binomial distribution. Defaults to True. lr ( float , default: 0.0001 ) \u2013 Learning rate. Defaults to 0.0001. optim ( str , default: 'adamW' ) \u2013 Optimizer type. Defaults to \"adamW\". weight_decay ( float , default: 0.01 ) \u2013 Weight decay for the optimizer. Defaults to 0.01. **flash_attention_kwargs ( dict , default: {} ) \u2013 Additional keyword arguments for the model. see @flashformer.py Notes for other parameters of the model that are not part of its class definition, see @trainer.trainer.py Raises: ValueError \u2013 If the expr_emb_style is not one of \"continuous\", \"binned_pos\", \"cont_pos\". Source code in scprint/model/model.py 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 def __init__ ( self , genes : list , organisms : list = [ \"NCBITaxon:9606\" ], precpt_gene_emb : Optional [ str ] = None , gene_pos_enc : Optional [ list ] = None , normalization : str = \"sum\" , d_model : int = 512 , nhead : int = 8 , attn_bias : str = \"none\" , d_hid : int = 512 , edge_dim : int = 12 , nlayers : int = 6 , expr_encoder_layers : int = 2 , layers_cls : list [ int ] = [], classes : Dict [ str , int ] = {}, labels_hierarchy : Dict [ str , Dict [ int , list [ int ]]] = {}, dropout : float = 0.2 , transformer : str = \"fast\" , expr_emb_style : str = \"continuous\" , # \"binned_pos\", \"cont_pos\" domain_spec_batchnorm : str = \"None\" , n_input_bins : int = 0 , num_batch_labels : int = 0 , mvc_decoder : str = \"None\" , pred_embedding : list [ str ] = [], cell_emb_style : str = \"cls\" , freeze_embeddings : bool = True , label_decoders : Optional [ Dict [ str , Dict [ int , str ]]] = None , zinb : bool = True , lr : float = 0.0001 , optim = \"adamW\" , # TODEL weight_decay = 0.01 , # TODEL ** flash_attention_kwargs , ): \"\"\" scPRINT transformer for single cell biology and the inference of Gene Regulatory networks Args: genes (list): List of gene names the model will work with. precpt_gene_emb (np.array, optional): Gene embeddings of size (len(genes), d_model). Should be in the same order as the genes. Defaults to None. gene_pos_enc (list, optional): Gene position encoding of the same size as genes. Provides a location value for each gene in genes. Defaults to None. d_model (int, optional): Dimension of the model. Defaults to 512. nhead (int, optional): Number of heads in the multihead attention models. Defaults to 8. d_hid (int, optional): Dimension of the feedforward network model. Defaults to 512. nlayers (int, optional): Number of layers in the transformer model. Defaults to 6. expr_encoder_layers (int, optional): Number of layers in the expression encoder. Defaults to 2. layers_cls (list[int], optional): List specifying the number of layers in the classifier. Defaults to []. classes (Dict[str, int], optional): Classes to predict with the number of classes for each. Defaults to {}. labels_hierarchy (Dict[str, Dict[int, list[int]]], optional): Class hierarchy for classes with hierarchical classes. Defaults to {}. dropout (float, optional): Dropout value. Defaults to 0.2. transformer (str, optional): Transformer type to use. One of \"linear\", \"flash\", \"flashsparse\", \"scprint\". Defaults to \"fast\". domain_spec_batchnorm (str, optional): Whether to apply domain-specific batch normalization. Defaults to \"None\". expr_emb_style (str, optional): Style of input embedding. One of \"continuous\", \"binned_pos\", \"cont_pos\". Defaults to \"continuous\". mvc_decoder (str, optional): Style of MVC decoder. One of \"None\", \"inner product\", \"concat query\", \"sum query\". Defaults to \"None\". pred_embedding (list[str], optional): List of classes to use for plotting embeddings. Defaults to []. cell_emb_style (str, optional): Style of cell embedding. One of \"cls\", \"avg-pool\", \"w-pool\". Defaults to \"cls\". freeze_embeddings (bool, optional): Whether to freeze the embeddings during training. Defaults to True. label_decoders (Optional[Dict[str, Dict[int, str]]], optional): Label decoders to use for plotting the UMAP during validations. Defaults to None. zinb (bool, optional): Whether to use Zero-Inflated Negative Binomial distribution. Defaults to True. lr (float, optional): Learning rate. Defaults to 0.0001. optim (str, optional): Optimizer type. Defaults to \"adamW\". weight_decay (float, optional): Weight decay for the optimizer. Defaults to 0.01. **flash_attention_kwargs (dict): Additional keyword arguments for the model. see @flashformer.py Notes: for other parameters of the model that are not part of its class definition, see @trainer.trainer.py Raises: ValueError: If the expr_emb_style is not one of \"continuous\", \"binned_pos\", \"cont_pos\". \"\"\" super () . __init__ () # training flags self . do_denoise = True self . noise = [ 0.6 ] self . do_cce = False self . cce_sim = 0.5 self . cce_scale = 0.002 self . do_ecs = False self . ecs_threshold = 0.3 self . ecs_scale = 0.05 self . do_mvc = False self . mvc_scale = 1.0 self . class_embd_diss_scale = 0.2 self . do_adv_cls = False self . adv_class_scale = 0.1 self . do_cls = False self . mean_attn_tot = None self . mean_attn_tot_c = 0 self . do_adv_batch = False self . run_full_forward = True self . class_scale = 0.4 self . do_next_tp = False self . do_generate = False self . mask_ratio = [] self . warmup_duration = 500 self . weight_decay = 0.01 self . optim = \"adamW\" self . fused_adam = False self . lr_reduce_patience = 1 self . lr_reduce_factor = 0.6 self . lr_reduce_monitor = \"val_loss\" self . name = \"\" self . lr = lr self . lrfinder_steps = 0 self . doplot = True self . get_attention_layer = [] self . embs = None self . pred_log_adata = True self . attn = utils . Attention ( len ( classes ) + 2 + len ( genes )) self . predict_depth_mult = 3 self . predict_mode = \"none\" self . keep_all_cls_pred = False # should be stored somehow self . d_model = d_model self . normalization = normalization self . organisms = organisms self . edge_dim = edge_dim self . attn_bias = attn_bias self . nlayers = nlayers self . gene_pos_enc = gene_pos_enc self . mvc_decoder = mvc_decoder self . domain_spec_batchnorm = domain_spec_batchnorm # need to store self . n_input_bins = n_input_bins self . transformer = transformer self . label_counts = classes self . classes = list ( classes . keys ()) self . cell_emb_style = cell_emb_style self . label_decoders = label_decoders self . pred_embedding = pred_embedding # compute tensor for mat_labels_hierarchy self . mat_labels_hierarchy = {} self . labels_hierarchy = labels_hierarchy if \"strict_loading\" in flash_attention_kwargs : flash_attention_kwargs . pop ( \"strict_loading\" ) for k , v in labels_hierarchy . items (): tens = torch . zeros (( len ( v ), classes [ k ])) for k2 , v2 in v . items (): tens [ k2 - classes [ k ], v2 ] = 1 self . mat_labels_hierarchy [ k ] = tens . to ( bool ) self . expr_emb_style = expr_emb_style if self . expr_emb_style not in [ \"category\" , \"continuous\" , \"none\" ]: raise ValueError ( f \"expr_emb_style should be one of category, continuous, scaling, \" f \"got { expr_emb_style } \" ) if cell_emb_style not in [ \"cls\" , \"avg-pool\" , \"w-pool\" ]: raise ValueError ( f \"Unknown cell_emb_style: { cell_emb_style } \" ) self . genes = genes self . vocab = { i : n for i , n in enumerate ( genes )} # encoder # gene encoder if precpt_gene_emb is not None : embeddings = pd . read_parquet ( precpt_gene_emb ) . loc [ self . genes ] if len ( embeddings ) == 0 : raise ValueError ( f \"the gene embeddings file { precpt_gene_emb } does not contain any of the genes given to the model\" ) elif len ( embeddings ) < len ( self . genes ): print ( \"Warning: only a subset of the genes available in the embeddings file.\" ) print ( \"number of genes: \" , len ( embeddings )) sembeddings = torch . nn . AdaptiveAvgPool1d ( d_model )( torch . tensor ( embeddings . values ) ) self . gene_encoder = encoders . GeneEncoder ( len ( self . vocab ), d_model , weights = sembeddings , freeze = freeze_embeddings ) else : self . gene_encoder = encoders . GeneEncoder ( len ( self . vocab ), d_model ) # Value Encoder, NOTE: the scaling style is also handled in _encode method if expr_emb_style in [ \"continuous\" , \"full_pos\" ]: self . expr_encoder = encoders . ContinuousValueEncoder ( d_model , dropout , layers = expr_encoder_layers ) elif expr_emb_style == \"binned_pos\" : assert n_input_bins > 0 self . expr_encoder = encoders . CategoryValueEncoder ( n_input_bins , d_model ) else : self . expr_encoder = torch . nn . Identity () # Positional Encoding if self . gene_pos_enc is not None : max_len = max ( gene_pos_enc ) token_to_pos = { token : pos for token , pos in enumerate ( self . gene_pos_enc )} self . pos_encoder = encoders . PositionalEncoding ( d_model , max_len = max_len , token_to_pos = token_to_pos ) self . cell_embs_count = len ( self . classes ) + 2 # Class Encoder # always have [base_cell_emb, time_embedding, depth_embedding] + any other class info # base cell embedding will store other cell specific information self . class_encoder = encoders . CategoryValueEncoder ( self . cell_embs_count - 1 , d_model ) # self.time_encoder = encoders.ContinuousValueEncoder(d_model, dropout) self . depth_encoder = encoders . ContinuousValueEncoder ( d_model , dropout , layers = expr_encoder_layers ) # Transformer # Linear if transformer == \"linear\" : # linear transformer using the fast transformer package # self.transformer = FastTransformerEncoder( # d_model, nhead, d_hid, nlayers, dropout, \"linear\" # ) raise NotImplementedError ( \"Linear transformer is not implemented\" ) # regular or flash else : self . transformer = FlashTransformerEncoder ( d_model , nhead , nlayers , dropout = dropout , use_flash_attn = ( transformer == \"flash\" ), ** flash_attention_kwargs , ) # decoders # expression self . expr_decoder = decoders . ExprDecoder ( d_model , nfirst_tokens_to_skip = self . cell_embs_count , dropout = dropout , zinb = zinb , ) # cls decoder self . cls_decoders = torch . nn . ModuleDict () # should be a very simple classifier for most things # (maybe scale with the number of classes) should be 1 layer... for clss , n_cls in classes . items (): self . cls_decoders [ clss ] = decoders . ClsDecoder ( d_model , n_cls , layers = layers_cls , dropout = dropout ) # Batch effect correction via adversarial training on batch classes if num_batch_labels > 0 : self . grad_reverse_discriminator_loss = loss . AdversarialDiscriminatorLoss ( d_model , n_cls = num_batch_labels , ) else : self . grad_reverse_discriminator_loss = None # expression decoder from batch embbedding if mvc_decoder != \"None\" : self . mvc_decoder = decoders . MVCDecoder ( d_model , arch_style = mvc_decoder , ) else : self . mvc_decoder = None self . apply ( partial ( utils . _init_weights , n_layer = nlayers , ) ) for i , dec in self . cls_decoders . items (): torch . nn . init . constant_ ( dec . out_layer . bias , - 0.13 ) self . save_hyperparameters () configure_optimizers @see pl.LightningModule Source code in scprint/model/model.py 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 def configure_optimizers ( self ): \"\"\"@see pl.LightningModule\"\"\" # https://pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam # not working because of poor weight decay implem if self . optim == \"adam\" : optimizer = optim . Adam ( self . parameters (), lr = self . hparams . lr , betas = ( 0.9 , 0.999 ), eps = 1e-08 , weight_decay = self . weight_decay , amsgrad = False , fused = self . fused_adam , ) elif self . optim == \"adamW\" : optimizer = optim . AdamW ( self . parameters (), lr = self . hparams . lr , betas = ( 0.9 , 0.999 ), eps = 1e-08 , weight_decay = self . weight_decay , amsgrad = False , fused = self . fused_adam , ) elif self . optim == \"galore\" : raise NotImplementedError ( \"Galore optimizer not implemented\" ) param_groups = [ { \"params\" : [ v for k , v in self . named_parameters () if \"transformer\" not in k ] }, { \"params\" : [ v for k , v in self . named_parameters () if \"transformer\" in k ], \"rank\" : 128 , \"update_proj_gap\" : 200 , \"scale\" : 0.25 , \"proj_type\" : \"std\" , }, ] # optimizer = GaLoreAdamW(param_groups, lr=self.hparams.lr) else : raise ValueError ( f \"Unknown optimizer: { self . optim } \" ) lr_scheduler = optim . lr_scheduler . ReduceLROnPlateau ( optimizer , mode = \"min\" , patience = self . lr_reduce_patience , factor = self . lr_reduce_factor , verbose = True , ) lr_dict = { \"scheduler\" : lr_scheduler , # The unit of the scheduler's step size, could also be 'step'. # 'epoch' updates the scheduler on epoch end whereas 'step' # updates it after a optimizer update. \"interval\" : \"epoch\" , # How many epochs/steps should pass between calls to # `scheduler.step()`. 1 corresponds to updating the learning # rate after every epoch/step. \"frequency\" : 1 , # Metric to to monitor for schedulers like `ReduceLROnPlateau` \"monitor\" : self . lr_reduce_monitor , } self . lrfinder_steps = 0 for val in self . trainer . callbacks : if type ( val ) is _LRCallback : self . lrfinder_steps = val . num_training if type ( val ) is LearningRateFinder : self . lrfinder_steps = val . _num_training_steps return [ optimizer ], [ lr_dict ] forward forward also called on self(), a full forward pass on the model Parameters: gene_pos ( Tensor ) \u2013 A tensor of shape (minibatch, seq_len) representing the genes used for each cell in the minibatch. expression ( Tensor , default: None ) \u2013 A tensor of shape (minibatch, seq_len) representing the expression levels of genes in the minibatch. Defaults to None. mask ( Tensor , default: None ) \u2013 A tensor of shape (minibatch, seq_len) used to mask certain elements in the sequence during the forward pass. Defaults to None. full_depth ( Tensor , default: None ) \u2013 A tensor of shape (minibatch,) representing the full depth of each sequence in the minibatch. Defaults to None. timepoint ( Tensor , default: None ) \u2013 A tensor of shape (minibatch,) representing the timepoint associated with each sequence in the minibatch. Defaults to None. get_gene_emb ( bool , default: False ) \u2013 A flag indicating whether to return the gene embeddings. If True, the gene embeddings are included in the output. Defaults to False. do_sample ( bool , default: False ) \u2013 A flag indicating whether to sample the expression levels. If True, the expression levels are sampled during the forward pass. Defaults to False. get_attention_layer ( list , default: [] ) \u2013 A list indicating which attention layers to return. If not empty, the specified attention layers are included in the output. Defaults to []. Returns: \u2013 dict of output Tensors: A dictionary containing the output tensors from the forward pass. The keys of the dictionary depend on the input flags (get_gene_emb, do_sample, get_attention_layer). at minima, the dictionary codntains the following: - \"mean\": the mean expression levels - \"zero_logits\": the logits for zero-inflated expression levels - \"disp\": the dispersion parameter - \"cell_embs\": the cell embeddings per class - \"cell_emb\": the main cell embedding - \"cls_output\": the output of the classifier Source code in scprint/model/model.py 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 def forward ( self , gene_pos : Tensor , expression : Optional [ Tensor ] = None , mask : Optional [ Tensor ] = None , full_depth : Optional [ Tensor ] = None , timepoint : Optional [ Tensor ] = None , # (new_minibatch_of_nxt_cells,) get_gene_emb : bool = False , depth_mult : Optional [ Tensor ] = None , do_sample : bool = False , do_mvc : bool = False , do_class : bool = False , get_attention_layer : list = [], ): \"\"\" forward also called on self(), a full forward pass on the model Args: gene_pos (Tensor): A tensor of shape (minibatch, seq_len) representing the genes used for each cell in the minibatch. expression (Tensor, optional): A tensor of shape (minibatch, seq_len) representing the expression levels of genes in the minibatch. Defaults to None. mask (Tensor, optional): A tensor of shape (minibatch, seq_len) used to mask certain elements in the sequence during the forward pass. Defaults to None. full_depth (Tensor, optional): A tensor of shape (minibatch,) representing the full depth of each sequence in the minibatch. Defaults to None. timepoint (Tensor, optional): A tensor of shape (minibatch,) representing the timepoint associated with each sequence in the minibatch. Defaults to None. get_gene_emb (bool, optional): A flag indicating whether to return the gene embeddings. If True, the gene embeddings are included in the output. Defaults to False. do_sample (bool, optional): A flag indicating whether to sample the expression levels. If True, the expression levels are sampled during the forward pass. Defaults to False. get_attention_layer (list, optional): A list indicating which attention layers to return. If not empty, the specified attention layers are included in the output. Defaults to []. Returns: dict of output Tensors: A dictionary containing the output tensors from the forward pass. The keys of the dictionary depend on the input flags (get_gene_emb, do_sample, get_attention_layer). at minima, the dictionary codntains the following: - \"mean\": the mean expression levels - \"zero_logits\": the logits for zero-inflated expression levels - \"disp\": the dispersion parameter - \"cell_embs\": the cell embeddings per class - \"cell_emb\": the main cell embedding - \"cls_output\": the output of the classifier \"\"\" encoding = self . _encoder ( gene_pos , expression , mask , full_depth , timepoint ) if self . attn_bias != \"none\" : if not hasattr ( self , \"nbias\" ): self . nbias = torch . Tensor ( load_npz ( FILEDIR + \"/../../data/bias_sparse.npz\" ) . todense () ) . to ( device = gene_pos . device , dtype = torch . float16 ) num = len ( self . classes ) + 2 bias = torch . zeros ( ( gene_pos . shape [ 0 ], gene_pos . shape [ 1 ] + num , gene_pos . shape [ 1 ] + num , ), device = gene_pos . device , dtype = torch . float16 , ) bias [:, num :, : num ] = - 10_000 # do not pay attention to the cls embeddings bias [:, num :, num :] = self . nbias [ gene_pos [:, :, None ], gene_pos [:, None , :]] transformer_output = self . transformer ( encoding , return_qkv = get_attention_layer , bias = bias if self . attn_bias != \"none\" else None , bias_layer = list ( range ( self . nlayers - 1 )), ) depth_mult = expression . sum ( 1 ) if depth_mult is None else depth_mult if len ( get_attention_layer ) > 0 : transformer_output , qkvs = transformer_output return ( self . _decoder ( transformer_output , depth_mult , get_gene_emb , do_sample , do_mvc , do_class , ), qkvs , ) else : return self . _decoder ( transformer_output , depth_mult , get_gene_emb , do_sample , do_mvc , do_class , ) get_cell_embs get_cell_embs Parameters: layer_output ( Tensor ) \u2013 The output tensor from a layer in the model. Raises: ValueError \u2013 Raised when an unknown cell embedding style is encountered. Returns: Tensor \u2013 The cell embeddings tensor. Source code in scprint/model/model.py 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 def get_cell_embs ( self , layer_output ): \"\"\" get_cell_embs Args: layer_output (Tensor): The output tensor from a layer in the model. Raises: ValueError: Raised when an unknown cell embedding style is encountered. Returns: Tensor: The cell embeddings tensor. \"\"\" if self . cell_emb_style == \"cls\" and self . classes is not None : # (minibatch, embsize) cell_emb = layer_output [:, : 2 + len ( self . classes )] elif self . cell_emb_style == \"avg-pool\" : cell_emb = torch . mean ( layer_output , dim = 1 ) else : raise ValueError ( f \"Unknown cell_emb_style: { self . cell_emb_style } \" ) return cell_emb log_adata log_adata will log an adata from predictions. It will log to tensorboard and wandb if available see @utils.log_adata Source code in scprint/model/model.py 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 def log_adata ( self , gtclass = None , name = \"\" ): \"\"\" log_adata will log an adata from predictions. It will log to tensorboard and wandb if available see @utils.log_adata \"\"\" try : mdir = self . logger . save_dir if self . logger . save_dir is not None else \"/tmp\" except : mdir = \"data/\" if not os . path . exists ( mdir ): os . makedirs ( mdir ) adata , fig = utils . make_adata ( self . embs , self . classes , self . pred if not self . keep_all_cls_pred else None , self . attn . get (), self . global_step , self . label_decoders , self . labels_hierarchy , gtclass , self . name + \"_\" + name + \"_\" + str ( self . global_rank ), mdir , self . doplot , ) if self . doplot : try : self . logger . experiment . add_figure ( fig ) except : print ( \"couldn't log to tensorboard\" ) try : self . logger . log_image ( key = \"umaps\" , images = [ fig ]) except : print ( \"couldn't log to wandb\" ) return adata on_fit_start @see pl.LightningModule Source code in scprint/model/model.py 641 642 643 644 645 646 647 def on_fit_start ( self ): \"\"\"@see pl.LightningModule\"\"\" if type ( self . transformer ) is FlashTransformerEncoder : for encoder_layers in self . transformer . blocks : encoder_layers . set_seq_parallel ( True ) for k , v in self . mat_labels_hierarchy . items (): self . mat_labels_hierarchy [ k ] = v . to ( self . device ) on_predict_epoch_end @see pl.LightningModule will Source code in scprint/model/model.py 1325 1326 1327 1328 1329 1330 1331 def on_predict_epoch_end ( self ): \"\"\"@see pl.LightningModule will\"\"\" if self . pos . shape [ 0 ] < 100 : return if self . pred_log_adata : print ( \"adding on disk\" ) return self . log_adata ( name = \"predict_part_\" + str ( self . counter )) on_predict_epoch_start @see pl.LightningModule Source code in scprint/model/model.py 1126 1127 1128 1129 1130 1131 1132 1133 1134 def on_predict_epoch_start ( self ): \"\"\"@see pl.LightningModule\"\"\" self . embs = None self . attn . data = None self . attn . attn = None self . counter = 0 if type ( self . transformer ) is FlashTransformerEncoder : for encoder_layers in self . transformer . blocks : encoder_layers . set_seq_parallel ( False ) on_validation_epoch_end @see pl.LightningModule Source code in scprint/model/model.py 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 def on_validation_epoch_end ( self ): \"\"\"@see pl.LightningModule\"\"\" self . embs = self . all_gather ( self . embs ) . view ( - 1 , self . embs . shape [ - 1 ]) self . info = self . all_gather ( self . info ) . view ( - 1 , self . info . shape [ - 1 ]) self . pred = ( self . all_gather ( self . pred ) . view ( - 1 , self . pred . shape [ - 1 ]) if self . pred is not None else None ) self . pos = self . all_gather ( self . pos ) . view ( - 1 , self . pos . shape [ - 1 ]) if not self . trainer . is_global_zero : # print(\"you are not on the main node. cancelling logging step\") return if self . trainer . state . stage != \"sanity_check\" : sch = self . lr_schedulers () sch . step ( self . trainer . callback_metrics [ \"val_loss\" ]) # run the test function on specific dataset self . log_adata ( gtclass = self . info , name = \"validation_part_\" + str ( self . counter ) ) if ( self . current_epoch + 1 ) % 30 == 0 : self . on_test_epoch_end () optimizer_step @see pl.LightningModule Source code in scprint/model/model.py 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 def optimizer_step ( self , epoch , batch_idx , optimizer , optimizer_closure ): \"\"\"@see pl.LightningModule\"\"\" # update params optimizer . step ( closure = optimizer_closure ) # manually warm up lr without a scheduler # making sure that we don't do this during lrfinder for i , pg in enumerate ( optimizer . param_groups ): if ( self . global_step < self . warmup_duration + self . lrfinder_steps ) and self . lrfinder_steps < self . global_step : lr_scale = min ( 1.0 , float ( self . global_step + 1 ) / self . warmup_duration ) pg [ \"lr\" ] = lr_scale * self . hparams . lr for i , pg in enumerate ( optimizer . param_groups ): # if pg[\"lr\"] < 2e-5: # pg[\"lr\"] = 2e-5 self . log ( \"lr_\" + str ( i ), pg [ \"lr\" ]) predict_step embed given gene expression, encode the gene embedding and cell embedding. Returns: Tensor \u2013 description Source code in scprint/model/model.py 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 def predict_step ( self , batch , batch_idx ): \"\"\" embed given gene expression, encode the gene embedding and cell embedding. Args: batch @see training_step Returns: Tensor: _description_ \"\"\" return self . _predict ( batch [ \"genes\" ], batch [ \"x\" ], batch [ \"depth\" ], self . predict_mode , self . pred_embedding , self . get_attention_layer , self . predict_depth_mult , ) training_step training_step defines the train loop. It is independent of forward @see pl.LightningModule Returns: _type_ \u2013 description Source code in scprint/model/model.py 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 def training_step ( self , batch : Dict [ str , Tensor ], batch_idx , ): \"\"\" training_step defines the train loop. It is independent of forward @see pl.LightningModule Returns: _type_: _description_ \"\"\" # TASK 1 & 2 & 3 (first pass, expression reconstruction, label prediction) total_loss , losses = self . _full_training ( batch = batch , do_denoise = self . do_denoise , noise = self . noise , do_next_tp = self . do_next_tp , do_cce = self . do_cce , cce_sim = self . cce_sim , do_ecs = self . do_ecs , do_mvc = self . do_mvc , do_adv_cls = self . do_adv_cls , do_adv_batch = self . do_adv_batch , do_cls = self . do_cls , do_generate = self . do_generate , run_full_forward = self . run_full_forward , mask_ratio = self . mask_ratio , ) self . log ( \"train_loss\" , total_loss , prog_bar = True , sync_dist = True ) self . log_dict ( losses , prog_bar = True , sync_dist = True ) return total_loss validation_step validation_step defines the validation loop. It is independent of forward @see pl.LightningModule Parameters: batch ( list [ Tensor ] ) \u2013 @see training_step Source code in scprint/model/model.py 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 def validation_step ( self , batch , batch_idx , ): \"\"\" validation_step defines the validation loop. It is independent of forward @see pl.LightningModule Args: batch (list[Tensor]): @see training_step \"\"\" val_loss , losses = self . _full_training ( batch = batch , do_denoise = self . do_denoise , noise = self . noise , do_next_tp = self . do_next_tp , do_cce = self . do_cce , cce_sim = self . cce_sim , do_ecs = self . do_ecs , do_mvc = self . do_mvc , do_adv_cls = self . do_adv_cls , do_adv_batch = self . do_adv_batch , do_cls = self . do_cls , do_generate = self . do_generate , run_full_forward = self . run_full_forward , mask_ratio = self . mask_ratio , ) expression = batch [ \"x\" ] gene_pos = batch [ \"genes\" ] depth = batch [ \"depth\" ] # TODO: make this faster by only calling val loss if self . embs is not None : if self . embs . shape [ 0 ] < 100_000 : self . info = torch . cat ([ self . info , batch [ \"class\" ]]) self . _predict ( gene_pos , expression , depth , pred_embedding = self . pred_embedding , max_size_in_mem = 100_000 , ) else : self . info = batch [ \"class\" ] self . _predict ( gene_pos , expression , depth , pred_embedding = self . pred_embedding , max_size_in_mem = 100_000 , ) self . log ( \"val_loss\" , val_loss , sync_dist = True ) self . log_dict ( losses , sync_dist = True ) return val_loss losses scprint.model.loss AdversarialDiscriminatorLoss Bases: Module Discriminator for the adversarial training for batch correction. Parameters: d_model ( int ) \u2013 The size of the input tensor. n_cls ( int ) \u2013 The number of classes. nlayers ( int , default: 3 ) \u2013 The number of layers in the discriminator. Defaults to 3. activation ( callable , default: LeakyReLU ) \u2013 The activation function. Defaults to nn.LeakyReLU. reverse_grad ( bool , default: True ) \u2013 Whether to reverse the gradient. Defaults Source code in scprint/model/loss.py 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 def __init__ ( self , d_model : int , n_cls : int , nlayers : int = 3 , activation : callable = nn . LeakyReLU , reverse_grad : bool = True , ): \"\"\" Discriminator for the adversarial training for batch correction. Args: d_model (int): The size of the input tensor. n_cls (int): The number of classes. nlayers (int, optional): The number of layers in the discriminator. Defaults to 3. activation (callable, optional): The activation function. Defaults to nn.LeakyReLU. reverse_grad (bool, optional): Whether to reverse the gradient. Defaults \"\"\" super () . __init__ () # module list self . decoder = nn . ModuleList () for _ in range ( nlayers - 1 ): self . decoder . append ( nn . Linear ( d_model , d_model )) self . decoder . append ( nn . LayerNorm ( d_model )) self . decoder . append ( activation ()) self . out_layer = nn . Linear ( d_model , n_cls ) self . reverse_grad = reverse_grad forward Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, embsize] Source code in scprint/model/loss.py 302 303 304 305 306 307 308 309 310 311 312 def forward ( self , x : Tensor , batch_labels : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, embsize] \"\"\" if self . reverse_grad : x = grad_reverse ( x , lambd = 1.0 ) for layer in self . decoder : x = layer ( x ) x = self . out_layer ( x ) return F . cross_entropy ( x , batch_labels ) classification Computes the classification loss for a given batch of predictions and ground truth labels. Parameters: clsname ( str ) \u2013 The name of the label. pred ( Tensor ) \u2013 The predicted logits for the batch. cl ( Tensor ) \u2013 The ground truth labels for the batch. maxsize ( int ) \u2013 The number of possible labels. labels_hierarchy ( dict , default: {} ) \u2013 The hierarchical structure of the labels. Defaults to {}. Raises: ValueError \u2013 If the clsname is not found in the labels_hierarchy dictionary. Returns: Tensor ( Tensor ) \u2013 The computed binary cross entropy loss for the given batch. Source code in scprint/model/loss.py 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 def classification ( clsname : str , pred : torch . Tensor , cl : torch . Tensor , maxsize : int , labels_hierarchy : Optional [ Dict [ str , Dict [ int , list [ int ]]]] = {}, ) -> torch . Tensor : \"\"\" Computes the classification loss for a given batch of predictions and ground truth labels. Args: clsname (str): The name of the label. pred (Tensor): The predicted logits for the batch. cl (Tensor): The ground truth labels for the batch. maxsize (int): The number of possible labels. labels_hierarchy (dict, optional): The hierarchical structure of the labels. Defaults to {}. Raises: ValueError: If the clsname is not found in the labels_hierarchy dictionary. Returns: Tensor: The computed binary cross entropy loss for the given batch. \"\"\" newcl = torch . zeros ( ( cl . shape [ 0 ], maxsize ), device = cl . device ) # batchsize * n_labels # if we don't know the label we set the weight to 0 else to 1 valid_indices = ( cl != - 1 ) & ( cl < maxsize ) valid_cl = cl [ valid_indices ] newcl [ valid_indices , valid_cl ] = 1 weight = torch . ones_like ( newcl , device = cl . device ) weight [ cl == - 1 , :] = 0 inv = cl >= maxsize # if we have non leaf values, we don't know so we don't compute grad and set weight to 0 # and add labels that won't be counted but so that we can still use them if inv . any (): if clsname in labels_hierarchy . keys (): clhier = labels_hierarchy [ clsname ] inv_weight = weight [ inv ] # we set the weight of the elements that are not leaf to 0 # i.e. the elements where we will compute the max inv_weight [ clhier [ cl [ inv ] - maxsize ]] = 0 weight [ inv ] = inv_weight addnewcl = torch . ones ( weight . shape [ 0 ], device = pred . device ) # no need to set the other to 0 as the weight of the loss is set to 0 addweight = torch . zeros ( weight . shape [ 0 ], device = pred . device ) addweight [ inv ] = 1 # computing hierarchical labels and adding them to cl addpred = pred . clone () # we only keep the elements where we need to compute the max, # for the rest we set them to -inf, so that they won't have any impact on the max() inv_addpred = addpred [ inv ] inv_addpred [ inv_weight . to ( bool )] = torch . finfo ( pred . dtype ) . min addpred [ inv ] = inv_addpred # differentiable max addpred = torch . logsumexp ( addpred , dim =- 1 ) # we add the new labels to the cl newcl = torch . cat ([ newcl , addnewcl . unsqueeze ( 1 )], dim = 1 ) pred = torch . cat ([ pred , addpred . unsqueeze ( 1 )], dim = 1 ) weight = torch . cat ([ weight , addweight . unsqueeze ( 1 )], dim = 1 ) else : raise ValueError ( \"need to use labels_hierarchy for this usecase\" ) myloss = torch . nn . functional . binary_cross_entropy_with_logits ( pred , target = newcl , weight = weight ) return myloss criterion_neg_log_bernoulli Compute the negative log-likelihood of Bernoulli distribution Source code in scprint/model/loss.py 143 144 145 146 147 148 149 150 def criterion_neg_log_bernoulli ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the negative log-likelihood of Bernoulli distribution \"\"\" mask = mask . float () bernoulli = torch . distributions . Bernoulli ( probs = input ) masked_log_probs = bernoulli . log_prob (( target > 0 ) . float ()) * mask return - masked_log_probs . sum () / mask . sum () ecs ecs Computes the similarity of cell embeddings based on a threshold. Parameters: cell_emb ( Tensor ) \u2013 A tensor representing cell embeddings. ecs_threshold ( float , default: 0.5 ) \u2013 A threshold for determining similarity. Defaults to 0.5. Returns: Tensor ( Tensor ) \u2013 A tensor representing the mean of 1 minus the square of the difference between the cosine similarity and the threshold. Source code in scprint/model/loss.py 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 def ecs ( cell_emb : Tensor , ecs_threshold : float = 0.5 ) -> Tensor : \"\"\" ecs Computes the similarity of cell embeddings based on a threshold. Args: cell_emb (Tensor): A tensor representing cell embeddings. ecs_threshold (float, optional): A threshold for determining similarity. Defaults to 0.5. Returns: Tensor: A tensor representing the mean of 1 minus the square of the difference between the cosine similarity and the threshold. \"\"\" # Here using customized cosine similarity instead of F.cosine_similarity # to avoid the pytorch issue of similarity larger than 1.0, pytorch # 78064 # normalize the embedding cell_emb_normed = F . normalize ( cell_emb , p = 2 , dim = 1 ) cos_sim = torch . mm ( cell_emb_normed , cell_emb_normed . t ()) # mask out diagnal elements mask = torch . eye ( cos_sim . size ( 0 )) . bool () . to ( cos_sim . device ) cos_sim = cos_sim . masked_fill ( mask , 0.0 ) # only optimize positive similarities cos_sim = F . relu ( cos_sim ) return torch . mean ( 1 - ( cos_sim - ecs_threshold ) ** 2 ) grad_reverse grad_reverse Reverses the gradient of the input tensor. Parameters: x ( Tensor ) \u2013 The input tensor whose gradient is to be reversed. lambd ( float , default: 1.0 ) \u2013 The scaling factor for the reversed gradient. Defaults to 1.0. Returns: Tensor ( Tensor ) \u2013 The input tensor with its gradient reversed during the backward pass. Source code in scprint/model/loss.py 326 327 328 329 330 331 332 333 334 335 336 337 def grad_reverse ( x : Tensor , lambd : float = 1.0 ) -> Tensor : \"\"\" grad_reverse Reverses the gradient of the input tensor. Args: x (Tensor): The input tensor whose gradient is to be reversed. lambd (float, optional): The scaling factor for the reversed gradient. Defaults to 1.0. Returns: Tensor: The input tensor with its gradient reversed during the backward pass. \"\"\" return GradReverse . apply ( x , lambd ) masked_mae Compute the masked MAE loss between input and target. MAE = mean absolute error Source code in scprint/model/loss.py 29 30 31 32 33 34 35 36 def masked_mae ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked MAE loss between input and target. MAE = mean absolute error \"\"\" mask = mask . float () loss = F . l1_loss ( input * mask , target * mask , reduction = \"sum\" ) return loss / mask . sum () masked_mse Compute the masked MSE loss between input and target. Source code in scprint/model/loss.py 20 21 22 23 24 25 26 def masked_mse ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked MSE loss between input and target. \"\"\" mask = mask . float () loss = F . mse_loss ( input * mask , target * mask , reduction = \"sum\" ) return loss / mask . sum () masked_nb Compute the masked negative binomial loss between input and target. Source code in scprint/model/loss.py 39 40 41 42 43 44 45 46 def masked_nb ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked negative binomial loss between input and target. \"\"\" mask = mask . float () nb = torch . distributions . NegativeBinomial ( total_count = target , probs = input ) masked_log_probs = nb . log_prob ( target ) * mask return - masked_log_probs . sum () / mask . sum () masked_relative_error Compute the masked relative error between input and target. Source code in scprint/model/loss.py 153 154 155 156 157 158 159 160 161 def masked_relative_error ( input : Tensor , target : Tensor , mask : torch . LongTensor ) -> Tensor : \"\"\" Compute the masked relative error between input and target. \"\"\" assert mask . any () loss = torch . abs ( input [ mask ] - target [ mask ]) / ( target [ mask ] + 1e-6 ) return loss . mean () mse Compute the MSE loss between input and target. Source code in scprint/model/loss.py 9 10 11 12 13 14 15 16 17 def mse ( input : Tensor , target : Tensor ) -> Tensor : \"\"\" Compute the MSE loss between input and target. \"\"\" input = torch . log2 ( input + 1 ) input = ( input / torch . sum ( input , dim = 1 , keepdim = True )) * 10000 target = torch . log2 ( target + 1 ) target = target / torch . sum ( target , dim = 1 , keepdim = True ) * 10000 return F . mse_loss ( input , target , reduction = \"mean\" ) nb Computes the negative binomial (NB) loss. This function was adapted from scvi-tools. Parameters: target ( Tensor ) \u2013 Ground truth data. mu ( Tensor ) \u2013 Means of the negative binomial distribution (must have positive support). theta ( Tensor ) \u2013 Inverse dispersion parameter (must have positive support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 NB loss value. Source code in scprint/model/loss.py 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 def nb ( target : Tensor , mu : Tensor , theta : Tensor , eps = 1e-8 ): \"\"\" Computes the negative binomial (NB) loss. This function was adapted from scvi-tools. Args: target (Tensor): Ground truth data. mu (Tensor): Means of the negative binomial distribution (must have positive support). theta (Tensor): Inverse dispersion parameter (must have positive support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: NB loss value. \"\"\" if theta . ndimension () == 1 : theta = theta . view ( 1 , theta . size ( 0 )) log_theta_mu_eps = torch . log ( theta + mu + eps ) res = ( theta * ( torch . log ( theta + eps ) - log_theta_mu_eps ) + target * ( torch . log ( mu + eps ) - log_theta_mu_eps ) + torch . lgamma ( target + theta ) - torch . lgamma ( theta ) - torch . lgamma ( target + 1 ) ) return - res . mean () nb_dist nb_dist Computes the negative binomial distribution. Parameters: x ( Tensor ) \u2013 Torch Tensor of observed data. mu ( Tensor ) \u2013 Torch Tensor of means of the negative binomial distribution (must have positive support). theta ( Tensor ) \u2013 Torch Tensor of inverse dispersion parameter (must have positive support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 Negative binomial loss value. Source code in scprint/model/loss.py 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 def nb_dist ( x : Tensor , mu : Tensor , theta : Tensor , eps = 1e-8 ): \"\"\" nb_dist Computes the negative binomial distribution. Args: x (Tensor): Torch Tensor of observed data. mu (Tensor): Torch Tensor of means of the negative binomial distribution (must have positive support). theta (Tensor): Torch Tensor of inverse dispersion parameter (must have positive support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: Negative binomial loss value. \"\"\" loss = - NegativeBinomial ( mu = mu , theta = theta ) . log_prob ( x ) return loss similarity Dot product or cosine similarity Source code in scprint/model/loss.py 164 165 166 167 168 169 170 def similarity ( x : Tensor , y : Tensor , temp : float ) -> Tensor : \"\"\" Dot product or cosine similarity \"\"\" res = F . cosine_similarity ( x . unsqueeze ( 1 ), y . unsqueeze ( 0 )) / temp labels = torch . arange ( res . size ( 0 )) . long () . to ( device = res . device ) return F . cross_entropy ( res , labels ) zinb Computes zero-inflated negative binomial (ZINB) loss. This function was modified from scvi-tools. Parameters: target ( Tensor ) \u2013 Torch Tensor of ground truth data. mu ( Tensor ) \u2013 Torch Tensor of means of the negative binomial (must have positive support). theta ( Tensor ) \u2013 Torch Tensor of inverse dispersion parameter (must have positive support). pi ( Tensor ) \u2013 Torch Tensor of logits of the dropout parameter (real support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 ZINB loss value. Source code in scprint/model/loss.py 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 def zinb ( target : Tensor , mu : Tensor , theta : Tensor , pi : Tensor , eps = 1e-8 , ): \"\"\" Computes zero-inflated negative binomial (ZINB) loss. This function was modified from scvi-tools. Args: target (Tensor): Torch Tensor of ground truth data. mu (Tensor): Torch Tensor of means of the negative binomial (must have positive support). theta (Tensor): Torch Tensor of inverse dispersion parameter (must have positive support). pi (Tensor): Torch Tensor of logits of the dropout parameter (real support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: ZINB loss value. \"\"\" # uses log(sigmoid(x)) = -softplus(-x) softplus_pi = F . softplus ( - pi ) # eps to make it positive support and taking the log log_theta_mu_eps = torch . log ( theta + mu + eps ) pi_theta_log = - pi + theta * ( torch . log ( theta + eps ) - log_theta_mu_eps ) case_zero = F . softplus ( pi_theta_log ) - softplus_pi mul_case_zero = torch . mul (( target < eps ) . type ( torch . float32 ), case_zero ) case_non_zero = ( - softplus_pi + pi_theta_log + target * ( torch . log ( mu + eps ) - log_theta_mu_eps ) + torch . lgamma ( target + theta ) - torch . lgamma ( theta ) - torch . lgamma ( target + 1 ) ) mul_case_non_zero = torch . mul (( target > eps ) . type ( torch . float32 ), case_non_zero ) res = mul_case_zero + mul_case_non_zero # we want to minize the loss but maximize the log likelyhood return - res . mean () utils scprint.model.utils Attention Initialize the Attention class. Parameters: gene_dim ( int ) \u2013 The dimension of the gene. comp_attn ( bool , default: False ) \u2013 Whether to compute attention. Defaults to False. Source code in scprint/model/utils.py 472 473 474 475 476 477 478 479 480 481 482 483 484 def __init__ ( self , gene_dim : int , comp_attn : bool = False ): \"\"\" Initialize the Attention class. Args: gene_dim (int): The dimension of the gene. comp_attn (bool, optional): Whether to compute attention. Defaults to False. \"\"\" self . data : Optional [ Tensor ] = None self . gene_dim : int = gene_dim self . div : Optional [ Tensor ] = None self . attn : Optional [ Tensor ] = None self . comp_attn : bool = comp_attn add Add data to the internal storage. Parameters: x ( List [ Tensor ] ) \u2013 List of tensors to add. pos ( Tensor ) \u2013 Position tensor. Source code in scprint/model/utils.py 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 def add ( self , x : List [ Tensor ], pos : Tensor ) -> None : \"\"\" Add data to the internal storage. Args: x (List[Tensor]): List of tensors to add. pos (Tensor): Position tensor. \"\"\" pos = pos . detach () . to ( \"cpu\" ) if self . data is None : self . data = torch . zeros ([ len ( x ), self . gene_dim ] + list ( x [ 0 ] . shape [ 2 :])) self . div = torch . zeros ( self . gene_dim ) for i in range ( x [ 0 ] . shape [ 0 ]): # loc = torch.cat([torch.Tensor([r for r in range(8)]), pos[i] + 8]).int() self . data . append ( torch . cat ([ x [ j ][ i ] . detach () . to ( \"cpu\" ) for j in range ( len ( x ))]) ) agg Aggregate the attention or data based on the comp_attn flag. Parameters: x ( List [ Tensor ] ) \u2013 List of tensors to aggregate. pos ( Tensor ) \u2013 Position tensor. Source code in scprint/model/utils.py 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 def agg ( self , x : List [ Tensor ], pos : Tensor ) -> None : \"\"\" Aggregate the attention or data based on the comp_attn flag. Args: x (List[Tensor]): List of tensors to aggregate. pos (Tensor): Position tensor. \"\"\" if self . comp_attn : if self . attn is None : self . attn = torch . zeros ([ self . gene_dim , self . gene_dim ], device = \"cuda\" ) self . div = torch . zeros ( self . gene_dim , device = \"cuda\" ) for j in range ( x [ 0 ] . shape [ 0 ]): # \u2022cells, \u2022context, \u2022QK, \u2022heads, \u2022dim loc = torch . cat ([ torch . arange ( 8 , device = \"cuda\" ), pos [ j ] + 8 ]) . int () for i in range ( len ( x )): for k in range ( x [ 0 ] . shape [ 3 ]): self . attn [ loc [:, None ], loc ] += torch . nn . functional . softmax ( ( x [ i ][ j , :, 0 , k , :] @ x [ i ][ j , :, 1 , k , :] . T ) * ( x [ 0 ] . shape [ - 1 ] ** - 0.5 ), dim =- 1 , ) self . div [ loc ] += x [ 0 ] . shape [ 3 ] * len ( x ) torch . cuda . empty_cache () else : pos = pos . detach () . to ( \"cpu\" ) if self . data is None : self . data = torch . zeros ([ len ( x ), self . gene_dim ] + list ( x [ 0 ] . shape [ 2 :])) self . div = torch . zeros ( self . gene_dim ) for i in range ( x [ 0 ] . shape [ 0 ]): loc = torch . cat ([ torch . arange ( 8 ), pos [ i ] + 8 ]) . int () for j in range ( len ( x )): self . data [ j , loc , :, :, :] += x [ j ][ i ] . detach () . to ( \"cpu\" ) self . div [ loc ] += 1 get Get the aggregated attention or data. Returns: Optional [ ndarray ] \u2013 Optional[np.ndarray]: The aggregated attention or data. Source code in scprint/model/utils.py 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 def get ( self ) -> Optional [ np . ndarray ]: \"\"\" Get the aggregated attention or data. Returns: Optional[np.ndarray]: The aggregated attention or data. \"\"\" if self . comp_attn : loc = self . attn . sum ( 1 ) != 0 return ( ( self . attn [ loc ][:, loc ] / ( self . attn . sum ( 1 )[ loc ] + 0.0001 )) . detach () . cpu () . numpy () ) else : if self . data is None : return None # shape is (layers, genes, qkv, heads, emb) return self . data / self . div . view ( 1 , self . div . shape [ 0 ], 1 , 1 , 1 ) downsample_profile This function downsamples the expression profile of a given single cell RNA matrix. The noise is applied based on the renoise parameter, the total counts of the matrix, and the number of genes. The function first calculates the noise threshold (scaler) based on the renoise parameter. It then generates an initial matrix count by applying a Poisson distribution to a random tensor scaled by the total counts and the number of genes. The function then models the sampling zeros by applying a Poisson distribution to a random tensor scaled by the noise threshold, the total counts, and the number of genes. The function also models the technical zeros by generating a random tensor and comparing it to the noise threshold. The final matrix count is calculated by subtracting the sampling zeros from the initial matrix count and multiplying by the technical zeros. The function ensures that the final matrix count is not less than zero by taking the maximum of the final matrix count and a tensor of zeros. The function returns the final matrix count. Parameters: mat ( Tensor ) \u2013 The input matrix. dropout ( float ) \u2013 The renoise parameter. Returns: \u2013 torch.Tensor: The matrix count after applying noise. Source code in scprint/model/utils.py 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 def downsample_profile ( mat : Tensor , dropout : float , method = \"new\" ): \"\"\" This function downsamples the expression profile of a given single cell RNA matrix. The noise is applied based on the renoise parameter, the total counts of the matrix, and the number of genes. The function first calculates the noise threshold (scaler) based on the renoise parameter. It then generates an initial matrix count by applying a Poisson distribution to a random tensor scaled by the total counts and the number of genes. The function then models the sampling zeros by applying a Poisson distribution to a random tensor scaled by the noise threshold, the total counts, and the number of genes. The function also models the technical zeros by generating a random tensor and comparing it to the noise threshold. The final matrix count is calculated by subtracting the sampling zeros from the initial matrix count and multiplying by the technical zeros. The function ensures that the final matrix count is not less than zero by taking the maximum of the final matrix count and a tensor of zeros. The function returns the final matrix count. Args: mat (torch.Tensor): The input matrix. dropout (float): The renoise parameter. Returns: torch.Tensor: The matrix count after applying noise. \"\"\" # Randomly drop on average N counts to each element of expression using a heavy tail Gaussian distribution # here we try to get the scale of the distribution so as to remove the right number of counts from each gene # https://genomebiology.biomedcentral.com/articles/10.1186/s13059-022-02601-5#:~:text=Zero%20measurements%20in%20scRNA%2Dseq,generation%20of%20scRNA%2Dseq%20data. if method == \"old\" : totcounts = mat . sum ( 1 ) batch = mat . shape [ 0 ] ngenes = mat . shape [ 1 ] tnoise = 1 - ( 1 - dropout ) ** ( 1 / 2 ) # we model the sampling zeros (dropping 30% of the reads) res = torch . poisson ( torch . rand (( batch , ngenes )) . to ( device = mat . device ) * (( tnoise * totcounts . unsqueeze ( 1 )) / ( 0.5 * ngenes )) ) . int () # we model the technical zeros (dropping 50% of the genes) drop = ( torch . rand (( batch , ngenes )) > tnoise ) . int () . to ( device = mat . device ) mat = ( mat - res ) * drop return torch . maximum ( mat , torch . Tensor ([[ 0 ]]) . to ( device = mat . device )) . int () elif method == \"jules\" : scaler = ( 1 - dropout ) ** ( 1 / 2 ) notdrop = ( torch . rand ( mat . shape , device = mat . device , ) < scaler ) . int () notdrop [ mat == 0 ] = 0 # apply the dropout after the poisson, right? return notdrop * torch . poisson ( mat * scaler ) elif method == \"new\" : batch = mat . shape [ 0 ] ngenes = mat . shape [ 1 ] dropout = dropout * 1.1 # we model the sampling zeros (dropping 30% of the reads) res = torch . poisson (( mat * ( dropout / 2 ))) . int () # we model the technical zeros (dropping 50% of the genes) notdrop = ( torch . rand (( batch , ngenes ), device = mat . device ) >= ( dropout / 2 ) ) . int () mat = ( mat - res ) * notdrop return torch . maximum ( mat , torch . zeros (( 1 , 1 ), device = mat . device , dtype = torch . int ) ) else : raise ValueError ( f \"method { method } not recognized\" ) make_adata This function creates an AnnData object from the given input parameters. Parameters: embs ( Tensor ) \u2013 Embeddings of the cells. The shape of the tensor is (n_cells, n_features). labels ( list ) \u2013 List of labels for the predicted classes. pred ( Tensor , default: None ) \u2013 Predicted labels. The shape of the tensor is (n_cells, n_classes). Default is None. attention ( Tensor , default: None ) \u2013 Attention weights. Default is None. step ( int , default: 0 ) \u2013 Step number for storing the AnnData without overwriting others. Default is 0. label_decoders ( dict , default: None ) \u2013 Dictionary to map class codes to class names. Default is None. labels_hierarchy ( dict , default: {} ) \u2013 Dictionary representing the hierarchy of labels. Default is {}. gtclass ( Tensor , default: None ) \u2013 Ground truth class. Default is None. name ( str , default: '' ) \u2013 Name of the AnnData object. Default is an empty string. mdir ( str , default: '/tmp' ) \u2013 Directory to save the AnnData object. Default is \"/tmp\". doplot ( bool , default: True ) \u2013 Whether to generate plots. Default is True. Returns: \u2013 anndata.AnnData: The created AnnData object. Source code in scprint/model/utils.py 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 def make_adata ( embs : Tensor , labels : List [ str ], pred : Tensor = None , attention : Optional [ Tensor ] = None , step : int = 0 , label_decoders : Optional [ Dict ] = None , labels_hierarchy : Dict = {}, gtclass : Optional [ Tensor ] = None , name : str = \"\" , mdir : str = \"/tmp\" , doplot : bool = True , ): \"\"\" This function creates an AnnData object from the given input parameters. Args: embs (torch.Tensor): Embeddings of the cells. The shape of the tensor is (n_cells, n_features). labels (list): List of labels for the predicted classes. pred (torch.Tensor, optional): Predicted labels. The shape of the tensor is (n_cells, n_classes). Default is None. attention (torch.Tensor, optional): Attention weights. Default is None. step (int, optional): Step number for storing the AnnData without overwriting others. Default is 0. label_decoders (dict, optional): Dictionary to map class codes to class names. Default is None. labels_hierarchy (dict, optional): Dictionary representing the hierarchy of labels. Default is {}. gtclass (torch.Tensor, optional): Ground truth class. Default is None. name (str, optional): Name of the AnnData object. Default is an empty string. mdir (str, optional): Directory to save the AnnData object. Default is \"/tmp\". doplot (bool, optional): Whether to generate plots. Default is True. Returns: anndata.AnnData: The created AnnData object. \"\"\" colname = [ \"pred_\" + i for i in labels ] if pred is not None : obs = np . array ( pred . to ( device = \"cpu\" , dtype = torch . int32 )) # label decoders is not cls_decoders. one is a dict to map class codes (ints) # to class names the other is the module the predict the class if label_decoders is not None : obs = np . array ( [ [ label_decoders [ labels [ i ]][ n ] for n in name ] for i , name in enumerate ( obs . T ) ] ) . T if gtclass is not None : colname += labels nobs = np . array ( gtclass . to ( device = \"cpu\" , dtype = torch . int32 )) if label_decoders is not None : nobs = np . array ( [ [ label_decoders [ labels [ i ]][ n ] for n in name ] for i , name in enumerate ( nobs . T ) ] ) . T obs = np . hstack ([ obs , nobs ]) adata = AnnData ( np . array ( embs . to ( device = \"cpu\" , dtype = torch . float32 )), obs = pd . DataFrame ( obs , columns = colname , ), ) accuracy = {} for label in labels : if gtclass is not None : tr = translate ( adata . obs [ label ] . tolist (), label ) if tr is not None : adata . obs [ \"conv_\" + label ] = adata . obs [ label ] . replace ( tr ) tr = translate ( adata . obs [ \"pred_\" + label ] . tolist (), label ) if tr is not None : adata . obs [ \"conv_pred_\" + label ] = adata . obs [ \"pred_\" + label ] . replace ( tr ) res = [] if label_decoders is not None and gtclass is not None : class_topred = label_decoders [ label ] . values () if label in labels_hierarchy : cur_labels_hierarchy = { label_decoders [ label ][ k ]: [ label_decoders [ label ][ i ] for i in v ] for k , v in labels_hierarchy [ label ] . items () } else : cur_labels_hierarchy = {} for pred , true in adata . obs [[ \"pred_\" + label , label ]] . values : if pred == true : res . append ( True ) continue if len ( labels_hierarchy ) > 0 : if true in cur_labels_hierarchy : res . append ( pred in cur_labels_hierarchy [ true ]) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) else : pass accuracy [ \"pred_\" + label ] = sum ( res ) / len ( res ) if len ( res ) > 0 else 0 adata . obs = adata . obs . astype ( \"category\" ) else : adata = AnnData ( np . array ( embs . to ( device = \"cpu\" , dtype = torch . float32 )), ) if False : adata . varm [ \"Qs\" ] = ( attention [:, :, 0 , :, :] . permute ( 1 , 3 , 0 , 2 ) . view ( attention . shape [ 0 ], attention . shape [ 1 ], attention . shape [ 3 ] * attention . shape [ 4 ], ) . detach () . cpu () . numpy () ) adata . varm [ \"Ks\" ] = ( attention [:, :, 1 , :, :] . permute ( 1 , 3 , 0 , 2 ) . view ( attention . shape [ 0 ], attention . shape [ 1 ], attention . shape [ 3 ] * attention . shape [ 4 ], ) . detach () . cpu () . numpy () ) print ( adata ) if doplot and adata . shape [ 0 ] > 100 and pred is not None : sc . pp . neighbors ( adata , use_rep = \"X\" ) sc . tl . umap ( adata ) sc . tl . leiden ( adata , key_added = \"sprint_leiden\" ) if gtclass is not None : color = [ i for pair in zip ( [ \"conv_\" + i if \"conv_\" + i in adata . obs . columns else i for i in labels ], [ ( \"conv_pred_\" + i if \"conv_pred_\" + i in adata . obs . columns else \"pred_\" + i ) for i in labels ], ) for i in pair ] fig , axs = plt . subplots ( int ( len ( color ) / 2 ), 2 , figsize = ( 24 , len ( color ) * 4 ) ) plt . subplots_adjust ( wspace = 1 ) for i , col in enumerate ( color ): sc . pl . umap ( adata , color = col , ax = axs [ i // 2 , i % 2 ], show = False , ) acc = \"\" if \"_pred_\" in col and col . split ( \"conv_\" )[ - 1 ] in accuracy : acc = \" (accuracy: {:.2f} )\" . format ( accuracy [ col . split ( \"conv_\" )[ - 1 ]]) axs [ i // 2 , i % 2 ] . set_title ( col + \" UMAP\" + acc ) if \"cell_type\" in col : axs [ i // 2 , i % 2 ] . legend ( fontsize = \"x-small\" ) axs [ i // 2 , i % 2 ] . set_xlabel ( \"UMAP1\" ) axs [ i // 2 , i % 2 ] . set_ylabel ( \"UMAP2\" ) else : color = [ ( \"conv_pred_\" + i if \"conv_pred_\" + i in adata . obs . columns else \"pred_\" + i ) for i in labels ] fig , axs = plt . subplots ( len ( color ), 1 , figsize = ( 16 , len ( color ) * 8 )) for i , col in enumerate ( color ): sc . pl . umap ( adata , color = col , ax = axs [ i ], show = False , ) acc = \"\" if \"_pred_\" in col and col . split ( \"conv_\" )[ - 1 ] in accuracy : acc = \" (accuracy: {:.2f} )\" . format ( accuracy [ col . split ( \"conv_\" )[ - 1 ]]) axs [ i ] . set_title ( col + \" UMAP\" + acc ) axs [ i ] . set_xlabel ( \"UMAP1\" ) axs [ i ] . set_ylabel ( \"UMAP2\" ) plt . show () else : fig = None adata . write ( mdir + \"/step_\" + str ( step ) + \"_\" + name + \".h5ad\" ) return adata , fig simple_masker Randomly mask a batch of data. Parameters: shape ( list [ int ] ) \u2013 The shape of the data. mask_ratio ( float , default: 0.15 ) \u2013 The ratio of genes to mask, default to 0.15. Returns: Tensor \u2013 torch.Tensor: A tensor of masked data. Source code in scprint/model/utils.py 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 def simple_masker ( shape : list [ int ], mask_ratio : float = 0.15 , ) -> torch . Tensor : \"\"\" Randomly mask a batch of data. Args: shape (list[int]): The shape of the data. mask_ratio (float): The ratio of genes to mask, default to 0.15. Returns: torch.Tensor: A tensor of masked data. \"\"\" return torch . rand ( shape ) < mask_ratio test Test the given model on the full set of benchmarks and save the results to JSON files. Parameters: model ( Module ) \u2013 The model to be tested. name ( str ) \u2013 The name to be used for the output JSON files. filedir ( str ) \u2013 The directory where the data files are located. Returns: None \u2013 None Source code in scprint/model/utils.py 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 def test ( model : torch . nn . Module , name : str , filedir : str ) -> None : \"\"\" Test the given model on the full set of benchmarks and save the results to JSON files. Args: model (torch.nn.Module): The model to be tested. name (str): The name to be used for the output JSON files. filedir (str): The directory where the data files are located. Returns: None \"\"\" metrics = {} res = embbed_task . default_benchmark ( model , default_dataset = \"lung\" , do_class = True , coarse = False ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"embed_lung\" : res }, indent = 4 )) f . close () metrics . update ( { \"emb_lung/scib\" : float ( res [ \"scib\" ][ \"Total\" ]), \"emb_lung/ct_class\" : float ( res [ \"classif\" ][ \"cell_type_ontology_term_id\" ][ \"accuracy\" ] ), } ) print ( metrics ) res = embbed_task . default_benchmark ( model , default_dataset = \"pancreas\" , do_class = True , coarse = False ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"embed_panc\" : res }, indent = 4 )) f . close () metrics . update ( { \"emb_panc/scib\" : float ( res [ \"scib\" ][ \"Total\" ]), \"emb_panc/ct_class\" : float ( res [ \"classif\" ][ \"cell_type_ontology_term_id\" ][ \"accuracy\" ] ), } ) print ( metrics ) gc . collect () res = denoise_task . default_benchmark ( model , filedir + \"/../../data/gNNpgpo6gATjuxTE7CCp.h5ad\" ) metrics . update ( { \"denoise/reco2full_vs_noisy2full\" : float ( res [ \"reco2full\" ] - res [ \"noisy2full\" ] ), } ) gc . collect () print ( metrics ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"denoise\" : res }, indent = 4 )) f . close () res = grn_task . default_benchmark ( model , \"gwps\" , batch_size = 32 if model . d_model <= 512 else 8 ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_gwps\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_gwps/auprc_self\" : float ( res [ \"self\" ][ \"auprc\" ]), \"grn_gwps/epr_self\" : float ( res [ \"self\" ][ \"epr\" ]), \"grn_gwps/auprc_omni\" : float ( res [ \"omni\" ][ \"auprc\" ]), \"grn_gwps/epr_omni\" : float ( res [ \"omni\" ][ \"epr\" ]), \"grn_gwps/auprc\" : float ( res [ \"mean\" ][ \"auprc\" ]), \"grn_gwps/epr\" : float ( res [ \"mean\" ][ \"epr\" ]), } ) print ( metrics ) gc . collect () res = grn_task . default_benchmark ( model , \"sroy\" , batch_size = 32 if model . d_model <= 512 else 8 ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_sroy\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_sroy/auprc_self\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"self_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr_self\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"self_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/auprc_omni\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"omni_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr_omni\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"omni_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/auprc\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"mean_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"mean_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), } ) print ( metrics ) gc . collect () res = grn_task . default_benchmark ( model , filedir + \"/../../data/yBCKp6HmXuHa0cZptMo7.h5ad\" , batch_size = 32 if model . d_model <= 512 else 8 , ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_omni\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_omni/auprc_class\" : float ( np . mean ([ i [ \"auprc\" ] for k , i in res . items () if \"_class\" in k ]) ), \"grn_omni/epr_class\" : float ( np . mean ([ i [ \"epr\" ] for k , i in res . items () if \"_class\" in k ]) ), \"grn_omni/tf_enr_class\" : float ( np . sum ( [ i . get ( \"TF_enr\" , False ) for k , i in res . items () if \"_class\" in k ] ) ), \"grn_omni/tf_targ_enr_class\" : float ( np . mean ( [ i [ \"significant_enriched_TFtargets\" ] for k , i in res . items () if \"_class\" in k ] ) ), \"grn_omni/auprc\" : float ( np . mean ([ i [ \"auprc\" ] for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/epr\" : float ( np . mean ([ i [ \"epr\" ] for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/tf_enr\" : float ( np . sum ([ i . get ( \"TF_enr\" , False ) for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/tf_targ_enr\" : float ( np . mean ( [ i [ \"significant_enriched_TFtargets\" ] for k , i in res . items () if \"_mean\" in k ] ) ), # 'grn_omni/ct': res['classif']['cell_type_ontology_term_id']['accuracy'], } ) return metrics translate translate This function translates the given value based on the specified type. Parameters: val ( str / list / set / dict / Counter ) \u2013 The value to be translated. t ( str , default: 'cell_type_ontology_term_id' ) \u2013 The type of translation to be performed. Defaults to \"cell_type_ontology_term_id\". Returns: dict \u2013 A dictionary with the translated values. Source code in scprint/model/utils.py 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 def translate ( val : Union [ str , list , set , dict , Counter ], t : str = \"cell_type_ontology_term_id\" ): \"\"\" translate This function translates the given value based on the specified type. Args: val (str/list/set/dict/Counter): The value to be translated. t (str, optional): The type of translation to be performed. Defaults to \"cell_type_ontology_term_id\". Returns: dict: A dictionary with the translated values. \"\"\" if t == \"cell_type_ontology_term_id\" : obj = bt . CellType . df () . set_index ( \"ontology_id\" ) elif t == \"assay_ontology_term_id\" : obj = bt . ExperimentalFactor . df () . set_index ( \"ontology_id\" ) elif t == \"tissue_ontology_term_id\" : obj = bt . Tissue . df () . set_index ( \"ontology_id\" ) elif t == \"disease_ontology_term_id\" : obj = bt . Disease . df () . set_index ( \"ontology_id\" ) elif t == \"self_reported_ethnicity_ontology_term_id\" : obj = bt . Ethnicity . df () . set_index ( \"ontology_id\" ) else : return None if type ( val ) is str : if val == \"unknown\" : return { val : val } return { val : obj . loc [ val ][ \"name\" ]} elif type ( val ) is list or type ( val ) is set : return { i : obj . loc [ i ][ \"name\" ] if i != \"unknown\" else i for i in set ( val )} elif type ( val ) is dict or type ( val ) is Counter : return { obj . loc [ k ][ \"name\" ] if k != \"unknown\" else k : v for k , v in val . items ()} weighted_masker Randomly mask a batch of data. Parameters: shape ( list [ int ] ) \u2013 The shape of the data. mask_ratio ( float , default: 0.15 ) \u2013 The ratio of genes to mask, default to 0.15. mask_value ( int , default: 1 ) \u2013 The value to mask with, default to -1. pad_value ( int ) \u2013 The value of padding in the values, will be kept unchanged. Returns: Tensor \u2013 torch.Tensor: A tensor of masked data. Source code in scprint/model/utils.py 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 def weighted_masker ( shape : list [ int ], mask_ratio : float = 0.15 , mask_prob : Optional [ Union [ torch . Tensor , np . ndarray ]] = None , # n_features mask_value : int = 1 , ) -> torch . Tensor : \"\"\" Randomly mask a batch of data. Args: shape (list[int]): The shape of the data. mask_ratio (float): The ratio of genes to mask, default to 0.15. mask_value (int): The value to mask with, default to -1. pad_value (int): The value of padding in the values, will be kept unchanged. Returns: torch.Tensor: A tensor of masked data. \"\"\" mask = [] for _ in range ( shape [ 0 ]): m = np . zeros ( shape [ 1 ]) loc = np . random . choice ( a = shape [ 1 ], size = int ( shape [ 1 ] * mask_ratio ), replace = False , p = mask_prob ) m [ loc ] = mask_value mask . append ( m ) return torch . Tensor ( np . array ( mask )) . to ( torch . bool ) zinb_sample zinb_sample This function generates a sample from a Zero-Inflated Negative Binomial (ZINB) distribution. Parameters: mu ( Tensor ) \u2013 The mean of the Negative Binomial (NB) distribution. theta ( Tensor ) \u2013 The dispersion parameter of the NB distribution. zi_probs ( Tensor ) \u2013 The zero-inflation probabilities. sample_shape ( Size , default: Size ([]) ) \u2013 The output shape. Defaults to torch.Size([]). Returns: \u2013 torch.Tensor: A sample from the ZINB distribution. Source code in scprint/model/utils.py 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 def zinb_sample ( mu : torch . Tensor , theta : torch . Tensor , zi_probs : torch . Tensor , sample_shape : torch . Size = torch . Size ([]), ): \"\"\" zinb_sample This function generates a sample from a Zero-Inflated Negative Binomial (ZINB) distribution. Args: mu (torch.Tensor): The mean of the Negative Binomial (NB) distribution. theta (torch.Tensor): The dispersion parameter of the NB distribution. zi_probs (torch.Tensor): The zero-inflation probabilities. sample_shape (torch.Size, optional): The output shape. Defaults to torch.Size([]). Returns: torch.Tensor: A sample from the ZINB distribution. \"\"\" concentration = theta rate = theta / mu # Important remark: Gamma is parametrized by the rate = 1/scale! gamma_d = Gamma ( concentration = concentration , rate = rate ) p_means = gamma_d . sample ( sample_shape ) # Clamping as distributions objects can have buggy behaviors when # their parameters are too high l_train = torch . clamp ( p_means , max = 1e8 ) samp = Poisson ( l_train ) . sample () # Shape : (n_samples, n_cells_batch, n_vars) is_zero = torch . rand_like ( samp ) <= zi_probs samp_ = torch . where ( is_zero , torch . zeros_like ( samp ), samp ) return samp_ encoder and decoder modules scprint.model.encoders CategoryValueEncoder Bases: Module Encodes categorical values into a vector using an embedding layer and layer normalization. Parameters: num_embeddings ( int ) \u2013 The number of possible values. embedding_dim ( int ) \u2013 The dimension of the output vectors. padding_idx ( int , default: None ) \u2013 The index of the padding token. Defaults to None. Returns: \u2013 torch.Tensor: A tensor representing the encoded categorical values. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 def __init__ ( self , num_embeddings : int , embedding_dim : int , padding_idx : Optional [ int ] = None , ): \"\"\" Encodes categorical values into a vector using an embedding layer and layer normalization. Args: num_embeddings (int): The number of possible values. embedding_dim (int): The dimension of the output vectors. padding_idx (int, optional): The index of the padding token. Defaults to None. Returns: torch.Tensor: A tensor representing the encoded categorical values. Note: not used in the current version of scprint. \"\"\" super ( CategoryValueEncoder , self ) . __init__ () self . embedding = nn . Embedding ( num_embeddings , embedding_dim , padding_idx = padding_idx ) ContinuousValueEncoder Bases: Module Encode real number values to a vector using neural nets projection. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float , default: 0.1 ) \u2013 The dropout rate to apply to the output of the positional encoding. max_value ( int , default: 100000 ) \u2013 The maximum value of the input. Defaults to 100_000. layers ( int , default: 1 ) \u2013 The number of layers in the encoder. Defaults to 1. size ( int , default: 1 ) \u2013 The size of the input. Defaults to 1. Returns: \u2013 torch.Tensor: A tensor representing the encoded continuous values. Source code in scprint/model/encoders.py 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 def __init__ ( self , d_model : int , dropout : float = 0.1 , max_value : int = 100_000 , layers : int = 1 , size : int = 1 , ): \"\"\" Encode real number values to a vector using neural nets projection. Args: d_model (int): The dimension of the input vectors. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. max_value (int, optional): The maximum value of the input. Defaults to 100_000. layers (int, optional): The number of layers in the encoder. Defaults to 1. size (int, optional): The size of the input. Defaults to 1. Returns: torch.Tensor: A tensor representing the encoded continuous values. \"\"\" super ( ContinuousValueEncoder , self ) . __init__ () self . max_value = max_value self . encoder = nn . ModuleList () self . encoder . append ( nn . Linear ( size , d_model )) for _ in range ( layers - 1 ): self . encoder . append ( nn . LayerNorm ( d_model )) self . encoder . append ( nn . ReLU ()) self . encoder . append ( nn . Dropout ( p = dropout )) self . encoder . append ( nn . Linear ( d_model , d_model )) forward Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, seq_len] Source code in scprint/model/encoders.py 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 def forward ( self , x : Tensor , mask : Tensor = None ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, seq_len] \"\"\" # expand last dimension x = x . unsqueeze ( - 1 ) # use the mask embedding when x=-1 # mask = (x == -1).float() x = torch . clamp ( x , min = 0 , max = self . max_value ) for val in self . encoder : x = val ( x ) if mask is not None : x = x . masked_fill_ ( mask . unsqueeze ( - 1 ), 0 ) return x DPositionalEncoding Bases: Module The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. max_len ( int ) \u2013 The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 def __init__ ( self , d_model : int , max_len_x : int , max_len_y : int , maxvalue_x = 10000.0 , maxvalue_y = 10000.0 , ): super ( DPositionalEncoding , self ) . __init__ () position2 = torch . arange ( max_len_y ) . unsqueeze ( 1 ) position1 = torch . arange ( max_len_x ) . unsqueeze ( 1 ) half_n = d_model // 2 div_term2 = torch . exp ( torch . arange ( 0 , half_n , 2 ) * ( - math . log ( maxvalue_y ) / d_model ) ) div_term1 = torch . exp ( torch . arange ( 0 , half_n , 2 ) * ( - math . log ( maxvalue_x ) / d_model ) ) pe1 = torch . zeros ( max_len_x , 1 , d_model ) pe2 = torch . zeros ( max_len_y , 1 , d_model ) pe1 [:, 0 , 0 : half_n : 2 ] = torch . sin ( position1 * div_term1 ) pe1 [:, 0 , 1 : half_n : 2 ] = torch . cos ( position1 * div_term1 ) pe2 [:, 0 , half_n :: 2 ] = torch . sin ( position2 * div_term2 ) pe2 [:, 0 , 1 + half_n :: 2 ] = torch . cos ( position2 * div_term2 ) # https://github.com/tatp22/multidim-positional-encoding/blob/master/positional_encodings/torch_encodings.py self . register_buffer ( \"pe1\" , pe1 ) self . register_buffer ( \"pe2\" , pe2 ) forward Parameters: x ( Tensor ) \u2013 Tensor, shape [seq_len, batch_size, embedding_dim] Source code in scprint/model/encoders.py 148 149 150 151 152 153 154 155 def forward ( self , x : Tensor , pos_x : Tensor , pos_y : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] \"\"\" x = x + self . pe1 [ pos_x ] x = x + self . pe2 [ pos_y ] return x GeneEncoder Bases: Module Encodes gene sequences into a continuous vector space using an embedding layer. The output is then normalized using a LayerNorm. Parameters: num_embeddings ( int ) \u2013 The number of possible values. embedding_dim ( int ) \u2013 The dimension of the output vectors. padding_idx ( int , default: None ) \u2013 The index of the padding token. Defaults to None. weights ( Tensor , default: None ) \u2013 The initial weights for the embedding layer. Defaults to None. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. freeze ( bool , default: False ) \u2013 Whether to freeze the weights of the embedding layer. Defaults to False. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def __init__ ( self , num_embeddings : int , embedding_dim : int , padding_idx : Optional [ int ] = None , weights : Optional [ Tensor ] = None , freeze : bool = False , ): \"\"\" Encodes gene sequences into a continuous vector space using an embedding layer. The output is then normalized using a LayerNorm. Args: num_embeddings (int): The number of possible values. embedding_dim (int): The dimension of the output vectors. padding_idx (int, optional): The index of the padding token. Defaults to None. weights (Tensor, optional): The initial weights for the embedding layer. Defaults to None. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. freeze (bool, optional): Whether to freeze the weights of the embedding layer. Defaults to False. Note: not used in the current version of scprint. \"\"\" super ( GeneEncoder , self ) . __init__ () self . embedding = nn . Embedding ( num_embeddings , embedding_dim , padding_idx = padding_idx , _freeze = freeze ) if weights is not None : # concat a zero vector to the weight # this is to make the embedding of the padding token to be zero # weights = torch.cat( # [torch.Tensor(weights), torch.zeros(1, embedding_dim)], dim=0 # ) self . embedding . weight . data . copy_ ( torch . Tensor ( weights )) PositionalEncoding Bases: Module The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. max_len ( int ) \u2013 The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 def __init__ ( self , d_model : int , max_len : int , token_to_pos : dict [ str , int ], # [token, pos] maxval = 10000.0 , ): \"\"\" The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Args: d_model (int): The dimension of the input vectors. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. max_len (int, optional): The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. \"\"\" super ( PositionalEncoding , self ) . __init__ () position = torch . arange ( max_len ) . unsqueeze ( 1 ) # Create a dictionary to convert token to position div_term = torch . exp ( torch . arange ( 0 , d_model , 2 ) * ( - math . log ( maxval ) / d_model ) ) pe = torch . zeros ( max_len , 1 , d_model ) pe [:, 0 , 0 :: 2 ] = torch . sin ( position * div_term ) pe [:, 0 , 1 :: 2 ] = torch . cos ( position * div_term ) # we reorder them and map them to gene_id (position) arr = [] for _ , v in token_to_pos . items (): arr . append ( pe [ v - 1 ] . numpy ()) pe = torch . Tensor ( np . array ( arr )) self . register_buffer ( \"pe\" , pe ) forward Parameters: x \u2013 Tensor, shape [seq_len, batch_size, embedding_dim] Source code in scprint/model/encoders.py 88 89 90 91 92 93 94 95 def forward ( self , gene_pos : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] \"\"\" return torch . index_select ( self . pe , 0 , gene_pos . view ( - 1 )) . view ( gene_pos . shape + ( - 1 ,) ) scprint.model.decoders ClsDecoder Bases: Module ClsDecoder Decoder for classification task. Parameters: d_model ( int ) \u2013 int, dimension of the input. n_cls ( int ) \u2013 int, number of classes. layers ( list [ int ] , default: [256, 128] ) \u2013 list[int], list of hidden layers. activation ( Callable , default: ReLU ) \u2013 nn.Module, activation function. dropout ( float , default: 0.1 ) \u2013 float, dropout rate. Returns: \u2013 Tensor, shape [batch_size, n_cls] Source code in scprint/model/decoders.py 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 def __init__ ( self , d_model : int , n_cls : int , layers : list [ int ] = [ 256 , 128 ], activation : Callable = nn . ReLU , dropout : float = 0.1 , ): \"\"\" ClsDecoder Decoder for classification task. Args: d_model: int, dimension of the input. n_cls: int, number of classes. layers: list[int], list of hidden layers. activation: nn.Module, activation function. dropout: float, dropout rate. Returns: Tensor, shape [batch_size, n_cls] \"\"\" super ( ClsDecoder , self ) . __init__ () # module list layers = [ d_model ] + layers self . decoder = nn . Sequential () for i , l in enumerate ( layers [ 1 :]): self . decoder . append ( nn . Linear ( layers [ i ], l )) self . decoder . append ( nn . LayerNorm ( l )) self . decoder . append ( activation ()) self . decoder . append ( nn . Dropout ( dropout )) self . out_layer = nn . Linear ( layers [ - 1 ], n_cls ) forward Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, embsize] Source code in scprint/model/decoders.py 206 207 208 209 210 211 212 def forward ( self , x : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, embsize] \"\"\" x = self . decoder ( x ) return self . out_layer ( x ) ExprDecoder Bases: Module ExprDecoder Decoder for the gene expression prediction. Will output the mean, variance and zero logits, parameters of a zero inflated negative binomial distribution. Parameters: d_model ( int ) \u2013 The dimension of the model. This is the size of the input feature vector. nfirst_tokens_to_skip ( int , default: 0 ) \u2013 The number of initial labels to skip in the sequence. Defaults to 0. dropout ( float , default: 0.1 ) \u2013 The dropout rate applied during training to prevent overfitting. Defaults to 0.1. zinb ( bool , default: True ) \u2013 Whether to use a zero inflated negative binomial distribution. Defaults to True. Source code in scprint/model/decoders.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 def __init__ ( self , d_model : int , nfirst_tokens_to_skip : int = 0 , dropout : float = 0.1 , zinb : bool = True , ): \"\"\" ExprDecoder Decoder for the gene expression prediction. Will output the mean, variance and zero logits, parameters of a zero inflated negative binomial distribution. Args: d_model (int): The dimension of the model. This is the size of the input feature vector. nfirst_tokens_to_skip (int, optional): The number of initial labels to skip in the sequence. Defaults to 0. dropout (float, optional): The dropout rate applied during training to prevent overfitting. Defaults to 0.1. zinb (bool, optional): Whether to use a zero inflated negative binomial distribution. Defaults to True. \"\"\" super ( ExprDecoder , self ) . __init__ () self . nfirst_tokens_to_skip = nfirst_tokens_to_skip self . fc = nn . Sequential ( nn . Linear ( d_model , d_model ), nn . LayerNorm ( d_model ), nn . LeakyReLU (), nn . Dropout ( dropout ), nn . Linear ( d_model , d_model ), nn . LayerNorm ( d_model ), nn . LeakyReLU (), ) self . pred_var_zero = nn . Linear ( d_model , 3 if zinb else 1 ) self . zinb = zinb forward x is the output of the transformer, (batch, seq_len, d_model) Source code in scprint/model/decoders.py 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 def forward ( self , x : Tensor ) -> Dict [ str , Tensor ]: \"\"\"x is the output of the transformer, (batch, seq_len, d_model)\"\"\" # we don't do it on the labels x = self . fc ( x [:, self . nfirst_tokens_to_skip :, :]) if self . zinb : pred_value , var_value , zero_logits = self . pred_var_zero ( x ) . split ( 1 , dim =- 1 ) # (batch, seq_len) # The sigmoid function is used to map the zero_logits to a probability between 0 and 1. return dict ( mean = F . softmax ( pred_value . squeeze ( - 1 ), dim =- 1 ), disp = torch . exp ( torch . clamp ( var_value . squeeze ( - 1 ), max = 15 )), zero_logits = zero_logits . squeeze ( - 1 ), ) else : pred_value = self . pred_var_zero ( x ) return dict ( mean = F . softmax ( pred_value . squeeze ( - 1 ), dim =- 1 )) GraphSDEExprDecoder Bases: Module Initialize the ExprNeuralSDEDecoder module. Parameters: d_model ( int ) \u2013 The dimension of the model. drift ( Module ) \u2013 The drift component of the SDE. diffusion ( Module ) \u2013 The diffusion component of the SDE. Source code in scprint/model/decoders.py 8 9 10 11 12 13 14 15 16 17 18 19 20 def __init__ ( self , d_model : int , drift : nn . Module , diffusion : nn . Module ): \"\"\" Initialize the ExprNeuralSDEDecoder module. Args: d_model (int): The dimension of the model. drift (nn.Module): The drift component of the SDE. diffusion (nn.Module): The diffusion component of the SDE. \"\"\" super () . __init__ () self . d_model = d_model self . drift = drift self . diffusion = diffusion MVCDecoder Bases: Module MVCDecoder Decoder for the masked value prediction for cell embeddings. Will use the gene embeddings with the cell embeddings to predict the mean, variance and zero logits Parameters: d_model \u2013 obj: int ): dimension of the gene embedding. arch_style \u2013 obj: str ): architecture style of the decoder, choice from 1. \"inner product\" or 2. \"cell product\" 3. \"concat query\" or 4. \"sum query\". query_activation \u2013 obj: nn.Module ): activation function for the query vectors. Defaults to nn.Sigmoid. hidden_activation \u2013 obj: nn.Module ): activation function for the hidden layers. Defaults to nn.PReLU. Source code in scprint/model/decoders.py 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 def __init__ ( self , d_model : int , arch_style : str = \"inner product\" , tot_labels : int = 1 , query_activation : nn . Module = nn . Sigmoid , hidden_activation : nn . Module = nn . PReLU , ) -> None : \"\"\" MVCDecoder Decoder for the masked value prediction for cell embeddings. Will use the gene embeddings with the cell embeddings to predict the mean, variance and zero logits Args: d_model (:obj:`int`): dimension of the gene embedding. arch_style (:obj:`str`): architecture style of the decoder, choice from 1. \"inner product\" or 2. \"cell product\" 3. \"concat query\" or 4. \"sum query\". query_activation (:obj:`nn.Module`): activation function for the query vectors. Defaults to nn.Sigmoid. hidden_activation (:obj:`nn.Module`): activation function for the hidden layers. Defaults to nn.PReLU. \"\"\" super ( MVCDecoder , self ) . __init__ () if arch_style == \"inner product\" : self . gene2query = nn . Linear ( d_model , d_model ) self . norm = nn . LayerNorm ( d_model ) self . query_activation = query_activation () self . pred_var_zero = nn . Linear ( d_model , d_model * 3 , bias = False ) elif arch_style == \"concat query\" : self . gene2query = nn . Linear ( d_model , d_model ) self . query_activation = query_activation () self . fc1 = nn . Linear ( d_model * ( 1 + tot_labels ), d_model / 2 ) self . hidden_activation = hidden_activation () self . fc2 = nn . Linear ( d_model / 2 , 3 ) elif arch_style == \"sum query\" : self . gene2query = nn . Linear ( d_model , d_model ) self . query_activation = query_activation () self . fc1 = nn . Linear ( d_model , 64 ) self . hidden_activation = hidden_activation () self . fc2 = nn . Linear ( 64 , 3 ) else : raise ValueError ( f \"Unknown arch_style: { arch_style } \" ) self . arch_style = arch_style self . do_detach = arch_style . endswith ( \"detach\" ) self . d_model = d_model forward Parameters: cell_emb ( Tensor ) \u2013 Tensor, shape (batch, embsize=d_model) gene_embs ( Tensor ) \u2013 Tensor, shape (batch, seq_len, embsize=d_model) Source code in scprint/model/decoders.py 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 def forward ( self , cell_emb : Tensor , gene_embs : Tensor , ) -> Union [ Tensor , Dict [ str , Tensor ]]: \"\"\" Args: cell_emb: Tensor, shape (batch, embsize=d_model) gene_embs: Tensor, shape (batch, seq_len, embsize=d_model) \"\"\" if self . arch_style == \"inner product\" : query_vecs = self . query_activation ( self . norm ( self . gene2query ( gene_embs ))) pred , var , zero_logits = self . pred_var_zero ( query_vecs ) . split ( self . d_model , dim =- 1 ) cell_emb = cell_emb . unsqueeze ( 2 ) pred , var , zero_logits = ( torch . bmm ( pred , cell_emb ) . squeeze ( 2 ), torch . bmm ( var , cell_emb ) . squeeze ( 2 ), torch . bmm ( zero_logits , cell_emb ) . squeeze ( 2 ), ) # zero logits need to based on the cell_emb, because of input exprs elif self . arch_style == \"concat query\" : query_vecs = self . query_activation ( self . gene2query ( gene_embs )) # expand cell_emb to (batch, seq_len, embsize) cell_emb = cell_emb . unsqueeze ( 1 ) . expand ( - 1 , gene_embs . shape [ 1 ], - 1 ) h = self . hidden_activation ( self . fc1 ( torch . cat ([ cell_emb , query_vecs ], dim = 2 )) ) pred , var , zero_logits = self . fc2 ( h ) . split ( 1 , dim =- 1 ) elif self . arch_style == \"sum query\" : query_vecs = self . query_activation ( self . gene2query ( gene_embs )) cell_emb = cell_emb . unsqueeze ( 1 ) h = self . hidden_activation ( self . fc1 ( cell_emb + query_vecs )) pred , var , zero_logits = self . fc2 ( h ) . split ( 1 , dim =- 1 ) return dict ( mvc_mean = F . softmax ( pred , dim =- 1 ), mvc_disp = torch . exp ( torch . clamp ( var , max = 15 )), mvc_zero_logits = zero_logits , ) flashattention scprint.model.flash_attn.flashformer FlashTransformerEncoder Bases: Module FlashTransformerEncoder a transformer encoder with flash attention. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. nhead ( int ) \u2013 The number of attention heads. nlayers ( int ) \u2013 The number of layers in the transformer. dropout ( float , default: 0.1 ) \u2013 The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. residual_in_fp32 ( bool , default: True ) \u2013 Whether to force the residual to be in fp32 format. Defaults to True. num_heads_kv ( _type_ , default: None ) \u2013 The number of heads for key/value. Defaults to None. checkpointing ( bool , default: False ) \u2013 Whether to use gradient checkpointing. Defaults to False. fused_dropout_add_ln ( bool , default: False ) \u2013 Whether to fuse dropout, addition and layer normalization operations. Defaults to False. return_residual ( bool , default: False ) \u2013 Whether to return the residual. Defaults to False. prenorm ( bool , default: True ) \u2013 Whether to use pre-normalization. Defaults to True. mlp_ratio ( float , default: 4.0 ) \u2013 The ratio for MLP. Defaults to 4.0. fused_mlp ( bool , default: False ) \u2013 Whether to use fused MLP. Defaults to False. fused_bias_fc ( bool , default: False ) \u2013 Whether to fuse bias and fully connected layers. Defaults to False. sequence_parallel ( bool , default: False ) \u2013 Whether to use sequence parallelism. Defaults to False. drop_path_rate ( float , default: 0.0 ) \u2013 The drop path rate. Defaults to 0.0. weight_init ( str , default: '' ) \u2013 The weight initialization method. Defaults to \"\". Raises: ImportError \u2013 Raised when Triton is not installed but fused_dropout_add_ln is set to True. NotImplementedError \u2013 Raised when an unsupported operation is attempted. Source code in scprint/model/flash_attn/flashformer.py 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 def __init__ ( self , d_model : int , nhead : int , nlayers : int , dropout : float = 0.1 , residual_in_fp32 : bool = True , num_heads_kv : Optional [ int ] = None , checkpointing : bool = False , fused_dropout_add_ln : bool = False , return_residual : bool = False , prenorm : bool = True , mlp_ratio : float = 4.0 , fused_mlp : bool = False , fused_bias_fc : bool = False , sequence_parallel : bool = False , drop_path_rate : float = 0.0 , use_flash_attn : bool = True , weight_init : str = \"\" , ): \"\"\" FlashTransformerEncoder a transformer encoder with flash attention. Args: d_model (int): The dimension of the input vectors. nhead (int): The number of attention heads. nlayers (int): The number of layers in the transformer. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. residual_in_fp32 (bool, optional): Whether to force the residual to be in fp32 format. Defaults to True. num_heads_kv (_type_, optional): The number of heads for key/value. Defaults to None. checkpointing (bool, optional): Whether to use gradient checkpointing. Defaults to False. fused_dropout_add_ln (bool, optional): Whether to fuse dropout, addition and layer normalization operations. Defaults to False. return_residual (bool, optional): Whether to return the residual. Defaults to False. prenorm (bool, optional): Whether to use pre-normalization. Defaults to True. mlp_ratio (float, optional): The ratio for MLP. Defaults to 4.0. fused_mlp (bool, optional): Whether to use fused MLP. Defaults to False. fused_bias_fc (bool, optional): Whether to fuse bias and fully connected layers. Defaults to False. sequence_parallel (bool, optional): Whether to use sequence parallelism. Defaults to False. drop_path_rate (float, optional): The drop path rate. Defaults to 0.0. weight_init (str, optional): The weight initialization method. Defaults to \"\". Raises: ImportError: Raised when Triton is not installed but fused_dropout_add_ln is set to True. NotImplementedError: Raised when an unsupported operation is attempted. \"\"\" super ( FlashTransformerEncoder , self ) . __init__ () self . blocks = nn . ModuleList () dpr = [ x . item () for x in torch . linspace ( 0 , drop_path_rate , nlayers ) ] # stochastic depth decay rule for i in range ( nlayers ): mlp = create_mlp_cls ( d_model , mlp_ratio , nn . GELU , fused_mlp ) attention = partial ( MHA , num_heads = nhead , dropout = dropout , causal = False , use_flash_attn = use_flash_attn , num_heads_kv = num_heads_kv , checkpointing = checkpointing , fused_bias_fc = fused_bias_fc , layer_idx = i , ) # or use parallelBlock where attn & MLP are done in parallel encoder_layers = Block ( d_model , attention , mlp , prenorm = prenorm , # need to set it here for now although it hinders some performances as it returns the residual and I need to see what to do with it # TD [2022-07-30]: Force residual in fp32, seems to make fp16 training more stable residual_in_fp32 = residual_in_fp32 , sequence_parallel = sequence_parallel , # for more parallelism resid_dropout1 = dropout , resid_dropout2 = dropout , drop_path1 = dpr [ i - 1 ] if i > 0 else 0.0 , drop_path2 = dpr [ i ], fused_dropout_add_ln = fused_dropout_add_ln , return_residual = return_residual , ) self . blocks . append ( encoder_layers ) self . prenorm = prenorm self . dropout = nn . Dropout ( p = dropout ) self . drop_path = StochasticDepth ( p = dpr [ - 1 ], mode = \"row\" ) self . norm = torch . nn . LayerNorm ( d_model , eps = 1e-6 ) self . fused_dropout_add_ln = fused_dropout_add_ln if self . fused_dropout_add_ln and layer_norm_fn is None : raise ImportError ( \"Triton is not installed\" ) if sequence_parallel : # This seems to only be important when doing tensor parallelism across GPUs, to increase even more the context length I guess? # not really necessary here I think raise NotImplementedError ( \"sequence_parallel not implemented yet\" ) self . init_weights ( weight_init ) scprint.model.flash_attn.mha CrossAttention Bases: Module Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. Default to 1/sqrt(d_keys) where d_keys is computed at runtime attention_dropout: The dropout rate to apply to the attention. default to 0.0. Source code in scprint/model/flash_attn/mha.py 245 246 247 248 249 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 ): super () . __init__ () self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout ) forward Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, Sk) Source code in scprint/model/flash_attn/mha.py 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 def forward ( self , q , kv , causal = None , key_padding_mask = None , bias = None ): \"\"\"Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, Sk) \"\"\" batch_size , seqlen_q = q . shape [ 0 ], q . shape [ 1 ] causal = self . causal if causal is None else causal seqlen_k = kv . shape [ 1 ] assert kv . shape [ 0 ] == batch_size and kv . shape [ 4 ] == q . shape [ 3 ] if kv . shape [ 3 ] != q . shape [ 2 ]: # MQA/GQA kv = repeat ( kv , \"... hkv d -> ... (hkv g) d\" , g = q . shape [ 2 ] // kv . shape [ 3 ]) k , v = kv . unbind ( dim = 2 ) softmax_scale = self . softmax_scale or 1.0 / math . sqrt ( q . shape [ - 1 ]) scores = torch . einsum ( \"bthd,bshd->bhts\" , q , k * softmax_scale ) if key_padding_mask is not None : padding_mask = torch . full ( ( batch_size , seqlen_k ), - 10000.0 , dtype = scores . dtype , device = scores . device , ) padding_mask . masked_fill_ ( key_padding_mask , 0.0 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + rearrange ( padding_mask , \"b s -> b 1 1 s\" ) if causal : # causal mask needs to take into account the difference between seqlen_q and seqlen_k row_idx = rearrange ( torch . arange ( seqlen_q , device = q . device , dtype = torch . long ), \"s -> s 1\" ) col_idx = torch . arange ( seqlen_k , device = kv . device , dtype = torch . long ) sk = ( seqlen_k if key_padding_mask is None else rearrange ( key_padding_mask . sum ( - 1 ), \"b -> b 1 1 1\" ) ) causal_mask = col_idx > row_idx + sk - seqlen_q scores = scores . masked_fill ( causal_mask , - 10000.0 ) attention = torch . softmax ( scores , dim =- 1 , dtype = v . dtype ) attention_drop = self . drop ( attention ) output = torch . einsum ( \"bhts,bshd->bthd\" , attention_drop , v ) return output FlashCrossAttention Bases: Module Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The dropout rate to apply to the attention (default: 0.0) Source code in scprint/model/flash_attn/mha.py 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 , alibi_slopes = None , deterministic = False , ): \"\"\" Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The dropout rate to apply to the attention (default: 0.0) \"\"\" super () . __init__ () assert flash_attn_kvpacked_func is not None , \"FlashAttention is not installed\" assert flash_attn_kvpacked_func is not None , \"FlashAttention is not installed\" self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout ) self . register_buffer ( \"alibi_slopes\" , alibi_slopes , persistent = False ) self . deterministic = deterministic forward Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into q. max_seqlen: int. Maximum sequence length in the batch of q. cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into kv. max_seqlen_k: int. Maximum sequence length in the batch of k and v. Source code in scprint/model/flash_attn/mha.py 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 def forward ( self , q , kv , causal = None , cu_seqlens = None , max_seqlen = None , cu_seqlens_k = None , max_seqlen_k = None , ): \"\"\" Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into q. max_seqlen: int. Maximum sequence length in the batch of q. cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into kv. max_seqlen_k: int. Maximum sequence length in the batch of k and v. \"\"\" assert q . dtype in [ torch . float16 , torch . bfloat16 ] assert q . is_cuda and kv . is_cuda causal = self . causal if causal is None else causal batch_size , seqlen_q = q . shape [ 0 ], q . shape [ 1 ] assert kv . shape [ 0 ] == batch_size and kv . shape [ 4 ] == q . shape [ 3 ] return flash_attn_kvpacked_func ( q , kv , None , # self.drop.p if self.training else 0.0, causal , self . softmax_scale , # alibi_slopes=self.alibi_slopes, # deterministic=self.deterministic, ) FlashSelfAttention Bases: Module Implement the scaled dot product attention with softmax. Parameters: softmax_scale ( float , default: None ) \u2013 The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout ( float , default: 0.0 ) \u2013 The dropout rate to apply to the attention (default: 0.0) causal ( bool , default: False ) \u2013 Whether to use causal attention. Defaults to False. Source code in scprint/model/flash_attn/mha.py 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 def __init__ ( self , causal : bool = False , softmax_scale : Optional [ float ] = None , attention_dropout : float = 0.0 , alibi_slopes : Optional [ Any ] = None , deterministic : bool = False , use_triton : bool = False , ): \"\"\"Implement the scaled dot product attention with softmax. Args: softmax_scale (float, optional): The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout (float, optional): The dropout rate to apply to the attention (default: 0.0) causal (bool, optional): Whether to use causal attention. Defaults to False. \"\"\" super () . __init__ () if flash_attn_qkvpacked_func is None : print ( \"FlashAttention is not installed, using triton instead\" ) use_triton = True self . use_triton = use_triton self . causal = causal self . softmax_scale = softmax_scale forward Implements the multihead softmax attention. Args qkv (Tensor): The tensor containing the query, key, and value. If cu_seqlens is None and max_seqlen is None, then qkv has shape (B, S, 3, H, D). If cu_seqlens is not None and max_seqlen is not None, then qkv has shape (total, 3, H, D), where total is the sum of the sequence lengths in the batch. causal (bool): if passed, will override self.causal cu_seqlens (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into qkv. max_seqlen (int). Maximum sequence length in the batch. Returns: out: (total, H, D) if cu_seqlens is not None and max_seqlen is not None, else (B, S, H, D). Source code in scprint/model/flash_attn/mha.py 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 def forward ( self , qkv : torch . Tensor , causal : Optional [ bool ] = None , cu_seqlens : Optional [ torch . Tensor ] = None , max_seqlen : Optional [ int ] = None , cu_seqlens_k : Optional [ torch . Tensor ] = None , max_seqlen_k : Optional [ int ] = None , bias : Optional [ torch . Tensor ] = None , ** kwargs , ): \"\"\"Implements the multihead softmax attention. Args qkv (Tensor): The tensor containing the query, key, and value. If cu_seqlens is None and max_seqlen is None, then qkv has shape (B, S, 3, H, D). If cu_seqlens is not None and max_seqlen is not None, then qkv has shape (total, 3, H, D), where total is the sum of the sequence lengths in the batch. causal (bool): if passed, will override self.causal cu_seqlens (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into qkv. max_seqlen (int). Maximum sequence length in the batch. Returns: out: (total, H, D) if cu_seqlens is not None and max_seqlen is not None, else (B, S, H, D). \"\"\" assert qkv . dtype in [ torch . float16 , torch . bfloat16 ] assert qkv . is_cuda causal = self . causal if causal is None else causal if self . use_triton : raise NotImplementedError ( \"OpenAI's flashattention is not implemented\" ) if qkv . stride ( - 1 ) != 1 : qkv = qkv . contiguous () # return triton_attention( # qkv[:, :, 0], # qkv[:, :, 1], # qkv[:, :, 2], # bias, # causal, # self.softmax_scale, # ) else : return flash_attn_qkvpacked_func ( qkv , bias , # self.drop.p if self.training else 0.0, causal , self . softmax_scale , ) LinearResidual Bases: Linear Wrap nn.Linear to return the residual as well. For compatibility with FusedDense. MHA Bases: Module MHA Multi-head self-attention and cross-attention Parameters: num_heads_kv ( int , default: None ) \u2013 can be used to toggle MQA / GQA. If None, use num_heads. return_residual ( bool , default: False ) \u2013 whether to return the input x along with the output. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. checkpointing ( bool , default: False ) \u2013 whether to use checkpointing to save memory. Defaults to False. num_heads_kv ( int , default: None ) \u2013 can be used to toggle MQA / GQA. If None, use num_heads. cross_attn ( bool , default: False ) \u2013 whether to use cross-attention. Defaults to False. qkv_proj_bias ( bool , default: True ) \u2013 whether to use bias in the query, key, value projection. Defaults to True. out_proj_bias ( bool , default: True ) \u2013 whether to use bias in the output projection. Defaults to True. dropout ( float , default: 0.0 ) \u2013 dropout rate. Defaults to 0.0. softmax_scale ( float , default: None ) \u2013 The temperature to use for the softmax attention. causal ( bool , default: False ) \u2013 whether to use causal attention. Defaults to False. layer_idx ( int , default: None ) \u2013 layer index for inference cache. Defaults to None. dwconv ( bool , default: False ) \u2013 whether to use depthwise convolution. Defaults to False. fused_bias_fc ( bool , default: False ) \u2013 whether to use fused_bias_fc. Defaults to False. use_flash_attn ( bool , default: False ) \u2013 whether to use FlashAttention. Defaults to False. device ( device , default: None ) \u2013 device. Defaults to None. dtype ( dtype , default: None ) \u2013 dtype. Defaults to None. Source code in scprint/model/flash_attn/mha.py 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 def __init__ ( self , embed_dim : int , num_heads : int , num_heads_kv : Optional [ int ] = None , cross_attn : bool = False , qkv_proj_bias : bool = True , out_proj_bias : bool = True , dropout : float = 0.0 , softmax_scale : Optional [ float ] = None , causal : bool = False , layer_idx : Optional [ int ] = None , dwconv : bool = False , rotary_emb_dim : int = 0 , rotary_emb_base : float = 10000.0 , rotary_emb_scale_base : Optional [ float ] = None , rotary_emb_interleaved : bool = False , use_alibi : bool = False , fused_bias_fc : bool = False , use_flash_attn : bool = False , return_residual : bool = False , checkpointing : bool = False , device : Optional [ torch . device ] = None , dtype : Optional [ torch . dtype ] = None , ) -> None : \"\"\" MHA Multi-head self-attention and cross-attention Args: embed_dim num_heads_kv (int): can be used to toggle MQA / GQA. If None, use num_heads. return_residual (bool, optional): whether to return the input x along with the output. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. checkpointing (bool, optional): whether to use checkpointing to save memory. Defaults to False. num_heads_kv (int, optional): can be used to toggle MQA / GQA. If None, use num_heads. cross_attn (bool, optional): whether to use cross-attention. Defaults to False. qkv_proj_bias (bool, optional): whether to use bias in the query, key, value projection. Defaults to True. out_proj_bias (bool, optional): whether to use bias in the output projection. Defaults to True. dropout (float, optional): dropout rate. Defaults to 0.0. softmax_scale (float, optional): The temperature to use for the softmax attention. causal (bool, optional): whether to use causal attention. Defaults to False. layer_idx (int, optional): layer index for inference cache. Defaults to None. dwconv (bool, optional): whether to use depthwise convolution. Defaults to False. fused_bias_fc (bool, optional): whether to use fused_bias_fc. Defaults to False. use_flash_attn (bool, optional): whether to use FlashAttention. Defaults to False. device (torch.device, optional): device. Defaults to None. dtype (torch.dtype, optional): dtype. Defaults to None. \"\"\" factory_kwargs = { \"device\" : device , \"dtype\" : dtype } super () . __init__ () self . embed_dim = embed_dim self . cross_attn = cross_attn self . causal = causal self . layer_idx = layer_idx self . dwconv = dwconv self . rotary_emb_dim = rotary_emb_dim self . use_flash_attn = use_flash_attn if self . use_flash_attn and ( flash_attn_kvpacked_func is None ): print ( \"you requested flash transformer but it requires the flash package which is not installed\" ) print ( \"falling back to regular transformer...\" ) self . use_flash_attn = False # NOT flash transformer using the special tritton kernel # or parallelMHA (add the process group thing and faster) self . return_residual = return_residual self . checkpointing = checkpointing alibi_slopes = None self . num_heads = num_heads self . num_heads_kv = num_heads_kv if num_heads_kv is not None else num_heads assert ( self . num_heads % self . num_heads_kv == 0 ), \"num_heads must be divisible by num_heads_kv\" assert ( self . embed_dim % num_heads == 0 ), \"embed_dim must be divisible by num_heads\" self . head_dim = self . embed_dim // num_heads qkv_dim = self . head_dim * ( self . num_heads + 2 * self . num_heads_kv ) kv_dim = 2 * self . head_dim * self . num_heads_kv if self . rotary_emb_dim > 0 : assert ( not cross_attn ), \"MHA with rotary embedding does not support cross-attention yet\" assert RotaryEmbedding is not None , \"rotary_emb is not installed\" self . rotary_emb = RotaryEmbedding ( self . rotary_emb_dim , base = rotary_emb_base , scale_base = rotary_emb_scale_base , interleaved = rotary_emb_interleaved , device = device , ) if fused_bias_fc and FusedDense is None : raise ImportError ( \"fused_dense is not installed\" ) linear_cls = nn . Linear if not fused_bias_fc else FusedDense linear_resid_cls = ( LinearResidual if not fused_bias_fc else partial ( FusedDense , return_residual = True ) ) wqkv_cls = linear_cls if not self . return_residual else linear_resid_cls inner_attn_cls = ( partial ( FlashSelfAttention , alibi_slopes = alibi_slopes ) if self . use_flash_attn else SelfAttention ) inner_cross_attn_cls = ( partial ( FlashCrossAttention , alibi_slopes = alibi_slopes ) if self . use_flash_attn else CrossAttention ) if not self . cross_attn : self . Wqkv = wqkv_cls ( embed_dim , qkv_dim , bias = qkv_proj_bias , ** factory_kwargs ) else : self . Wq = linear_cls ( embed_dim , embed_dim , bias = qkv_proj_bias , ** factory_kwargs ) self . Wkv = wqkv_cls ( embed_dim , kv_dim , bias = qkv_proj_bias , ** factory_kwargs ) if self . dwconv : if self . num_heads_kv == self . num_heads : self . dwconv_qkv = nn . Conv1d ( qkv_dim , qkv_dim , kernel_size = 3 , padding = 2 , groups = qkv_dim ) else : self . dwconv_q = nn . Conv1d ( embed_dim , embed_dim , kernel_size = 3 , padding = 2 , groups = embed_dim ) self . dwconv_kv = nn . Conv1d ( kv_dim , kv_dim , kernel_size = 3 , padding = 2 , groups = kv_dim ) self . inner_attn = inner_attn_cls ( causal = causal , softmax_scale = softmax_scale , attention_dropout = dropout , ) self . inner_cross_attn = inner_cross_attn_cls ( causal = causal , softmax_scale = softmax_scale , attention_dropout = dropout ) self . out_proj = linear_cls ( embed_dim , embed_dim , bias = out_proj_bias , ** factory_kwargs ) forward Parameters: x ( Tensor ) \u2013 (batch, seqlen, hidden_dim) (where hidden_dim = num heads * head dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the is the sum of the sequence lengths in the batch. x_kv ( Optional [ Tensor ] , default: None ) \u2013 (batch, seqlen, hidden_dim), only applicable for cross-attention. If None, use x. cu_seqlens ( Optional [ Tensor ] , default: None ) \u2013 (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into x. Only applicable when using FlashAttention. max_seqlen ( Optional [ int ] , default: None ) \u2013 int. Maximum sequence length in the batch. key_padding_mask ( Optional [ Tensor ] , default: None ) \u2013 boolean mask, True means to keep, False means to mask out. (batch, seqlen). Only applicable when not using FlashAttention. mixer_subset ( Optional [ Tensor ] , default: None ) \u2013 for cross-attention only. If not None, will take a subset of x before applying the query projection. Useful for e.g., ViT where we only care about the CLS token in the last layer. inference_params ( Optional [ dict ] , default: None ) \u2013 for generation. Adapted from Megatron-LM (and Apex) https \u2013 //github.com/NVIDIA/apex/blob/3ff1a10f72ec07067c4e44759442329804ac5162/apex/transformer/testing/standalone_transformer_lm.py#L470 return_qkv ( bool , default: False ) \u2013 whether to return the qkv tensor. Defaults to False. Returns: out \u2013 (batch, seqlen, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the sum of the sequence lengths in the batch. qkv \u2013 (batch, seqlen, 3, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, 3, hidden_dim) where total is the sum of the sequence lengths in the batch. Source code in scprint/model/flash_attn/mha.py 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 def forward ( self , x : torch . Tensor , x_kv : Optional [ torch . Tensor ] = None , key_padding_mask : Optional [ torch . Tensor ] = None , cu_seqlens : Optional [ torch . Tensor ] = None , max_seqlen : Optional [ int ] = None , mixer_subset : Optional [ torch . Tensor ] = None , inference_params : Optional [ dict ] = None , return_qkv : bool = False , ** kwargs , ): \"\"\" Args: x: (batch, seqlen, hidden_dim) (where hidden_dim = num heads * head dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the is the sum of the sequence lengths in the batch. x_kv: (batch, seqlen, hidden_dim), only applicable for cross-attention. If None, use x. cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into x. Only applicable when using FlashAttention. max_seqlen: int. Maximum sequence length in the batch. key_padding_mask: boolean mask, True means to keep, False means to mask out. (batch, seqlen). Only applicable when not using FlashAttention. mixer_subset: for cross-attention only. If not None, will take a subset of x before applying the query projection. Useful for e.g., ViT where we only care about the CLS token in the last layer. inference_params: for generation. Adapted from Megatron-LM (and Apex) https://github.com/NVIDIA/apex/blob/3ff1a10f72ec07067c4e44759442329804ac5162/apex/transformer/testing/standalone_transformer_lm.py#L470 return_qkv: whether to return the qkv tensor. Defaults to False. Returns: out: (batch, seqlen, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the sum of the sequence lengths in the batch. qkv: (batch, seqlen, 3, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, 3, hidden_dim) where total is the sum of the sequence lengths in the batch. \"\"\" if cu_seqlens is not None : assert max_seqlen is not None assert key_padding_mask is None assert self . use_flash_attn assert not self . dwconv assert self . rotary_emb_dim == 0 if key_padding_mask is not None : assert cu_seqlens is None assert max_seqlen is None assert not self . use_flash_attn if inference_params is not None : assert key_padding_mask is None assert cu_seqlens is None and max_seqlen is None assert not self . dwconv kwargs = ( {} # \"cu_seqlens\": cu_seqlens, \"max_seqlen\": max_seqlen, **kwargs} if self . use_flash_attn else { \"key_padding_mask\" : key_padding_mask , ** kwargs } ) seqlen_offset = ( 0 if inference_params is None else ( inference_params . lengths_per_sample if inference_params . lengths_per_sample is not None else inference_params . seqlen_offset ) ) rotary_max_seqlen = ( inference_params . max_seqlen if inference_params is not None else None ) batch , seqlen = x . shape [: 2 ] if not self . cross_attn and self . num_heads_kv == self . num_heads : assert x_kv is None and mixer_subset is None if not self . return_residual : qkv = self . Wqkv ( x ) # .to(torch.float16, device=\"cuda\") else : qkv , x = self . Wqkv ( x ) if self . dwconv : qkv = rearrange ( self . dwconv_qkv ( rearrange ( qkv , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () qkv = rearrange ( qkv , \"... (three h d) -> ... three h d\" , three = 3 , d = self . head_dim ) if ( inference_params is None or inference_params . seqlen_offset == 0 or ( self . rotary_emb_dim == 0 or self . rotary_emb_dim % 16 != 0 ) or not self . use_flash_attn ): if self . rotary_emb_dim > 0 : qkv = self . rotary_emb ( qkv , seqlen_offset = seqlen_offset , max_seqlen = rotary_max_seqlen ) if inference_params is None : if not self . checkpointing : context = self . inner_attn ( qkv , ** kwargs ) else : context = torch . utils . checkpoint . checkpoint ( self . inner_attn , qkv , ** kwargs ) else : context = self . _update_kvcache_attention ( qkv [:, :, 0 ], qkv [:, :, 1 :], inference_params ) else : context = self . _apply_rotary_update_kvcache_attention ( qkv [:, :, 0 ], qkv [:, :, 1 :], inference_params ) else : if self . cross_attn : if not self . return_residual : q = self . Wq ( x if mixer_subset is None else x [:, mixer_subset ]) kv = self . Wkv ( x_kv if x_kv is not None else x ) else : if x_kv is not None : kv , x_kv = self . Wkv ( x_kv ) else : kv , x = self . Wkv ( x ) q = self . Wq ( x if mixer_subset is None else x [:, mixer_subset ]) else : assert self . num_heads_kv != self . num_heads if not self . return_residual : qkv = self . Wqkv ( x ) else : qkv , x = self . Wqkv ( x ) q = qkv [ ... , : self . num_heads * self . head_dim ] kv = qkv [ ... , self . num_heads * self . head_dim :] q = rearrange ( q , \"... (h d) -> ... h d\" , d = self . head_dim ) kv = rearrange ( kv , \"... (two hkv d) -> ... two hkv d\" , two = 2 , d = self . head_dim ) if self . dwconv : q = rearrange ( self . dwconv_q ( rearrange ( q , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () kv = rearrange ( self . dwconv_kv ( rearrange ( kv , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () if ( inference_params is None or inference_params . seqlen_offset == 0 or ( self . rotary_emb_dim == 0 or self . rotary_emb_dim % 16 != 0 ) or not self . use_flash_attn ): if self . rotary_emb_dim > 0 : q , kv = self . rotary_emb ( q , kv , seqlen_offset = seqlen_offset , max_seqlen = rotary_max_seqlen ) if inference_params is None : if not self . checkpointing : context = self . inner_cross_attn ( q , kv , ** kwargs ) else : context = torch . utils . checkpoint . checkpoint ( self . inner_cross_attn , q , kv , ** kwargs ) else : context = self . _update_kvcache_attention ( q , kv , inference_params ) else : context = self . _apply_rotary_update_kvcache_attention ( q , kv , inference_params ) out = self . out_proj ( rearrange ( context , \"... h d -> ... (h d)\" )) if return_qkv : return out if not self . return_residual else ( out , x ), qkv else : return out if not self . return_residual else ( out , x ) SelfAttention Bases: Module Implement the scaled dot product attention with softmax. Parameters: softmax_scale \u2013 The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout \u2013 The dropout rate to apply to the attention (default: 0.0) Source code in scprint/model/flash_attn/mha.py 195 196 197 198 199 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 ): super () . __init__ () self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout ) forward Implements the multihead softmax attention. Parameters: qkv \u2013 The tensor containing the query, key, and value. (B, S, 3, H, D) causal \u2013 if passed, will override self.causal key_padding_mask \u2013 boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, S) Source code in scprint/model/flash_attn/mha.py 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 def forward ( self , qkv , causal = None , key_padding_mask = None , bias = None ): \"\"\" Implements the multihead softmax attention. Args: qkv: The tensor containing the query, key, and value. (B, S, 3, H, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, S) \"\"\" batch_size , seqlen = qkv . shape [ 0 ], qkv . shape [ 1 ] causal = self . causal if causal is None else causal q , k , v = qkv . unbind ( dim = 2 ) softmax_scale = self . softmax_scale or 1.0 / math . sqrt ( q . shape [ - 1 ]) scores = torch . einsum ( \"bthd,bshd->bhts\" , q , k * softmax_scale ) if key_padding_mask is not None : padding_mask = torch . full ( ( batch_size , seqlen ), - 10000.0 , dtype = scores . dtype , device = scores . device ) padding_mask . masked_fill_ ( key_padding_mask , 0.0 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + rearrange ( padding_mask , \"b s -> b 1 1 s\" ) if causal : # \"triu_tril_cuda_template\" not implemented for 'BFloat16' # So we have to construct the mask in float causal_mask = torch . triu ( torch . full (( seqlen , seqlen ), - 10000.0 , device = scores . device ), 1 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + causal_mask . to ( dtype = scores . dtype ) attention = torch . softmax ( scores , dim =- 1 , dtype = v . dtype ) attention_drop = self . drop ( attention ) output = torch . einsum ( \"bhts,bshd->bthd\" , attention_drop , v ) return output scprint.model.flash_attn.mlp Mlp Bases: Module Multi-layer perceptron (MLP) module. Parameters: in_features ( int ) \u2013 Size of each input sample. hidden_features ( Optional [ int ] , default: None ) \u2013 Size of the hidden layer. Defaults to 4 * in_features. out_features ( Optional [ int ] , default: None ) \u2013 Size of each output sample. Defaults to in_features. activation ( Callable [[ Tensor ], Tensor ] , default: gelu ) \u2013 Activation function. Defaults to F.gelu. bias1 ( bool , default: True ) \u2013 If set to False, the first linear layer will not learn an additive bias. Defaults to True. bias2 ( bool , default: True ) \u2013 If set to False, the second linear layer will not learn an additive bias. Defaults to True. return_residual ( bool , default: False ) \u2013 If set to True, the forward method will return a tuple (output, input). Defaults to False. device ( Optional [ device ] , default: None ) \u2013 The desired device of the parameters. Defaults to None. dtype ( Optional [ dtype ] , default: None ) \u2013 The desired data type of the parameters. Defaults to None. Source code in scprint/model/flash_attn/mlp.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 def __init__ ( self , in_features : int , hidden_features : Optional [ int ] = None , out_features : Optional [ int ] = None , activation : Callable [[ torch . Tensor ], torch . Tensor ] = F . gelu , bias1 : bool = True , bias2 : bool = True , return_residual : bool = False , device : Optional [ torch . device ] = None , dtype : Optional [ torch . dtype ] = None , ) -> None : \"\"\" Multi-layer perceptron (MLP) module. Args: in_features (int): Size of each input sample. hidden_features (Optional[int], optional): Size of the hidden layer. Defaults to 4 * in_features. out_features (Optional[int], optional): Size of each output sample. Defaults to in_features. activation (Callable[[torch.Tensor], torch.Tensor], optional): Activation function. Defaults to F.gelu. bias1 (bool, optional): If set to False, the first linear layer will not learn an additive bias. Defaults to True. bias2 (bool, optional): If set to False, the second linear layer will not learn an additive bias. Defaults to True. return_residual (bool, optional): If set to True, the forward method will return a tuple (output, input). Defaults to False. device (Optional[torch.device], optional): The desired device of the parameters. Defaults to None. dtype (Optional[torch.dtype], optional): The desired data type of the parameters. Defaults to None. \"\"\" factory_kwargs = { \"device\" : device , \"dtype\" : dtype } super () . __init__ () out_features = out_features if out_features is not None else in_features hidden_features = ( hidden_features if hidden_features is not None else in_features * 4 ) self . return_residual = return_residual self . fc1 = nn . Linear ( in_features , hidden_features , bias = bias1 , ** factory_kwargs ) self . activation = activation self . fc2 = nn . Linear ( hidden_features , out_features , bias = bias2 , ** factory_kwargs ) forward Forward pass of the MLP. Parameters: x ( Tensor ) \u2013 Input tensor. Returns: Union [ Tensor , Tuple [ Tensor , Tensor ]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: Output tensor, or a tuple (output, input) if return_residual is True. Source code in scprint/model/flash_attn/mlp.py 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 def forward ( self , x : torch . Tensor ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , torch . Tensor ]]: \"\"\" Forward pass of the MLP. Args: x (torch.Tensor): Input tensor. Returns: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: Output tensor, or a tuple (output, input) if return_residual is True. \"\"\" y = self . fc1 ( x ) y = self . activation ( y ) y = self . fc2 ( y ) return y if not self . return_residual else ( y , x ) scprint.model.flash_attn.block Block Bases: Module For prenorm=True, this Block has a slightly different structure compared to a regular prenorm Transformer block. The standard block is: LN -> MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add. [Ref: https://arxiv.org/abs/2002.04745] Here we have: Dropout -> Add -> LN -> MHA -> Dropout -> Add -> LN -> MLP, returning both the hidden_states (output of the MLP) and the residual. This is for performance reasons, as we can fuse the dropout, add and LayerNorm. The residual needs to be provided (except for the very first block). For prenorm=False, this Block has the same structure as a regular postnorm Transformer block: MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add -> LN. Parameters: dim ( int ) \u2013 the number of features in the input. mixer_cls ( Optional [ Callable ] , default: None ) \u2013 the class to use for the mixer layer. Defaults to None. mlp_cls ( Optional [ Callable ] , default: None ) \u2013 the class to use for the mlp layer. Defaults to None. norm_cls ( Callable , default: partial ( LayerNorm , eps=1e-06) ) \u2013 the class to use for the layer norm. Defaults to partial(nn.LayerNorm, eps=1e-6). dropout_cls ( Type [ Dropout ] , default: Dropout ) \u2013 the class to use for the dropout. Defaults to nn.Dropout. prenorm ( bool , default: True ) \u2013 whether to use pre-norm or post-norm. Defaults to True. resid_dropout1 ( float , default: 0.0 ) \u2013 the dropout probability for the first dropout layer. Defaults to 0.0. resid_dropout2 ( float , default: 0.0 ) \u2013 the dropout probability for the second dropout layer. Defaults to 0.0. drop_path1 ( float , default: 0.0 ) \u2013 the drop path probability for the first drop path layer. Defaults to 0.0. drop_path2 ( float , default: 0.0 ) \u2013 the drop path probability for the second drop path layer. Defaults to 0.0. fused_dropout_add_ln ( bool , default: False ) \u2013 whether to fuse the dropout, add and layer norm. Defaults to False. return_residual ( bool , default: False ) \u2013 whether each of the sub-layers (mixer and mlp) will return the residual. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. residual_in_fp32 ( bool , default: False ) \u2013 whether to keep the residual in fp32. This is for performance reason: for post-norm architecture, keeping the residual in fp32 allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. sequence_parallel ( bool , default: False ) \u2013 whether to use sequence parallelism. Defaults to False. mark_shared_params ( bool , default: False ) \u2013 whether to mark the norm parameters as \"shared_params\". This is useful when we want to sync the norm parameters across workers. Defaults to False. Source code in scprint/model/flash_attn/block.py 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 def __init__ ( self , dim : int , mixer_cls : Optional [ Callable ] = None , mlp_cls : Optional [ Callable ] = None , norm_cls : Callable = partial ( nn . LayerNorm , eps = 1e-6 ), dropout_cls : Type [ nn . Dropout ] = nn . Dropout , prenorm : bool = True , resid_dropout1 : float = 0.0 , resid_dropout2 : float = 0.0 , drop_path1 : float = 0.0 , drop_path2 : float = 0.0 , fused_dropout_add_ln : bool = False , return_residual : bool = False , residual_in_fp32 : bool = False , sequence_parallel : bool = False , mark_shared_params : bool = False , ): \"\"\" For prenorm=True, this Block has a slightly different structure compared to a regular prenorm Transformer block. The standard block is: LN -> MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add. [Ref: https://arxiv.org/abs/2002.04745] Here we have: Dropout -> Add -> LN -> MHA -> Dropout -> Add -> LN -> MLP, returning both the hidden_states (output of the MLP) and the residual. This is for performance reasons, as we can fuse the dropout, add and LayerNorm. The residual needs to be provided (except for the very first block). For prenorm=False, this Block has the same structure as a regular postnorm Transformer block: MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add -> LN. Args: dim (int): the number of features in the input. mixer_cls (Optional[Callable], optional): the class to use for the mixer layer. Defaults to None. mlp_cls (Optional[Callable], optional): the class to use for the mlp layer. Defaults to None. norm_cls (Callable, optional): the class to use for the layer norm. Defaults to partial(nn.LayerNorm, eps=1e-6). dropout_cls (Type[nn.Dropout], optional): the class to use for the dropout. Defaults to nn.Dropout. prenorm (bool, optional): whether to use pre-norm or post-norm. Defaults to True. resid_dropout1 (float, optional): the dropout probability for the first dropout layer. Defaults to 0.0. resid_dropout2 (float, optional): the dropout probability for the second dropout layer. Defaults to 0.0. drop_path1 (float, optional): the drop path probability for the first drop path layer. Defaults to 0.0. drop_path2 (float, optional): the drop path probability for the second drop path layer. Defaults to 0.0. fused_dropout_add_ln (bool, optional): whether to fuse the dropout, add and layer norm. Defaults to False. return_residual (bool, optional): whether each of the sub-layers (mixer and mlp) will return the residual. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. residual_in_fp32 (bool, optional): whether to keep the residual in fp32. This is for performance reason: for post-norm architecture, keeping the residual in fp32 allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. sequence_parallel (bool, optional): whether to use sequence parallelism. Defaults to False. mark_shared_params (bool, optional): whether to mark the norm parameters as \"shared_params\". This is useful when we want to sync the norm parameters across workers. Defaults to False. \"\"\" super () . __init__ () self . prenorm = prenorm self . fused_dropout_add_ln = fused_dropout_add_ln self . return_residual = return_residual self . residual_in_fp32 = residual_in_fp32 if self . residual_in_fp32 : assert self . prenorm , \"residual_in_fp32 is only compatible with prenorm=True\" if mixer_cls is None : mixer_cls = partial ( MHA , num_heads = dim // 64 ) if mlp_cls is None : mlp_cls = partial ( Mlp , hidden_features = 4 * dim ) self . mixer = mixer_cls ( dim ) self . dropout1 = dropout_cls ( resid_dropout1 ) self . drop_path1 = StochasticDepth ( drop_path1 , mode = \"row\" ) self . norm1 = norm_cls ( dim ) self . mlp = mlp_cls ( dim ) if not isinstance ( self . mlp , nn . Identity ): self . dropout2 = dropout_cls ( resid_dropout2 ) self . drop_path2 = StochasticDepth ( drop_path2 , mode = \"row\" ) self . norm2 = norm_cls ( dim ) if self . fused_dropout_add_ln : assert layer_norm_fn is not None , \"Triton is not installed\" assert isinstance ( self . norm1 , ( nn . LayerNorm , RMSNorm )) and isinstance ( self . dropout1 , nn . Dropout ) # TD [2023-01-07]: TODO: During training, if sequence_parallel is False and dropout != 0.0, # then the input to each worker in the tensor parallel group will be different. # This would produce wrong outputs? Somehow we'd need to sync the RNG state across workers. # For now this is not an issue because we always use sequence_parallel=True during training # and only use sequence_parallel=False during inference. # Mark the norm parameters as \"sequence_parallel\" so that we run all-reduce on their grads. if sequence_parallel : for p in self . norm1 . parameters (): p . _sequence_parallel = True if hasattr ( self , \"norm2\" ): for p in self . norm2 . parameters (): p . _sequence_parallel = True # Mark the norm parameters as \"shared_params\" so that we sync their values at init. if mark_shared_params : for p in self . norm1 . parameters (): p . _shared_params = True if hasattr ( self , \"norm2\" ): for p in self . norm2 . parameters (): p . _shared_params = True forward Pass the input through the encoder layer. Parameters: hidden_states ( Tensor ) \u2013 The sequence to be passed to the encoder layer. This is a required argument. residual ( Optional [ Tensor ] , default: None ) \u2013 This argument is used differently based on the normalization method. If postnorm is used, residual should be None. If prenorm is used, hidden_states is updated as Attn/MLP(LN(residual)). mixer_subset ( Optional [ Tensor ] , default: None ) \u2013 This argument is used only for cross-attention. If not None, a subset of the input sequence 'x' is taken before applying the query projection. This is particularly useful for models like ViT where only the CLS token in the last layer is of interest. mixer_kwargs ( Optional [ Dict [ str , Any ]] , default: None ) \u2013 This argument is used only for cross-attention. It is a dictionary of additional arguments to be passed to the mixer. return_qkv ( bool , default: False ) \u2013 If True, the function will return the query, key, and value tensors. Returns: \u2013 Tensor or Tuple[Tensor, Tensor]: The output tensor of the encoder layer. \u2013 If return_qkv is True, the function will return a tuple of the output tensor and the query, key, and value tensors. Source code in scprint/model/flash_attn/block.py 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 def forward ( self , hidden_states : Tensor , residual : Optional [ Tensor ] = None , bias : Optional [ Tensor ] = None , src_mask : Optional [ Tensor ] = None , is_causal : Optional [ bool ] = None , src_key_padding_mask : Optional [ Tensor ] = None , mixer_subset : Optional [ Tensor ] = None , mixer_kwargs : Optional [ Dict [ str , Any ]] = None , return_qkv : bool = False , ): r \"\"\"Pass the input through the encoder layer. Args: hidden_states (Tensor): The sequence to be passed to the encoder layer. This is a required argument. residual (Optional[Tensor]): This argument is used differently based on the normalization method. If postnorm is used, residual should be None. If prenorm is used, hidden_states is updated as Attn/MLP(LN(residual)). mixer_subset: This argument is used only for cross-attention. If not None, a subset of the input sequence 'x' is taken before applying the query projection. This is particularly useful for models like ViT where only the CLS token in the last layer is of interest. mixer_kwargs: This argument is used only for cross-attention. It is a dictionary of additional arguments to be passed to the mixer. return_qkv: If True, the function will return the query, key, and value tensors. Returns: Tensor or Tuple[Tensor, Tensor]: The output tensor of the encoder layer. If return_qkv is True, the function will return a tuple of the output tensor and the query, key, and value tensors. \"\"\" if self . prenorm : if not self . fused_dropout_add_ln : dropped = self . drop_path1 ( self . dropout1 ( hidden_states )) residual = ( dropped + residual ) if residual is not None else dropped hidden_states = self . norm1 ( residual . to ( dtype = self . norm1 . weight . dtype )) if self . residual_in_fp32 : residual = residual . to ( torch . float32 ) else : if self . drop_path1 . p == 0 or not self . training : rowscale1 = None else : rowscale1 = self . drop_path1 ( torch . ones ( hidden_states . shape [: - 1 ], device = hidden_states . device , dtype = hidden_states . dtype , ) ) hidden_states , residual = layer_norm_fn ( hidden_states , self . norm1 . weight , self . norm1 . bias , residual = residual , eps = self . norm1 . eps , dropout_p = self . dropout1 . p if self . training else 0.0 , rowscale = rowscale1 , prenorm = True , residual_in_fp32 = self . residual_in_fp32 , is_rms_norm = isinstance ( self . norm1 , RMSNorm ), ) if mixer_kwargs is None : mixer_kwargs = {} if mixer_subset is not None : mixer_kwargs [ \"mixer_subset\" ] = mixer_subset hidden_states = self . mixer ( hidden_states , return_qkv = return_qkv , bias = bias , ** mixer_kwargs ) if return_qkv : qkv = hidden_states [ 1 ] hidden_states = hidden_states [ 0 ] if mixer_subset is not None : residual = residual [:, mixer_subset ] if not isinstance ( self . mlp , nn . Identity ): if not self . fused_dropout_add_ln : dropped = self . drop_path2 ( self . dropout2 ( hidden_states )) residual = ( dropped + residual ) if residual is not None else dropped hidden_states = self . norm2 ( residual . to ( dtype = self . norm2 . weight . dtype ) ) if self . residual_in_fp32 : residual = residual . to ( torch . float32 ) else : if self . drop_path2 . p == 0 or not self . training : rowscale2 = None else : rowscale2 = self . drop_path2 ( torch . ones ( hidden_states . shape [: - 1 ], device = hidden_states . device , dtype = hidden_states . dtype , ) ) hidden_states , residual = layer_norm_fn ( hidden_states , self . norm2 . weight , self . norm2 . bias , residual = residual , eps = self . norm2 . eps , dropout_p = self . dropout2 . p if self . training else 0.0 , rowscale = rowscale2 , prenorm = True , residual_in_fp32 = self . residual_in_fp32 , is_rms_norm = isinstance ( self . norm2 , RMSNorm ), ) hidden_states = self . mlp ( hidden_states ) return ( ( hidden_states , residual ) if not return_qkv else ( hidden_states , residual , qkv , ) ) # if not prenorm (disregard for scPRINT) else : assert residual is None mixer_out = self . mixer ( hidden_states , return_qkv = return_qkv , bias = bias , ** ( mixer_kwargs if mixer_kwargs is not None else {}) ) if return_qkv : qkv = mixer_out [ - 1 ] mixer_out = mixer_out [: - 1 ] if self . return_residual : # mixer out is actually a pair here mixer_out , hidden_states = mixer_out if not self . fused_dropout_add_ln : hidden_states = self . norm1 ( ( self . drop_path1 ( self . dropout1 ( mixer_out )) + hidden_states ) . to ( dtype = self . norm1 . weight . dtype ) ) else : if self . drop_path1 . p == 0 or not self . training : rowscale1 = None else : rowscale1 = self . drop_path1 ( torch . ones ( mixer_out . shape [: - 1 ], device = mixer_out . device , dtype = mixer_out . dtype , ) ) hidden_states = layer_norm_fn ( mixer_out , self . norm1 . weight , self . norm1 . bias , residual = hidden_states , eps = self . norm1 . eps , dropout_p = self . dropout1 . p if self . training else 0.0 , rowscale = rowscale1 , prenorm = False , is_rms_norm = isinstance ( self . norm1 , RMSNorm ), ) if not isinstance ( self . mlp , nn . Identity ): mlp_out = self . mlp ( hidden_states ) if self . return_residual : # mlp out is actually a pair here mlp_out , hidden_states = mlp_out if not self . fused_dropout_add_ln : hidden_states = self . norm2 ( ( self . drop_path2 ( self . dropout2 ( mlp_out )) + hidden_states ) . to ( dtype = self . norm2 . weight . dtype ) ) else : if self . drop_path2 . p == 0 or not self . training : rowscale2 = None else : rowscale2 = self . drop_path2 ( torch . ones ( mlp_out . shape [: - 1 ], device = mlp_out . device , dtype = mlp_out . dtype , ) ) hidden_states = layer_norm_fn ( mlp_out , self . norm2 . weight , self . norm2 . bias , residual = hidden_states , eps = self . norm2 . eps , dropout_p = self . dropout2 . p if self . training else 0.0 , rowscale = rowscale2 , prenorm = False , is_rms_norm = isinstance ( self . norm2 , RMSNorm ), ) return hidden_states if not return_qkv else ( hidden_states , qkv ) scprint.model.flash_attn.flashattention Experimental implementation of FlashAttention in Triton. Tested with triton==2.0.0.dev20221202. Triton 2.0 has a new backend (MLIR) but seems like it doesn't yet work for head dimensions other than 64: https://github.com/openai/triton/blob/d376020f90002757eea3ea9475d4f7cfc2ec5ead/python/triton/ops/flash_attention.py#L207 We'll update this implementation with the new Triton backend once this is fixed. We use the FlashAttention implementation from Phil Tillet a starting point. https://github.com/openai/triton/blob/master/python/tutorials/06-fused-attention.py Changes: - Implement both causal and non-causal attention. - Implement both self-attention and cross-attention. - Support arbitrary seqlens (not just multiples of 128), for both forward and backward. - Support all head dimensions up to 128 (not just 16, 32, 64, 128), for both forward and backward. - Support attention bias. - Speed up the forward pass a bit, and only store the LSE instead of m and l. - Make the backward for d=128 much faster by reducing register spilling. - Optionally parallelize the backward pass across seqlen_k, to deal with the case of small batch size * nheads. Caution: - This is an experimental implementation. The forward pass should be quite robust but I'm not 100% sure that the backward pass doesn't have race conditions (due to the Triton compiler). - This implementation has only been tested on A100. - If you plan to use headdim other than 64 and 128, you should test for race conditions (due to the Triton compiler), as done in tests/test_flash_attn.py \"test_flash_attn_triton_race_condition\". I've tested and fixed many race conditions for different head dimensions (40, 48, 64, 128, 80, 88, 96), but I'm still not 100% confident that there are none left for other head dimensions. Differences between this Triton version and the CUDA version: - Triton version doesn't support dropout. - Triton forward is generally faster than CUDA forward, while Triton backward is generally slower than CUDA backward. Overall Triton forward + backward is slightly slower than CUDA forward + backward. - Triton version doesn't support different sequence lengths in a batch (i.e., RaggedTensor/NestedTensor). - Triton version supports attention bias, while CUDA version doesn't. FlashAttnFunc Bases: Function forward staticmethod Perform the forward pass of FlashAttention. Parameters: q ( Tensor ) \u2013 Query tensor of shape (batch_size, seqlen_q, nheads, headdim). k ( Tensor ) \u2013 Key tensor of shape (batch_size, seqlen_k, nheads, headdim). v ( Tensor ) \u2013 Value tensor of shape (batch_size, seqlen_k, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor, shape broadcastible to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Scaling factor for the softmax operation. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 @staticmethod def forward ( ctx : torch . autograd . Function , q : torch . Tensor , k : torch . Tensor , v : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Perform the forward pass of FlashAttention. Args: q (torch.Tensor): Query tensor of shape (batch_size, seqlen_q, nheads, headdim). k (torch.Tensor): Key tensor of shape (batch_size, seqlen_k, nheads, headdim). v (torch.Tensor): Value tensor of shape (batch_size, seqlen_k, nheads, headdim). bias (Optional[torch.Tensor]): Bias tensor, shape broadcastible to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Scaling factor for the softmax operation. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous q , k , v = [ x if x . stride ( - 1 ) == 1 else x . contiguous () for x in [ q , k , v ]] o , lse , ctx . softmax_scale = _flash_attn_forward ( q , k , v , bias = bias , causal = causal , softmax_scale = softmax_scale ) ctx . save_for_backward ( q , k , v , o , lse , bias ) ctx . causal = causal return o FlashAttnKVPackedFunc Bases: Function forward staticmethod Perform the forward pass of FlashAttention with packed key and value tensors. Parameters: q ( Tensor ) \u2013 Query tensor of shape (batch, seqlen_q, nheads, headdim). kv ( Tensor ) \u2013 Key and value tensor of shape (batch, seqlen_k, 2, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor, shape broadcastable to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Scaling factor for the softmax operation. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 @staticmethod def forward ( ctx , q : torch . Tensor , kv : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Perform the forward pass of FlashAttention with packed key and value tensors. Args: q (torch.Tensor): Query tensor of shape (batch, seqlen_q, nheads, headdim). kv (torch.Tensor): Key and value tensor of shape (batch, seqlen_k, 2, nheads, headdim). bias (Optional[torch.Tensor]): Bias tensor, shape broadcastable to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Scaling factor for the softmax operation. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous q , kv = [ x if x . stride ( - 1 ) == 1 else x . contiguous () for x in [ q , kv ]] o , lse , ctx . softmax_scale = _flash_attn_forward ( q , kv [:, :, 0 ], kv [:, :, 1 ], bias = bias , causal = causal , softmax_scale = softmax_scale , ) ctx . save_for_backward ( q , kv , o , lse , bias ) ctx . causal = causal return o FlashAttnQKVPackedFunc Bases: Function forward staticmethod Forward pass for FlashAttention. Parameters: ctx ( Function ) \u2013 The context object to save information for backward computation. qkv ( Tensor ) \u2013 Input tensor of shape (batch, seqlen, 3, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Optional bias tensor, shape broadcastible to (batch, nheads, seqlen, seqlen). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen). ALiBi mask for non-causal would have shape (1, nheads, seqlen, seqlen). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Optional scaling factor for softmax. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 @staticmethod def forward ( ctx : torch . autograd . Function , qkv : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Forward pass for FlashAttention. Args: ctx (torch.autograd.Function): The context object to save information for backward computation. qkv (torch.Tensor): Input tensor of shape (batch, seqlen, 3, nheads, headdim). bias (Optional[torch.Tensor]): Optional bias tensor, shape broadcastible to (batch, nheads, seqlen, seqlen). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen). ALiBi mask for non-causal would have shape (1, nheads, seqlen, seqlen). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Optional scaling factor for softmax. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous if qkv . stride ( - 1 ) != 1 : qkv = qkv . contiguous () o , lse , ctx . softmax_scale = _flash_attn_forward ( qkv [:, :, 0 ], qkv [:, :, 1 ], qkv [:, :, 2 ], bias = bias , causal = causal , softmax_scale = softmax_scale , ) ctx . save_for_backward ( qkv , o , lse , bias ) ctx . causal = causal return o scprint.model.flash_attn.activations bias_gelu_back Assume that y has shape (B, D) and bias has shape (D) Source code in scprint/model/flash_attn/activations.py 24 25 26 27 28 29 30 31 32 33 34 @torch . jit . script def bias_gelu_back ( g , y , bias ): \"\"\"Assume that y has shape (B, D) and bias has shape (D)\"\"\" x = bias + y tanh_out = torch . tanh ( 0.79788456 * x * ( 1 + 0.044715 * x * x )) # sqrt(2/pi) * 3 * 0.044715 -> 0.1070322243 ff = 0.5 * x * ( ( 1 - tanh_out * tanh_out ) * ( 0.79788456 + 0.1070322243 * x * x ) ) + 0.5 * ( 1 + tanh_out ) grad_y = ff * g return grad_y . to ( dtype = y . dtype ), grad_y . sum ( dim = ( 0 ), dtype = bias . dtype ) scprint.model.flash_attn.layer_norm layer_norm_ref Reference implementation of Layer Normalization with optional dropout and residual connections. Parameters: x ( Tensor ) \u2013 Input tensor. weight ( Tensor ) \u2013 Weight tensor for normalization. bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor for normalization. residual ( Optional [ Tensor ] , default: None ) \u2013 Residual tensor to be added to the input. x1 ( Optional [ Tensor ] , default: None ) \u2013 Additional input tensor for parallel LayerNorm. weight1 ( Optional [ Tensor ] , default: None ) \u2013 Additional weight tensor for parallel LayerNorm. bias1 ( Optional [ Tensor ] , default: None ) \u2013 Additional bias tensor for parallel LayerNorm. eps ( float , default: 1e-06 ) \u2013 Epsilon value to avoid division by zero. dropout_p ( float , default: 0.0 ) \u2013 Dropout probability. rowscale ( Optional [ Tensor ] , default: None ) \u2013 Row scaling tensor. prenorm ( bool , default: False ) \u2013 Whether to return the prenormalized output. dropout_mask ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the input tensor. dropout_mask1 ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the additional input tensor. upcast ( bool , default: False ) \u2013 Whether to upcast the input tensors to float. Returns: Union [ Tensor , Tuple [ Tensor , ...]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). Source code in scprint/model/flash_attn/layer_norm.py 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 def layer_norm_ref ( x : torch . Tensor , weight : torch . Tensor , bias : Optional [ torch . Tensor ] = None , residual : Optional [ torch . Tensor ] = None , x1 : Optional [ torch . Tensor ] = None , weight1 : Optional [ torch . Tensor ] = None , bias1 : Optional [ torch . Tensor ] = None , eps : float = 1e-6 , dropout_p : float = 0.0 , rowscale : Optional [ torch . Tensor ] = None , prenorm : bool = False , dropout_mask : Optional [ torch . Tensor ] = None , dropout_mask1 : Optional [ torch . Tensor ] = None , upcast : bool = False , ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , ... ]]: \"\"\" Reference implementation of Layer Normalization with optional dropout and residual connections. Args: x (torch.Tensor): Input tensor. weight (torch.Tensor): Weight tensor for normalization. bias (Optional[torch.Tensor]): Bias tensor for normalization. residual (Optional[torch.Tensor]): Residual tensor to be added to the input. x1 (Optional[torch.Tensor]): Additional input tensor for parallel LayerNorm. weight1 (Optional[torch.Tensor]): Additional weight tensor for parallel LayerNorm. bias1 (Optional[torch.Tensor]): Additional bias tensor for parallel LayerNorm. eps (float): Epsilon value to avoid division by zero. dropout_p (float): Dropout probability. rowscale (Optional[torch.Tensor]): Row scaling tensor. prenorm (bool): Whether to return the prenormalized output. dropout_mask (Optional[torch.Tensor]): Dropout mask for the input tensor. dropout_mask1 (Optional[torch.Tensor]): Dropout mask for the additional input tensor. upcast (bool): Whether to upcast the input tensors to float. Returns: Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). \"\"\" dtype = x . dtype if upcast : x = x . float () weight = weight . float () bias = bias . float () if bias is not None else None residual = residual . float () if residual is not None else residual x1 = x1 . float () if x1 is not None else None weight1 = weight1 . float () if weight1 is not None else None bias1 = bias1 . float () if bias1 is not None else None if x1 is not None : assert rowscale is None , \"rowscale is not supported with parallel LayerNorm\" if rowscale is not None : x = x * rowscale [ ... , None ] if dropout_p > 0.0 : if dropout_mask is not None : x = x . masked_fill ( ~ dropout_mask , 0.0 ) / ( 1.0 - dropout_p ) else : x = F . dropout ( x , p = dropout_p ) if x1 is not None : if dropout_mask1 is not None : x1 = x1 . masked_fill ( ~ dropout_mask1 , 0.0 ) / ( 1.0 - dropout_p ) else : x1 = F . dropout ( x1 , p = dropout_p ) if x1 is not None : x = x + x1 if residual is not None : x = ( x + residual ) . to ( x . dtype ) out = F . layer_norm ( x . to ( weight . dtype ), x . shape [ - 1 :], weight = weight , bias = bias , eps = eps ) . to ( dtype ) if weight1 is None : return out if not prenorm else ( out , x ) else : out1 = F . layer_norm ( x . to ( weight1 . dtype ), x . shape [ - 1 :], weight = weight1 , bias = bias1 , eps = eps ) . to ( dtype ) return ( out , out1 ) if not prenorm else ( out , out1 , x ) rms_norm_ref Reference implementation of RMS Normalization with optional dropout and residual connections. Parameters: x ( Tensor ) \u2013 Input tensor. weight ( Tensor ) \u2013 Weight tensor for normalization. bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor for normalization. residual ( Optional [ Tensor ] , default: None ) \u2013 Residual tensor to be added to the input. x1 ( Optional [ Tensor ] , default: None ) \u2013 Additional input tensor for parallel RMSNorm. weight1 ( Optional [ Tensor ] , default: None ) \u2013 Additional weight tensor for parallel RMSNorm. bias1 ( Optional [ Tensor ] , default: None ) \u2013 Additional bias tensor for parallel RMSNorm. eps ( float , default: 1e-06 ) \u2013 Epsilon value to avoid division by zero. dropout_p ( float , default: 0.0 ) \u2013 Dropout probability. rowscale ( Optional [ Tensor ] , default: None ) \u2013 Row scaling tensor. prenorm ( bool , default: False ) \u2013 Whether to return the prenormalized output. dropout_mask ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the input tensor. dropout_mask1 ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the additional input tensor. upcast ( bool , default: False ) \u2013 Whether to upcast the input tensors to float. Returns: Union [ Tensor , Tuple [ Tensor , ...]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). Source code in scprint/model/flash_attn/layer_norm.py 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 def rms_norm_ref ( x : torch . Tensor , weight : torch . Tensor , bias : Optional [ torch . Tensor ] = None , residual : Optional [ torch . Tensor ] = None , x1 : Optional [ torch . Tensor ] = None , weight1 : Optional [ torch . Tensor ] = None , bias1 : Optional [ torch . Tensor ] = None , eps : float = 1e-6 , dropout_p : float = 0.0 , rowscale : Optional [ torch . Tensor ] = None , prenorm : bool = False , dropout_mask : Optional [ torch . Tensor ] = None , dropout_mask1 : Optional [ torch . Tensor ] = None , upcast : bool = False , ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , ... ]]: \"\"\" Reference implementation of RMS Normalization with optional dropout and residual connections. Args: x (torch.Tensor): Input tensor. weight (torch.Tensor): Weight tensor for normalization. bias (Optional[torch.Tensor]): Bias tensor for normalization. residual (Optional[torch.Tensor]): Residual tensor to be added to the input. x1 (Optional[torch.Tensor]): Additional input tensor for parallel RMSNorm. weight1 (Optional[torch.Tensor]): Additional weight tensor for parallel RMSNorm. bias1 (Optional[torch.Tensor]): Additional bias tensor for parallel RMSNorm. eps (float): Epsilon value to avoid division by zero. dropout_p (float): Dropout probability. rowscale (Optional[torch.Tensor]): Row scaling tensor. prenorm (bool): Whether to return the prenormalized output. dropout_mask (Optional[torch.Tensor]): Dropout mask for the input tensor. dropout_mask1 (Optional[torch.Tensor]): Dropout mask for the additional input tensor. upcast (bool): Whether to upcast the input tensors to float. Returns: Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). \"\"\" dtype = x . dtype if upcast : x = x . float () weight = weight . float () bias = bias . float () if bias is not None else None residual = residual . float () if residual is not None else residual x1 = x1 . float () if x1 is not None else None weight1 = weight1 . float () if weight1 is not None else None bias1 = bias1 . float () if bias1 is not None else None if x1 is not None : assert rowscale is None , \"rowscale is not supported with parallel LayerNorm\" if rowscale is not None : x = x * rowscale [ ... , None ] if dropout_p > 0.0 : if dropout_mask is not None : x = x . masked_fill ( ~ dropout_mask , 0.0 ) / ( 1.0 - dropout_p ) else : x = F . dropout ( x , p = dropout_p ) if x1 is not None : if dropout_mask1 is not None : x1 = x1 . masked_fill ( ~ dropout_mask1 , 0.0 ) / ( 1.0 - dropout_p ) else : x1 = F . dropout ( x1 , p = dropout_p ) if x1 is not None : x = x + x1 if residual is not None : x = ( x + residual ) . to ( x . dtype ) rstd = 1 / torch . sqrt (( x . square ()) . mean ( dim =- 1 , keepdim = True ) + eps ) out = (( x * rstd * weight ) + bias if bias is not None else ( x * rstd * weight )) . to ( dtype ) if weight1 is None : return out if not prenorm else ( out , x ) else : out1 = ( ( x * rstd * weight1 ) + bias1 if bias1 is not None else ( x * rstd * weight1 ) ) . to ( dtype ) return ( out , out1 ) if not prenorm else ( out , out1 , x )","title":"model"},{"location":"model/#documentation-for-the-model","text":"","title":"Documentation for the model"},{"location":"model/#model-description","text":"","title":"model description"},{"location":"model/#scprint.model.model","text":"","title":"model"},{"location":"model/#scprint.model.model.scPrint","text":"Bases: LightningModule , PyTorchModelHubMixin scPRINT transformer for single cell biology and the inference of Gene Regulatory networks Parameters: genes ( list ) \u2013 List of gene names the model will work with. precpt_gene_emb ( array , default: None ) \u2013 Gene embeddings of size (len(genes), d_model). Should be in the same order as the genes. Defaults to None. gene_pos_enc ( list , default: None ) \u2013 Gene position encoding of the same size as genes. Provides a location value for each gene in genes. Defaults to None. d_model ( int , default: 512 ) \u2013 Dimension of the model. Defaults to 512. nhead ( int , default: 8 ) \u2013 Number of heads in the multihead attention models. Defaults to 8. d_hid ( int , default: 512 ) \u2013 Dimension of the feedforward network model. Defaults to 512. nlayers ( int , default: 6 ) \u2013 Number of layers in the transformer model. Defaults to 6. expr_encoder_layers ( int , default: 2 ) \u2013 Number of layers in the expression encoder. Defaults to 2. layers_cls ( list [ int ] , default: [] ) \u2013 List specifying the number of layers in the classifier. Defaults to []. classes ( Dict [ str , int ] , default: {} ) \u2013 Classes to predict with the number of classes for each. Defaults to {}. labels_hierarchy ( Dict [ str , Dict [ int , list [ int ]]] , default: {} ) \u2013 Class hierarchy for classes with hierarchical classes. Defaults to {}. dropout ( float , default: 0.2 ) \u2013 Dropout value. Defaults to 0.2. transformer ( str , default: 'fast' ) \u2013 Transformer type to use. One of \"linear\", \"flash\", \"flashsparse\", \"scprint\". Defaults to \"fast\". domain_spec_batchnorm ( str , default: 'None' ) \u2013 Whether to apply domain-specific batch normalization. Defaults to \"None\". expr_emb_style ( str , default: 'continuous' ) \u2013 Style of input embedding. One of \"continuous\", \"binned_pos\", \"cont_pos\". Defaults to \"continuous\". mvc_decoder ( str , default: 'None' ) \u2013 Style of MVC decoder. One of \"None\", \"inner product\", \"concat query\", \"sum query\". Defaults to \"None\". pred_embedding ( list [ str ] , default: [] ) \u2013 List of classes to use for plotting embeddings. Defaults to []. cell_emb_style ( str , default: 'cls' ) \u2013 Style of cell embedding. One of \"cls\", \"avg-pool\", \"w-pool\". Defaults to \"cls\". freeze_embeddings ( bool , default: True ) \u2013 Whether to freeze the embeddings during training. Defaults to True. label_decoders ( Optional [ Dict [ str , Dict [ int , str ]]] , default: None ) \u2013 Label decoders to use for plotting the UMAP during validations. Defaults to None. zinb ( bool , default: True ) \u2013 Whether to use Zero-Inflated Negative Binomial distribution. Defaults to True. lr ( float , default: 0.0001 ) \u2013 Learning rate. Defaults to 0.0001. optim ( str , default: 'adamW' ) \u2013 Optimizer type. Defaults to \"adamW\". weight_decay ( float , default: 0.01 ) \u2013 Weight decay for the optimizer. Defaults to 0.01. **flash_attention_kwargs ( dict , default: {} ) \u2013 Additional keyword arguments for the model. see @flashformer.py Notes for other parameters of the model that are not part of its class definition, see @trainer.trainer.py Raises: ValueError \u2013 If the expr_emb_style is not one of \"continuous\", \"binned_pos\", \"cont_pos\". Source code in scprint/model/model.py 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 def __init__ ( self , genes : list , organisms : list = [ \"NCBITaxon:9606\" ], precpt_gene_emb : Optional [ str ] = None , gene_pos_enc : Optional [ list ] = None , normalization : str = \"sum\" , d_model : int = 512 , nhead : int = 8 , attn_bias : str = \"none\" , d_hid : int = 512 , edge_dim : int = 12 , nlayers : int = 6 , expr_encoder_layers : int = 2 , layers_cls : list [ int ] = [], classes : Dict [ str , int ] = {}, labels_hierarchy : Dict [ str , Dict [ int , list [ int ]]] = {}, dropout : float = 0.2 , transformer : str = \"fast\" , expr_emb_style : str = \"continuous\" , # \"binned_pos\", \"cont_pos\" domain_spec_batchnorm : str = \"None\" , n_input_bins : int = 0 , num_batch_labels : int = 0 , mvc_decoder : str = \"None\" , pred_embedding : list [ str ] = [], cell_emb_style : str = \"cls\" , freeze_embeddings : bool = True , label_decoders : Optional [ Dict [ str , Dict [ int , str ]]] = None , zinb : bool = True , lr : float = 0.0001 , optim = \"adamW\" , # TODEL weight_decay = 0.01 , # TODEL ** flash_attention_kwargs , ): \"\"\" scPRINT transformer for single cell biology and the inference of Gene Regulatory networks Args: genes (list): List of gene names the model will work with. precpt_gene_emb (np.array, optional): Gene embeddings of size (len(genes), d_model). Should be in the same order as the genes. Defaults to None. gene_pos_enc (list, optional): Gene position encoding of the same size as genes. Provides a location value for each gene in genes. Defaults to None. d_model (int, optional): Dimension of the model. Defaults to 512. nhead (int, optional): Number of heads in the multihead attention models. Defaults to 8. d_hid (int, optional): Dimension of the feedforward network model. Defaults to 512. nlayers (int, optional): Number of layers in the transformer model. Defaults to 6. expr_encoder_layers (int, optional): Number of layers in the expression encoder. Defaults to 2. layers_cls (list[int], optional): List specifying the number of layers in the classifier. Defaults to []. classes (Dict[str, int], optional): Classes to predict with the number of classes for each. Defaults to {}. labels_hierarchy (Dict[str, Dict[int, list[int]]], optional): Class hierarchy for classes with hierarchical classes. Defaults to {}. dropout (float, optional): Dropout value. Defaults to 0.2. transformer (str, optional): Transformer type to use. One of \"linear\", \"flash\", \"flashsparse\", \"scprint\". Defaults to \"fast\". domain_spec_batchnorm (str, optional): Whether to apply domain-specific batch normalization. Defaults to \"None\". expr_emb_style (str, optional): Style of input embedding. One of \"continuous\", \"binned_pos\", \"cont_pos\". Defaults to \"continuous\". mvc_decoder (str, optional): Style of MVC decoder. One of \"None\", \"inner product\", \"concat query\", \"sum query\". Defaults to \"None\". pred_embedding (list[str], optional): List of classes to use for plotting embeddings. Defaults to []. cell_emb_style (str, optional): Style of cell embedding. One of \"cls\", \"avg-pool\", \"w-pool\". Defaults to \"cls\". freeze_embeddings (bool, optional): Whether to freeze the embeddings during training. Defaults to True. label_decoders (Optional[Dict[str, Dict[int, str]]], optional): Label decoders to use for plotting the UMAP during validations. Defaults to None. zinb (bool, optional): Whether to use Zero-Inflated Negative Binomial distribution. Defaults to True. lr (float, optional): Learning rate. Defaults to 0.0001. optim (str, optional): Optimizer type. Defaults to \"adamW\". weight_decay (float, optional): Weight decay for the optimizer. Defaults to 0.01. **flash_attention_kwargs (dict): Additional keyword arguments for the model. see @flashformer.py Notes: for other parameters of the model that are not part of its class definition, see @trainer.trainer.py Raises: ValueError: If the expr_emb_style is not one of \"continuous\", \"binned_pos\", \"cont_pos\". \"\"\" super () . __init__ () # training flags self . do_denoise = True self . noise = [ 0.6 ] self . do_cce = False self . cce_sim = 0.5 self . cce_scale = 0.002 self . do_ecs = False self . ecs_threshold = 0.3 self . ecs_scale = 0.05 self . do_mvc = False self . mvc_scale = 1.0 self . class_embd_diss_scale = 0.2 self . do_adv_cls = False self . adv_class_scale = 0.1 self . do_cls = False self . mean_attn_tot = None self . mean_attn_tot_c = 0 self . do_adv_batch = False self . run_full_forward = True self . class_scale = 0.4 self . do_next_tp = False self . do_generate = False self . mask_ratio = [] self . warmup_duration = 500 self . weight_decay = 0.01 self . optim = \"adamW\" self . fused_adam = False self . lr_reduce_patience = 1 self . lr_reduce_factor = 0.6 self . lr_reduce_monitor = \"val_loss\" self . name = \"\" self . lr = lr self . lrfinder_steps = 0 self . doplot = True self . get_attention_layer = [] self . embs = None self . pred_log_adata = True self . attn = utils . Attention ( len ( classes ) + 2 + len ( genes )) self . predict_depth_mult = 3 self . predict_mode = \"none\" self . keep_all_cls_pred = False # should be stored somehow self . d_model = d_model self . normalization = normalization self . organisms = organisms self . edge_dim = edge_dim self . attn_bias = attn_bias self . nlayers = nlayers self . gene_pos_enc = gene_pos_enc self . mvc_decoder = mvc_decoder self . domain_spec_batchnorm = domain_spec_batchnorm # need to store self . n_input_bins = n_input_bins self . transformer = transformer self . label_counts = classes self . classes = list ( classes . keys ()) self . cell_emb_style = cell_emb_style self . label_decoders = label_decoders self . pred_embedding = pred_embedding # compute tensor for mat_labels_hierarchy self . mat_labels_hierarchy = {} self . labels_hierarchy = labels_hierarchy if \"strict_loading\" in flash_attention_kwargs : flash_attention_kwargs . pop ( \"strict_loading\" ) for k , v in labels_hierarchy . items (): tens = torch . zeros (( len ( v ), classes [ k ])) for k2 , v2 in v . items (): tens [ k2 - classes [ k ], v2 ] = 1 self . mat_labels_hierarchy [ k ] = tens . to ( bool ) self . expr_emb_style = expr_emb_style if self . expr_emb_style not in [ \"category\" , \"continuous\" , \"none\" ]: raise ValueError ( f \"expr_emb_style should be one of category, continuous, scaling, \" f \"got { expr_emb_style } \" ) if cell_emb_style not in [ \"cls\" , \"avg-pool\" , \"w-pool\" ]: raise ValueError ( f \"Unknown cell_emb_style: { cell_emb_style } \" ) self . genes = genes self . vocab = { i : n for i , n in enumerate ( genes )} # encoder # gene encoder if precpt_gene_emb is not None : embeddings = pd . read_parquet ( precpt_gene_emb ) . loc [ self . genes ] if len ( embeddings ) == 0 : raise ValueError ( f \"the gene embeddings file { precpt_gene_emb } does not contain any of the genes given to the model\" ) elif len ( embeddings ) < len ( self . genes ): print ( \"Warning: only a subset of the genes available in the embeddings file.\" ) print ( \"number of genes: \" , len ( embeddings )) sembeddings = torch . nn . AdaptiveAvgPool1d ( d_model )( torch . tensor ( embeddings . values ) ) self . gene_encoder = encoders . GeneEncoder ( len ( self . vocab ), d_model , weights = sembeddings , freeze = freeze_embeddings ) else : self . gene_encoder = encoders . GeneEncoder ( len ( self . vocab ), d_model ) # Value Encoder, NOTE: the scaling style is also handled in _encode method if expr_emb_style in [ \"continuous\" , \"full_pos\" ]: self . expr_encoder = encoders . ContinuousValueEncoder ( d_model , dropout , layers = expr_encoder_layers ) elif expr_emb_style == \"binned_pos\" : assert n_input_bins > 0 self . expr_encoder = encoders . CategoryValueEncoder ( n_input_bins , d_model ) else : self . expr_encoder = torch . nn . Identity () # Positional Encoding if self . gene_pos_enc is not None : max_len = max ( gene_pos_enc ) token_to_pos = { token : pos for token , pos in enumerate ( self . gene_pos_enc )} self . pos_encoder = encoders . PositionalEncoding ( d_model , max_len = max_len , token_to_pos = token_to_pos ) self . cell_embs_count = len ( self . classes ) + 2 # Class Encoder # always have [base_cell_emb, time_embedding, depth_embedding] + any other class info # base cell embedding will store other cell specific information self . class_encoder = encoders . CategoryValueEncoder ( self . cell_embs_count - 1 , d_model ) # self.time_encoder = encoders.ContinuousValueEncoder(d_model, dropout) self . depth_encoder = encoders . ContinuousValueEncoder ( d_model , dropout , layers = expr_encoder_layers ) # Transformer # Linear if transformer == \"linear\" : # linear transformer using the fast transformer package # self.transformer = FastTransformerEncoder( # d_model, nhead, d_hid, nlayers, dropout, \"linear\" # ) raise NotImplementedError ( \"Linear transformer is not implemented\" ) # regular or flash else : self . transformer = FlashTransformerEncoder ( d_model , nhead , nlayers , dropout = dropout , use_flash_attn = ( transformer == \"flash\" ), ** flash_attention_kwargs , ) # decoders # expression self . expr_decoder = decoders . ExprDecoder ( d_model , nfirst_tokens_to_skip = self . cell_embs_count , dropout = dropout , zinb = zinb , ) # cls decoder self . cls_decoders = torch . nn . ModuleDict () # should be a very simple classifier for most things # (maybe scale with the number of classes) should be 1 layer... for clss , n_cls in classes . items (): self . cls_decoders [ clss ] = decoders . ClsDecoder ( d_model , n_cls , layers = layers_cls , dropout = dropout ) # Batch effect correction via adversarial training on batch classes if num_batch_labels > 0 : self . grad_reverse_discriminator_loss = loss . AdversarialDiscriminatorLoss ( d_model , n_cls = num_batch_labels , ) else : self . grad_reverse_discriminator_loss = None # expression decoder from batch embbedding if mvc_decoder != \"None\" : self . mvc_decoder = decoders . MVCDecoder ( d_model , arch_style = mvc_decoder , ) else : self . mvc_decoder = None self . apply ( partial ( utils . _init_weights , n_layer = nlayers , ) ) for i , dec in self . cls_decoders . items (): torch . nn . init . constant_ ( dec . out_layer . bias , - 0.13 ) self . save_hyperparameters ()","title":"scPrint"},{"location":"model/#scprint.model.model.scPrint.configure_optimizers","text":"@see pl.LightningModule Source code in scprint/model/model.py 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 def configure_optimizers ( self ): \"\"\"@see pl.LightningModule\"\"\" # https://pytorch.org/docs/stable/generated/torch.optim.Adam.html#torch.optim.Adam # not working because of poor weight decay implem if self . optim == \"adam\" : optimizer = optim . Adam ( self . parameters (), lr = self . hparams . lr , betas = ( 0.9 , 0.999 ), eps = 1e-08 , weight_decay = self . weight_decay , amsgrad = False , fused = self . fused_adam , ) elif self . optim == \"adamW\" : optimizer = optim . AdamW ( self . parameters (), lr = self . hparams . lr , betas = ( 0.9 , 0.999 ), eps = 1e-08 , weight_decay = self . weight_decay , amsgrad = False , fused = self . fused_adam , ) elif self . optim == \"galore\" : raise NotImplementedError ( \"Galore optimizer not implemented\" ) param_groups = [ { \"params\" : [ v for k , v in self . named_parameters () if \"transformer\" not in k ] }, { \"params\" : [ v for k , v in self . named_parameters () if \"transformer\" in k ], \"rank\" : 128 , \"update_proj_gap\" : 200 , \"scale\" : 0.25 , \"proj_type\" : \"std\" , }, ] # optimizer = GaLoreAdamW(param_groups, lr=self.hparams.lr) else : raise ValueError ( f \"Unknown optimizer: { self . optim } \" ) lr_scheduler = optim . lr_scheduler . ReduceLROnPlateau ( optimizer , mode = \"min\" , patience = self . lr_reduce_patience , factor = self . lr_reduce_factor , verbose = True , ) lr_dict = { \"scheduler\" : lr_scheduler , # The unit of the scheduler's step size, could also be 'step'. # 'epoch' updates the scheduler on epoch end whereas 'step' # updates it after a optimizer update. \"interval\" : \"epoch\" , # How many epochs/steps should pass between calls to # `scheduler.step()`. 1 corresponds to updating the learning # rate after every epoch/step. \"frequency\" : 1 , # Metric to to monitor for schedulers like `ReduceLROnPlateau` \"monitor\" : self . lr_reduce_monitor , } self . lrfinder_steps = 0 for val in self . trainer . callbacks : if type ( val ) is _LRCallback : self . lrfinder_steps = val . num_training if type ( val ) is LearningRateFinder : self . lrfinder_steps = val . _num_training_steps return [ optimizer ], [ lr_dict ]","title":"configure_optimizers"},{"location":"model/#scprint.model.model.scPrint.forward","text":"forward also called on self(), a full forward pass on the model Parameters: gene_pos ( Tensor ) \u2013 A tensor of shape (minibatch, seq_len) representing the genes used for each cell in the minibatch. expression ( Tensor , default: None ) \u2013 A tensor of shape (minibatch, seq_len) representing the expression levels of genes in the minibatch. Defaults to None. mask ( Tensor , default: None ) \u2013 A tensor of shape (minibatch, seq_len) used to mask certain elements in the sequence during the forward pass. Defaults to None. full_depth ( Tensor , default: None ) \u2013 A tensor of shape (minibatch,) representing the full depth of each sequence in the minibatch. Defaults to None. timepoint ( Tensor , default: None ) \u2013 A tensor of shape (minibatch,) representing the timepoint associated with each sequence in the minibatch. Defaults to None. get_gene_emb ( bool , default: False ) \u2013 A flag indicating whether to return the gene embeddings. If True, the gene embeddings are included in the output. Defaults to False. do_sample ( bool , default: False ) \u2013 A flag indicating whether to sample the expression levels. If True, the expression levels are sampled during the forward pass. Defaults to False. get_attention_layer ( list , default: [] ) \u2013 A list indicating which attention layers to return. If not empty, the specified attention layers are included in the output. Defaults to []. Returns: \u2013 dict of output Tensors: A dictionary containing the output tensors from the forward pass. The keys of the dictionary depend on the input flags (get_gene_emb, do_sample, get_attention_layer). at minima, the dictionary codntains the following: - \"mean\": the mean expression levels - \"zero_logits\": the logits for zero-inflated expression levels - \"disp\": the dispersion parameter - \"cell_embs\": the cell embeddings per class - \"cell_emb\": the main cell embedding - \"cls_output\": the output of the classifier Source code in scprint/model/model.py 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 def forward ( self , gene_pos : Tensor , expression : Optional [ Tensor ] = None , mask : Optional [ Tensor ] = None , full_depth : Optional [ Tensor ] = None , timepoint : Optional [ Tensor ] = None , # (new_minibatch_of_nxt_cells,) get_gene_emb : bool = False , depth_mult : Optional [ Tensor ] = None , do_sample : bool = False , do_mvc : bool = False , do_class : bool = False , get_attention_layer : list = [], ): \"\"\" forward also called on self(), a full forward pass on the model Args: gene_pos (Tensor): A tensor of shape (minibatch, seq_len) representing the genes used for each cell in the minibatch. expression (Tensor, optional): A tensor of shape (minibatch, seq_len) representing the expression levels of genes in the minibatch. Defaults to None. mask (Tensor, optional): A tensor of shape (minibatch, seq_len) used to mask certain elements in the sequence during the forward pass. Defaults to None. full_depth (Tensor, optional): A tensor of shape (minibatch,) representing the full depth of each sequence in the minibatch. Defaults to None. timepoint (Tensor, optional): A tensor of shape (minibatch,) representing the timepoint associated with each sequence in the minibatch. Defaults to None. get_gene_emb (bool, optional): A flag indicating whether to return the gene embeddings. If True, the gene embeddings are included in the output. Defaults to False. do_sample (bool, optional): A flag indicating whether to sample the expression levels. If True, the expression levels are sampled during the forward pass. Defaults to False. get_attention_layer (list, optional): A list indicating which attention layers to return. If not empty, the specified attention layers are included in the output. Defaults to []. Returns: dict of output Tensors: A dictionary containing the output tensors from the forward pass. The keys of the dictionary depend on the input flags (get_gene_emb, do_sample, get_attention_layer). at minima, the dictionary codntains the following: - \"mean\": the mean expression levels - \"zero_logits\": the logits for zero-inflated expression levels - \"disp\": the dispersion parameter - \"cell_embs\": the cell embeddings per class - \"cell_emb\": the main cell embedding - \"cls_output\": the output of the classifier \"\"\" encoding = self . _encoder ( gene_pos , expression , mask , full_depth , timepoint ) if self . attn_bias != \"none\" : if not hasattr ( self , \"nbias\" ): self . nbias = torch . Tensor ( load_npz ( FILEDIR + \"/../../data/bias_sparse.npz\" ) . todense () ) . to ( device = gene_pos . device , dtype = torch . float16 ) num = len ( self . classes ) + 2 bias = torch . zeros ( ( gene_pos . shape [ 0 ], gene_pos . shape [ 1 ] + num , gene_pos . shape [ 1 ] + num , ), device = gene_pos . device , dtype = torch . float16 , ) bias [:, num :, : num ] = - 10_000 # do not pay attention to the cls embeddings bias [:, num :, num :] = self . nbias [ gene_pos [:, :, None ], gene_pos [:, None , :]] transformer_output = self . transformer ( encoding , return_qkv = get_attention_layer , bias = bias if self . attn_bias != \"none\" else None , bias_layer = list ( range ( self . nlayers - 1 )), ) depth_mult = expression . sum ( 1 ) if depth_mult is None else depth_mult if len ( get_attention_layer ) > 0 : transformer_output , qkvs = transformer_output return ( self . _decoder ( transformer_output , depth_mult , get_gene_emb , do_sample , do_mvc , do_class , ), qkvs , ) else : return self . _decoder ( transformer_output , depth_mult , get_gene_emb , do_sample , do_mvc , do_class , )","title":"forward"},{"location":"model/#scprint.model.model.scPrint.get_cell_embs","text":"get_cell_embs Parameters: layer_output ( Tensor ) \u2013 The output tensor from a layer in the model. Raises: ValueError \u2013 Raised when an unknown cell embedding style is encountered. Returns: Tensor \u2013 The cell embeddings tensor. Source code in scprint/model/model.py 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 def get_cell_embs ( self , layer_output ): \"\"\" get_cell_embs Args: layer_output (Tensor): The output tensor from a layer in the model. Raises: ValueError: Raised when an unknown cell embedding style is encountered. Returns: Tensor: The cell embeddings tensor. \"\"\" if self . cell_emb_style == \"cls\" and self . classes is not None : # (minibatch, embsize) cell_emb = layer_output [:, : 2 + len ( self . classes )] elif self . cell_emb_style == \"avg-pool\" : cell_emb = torch . mean ( layer_output , dim = 1 ) else : raise ValueError ( f \"Unknown cell_emb_style: { self . cell_emb_style } \" ) return cell_emb","title":"get_cell_embs"},{"location":"model/#scprint.model.model.scPrint.log_adata","text":"log_adata will log an adata from predictions. It will log to tensorboard and wandb if available see @utils.log_adata Source code in scprint/model/model.py 1395 1396 1397 1398 1399 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 def log_adata ( self , gtclass = None , name = \"\" ): \"\"\" log_adata will log an adata from predictions. It will log to tensorboard and wandb if available see @utils.log_adata \"\"\" try : mdir = self . logger . save_dir if self . logger . save_dir is not None else \"/tmp\" except : mdir = \"data/\" if not os . path . exists ( mdir ): os . makedirs ( mdir ) adata , fig = utils . make_adata ( self . embs , self . classes , self . pred if not self . keep_all_cls_pred else None , self . attn . get (), self . global_step , self . label_decoders , self . labels_hierarchy , gtclass , self . name + \"_\" + name + \"_\" + str ( self . global_rank ), mdir , self . doplot , ) if self . doplot : try : self . logger . experiment . add_figure ( fig ) except : print ( \"couldn't log to tensorboard\" ) try : self . logger . log_image ( key = \"umaps\" , images = [ fig ]) except : print ( \"couldn't log to wandb\" ) return adata","title":"log_adata"},{"location":"model/#scprint.model.model.scPrint.on_fit_start","text":"@see pl.LightningModule Source code in scprint/model/model.py 641 642 643 644 645 646 647 def on_fit_start ( self ): \"\"\"@see pl.LightningModule\"\"\" if type ( self . transformer ) is FlashTransformerEncoder : for encoder_layers in self . transformer . blocks : encoder_layers . set_seq_parallel ( True ) for k , v in self . mat_labels_hierarchy . items (): self . mat_labels_hierarchy [ k ] = v . to ( self . device )","title":"on_fit_start"},{"location":"model/#scprint.model.model.scPrint.on_predict_epoch_end","text":"@see pl.LightningModule will Source code in scprint/model/model.py 1325 1326 1327 1328 1329 1330 1331 def on_predict_epoch_end ( self ): \"\"\"@see pl.LightningModule will\"\"\" if self . pos . shape [ 0 ] < 100 : return if self . pred_log_adata : print ( \"adding on disk\" ) return self . log_adata ( name = \"predict_part_\" + str ( self . counter ))","title":"on_predict_epoch_end"},{"location":"model/#scprint.model.model.scPrint.on_predict_epoch_start","text":"@see pl.LightningModule Source code in scprint/model/model.py 1126 1127 1128 1129 1130 1131 1132 1133 1134 def on_predict_epoch_start ( self ): \"\"\"@see pl.LightningModule\"\"\" self . embs = None self . attn . data = None self . attn . attn = None self . counter = 0 if type ( self . transformer ) is FlashTransformerEncoder : for encoder_layers in self . transformer . blocks : encoder_layers . set_seq_parallel ( False )","title":"on_predict_epoch_start"},{"location":"model/#scprint.model.model.scPrint.on_validation_epoch_end","text":"@see pl.LightningModule Source code in scprint/model/model.py 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 def on_validation_epoch_end ( self ): \"\"\"@see pl.LightningModule\"\"\" self . embs = self . all_gather ( self . embs ) . view ( - 1 , self . embs . shape [ - 1 ]) self . info = self . all_gather ( self . info ) . view ( - 1 , self . info . shape [ - 1 ]) self . pred = ( self . all_gather ( self . pred ) . view ( - 1 , self . pred . shape [ - 1 ]) if self . pred is not None else None ) self . pos = self . all_gather ( self . pos ) . view ( - 1 , self . pos . shape [ - 1 ]) if not self . trainer . is_global_zero : # print(\"you are not on the main node. cancelling logging step\") return if self . trainer . state . stage != \"sanity_check\" : sch = self . lr_schedulers () sch . step ( self . trainer . callback_metrics [ \"val_loss\" ]) # run the test function on specific dataset self . log_adata ( gtclass = self . info , name = \"validation_part_\" + str ( self . counter ) ) if ( self . current_epoch + 1 ) % 30 == 0 : self . on_test_epoch_end ()","title":"on_validation_epoch_end"},{"location":"model/#scprint.model.model.scPrint.optimizer_step","text":"@see pl.LightningModule Source code in scprint/model/model.py 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 def optimizer_step ( self , epoch , batch_idx , optimizer , optimizer_closure ): \"\"\"@see pl.LightningModule\"\"\" # update params optimizer . step ( closure = optimizer_closure ) # manually warm up lr without a scheduler # making sure that we don't do this during lrfinder for i , pg in enumerate ( optimizer . param_groups ): if ( self . global_step < self . warmup_duration + self . lrfinder_steps ) and self . lrfinder_steps < self . global_step : lr_scale = min ( 1.0 , float ( self . global_step + 1 ) / self . warmup_duration ) pg [ \"lr\" ] = lr_scale * self . hparams . lr for i , pg in enumerate ( optimizer . param_groups ): # if pg[\"lr\"] < 2e-5: # pg[\"lr\"] = 2e-5 self . log ( \"lr_\" + str ( i ), pg [ \"lr\" ])","title":"optimizer_step"},{"location":"model/#scprint.model.model.scPrint.predict_step","text":"embed given gene expression, encode the gene embedding and cell embedding. Returns: Tensor \u2013 description Source code in scprint/model/model.py 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 def predict_step ( self , batch , batch_idx ): \"\"\" embed given gene expression, encode the gene embedding and cell embedding. Args: batch @see training_step Returns: Tensor: _description_ \"\"\" return self . _predict ( batch [ \"genes\" ], batch [ \"x\" ], batch [ \"depth\" ], self . predict_mode , self . pred_embedding , self . get_attention_layer , self . predict_depth_mult , )","title":"predict_step"},{"location":"model/#scprint.model.model.scPrint.training_step","text":"training_step defines the train loop. It is independent of forward @see pl.LightningModule Returns: _type_ \u2013 description Source code in scprint/model/model.py 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 def training_step ( self , batch : Dict [ str , Tensor ], batch_idx , ): \"\"\" training_step defines the train loop. It is independent of forward @see pl.LightningModule Returns: _type_: _description_ \"\"\" # TASK 1 & 2 & 3 (first pass, expression reconstruction, label prediction) total_loss , losses = self . _full_training ( batch = batch , do_denoise = self . do_denoise , noise = self . noise , do_next_tp = self . do_next_tp , do_cce = self . do_cce , cce_sim = self . cce_sim , do_ecs = self . do_ecs , do_mvc = self . do_mvc , do_adv_cls = self . do_adv_cls , do_adv_batch = self . do_adv_batch , do_cls = self . do_cls , do_generate = self . do_generate , run_full_forward = self . run_full_forward , mask_ratio = self . mask_ratio , ) self . log ( \"train_loss\" , total_loss , prog_bar = True , sync_dist = True ) self . log_dict ( losses , prog_bar = True , sync_dist = True ) return total_loss","title":"training_step"},{"location":"model/#scprint.model.model.scPrint.validation_step","text":"validation_step defines the validation loop. It is independent of forward @see pl.LightningModule Parameters: batch ( list [ Tensor ] ) \u2013 @see training_step Source code in scprint/model/model.py 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 def validation_step ( self , batch , batch_idx , ): \"\"\" validation_step defines the validation loop. It is independent of forward @see pl.LightningModule Args: batch (list[Tensor]): @see training_step \"\"\" val_loss , losses = self . _full_training ( batch = batch , do_denoise = self . do_denoise , noise = self . noise , do_next_tp = self . do_next_tp , do_cce = self . do_cce , cce_sim = self . cce_sim , do_ecs = self . do_ecs , do_mvc = self . do_mvc , do_adv_cls = self . do_adv_cls , do_adv_batch = self . do_adv_batch , do_cls = self . do_cls , do_generate = self . do_generate , run_full_forward = self . run_full_forward , mask_ratio = self . mask_ratio , ) expression = batch [ \"x\" ] gene_pos = batch [ \"genes\" ] depth = batch [ \"depth\" ] # TODO: make this faster by only calling val loss if self . embs is not None : if self . embs . shape [ 0 ] < 100_000 : self . info = torch . cat ([ self . info , batch [ \"class\" ]]) self . _predict ( gene_pos , expression , depth , pred_embedding = self . pred_embedding , max_size_in_mem = 100_000 , ) else : self . info = batch [ \"class\" ] self . _predict ( gene_pos , expression , depth , pred_embedding = self . pred_embedding , max_size_in_mem = 100_000 , ) self . log ( \"val_loss\" , val_loss , sync_dist = True ) self . log_dict ( losses , sync_dist = True ) return val_loss","title":"validation_step"},{"location":"model/#losses","text":"","title":"losses"},{"location":"model/#scprint.model.loss","text":"","title":"loss"},{"location":"model/#scprint.model.loss.AdversarialDiscriminatorLoss","text":"Bases: Module Discriminator for the adversarial training for batch correction. Parameters: d_model ( int ) \u2013 The size of the input tensor. n_cls ( int ) \u2013 The number of classes. nlayers ( int , default: 3 ) \u2013 The number of layers in the discriminator. Defaults to 3. activation ( callable , default: LeakyReLU ) \u2013 The activation function. Defaults to nn.LeakyReLU. reverse_grad ( bool , default: True ) \u2013 Whether to reverse the gradient. Defaults Source code in scprint/model/loss.py 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 def __init__ ( self , d_model : int , n_cls : int , nlayers : int = 3 , activation : callable = nn . LeakyReLU , reverse_grad : bool = True , ): \"\"\" Discriminator for the adversarial training for batch correction. Args: d_model (int): The size of the input tensor. n_cls (int): The number of classes. nlayers (int, optional): The number of layers in the discriminator. Defaults to 3. activation (callable, optional): The activation function. Defaults to nn.LeakyReLU. reverse_grad (bool, optional): Whether to reverse the gradient. Defaults \"\"\" super () . __init__ () # module list self . decoder = nn . ModuleList () for _ in range ( nlayers - 1 ): self . decoder . append ( nn . Linear ( d_model , d_model )) self . decoder . append ( nn . LayerNorm ( d_model )) self . decoder . append ( activation ()) self . out_layer = nn . Linear ( d_model , n_cls ) self . reverse_grad = reverse_grad","title":"AdversarialDiscriminatorLoss"},{"location":"model/#scprint.model.loss.AdversarialDiscriminatorLoss.forward","text":"Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, embsize] Source code in scprint/model/loss.py 302 303 304 305 306 307 308 309 310 311 312 def forward ( self , x : Tensor , batch_labels : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, embsize] \"\"\" if self . reverse_grad : x = grad_reverse ( x , lambd = 1.0 ) for layer in self . decoder : x = layer ( x ) x = self . out_layer ( x ) return F . cross_entropy ( x , batch_labels )","title":"forward"},{"location":"model/#scprint.model.loss.classification","text":"Computes the classification loss for a given batch of predictions and ground truth labels. Parameters: clsname ( str ) \u2013 The name of the label. pred ( Tensor ) \u2013 The predicted logits for the batch. cl ( Tensor ) \u2013 The ground truth labels for the batch. maxsize ( int ) \u2013 The number of possible labels. labels_hierarchy ( dict , default: {} ) \u2013 The hierarchical structure of the labels. Defaults to {}. Raises: ValueError \u2013 If the clsname is not found in the labels_hierarchy dictionary. Returns: Tensor ( Tensor ) \u2013 The computed binary cross entropy loss for the given batch. Source code in scprint/model/loss.py 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 def classification ( clsname : str , pred : torch . Tensor , cl : torch . Tensor , maxsize : int , labels_hierarchy : Optional [ Dict [ str , Dict [ int , list [ int ]]]] = {}, ) -> torch . Tensor : \"\"\" Computes the classification loss for a given batch of predictions and ground truth labels. Args: clsname (str): The name of the label. pred (Tensor): The predicted logits for the batch. cl (Tensor): The ground truth labels for the batch. maxsize (int): The number of possible labels. labels_hierarchy (dict, optional): The hierarchical structure of the labels. Defaults to {}. Raises: ValueError: If the clsname is not found in the labels_hierarchy dictionary. Returns: Tensor: The computed binary cross entropy loss for the given batch. \"\"\" newcl = torch . zeros ( ( cl . shape [ 0 ], maxsize ), device = cl . device ) # batchsize * n_labels # if we don't know the label we set the weight to 0 else to 1 valid_indices = ( cl != - 1 ) & ( cl < maxsize ) valid_cl = cl [ valid_indices ] newcl [ valid_indices , valid_cl ] = 1 weight = torch . ones_like ( newcl , device = cl . device ) weight [ cl == - 1 , :] = 0 inv = cl >= maxsize # if we have non leaf values, we don't know so we don't compute grad and set weight to 0 # and add labels that won't be counted but so that we can still use them if inv . any (): if clsname in labels_hierarchy . keys (): clhier = labels_hierarchy [ clsname ] inv_weight = weight [ inv ] # we set the weight of the elements that are not leaf to 0 # i.e. the elements where we will compute the max inv_weight [ clhier [ cl [ inv ] - maxsize ]] = 0 weight [ inv ] = inv_weight addnewcl = torch . ones ( weight . shape [ 0 ], device = pred . device ) # no need to set the other to 0 as the weight of the loss is set to 0 addweight = torch . zeros ( weight . shape [ 0 ], device = pred . device ) addweight [ inv ] = 1 # computing hierarchical labels and adding them to cl addpred = pred . clone () # we only keep the elements where we need to compute the max, # for the rest we set them to -inf, so that they won't have any impact on the max() inv_addpred = addpred [ inv ] inv_addpred [ inv_weight . to ( bool )] = torch . finfo ( pred . dtype ) . min addpred [ inv ] = inv_addpred # differentiable max addpred = torch . logsumexp ( addpred , dim =- 1 ) # we add the new labels to the cl newcl = torch . cat ([ newcl , addnewcl . unsqueeze ( 1 )], dim = 1 ) pred = torch . cat ([ pred , addpred . unsqueeze ( 1 )], dim = 1 ) weight = torch . cat ([ weight , addweight . unsqueeze ( 1 )], dim = 1 ) else : raise ValueError ( \"need to use labels_hierarchy for this usecase\" ) myloss = torch . nn . functional . binary_cross_entropy_with_logits ( pred , target = newcl , weight = weight ) return myloss","title":"classification"},{"location":"model/#scprint.model.loss.criterion_neg_log_bernoulli","text":"Compute the negative log-likelihood of Bernoulli distribution Source code in scprint/model/loss.py 143 144 145 146 147 148 149 150 def criterion_neg_log_bernoulli ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the negative log-likelihood of Bernoulli distribution \"\"\" mask = mask . float () bernoulli = torch . distributions . Bernoulli ( probs = input ) masked_log_probs = bernoulli . log_prob (( target > 0 ) . float ()) * mask return - masked_log_probs . sum () / mask . sum ()","title":"criterion_neg_log_bernoulli"},{"location":"model/#scprint.model.loss.ecs","text":"ecs Computes the similarity of cell embeddings based on a threshold. Parameters: cell_emb ( Tensor ) \u2013 A tensor representing cell embeddings. ecs_threshold ( float , default: 0.5 ) \u2013 A threshold for determining similarity. Defaults to 0.5. Returns: Tensor ( Tensor ) \u2013 A tensor representing the mean of 1 minus the square of the difference between the cosine similarity and the threshold. Source code in scprint/model/loss.py 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 def ecs ( cell_emb : Tensor , ecs_threshold : float = 0.5 ) -> Tensor : \"\"\" ecs Computes the similarity of cell embeddings based on a threshold. Args: cell_emb (Tensor): A tensor representing cell embeddings. ecs_threshold (float, optional): A threshold for determining similarity. Defaults to 0.5. Returns: Tensor: A tensor representing the mean of 1 minus the square of the difference between the cosine similarity and the threshold. \"\"\" # Here using customized cosine similarity instead of F.cosine_similarity # to avoid the pytorch issue of similarity larger than 1.0, pytorch # 78064 # normalize the embedding cell_emb_normed = F . normalize ( cell_emb , p = 2 , dim = 1 ) cos_sim = torch . mm ( cell_emb_normed , cell_emb_normed . t ()) # mask out diagnal elements mask = torch . eye ( cos_sim . size ( 0 )) . bool () . to ( cos_sim . device ) cos_sim = cos_sim . masked_fill ( mask , 0.0 ) # only optimize positive similarities cos_sim = F . relu ( cos_sim ) return torch . mean ( 1 - ( cos_sim - ecs_threshold ) ** 2 )","title":"ecs"},{"location":"model/#scprint.model.loss.grad_reverse","text":"grad_reverse Reverses the gradient of the input tensor. Parameters: x ( Tensor ) \u2013 The input tensor whose gradient is to be reversed. lambd ( float , default: 1.0 ) \u2013 The scaling factor for the reversed gradient. Defaults to 1.0. Returns: Tensor ( Tensor ) \u2013 The input tensor with its gradient reversed during the backward pass. Source code in scprint/model/loss.py 326 327 328 329 330 331 332 333 334 335 336 337 def grad_reverse ( x : Tensor , lambd : float = 1.0 ) -> Tensor : \"\"\" grad_reverse Reverses the gradient of the input tensor. Args: x (Tensor): The input tensor whose gradient is to be reversed. lambd (float, optional): The scaling factor for the reversed gradient. Defaults to 1.0. Returns: Tensor: The input tensor with its gradient reversed during the backward pass. \"\"\" return GradReverse . apply ( x , lambd )","title":"grad_reverse"},{"location":"model/#scprint.model.loss.masked_mae","text":"Compute the masked MAE loss between input and target. MAE = mean absolute error Source code in scprint/model/loss.py 29 30 31 32 33 34 35 36 def masked_mae ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked MAE loss between input and target. MAE = mean absolute error \"\"\" mask = mask . float () loss = F . l1_loss ( input * mask , target * mask , reduction = \"sum\" ) return loss / mask . sum ()","title":"masked_mae"},{"location":"model/#scprint.model.loss.masked_mse","text":"Compute the masked MSE loss between input and target. Source code in scprint/model/loss.py 20 21 22 23 24 25 26 def masked_mse ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked MSE loss between input and target. \"\"\" mask = mask . float () loss = F . mse_loss ( input * mask , target * mask , reduction = \"sum\" ) return loss / mask . sum ()","title":"masked_mse"},{"location":"model/#scprint.model.loss.masked_nb","text":"Compute the masked negative binomial loss between input and target. Source code in scprint/model/loss.py 39 40 41 42 43 44 45 46 def masked_nb ( input : Tensor , target : Tensor , mask : Tensor ) -> Tensor : \"\"\" Compute the masked negative binomial loss between input and target. \"\"\" mask = mask . float () nb = torch . distributions . NegativeBinomial ( total_count = target , probs = input ) masked_log_probs = nb . log_prob ( target ) * mask return - masked_log_probs . sum () / mask . sum ()","title":"masked_nb"},{"location":"model/#scprint.model.loss.masked_relative_error","text":"Compute the masked relative error between input and target. Source code in scprint/model/loss.py 153 154 155 156 157 158 159 160 161 def masked_relative_error ( input : Tensor , target : Tensor , mask : torch . LongTensor ) -> Tensor : \"\"\" Compute the masked relative error between input and target. \"\"\" assert mask . any () loss = torch . abs ( input [ mask ] - target [ mask ]) / ( target [ mask ] + 1e-6 ) return loss . mean ()","title":"masked_relative_error"},{"location":"model/#scprint.model.loss.mse","text":"Compute the MSE loss between input and target. Source code in scprint/model/loss.py 9 10 11 12 13 14 15 16 17 def mse ( input : Tensor , target : Tensor ) -> Tensor : \"\"\" Compute the MSE loss between input and target. \"\"\" input = torch . log2 ( input + 1 ) input = ( input / torch . sum ( input , dim = 1 , keepdim = True )) * 10000 target = torch . log2 ( target + 1 ) target = target / torch . sum ( target , dim = 1 , keepdim = True ) * 10000 return F . mse_loss ( input , target , reduction = \"mean\" )","title":"mse"},{"location":"model/#scprint.model.loss.nb","text":"Computes the negative binomial (NB) loss. This function was adapted from scvi-tools. Parameters: target ( Tensor ) \u2013 Ground truth data. mu ( Tensor ) \u2013 Means of the negative binomial distribution (must have positive support). theta ( Tensor ) \u2013 Inverse dispersion parameter (must have positive support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 NB loss value. Source code in scprint/model/loss.py 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 def nb ( target : Tensor , mu : Tensor , theta : Tensor , eps = 1e-8 ): \"\"\" Computes the negative binomial (NB) loss. This function was adapted from scvi-tools. Args: target (Tensor): Ground truth data. mu (Tensor): Means of the negative binomial distribution (must have positive support). theta (Tensor): Inverse dispersion parameter (must have positive support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: NB loss value. \"\"\" if theta . ndimension () == 1 : theta = theta . view ( 1 , theta . size ( 0 )) log_theta_mu_eps = torch . log ( theta + mu + eps ) res = ( theta * ( torch . log ( theta + eps ) - log_theta_mu_eps ) + target * ( torch . log ( mu + eps ) - log_theta_mu_eps ) + torch . lgamma ( target + theta ) - torch . lgamma ( theta ) - torch . lgamma ( target + 1 ) ) return - res . mean ()","title":"nb"},{"location":"model/#scprint.model.loss.nb_dist","text":"nb_dist Computes the negative binomial distribution. Parameters: x ( Tensor ) \u2013 Torch Tensor of observed data. mu ( Tensor ) \u2013 Torch Tensor of means of the negative binomial distribution (must have positive support). theta ( Tensor ) \u2013 Torch Tensor of inverse dispersion parameter (must have positive support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 Negative binomial loss value. Source code in scprint/model/loss.py 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 def nb_dist ( x : Tensor , mu : Tensor , theta : Tensor , eps = 1e-8 ): \"\"\" nb_dist Computes the negative binomial distribution. Args: x (Tensor): Torch Tensor of observed data. mu (Tensor): Torch Tensor of means of the negative binomial distribution (must have positive support). theta (Tensor): Torch Tensor of inverse dispersion parameter (must have positive support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: Negative binomial loss value. \"\"\" loss = - NegativeBinomial ( mu = mu , theta = theta ) . log_prob ( x ) return loss","title":"nb_dist"},{"location":"model/#scprint.model.loss.similarity","text":"Dot product or cosine similarity Source code in scprint/model/loss.py 164 165 166 167 168 169 170 def similarity ( x : Tensor , y : Tensor , temp : float ) -> Tensor : \"\"\" Dot product or cosine similarity \"\"\" res = F . cosine_similarity ( x . unsqueeze ( 1 ), y . unsqueeze ( 0 )) / temp labels = torch . arange ( res . size ( 0 )) . long () . to ( device = res . device ) return F . cross_entropy ( res , labels )","title":"similarity"},{"location":"model/#scprint.model.loss.zinb","text":"Computes zero-inflated negative binomial (ZINB) loss. This function was modified from scvi-tools. Parameters: target ( Tensor ) \u2013 Torch Tensor of ground truth data. mu ( Tensor ) \u2013 Torch Tensor of means of the negative binomial (must have positive support). theta ( Tensor ) \u2013 Torch Tensor of inverse dispersion parameter (must have positive support). pi ( Tensor ) \u2013 Torch Tensor of logits of the dropout parameter (real support). eps ( float , default: 1e-08 ) \u2013 Numerical stability constant. Defaults to 1e-8. Returns: Tensor \u2013 ZINB loss value. Source code in scprint/model/loss.py 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 def zinb ( target : Tensor , mu : Tensor , theta : Tensor , pi : Tensor , eps = 1e-8 , ): \"\"\" Computes zero-inflated negative binomial (ZINB) loss. This function was modified from scvi-tools. Args: target (Tensor): Torch Tensor of ground truth data. mu (Tensor): Torch Tensor of means of the negative binomial (must have positive support). theta (Tensor): Torch Tensor of inverse dispersion parameter (must have positive support). pi (Tensor): Torch Tensor of logits of the dropout parameter (real support). eps (float, optional): Numerical stability constant. Defaults to 1e-8. Returns: Tensor: ZINB loss value. \"\"\" # uses log(sigmoid(x)) = -softplus(-x) softplus_pi = F . softplus ( - pi ) # eps to make it positive support and taking the log log_theta_mu_eps = torch . log ( theta + mu + eps ) pi_theta_log = - pi + theta * ( torch . log ( theta + eps ) - log_theta_mu_eps ) case_zero = F . softplus ( pi_theta_log ) - softplus_pi mul_case_zero = torch . mul (( target < eps ) . type ( torch . float32 ), case_zero ) case_non_zero = ( - softplus_pi + pi_theta_log + target * ( torch . log ( mu + eps ) - log_theta_mu_eps ) + torch . lgamma ( target + theta ) - torch . lgamma ( theta ) - torch . lgamma ( target + 1 ) ) mul_case_non_zero = torch . mul (( target > eps ) . type ( torch . float32 ), case_non_zero ) res = mul_case_zero + mul_case_non_zero # we want to minize the loss but maximize the log likelyhood return - res . mean ()","title":"zinb"},{"location":"model/#utils","text":"","title":"utils"},{"location":"model/#scprint.model.utils","text":"","title":"utils"},{"location":"model/#scprint.model.utils.Attention","text":"Initialize the Attention class. Parameters: gene_dim ( int ) \u2013 The dimension of the gene. comp_attn ( bool , default: False ) \u2013 Whether to compute attention. Defaults to False. Source code in scprint/model/utils.py 472 473 474 475 476 477 478 479 480 481 482 483 484 def __init__ ( self , gene_dim : int , comp_attn : bool = False ): \"\"\" Initialize the Attention class. Args: gene_dim (int): The dimension of the gene. comp_attn (bool, optional): Whether to compute attention. Defaults to False. \"\"\" self . data : Optional [ Tensor ] = None self . gene_dim : int = gene_dim self . div : Optional [ Tensor ] = None self . attn : Optional [ Tensor ] = None self . comp_attn : bool = comp_attn","title":"Attention"},{"location":"model/#scprint.model.utils.Attention.add","text":"Add data to the internal storage. Parameters: x ( List [ Tensor ] ) \u2013 List of tensors to add. pos ( Tensor ) \u2013 Position tensor. Source code in scprint/model/utils.py 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 def add ( self , x : List [ Tensor ], pos : Tensor ) -> None : \"\"\" Add data to the internal storage. Args: x (List[Tensor]): List of tensors to add. pos (Tensor): Position tensor. \"\"\" pos = pos . detach () . to ( \"cpu\" ) if self . data is None : self . data = torch . zeros ([ len ( x ), self . gene_dim ] + list ( x [ 0 ] . shape [ 2 :])) self . div = torch . zeros ( self . gene_dim ) for i in range ( x [ 0 ] . shape [ 0 ]): # loc = torch.cat([torch.Tensor([r for r in range(8)]), pos[i] + 8]).int() self . data . append ( torch . cat ([ x [ j ][ i ] . detach () . to ( \"cpu\" ) for j in range ( len ( x ))]) )","title":"add"},{"location":"model/#scprint.model.utils.Attention.agg","text":"Aggregate the attention or data based on the comp_attn flag. Parameters: x ( List [ Tensor ] ) \u2013 List of tensors to aggregate. pos ( Tensor ) \u2013 Position tensor. Source code in scprint/model/utils.py 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 def agg ( self , x : List [ Tensor ], pos : Tensor ) -> None : \"\"\" Aggregate the attention or data based on the comp_attn flag. Args: x (List[Tensor]): List of tensors to aggregate. pos (Tensor): Position tensor. \"\"\" if self . comp_attn : if self . attn is None : self . attn = torch . zeros ([ self . gene_dim , self . gene_dim ], device = \"cuda\" ) self . div = torch . zeros ( self . gene_dim , device = \"cuda\" ) for j in range ( x [ 0 ] . shape [ 0 ]): # \u2022cells, \u2022context, \u2022QK, \u2022heads, \u2022dim loc = torch . cat ([ torch . arange ( 8 , device = \"cuda\" ), pos [ j ] + 8 ]) . int () for i in range ( len ( x )): for k in range ( x [ 0 ] . shape [ 3 ]): self . attn [ loc [:, None ], loc ] += torch . nn . functional . softmax ( ( x [ i ][ j , :, 0 , k , :] @ x [ i ][ j , :, 1 , k , :] . T ) * ( x [ 0 ] . shape [ - 1 ] ** - 0.5 ), dim =- 1 , ) self . div [ loc ] += x [ 0 ] . shape [ 3 ] * len ( x ) torch . cuda . empty_cache () else : pos = pos . detach () . to ( \"cpu\" ) if self . data is None : self . data = torch . zeros ([ len ( x ), self . gene_dim ] + list ( x [ 0 ] . shape [ 2 :])) self . div = torch . zeros ( self . gene_dim ) for i in range ( x [ 0 ] . shape [ 0 ]): loc = torch . cat ([ torch . arange ( 8 ), pos [ i ] + 8 ]) . int () for j in range ( len ( x )): self . data [ j , loc , :, :, :] += x [ j ][ i ] . detach () . to ( \"cpu\" ) self . div [ loc ] += 1","title":"agg"},{"location":"model/#scprint.model.utils.Attention.get","text":"Get the aggregated attention or data. Returns: Optional [ ndarray ] \u2013 Optional[np.ndarray]: The aggregated attention or data. Source code in scprint/model/utils.py 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 def get ( self ) -> Optional [ np . ndarray ]: \"\"\" Get the aggregated attention or data. Returns: Optional[np.ndarray]: The aggregated attention or data. \"\"\" if self . comp_attn : loc = self . attn . sum ( 1 ) != 0 return ( ( self . attn [ loc ][:, loc ] / ( self . attn . sum ( 1 )[ loc ] + 0.0001 )) . detach () . cpu () . numpy () ) else : if self . data is None : return None # shape is (layers, genes, qkv, heads, emb) return self . data / self . div . view ( 1 , self . div . shape [ 0 ], 1 , 1 , 1 )","title":"get"},{"location":"model/#scprint.model.utils.downsample_profile","text":"This function downsamples the expression profile of a given single cell RNA matrix. The noise is applied based on the renoise parameter, the total counts of the matrix, and the number of genes. The function first calculates the noise threshold (scaler) based on the renoise parameter. It then generates an initial matrix count by applying a Poisson distribution to a random tensor scaled by the total counts and the number of genes. The function then models the sampling zeros by applying a Poisson distribution to a random tensor scaled by the noise threshold, the total counts, and the number of genes. The function also models the technical zeros by generating a random tensor and comparing it to the noise threshold. The final matrix count is calculated by subtracting the sampling zeros from the initial matrix count and multiplying by the technical zeros. The function ensures that the final matrix count is not less than zero by taking the maximum of the final matrix count and a tensor of zeros. The function returns the final matrix count. Parameters: mat ( Tensor ) \u2013 The input matrix. dropout ( float ) \u2013 The renoise parameter. Returns: \u2013 torch.Tensor: The matrix count after applying noise. Source code in scprint/model/utils.py 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 def downsample_profile ( mat : Tensor , dropout : float , method = \"new\" ): \"\"\" This function downsamples the expression profile of a given single cell RNA matrix. The noise is applied based on the renoise parameter, the total counts of the matrix, and the number of genes. The function first calculates the noise threshold (scaler) based on the renoise parameter. It then generates an initial matrix count by applying a Poisson distribution to a random tensor scaled by the total counts and the number of genes. The function then models the sampling zeros by applying a Poisson distribution to a random tensor scaled by the noise threshold, the total counts, and the number of genes. The function also models the technical zeros by generating a random tensor and comparing it to the noise threshold. The final matrix count is calculated by subtracting the sampling zeros from the initial matrix count and multiplying by the technical zeros. The function ensures that the final matrix count is not less than zero by taking the maximum of the final matrix count and a tensor of zeros. The function returns the final matrix count. Args: mat (torch.Tensor): The input matrix. dropout (float): The renoise parameter. Returns: torch.Tensor: The matrix count after applying noise. \"\"\" # Randomly drop on average N counts to each element of expression using a heavy tail Gaussian distribution # here we try to get the scale of the distribution so as to remove the right number of counts from each gene # https://genomebiology.biomedcentral.com/articles/10.1186/s13059-022-02601-5#:~:text=Zero%20measurements%20in%20scRNA%2Dseq,generation%20of%20scRNA%2Dseq%20data. if method == \"old\" : totcounts = mat . sum ( 1 ) batch = mat . shape [ 0 ] ngenes = mat . shape [ 1 ] tnoise = 1 - ( 1 - dropout ) ** ( 1 / 2 ) # we model the sampling zeros (dropping 30% of the reads) res = torch . poisson ( torch . rand (( batch , ngenes )) . to ( device = mat . device ) * (( tnoise * totcounts . unsqueeze ( 1 )) / ( 0.5 * ngenes )) ) . int () # we model the technical zeros (dropping 50% of the genes) drop = ( torch . rand (( batch , ngenes )) > tnoise ) . int () . to ( device = mat . device ) mat = ( mat - res ) * drop return torch . maximum ( mat , torch . Tensor ([[ 0 ]]) . to ( device = mat . device )) . int () elif method == \"jules\" : scaler = ( 1 - dropout ) ** ( 1 / 2 ) notdrop = ( torch . rand ( mat . shape , device = mat . device , ) < scaler ) . int () notdrop [ mat == 0 ] = 0 # apply the dropout after the poisson, right? return notdrop * torch . poisson ( mat * scaler ) elif method == \"new\" : batch = mat . shape [ 0 ] ngenes = mat . shape [ 1 ] dropout = dropout * 1.1 # we model the sampling zeros (dropping 30% of the reads) res = torch . poisson (( mat * ( dropout / 2 ))) . int () # we model the technical zeros (dropping 50% of the genes) notdrop = ( torch . rand (( batch , ngenes ), device = mat . device ) >= ( dropout / 2 ) ) . int () mat = ( mat - res ) * notdrop return torch . maximum ( mat , torch . zeros (( 1 , 1 ), device = mat . device , dtype = torch . int ) ) else : raise ValueError ( f \"method { method } not recognized\" )","title":"downsample_profile"},{"location":"model/#scprint.model.utils.make_adata","text":"This function creates an AnnData object from the given input parameters. Parameters: embs ( Tensor ) \u2013 Embeddings of the cells. The shape of the tensor is (n_cells, n_features). labels ( list ) \u2013 List of labels for the predicted classes. pred ( Tensor , default: None ) \u2013 Predicted labels. The shape of the tensor is (n_cells, n_classes). Default is None. attention ( Tensor , default: None ) \u2013 Attention weights. Default is None. step ( int , default: 0 ) \u2013 Step number for storing the AnnData without overwriting others. Default is 0. label_decoders ( dict , default: None ) \u2013 Dictionary to map class codes to class names. Default is None. labels_hierarchy ( dict , default: {} ) \u2013 Dictionary representing the hierarchy of labels. Default is {}. gtclass ( Tensor , default: None ) \u2013 Ground truth class. Default is None. name ( str , default: '' ) \u2013 Name of the AnnData object. Default is an empty string. mdir ( str , default: '/tmp' ) \u2013 Directory to save the AnnData object. Default is \"/tmp\". doplot ( bool , default: True ) \u2013 Whether to generate plots. Default is True. Returns: \u2013 anndata.AnnData: The created AnnData object. Source code in scprint/model/utils.py 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 def make_adata ( embs : Tensor , labels : List [ str ], pred : Tensor = None , attention : Optional [ Tensor ] = None , step : int = 0 , label_decoders : Optional [ Dict ] = None , labels_hierarchy : Dict = {}, gtclass : Optional [ Tensor ] = None , name : str = \"\" , mdir : str = \"/tmp\" , doplot : bool = True , ): \"\"\" This function creates an AnnData object from the given input parameters. Args: embs (torch.Tensor): Embeddings of the cells. The shape of the tensor is (n_cells, n_features). labels (list): List of labels for the predicted classes. pred (torch.Tensor, optional): Predicted labels. The shape of the tensor is (n_cells, n_classes). Default is None. attention (torch.Tensor, optional): Attention weights. Default is None. step (int, optional): Step number for storing the AnnData without overwriting others. Default is 0. label_decoders (dict, optional): Dictionary to map class codes to class names. Default is None. labels_hierarchy (dict, optional): Dictionary representing the hierarchy of labels. Default is {}. gtclass (torch.Tensor, optional): Ground truth class. Default is None. name (str, optional): Name of the AnnData object. Default is an empty string. mdir (str, optional): Directory to save the AnnData object. Default is \"/tmp\". doplot (bool, optional): Whether to generate plots. Default is True. Returns: anndata.AnnData: The created AnnData object. \"\"\" colname = [ \"pred_\" + i for i in labels ] if pred is not None : obs = np . array ( pred . to ( device = \"cpu\" , dtype = torch . int32 )) # label decoders is not cls_decoders. one is a dict to map class codes (ints) # to class names the other is the module the predict the class if label_decoders is not None : obs = np . array ( [ [ label_decoders [ labels [ i ]][ n ] for n in name ] for i , name in enumerate ( obs . T ) ] ) . T if gtclass is not None : colname += labels nobs = np . array ( gtclass . to ( device = \"cpu\" , dtype = torch . int32 )) if label_decoders is not None : nobs = np . array ( [ [ label_decoders [ labels [ i ]][ n ] for n in name ] for i , name in enumerate ( nobs . T ) ] ) . T obs = np . hstack ([ obs , nobs ]) adata = AnnData ( np . array ( embs . to ( device = \"cpu\" , dtype = torch . float32 )), obs = pd . DataFrame ( obs , columns = colname , ), ) accuracy = {} for label in labels : if gtclass is not None : tr = translate ( adata . obs [ label ] . tolist (), label ) if tr is not None : adata . obs [ \"conv_\" + label ] = adata . obs [ label ] . replace ( tr ) tr = translate ( adata . obs [ \"pred_\" + label ] . tolist (), label ) if tr is not None : adata . obs [ \"conv_pred_\" + label ] = adata . obs [ \"pred_\" + label ] . replace ( tr ) res = [] if label_decoders is not None and gtclass is not None : class_topred = label_decoders [ label ] . values () if label in labels_hierarchy : cur_labels_hierarchy = { label_decoders [ label ][ k ]: [ label_decoders [ label ][ i ] for i in v ] for k , v in labels_hierarchy [ label ] . items () } else : cur_labels_hierarchy = {} for pred , true in adata . obs [[ \"pred_\" + label , label ]] . values : if pred == true : res . append ( True ) continue if len ( labels_hierarchy ) > 0 : if true in cur_labels_hierarchy : res . append ( pred in cur_labels_hierarchy [ true ]) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) else : pass accuracy [ \"pred_\" + label ] = sum ( res ) / len ( res ) if len ( res ) > 0 else 0 adata . obs = adata . obs . astype ( \"category\" ) else : adata = AnnData ( np . array ( embs . to ( device = \"cpu\" , dtype = torch . float32 )), ) if False : adata . varm [ \"Qs\" ] = ( attention [:, :, 0 , :, :] . permute ( 1 , 3 , 0 , 2 ) . view ( attention . shape [ 0 ], attention . shape [ 1 ], attention . shape [ 3 ] * attention . shape [ 4 ], ) . detach () . cpu () . numpy () ) adata . varm [ \"Ks\" ] = ( attention [:, :, 1 , :, :] . permute ( 1 , 3 , 0 , 2 ) . view ( attention . shape [ 0 ], attention . shape [ 1 ], attention . shape [ 3 ] * attention . shape [ 4 ], ) . detach () . cpu () . numpy () ) print ( adata ) if doplot and adata . shape [ 0 ] > 100 and pred is not None : sc . pp . neighbors ( adata , use_rep = \"X\" ) sc . tl . umap ( adata ) sc . tl . leiden ( adata , key_added = \"sprint_leiden\" ) if gtclass is not None : color = [ i for pair in zip ( [ \"conv_\" + i if \"conv_\" + i in adata . obs . columns else i for i in labels ], [ ( \"conv_pred_\" + i if \"conv_pred_\" + i in adata . obs . columns else \"pred_\" + i ) for i in labels ], ) for i in pair ] fig , axs = plt . subplots ( int ( len ( color ) / 2 ), 2 , figsize = ( 24 , len ( color ) * 4 ) ) plt . subplots_adjust ( wspace = 1 ) for i , col in enumerate ( color ): sc . pl . umap ( adata , color = col , ax = axs [ i // 2 , i % 2 ], show = False , ) acc = \"\" if \"_pred_\" in col and col . split ( \"conv_\" )[ - 1 ] in accuracy : acc = \" (accuracy: {:.2f} )\" . format ( accuracy [ col . split ( \"conv_\" )[ - 1 ]]) axs [ i // 2 , i % 2 ] . set_title ( col + \" UMAP\" + acc ) if \"cell_type\" in col : axs [ i // 2 , i % 2 ] . legend ( fontsize = \"x-small\" ) axs [ i // 2 , i % 2 ] . set_xlabel ( \"UMAP1\" ) axs [ i // 2 , i % 2 ] . set_ylabel ( \"UMAP2\" ) else : color = [ ( \"conv_pred_\" + i if \"conv_pred_\" + i in adata . obs . columns else \"pred_\" + i ) for i in labels ] fig , axs = plt . subplots ( len ( color ), 1 , figsize = ( 16 , len ( color ) * 8 )) for i , col in enumerate ( color ): sc . pl . umap ( adata , color = col , ax = axs [ i ], show = False , ) acc = \"\" if \"_pred_\" in col and col . split ( \"conv_\" )[ - 1 ] in accuracy : acc = \" (accuracy: {:.2f} )\" . format ( accuracy [ col . split ( \"conv_\" )[ - 1 ]]) axs [ i ] . set_title ( col + \" UMAP\" + acc ) axs [ i ] . set_xlabel ( \"UMAP1\" ) axs [ i ] . set_ylabel ( \"UMAP2\" ) plt . show () else : fig = None adata . write ( mdir + \"/step_\" + str ( step ) + \"_\" + name + \".h5ad\" ) return adata , fig","title":"make_adata"},{"location":"model/#scprint.model.utils.simple_masker","text":"Randomly mask a batch of data. Parameters: shape ( list [ int ] ) \u2013 The shape of the data. mask_ratio ( float , default: 0.15 ) \u2013 The ratio of genes to mask, default to 0.15. Returns: Tensor \u2013 torch.Tensor: A tensor of masked data. Source code in scprint/model/utils.py 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 def simple_masker ( shape : list [ int ], mask_ratio : float = 0.15 , ) -> torch . Tensor : \"\"\" Randomly mask a batch of data. Args: shape (list[int]): The shape of the data. mask_ratio (float): The ratio of genes to mask, default to 0.15. Returns: torch.Tensor: A tensor of masked data. \"\"\" return torch . rand ( shape ) < mask_ratio","title":"simple_masker"},{"location":"model/#scprint.model.utils.test","text":"Test the given model on the full set of benchmarks and save the results to JSON files. Parameters: model ( Module ) \u2013 The model to be tested. name ( str ) \u2013 The name to be used for the output JSON files. filedir ( str ) \u2013 The directory where the data files are located. Returns: None \u2013 None Source code in scprint/model/utils.py 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 def test ( model : torch . nn . Module , name : str , filedir : str ) -> None : \"\"\" Test the given model on the full set of benchmarks and save the results to JSON files. Args: model (torch.nn.Module): The model to be tested. name (str): The name to be used for the output JSON files. filedir (str): The directory where the data files are located. Returns: None \"\"\" metrics = {} res = embbed_task . default_benchmark ( model , default_dataset = \"lung\" , do_class = True , coarse = False ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"embed_lung\" : res }, indent = 4 )) f . close () metrics . update ( { \"emb_lung/scib\" : float ( res [ \"scib\" ][ \"Total\" ]), \"emb_lung/ct_class\" : float ( res [ \"classif\" ][ \"cell_type_ontology_term_id\" ][ \"accuracy\" ] ), } ) print ( metrics ) res = embbed_task . default_benchmark ( model , default_dataset = \"pancreas\" , do_class = True , coarse = False ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"embed_panc\" : res }, indent = 4 )) f . close () metrics . update ( { \"emb_panc/scib\" : float ( res [ \"scib\" ][ \"Total\" ]), \"emb_panc/ct_class\" : float ( res [ \"classif\" ][ \"cell_type_ontology_term_id\" ][ \"accuracy\" ] ), } ) print ( metrics ) gc . collect () res = denoise_task . default_benchmark ( model , filedir + \"/../../data/gNNpgpo6gATjuxTE7CCp.h5ad\" ) metrics . update ( { \"denoise/reco2full_vs_noisy2full\" : float ( res [ \"reco2full\" ] - res [ \"noisy2full\" ] ), } ) gc . collect () print ( metrics ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"denoise\" : res }, indent = 4 )) f . close () res = grn_task . default_benchmark ( model , \"gwps\" , batch_size = 32 if model . d_model <= 512 else 8 ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_gwps\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_gwps/auprc_self\" : float ( res [ \"self\" ][ \"auprc\" ]), \"grn_gwps/epr_self\" : float ( res [ \"self\" ][ \"epr\" ]), \"grn_gwps/auprc_omni\" : float ( res [ \"omni\" ][ \"auprc\" ]), \"grn_gwps/epr_omni\" : float ( res [ \"omni\" ][ \"epr\" ]), \"grn_gwps/auprc\" : float ( res [ \"mean\" ][ \"auprc\" ]), \"grn_gwps/epr\" : float ( res [ \"mean\" ][ \"epr\" ]), } ) print ( metrics ) gc . collect () res = grn_task . default_benchmark ( model , \"sroy\" , batch_size = 32 if model . d_model <= 512 else 8 ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_sroy\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_sroy/auprc_self\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"self_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr_self\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"self_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/auprc_omni\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"omni_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr_omni\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"omni_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/auprc\" : float ( np . mean ( [ i [ \"auprc\" ] for k , i in res . items () if k . startswith ( \"mean_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), \"grn_sroy/epr\" : float ( np . mean ( [ i [ \"epr\" ] for k , i in res . items () if k . startswith ( \"mean_\" ) and not any ( x in k for x in [ \"chip_\" , \"ko_\" , \"classifier\" , \"_base\" ] ) ] ) ), } ) print ( metrics ) gc . collect () res = grn_task . default_benchmark ( model , filedir + \"/../../data/yBCKp6HmXuHa0cZptMo7.h5ad\" , batch_size = 32 if model . d_model <= 512 else 8 , ) f = open ( \"metrics_\" + name + \".json\" , \"a\" ) f . write ( json . dumps ({ \"grn_omni\" : res }, default = lambda o : str ( o ), indent = 4 )) f . close () metrics . update ( { \"grn_omni/auprc_class\" : float ( np . mean ([ i [ \"auprc\" ] for k , i in res . items () if \"_class\" in k ]) ), \"grn_omni/epr_class\" : float ( np . mean ([ i [ \"epr\" ] for k , i in res . items () if \"_class\" in k ]) ), \"grn_omni/tf_enr_class\" : float ( np . sum ( [ i . get ( \"TF_enr\" , False ) for k , i in res . items () if \"_class\" in k ] ) ), \"grn_omni/tf_targ_enr_class\" : float ( np . mean ( [ i [ \"significant_enriched_TFtargets\" ] for k , i in res . items () if \"_class\" in k ] ) ), \"grn_omni/auprc\" : float ( np . mean ([ i [ \"auprc\" ] for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/epr\" : float ( np . mean ([ i [ \"epr\" ] for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/tf_enr\" : float ( np . sum ([ i . get ( \"TF_enr\" , False ) for k , i in res . items () if \"_mean\" in k ]) ), \"grn_omni/tf_targ_enr\" : float ( np . mean ( [ i [ \"significant_enriched_TFtargets\" ] for k , i in res . items () if \"_mean\" in k ] ) ), # 'grn_omni/ct': res['classif']['cell_type_ontology_term_id']['accuracy'], } ) return metrics","title":"test"},{"location":"model/#scprint.model.utils.translate","text":"translate This function translates the given value based on the specified type. Parameters: val ( str / list / set / dict / Counter ) \u2013 The value to be translated. t ( str , default: 'cell_type_ontology_term_id' ) \u2013 The type of translation to be performed. Defaults to \"cell_type_ontology_term_id\". Returns: dict \u2013 A dictionary with the translated values. Source code in scprint/model/utils.py 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 def translate ( val : Union [ str , list , set , dict , Counter ], t : str = \"cell_type_ontology_term_id\" ): \"\"\" translate This function translates the given value based on the specified type. Args: val (str/list/set/dict/Counter): The value to be translated. t (str, optional): The type of translation to be performed. Defaults to \"cell_type_ontology_term_id\". Returns: dict: A dictionary with the translated values. \"\"\" if t == \"cell_type_ontology_term_id\" : obj = bt . CellType . df () . set_index ( \"ontology_id\" ) elif t == \"assay_ontology_term_id\" : obj = bt . ExperimentalFactor . df () . set_index ( \"ontology_id\" ) elif t == \"tissue_ontology_term_id\" : obj = bt . Tissue . df () . set_index ( \"ontology_id\" ) elif t == \"disease_ontology_term_id\" : obj = bt . Disease . df () . set_index ( \"ontology_id\" ) elif t == \"self_reported_ethnicity_ontology_term_id\" : obj = bt . Ethnicity . df () . set_index ( \"ontology_id\" ) else : return None if type ( val ) is str : if val == \"unknown\" : return { val : val } return { val : obj . loc [ val ][ \"name\" ]} elif type ( val ) is list or type ( val ) is set : return { i : obj . loc [ i ][ \"name\" ] if i != \"unknown\" else i for i in set ( val )} elif type ( val ) is dict or type ( val ) is Counter : return { obj . loc [ k ][ \"name\" ] if k != \"unknown\" else k : v for k , v in val . items ()}","title":"translate"},{"location":"model/#scprint.model.utils.weighted_masker","text":"Randomly mask a batch of data. Parameters: shape ( list [ int ] ) \u2013 The shape of the data. mask_ratio ( float , default: 0.15 ) \u2013 The ratio of genes to mask, default to 0.15. mask_value ( int , default: 1 ) \u2013 The value to mask with, default to -1. pad_value ( int ) \u2013 The value of padding in the values, will be kept unchanged. Returns: Tensor \u2013 torch.Tensor: A tensor of masked data. Source code in scprint/model/utils.py 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 def weighted_masker ( shape : list [ int ], mask_ratio : float = 0.15 , mask_prob : Optional [ Union [ torch . Tensor , np . ndarray ]] = None , # n_features mask_value : int = 1 , ) -> torch . Tensor : \"\"\" Randomly mask a batch of data. Args: shape (list[int]): The shape of the data. mask_ratio (float): The ratio of genes to mask, default to 0.15. mask_value (int): The value to mask with, default to -1. pad_value (int): The value of padding in the values, will be kept unchanged. Returns: torch.Tensor: A tensor of masked data. \"\"\" mask = [] for _ in range ( shape [ 0 ]): m = np . zeros ( shape [ 1 ]) loc = np . random . choice ( a = shape [ 1 ], size = int ( shape [ 1 ] * mask_ratio ), replace = False , p = mask_prob ) m [ loc ] = mask_value mask . append ( m ) return torch . Tensor ( np . array ( mask )) . to ( torch . bool )","title":"weighted_masker"},{"location":"model/#scprint.model.utils.zinb_sample","text":"zinb_sample This function generates a sample from a Zero-Inflated Negative Binomial (ZINB) distribution. Parameters: mu ( Tensor ) \u2013 The mean of the Negative Binomial (NB) distribution. theta ( Tensor ) \u2013 The dispersion parameter of the NB distribution. zi_probs ( Tensor ) \u2013 The zero-inflation probabilities. sample_shape ( Size , default: Size ([]) ) \u2013 The output shape. Defaults to torch.Size([]). Returns: \u2013 torch.Tensor: A sample from the ZINB distribution. Source code in scprint/model/utils.py 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 def zinb_sample ( mu : torch . Tensor , theta : torch . Tensor , zi_probs : torch . Tensor , sample_shape : torch . Size = torch . Size ([]), ): \"\"\" zinb_sample This function generates a sample from a Zero-Inflated Negative Binomial (ZINB) distribution. Args: mu (torch.Tensor): The mean of the Negative Binomial (NB) distribution. theta (torch.Tensor): The dispersion parameter of the NB distribution. zi_probs (torch.Tensor): The zero-inflation probabilities. sample_shape (torch.Size, optional): The output shape. Defaults to torch.Size([]). Returns: torch.Tensor: A sample from the ZINB distribution. \"\"\" concentration = theta rate = theta / mu # Important remark: Gamma is parametrized by the rate = 1/scale! gamma_d = Gamma ( concentration = concentration , rate = rate ) p_means = gamma_d . sample ( sample_shape ) # Clamping as distributions objects can have buggy behaviors when # their parameters are too high l_train = torch . clamp ( p_means , max = 1e8 ) samp = Poisson ( l_train ) . sample () # Shape : (n_samples, n_cells_batch, n_vars) is_zero = torch . rand_like ( samp ) <= zi_probs samp_ = torch . where ( is_zero , torch . zeros_like ( samp ), samp ) return samp_","title":"zinb_sample"},{"location":"model/#encoder-and-decoder-modules","text":"","title":"encoder and decoder modules"},{"location":"model/#scprint.model.encoders","text":"","title":"encoders"},{"location":"model/#scprint.model.encoders.CategoryValueEncoder","text":"Bases: Module Encodes categorical values into a vector using an embedding layer and layer normalization. Parameters: num_embeddings ( int ) \u2013 The number of possible values. embedding_dim ( int ) \u2013 The dimension of the output vectors. padding_idx ( int , default: None ) \u2013 The index of the padding token. Defaults to None. Returns: \u2013 torch.Tensor: A tensor representing the encoded categorical values. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 def __init__ ( self , num_embeddings : int , embedding_dim : int , padding_idx : Optional [ int ] = None , ): \"\"\" Encodes categorical values into a vector using an embedding layer and layer normalization. Args: num_embeddings (int): The number of possible values. embedding_dim (int): The dimension of the output vectors. padding_idx (int, optional): The index of the padding token. Defaults to None. Returns: torch.Tensor: A tensor representing the encoded categorical values. Note: not used in the current version of scprint. \"\"\" super ( CategoryValueEncoder , self ) . __init__ () self . embedding = nn . Embedding ( num_embeddings , embedding_dim , padding_idx = padding_idx )","title":"CategoryValueEncoder"},{"location":"model/#scprint.model.encoders.ContinuousValueEncoder","text":"Bases: Module Encode real number values to a vector using neural nets projection. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float , default: 0.1 ) \u2013 The dropout rate to apply to the output of the positional encoding. max_value ( int , default: 100000 ) \u2013 The maximum value of the input. Defaults to 100_000. layers ( int , default: 1 ) \u2013 The number of layers in the encoder. Defaults to 1. size ( int , default: 1 ) \u2013 The size of the input. Defaults to 1. Returns: \u2013 torch.Tensor: A tensor representing the encoded continuous values. Source code in scprint/model/encoders.py 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 def __init__ ( self , d_model : int , dropout : float = 0.1 , max_value : int = 100_000 , layers : int = 1 , size : int = 1 , ): \"\"\" Encode real number values to a vector using neural nets projection. Args: d_model (int): The dimension of the input vectors. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. max_value (int, optional): The maximum value of the input. Defaults to 100_000. layers (int, optional): The number of layers in the encoder. Defaults to 1. size (int, optional): The size of the input. Defaults to 1. Returns: torch.Tensor: A tensor representing the encoded continuous values. \"\"\" super ( ContinuousValueEncoder , self ) . __init__ () self . max_value = max_value self . encoder = nn . ModuleList () self . encoder . append ( nn . Linear ( size , d_model )) for _ in range ( layers - 1 ): self . encoder . append ( nn . LayerNorm ( d_model )) self . encoder . append ( nn . ReLU ()) self . encoder . append ( nn . Dropout ( p = dropout )) self . encoder . append ( nn . Linear ( d_model , d_model ))","title":"ContinuousValueEncoder"},{"location":"model/#scprint.model.encoders.ContinuousValueEncoder.forward","text":"Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, seq_len] Source code in scprint/model/encoders.py 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 def forward ( self , x : Tensor , mask : Tensor = None ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, seq_len] \"\"\" # expand last dimension x = x . unsqueeze ( - 1 ) # use the mask embedding when x=-1 # mask = (x == -1).float() x = torch . clamp ( x , min = 0 , max = self . max_value ) for val in self . encoder : x = val ( x ) if mask is not None : x = x . masked_fill_ ( mask . unsqueeze ( - 1 ), 0 ) return x","title":"forward"},{"location":"model/#scprint.model.encoders.DPositionalEncoding","text":"Bases: Module The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. max_len ( int ) \u2013 The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 def __init__ ( self , d_model : int , max_len_x : int , max_len_y : int , maxvalue_x = 10000.0 , maxvalue_y = 10000.0 , ): super ( DPositionalEncoding , self ) . __init__ () position2 = torch . arange ( max_len_y ) . unsqueeze ( 1 ) position1 = torch . arange ( max_len_x ) . unsqueeze ( 1 ) half_n = d_model // 2 div_term2 = torch . exp ( torch . arange ( 0 , half_n , 2 ) * ( - math . log ( maxvalue_y ) / d_model ) ) div_term1 = torch . exp ( torch . arange ( 0 , half_n , 2 ) * ( - math . log ( maxvalue_x ) / d_model ) ) pe1 = torch . zeros ( max_len_x , 1 , d_model ) pe2 = torch . zeros ( max_len_y , 1 , d_model ) pe1 [:, 0 , 0 : half_n : 2 ] = torch . sin ( position1 * div_term1 ) pe1 [:, 0 , 1 : half_n : 2 ] = torch . cos ( position1 * div_term1 ) pe2 [:, 0 , half_n :: 2 ] = torch . sin ( position2 * div_term2 ) pe2 [:, 0 , 1 + half_n :: 2 ] = torch . cos ( position2 * div_term2 ) # https://github.com/tatp22/multidim-positional-encoding/blob/master/positional_encodings/torch_encodings.py self . register_buffer ( \"pe1\" , pe1 ) self . register_buffer ( \"pe2\" , pe2 )","title":"DPositionalEncoding"},{"location":"model/#scprint.model.encoders.DPositionalEncoding.forward","text":"Parameters: x ( Tensor ) \u2013 Tensor, shape [seq_len, batch_size, embedding_dim] Source code in scprint/model/encoders.py 148 149 150 151 152 153 154 155 def forward ( self , x : Tensor , pos_x : Tensor , pos_y : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] \"\"\" x = x + self . pe1 [ pos_x ] x = x + self . pe2 [ pos_y ] return x","title":"forward"},{"location":"model/#scprint.model.encoders.GeneEncoder","text":"Bases: Module Encodes gene sequences into a continuous vector space using an embedding layer. The output is then normalized using a LayerNorm. Parameters: num_embeddings ( int ) \u2013 The number of possible values. embedding_dim ( int ) \u2013 The dimension of the output vectors. padding_idx ( int , default: None ) \u2013 The index of the padding token. Defaults to None. weights ( Tensor , default: None ) \u2013 The initial weights for the embedding layer. Defaults to None. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. freeze ( bool , default: False ) \u2013 Whether to freeze the weights of the embedding layer. Defaults to False. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def __init__ ( self , num_embeddings : int , embedding_dim : int , padding_idx : Optional [ int ] = None , weights : Optional [ Tensor ] = None , freeze : bool = False , ): \"\"\" Encodes gene sequences into a continuous vector space using an embedding layer. The output is then normalized using a LayerNorm. Args: num_embeddings (int): The number of possible values. embedding_dim (int): The dimension of the output vectors. padding_idx (int, optional): The index of the padding token. Defaults to None. weights (Tensor, optional): The initial weights for the embedding layer. Defaults to None. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. freeze (bool, optional): Whether to freeze the weights of the embedding layer. Defaults to False. Note: not used in the current version of scprint. \"\"\" super ( GeneEncoder , self ) . __init__ () self . embedding = nn . Embedding ( num_embeddings , embedding_dim , padding_idx = padding_idx , _freeze = freeze ) if weights is not None : # concat a zero vector to the weight # this is to make the embedding of the padding token to be zero # weights = torch.cat( # [torch.Tensor(weights), torch.zeros(1, embedding_dim)], dim=0 # ) self . embedding . weight . data . copy_ ( torch . Tensor ( weights ))","title":"GeneEncoder"},{"location":"model/#scprint.model.encoders.PositionalEncoding","text":"Bases: Module The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. dropout ( float ) \u2013 The dropout rate to apply to the output of the positional encoding. max_len ( int ) \u2013 The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. Source code in scprint/model/encoders.py 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 def __init__ ( self , d_model : int , max_len : int , token_to_pos : dict [ str , int ], # [token, pos] maxval = 10000.0 , ): \"\"\" The PositionalEncoding module applies a positional encoding to a sequence of vectors. This is necessary for the Transformer model, which does not have any inherent notion of position in a sequence. The positional encoding is added to the input embeddings and allows the model to attend to positions in the sequence. Args: d_model (int): The dimension of the input vectors. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. max_len (int, optional): The maximum length of a sequence that this module can handle. Note: not used in the current version of scprint. \"\"\" super ( PositionalEncoding , self ) . __init__ () position = torch . arange ( max_len ) . unsqueeze ( 1 ) # Create a dictionary to convert token to position div_term = torch . exp ( torch . arange ( 0 , d_model , 2 ) * ( - math . log ( maxval ) / d_model ) ) pe = torch . zeros ( max_len , 1 , d_model ) pe [:, 0 , 0 :: 2 ] = torch . sin ( position * div_term ) pe [:, 0 , 1 :: 2 ] = torch . cos ( position * div_term ) # we reorder them and map them to gene_id (position) arr = [] for _ , v in token_to_pos . items (): arr . append ( pe [ v - 1 ] . numpy ()) pe = torch . Tensor ( np . array ( arr )) self . register_buffer ( \"pe\" , pe )","title":"PositionalEncoding"},{"location":"model/#scprint.model.encoders.PositionalEncoding.forward","text":"Parameters: x \u2013 Tensor, shape [seq_len, batch_size, embedding_dim] Source code in scprint/model/encoders.py 88 89 90 91 92 93 94 95 def forward ( self , gene_pos : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [seq_len, batch_size, embedding_dim] \"\"\" return torch . index_select ( self . pe , 0 , gene_pos . view ( - 1 )) . view ( gene_pos . shape + ( - 1 ,) )","title":"forward"},{"location":"model/#scprint.model.decoders","text":"","title":"decoders"},{"location":"model/#scprint.model.decoders.ClsDecoder","text":"Bases: Module ClsDecoder Decoder for classification task. Parameters: d_model ( int ) \u2013 int, dimension of the input. n_cls ( int ) \u2013 int, number of classes. layers ( list [ int ] , default: [256, 128] ) \u2013 list[int], list of hidden layers. activation ( Callable , default: ReLU ) \u2013 nn.Module, activation function. dropout ( float , default: 0.1 ) \u2013 float, dropout rate. Returns: \u2013 Tensor, shape [batch_size, n_cls] Source code in scprint/model/decoders.py 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 def __init__ ( self , d_model : int , n_cls : int , layers : list [ int ] = [ 256 , 128 ], activation : Callable = nn . ReLU , dropout : float = 0.1 , ): \"\"\" ClsDecoder Decoder for classification task. Args: d_model: int, dimension of the input. n_cls: int, number of classes. layers: list[int], list of hidden layers. activation: nn.Module, activation function. dropout: float, dropout rate. Returns: Tensor, shape [batch_size, n_cls] \"\"\" super ( ClsDecoder , self ) . __init__ () # module list layers = [ d_model ] + layers self . decoder = nn . Sequential () for i , l in enumerate ( layers [ 1 :]): self . decoder . append ( nn . Linear ( layers [ i ], l )) self . decoder . append ( nn . LayerNorm ( l )) self . decoder . append ( activation ()) self . decoder . append ( nn . Dropout ( dropout )) self . out_layer = nn . Linear ( layers [ - 1 ], n_cls )","title":"ClsDecoder"},{"location":"model/#scprint.model.decoders.ClsDecoder.forward","text":"Parameters: x ( Tensor ) \u2013 Tensor, shape [batch_size, embsize] Source code in scprint/model/decoders.py 206 207 208 209 210 211 212 def forward ( self , x : Tensor ) -> Tensor : \"\"\" Args: x: Tensor, shape [batch_size, embsize] \"\"\" x = self . decoder ( x ) return self . out_layer ( x )","title":"forward"},{"location":"model/#scprint.model.decoders.ExprDecoder","text":"Bases: Module ExprDecoder Decoder for the gene expression prediction. Will output the mean, variance and zero logits, parameters of a zero inflated negative binomial distribution. Parameters: d_model ( int ) \u2013 The dimension of the model. This is the size of the input feature vector. nfirst_tokens_to_skip ( int , default: 0 ) \u2013 The number of initial labels to skip in the sequence. Defaults to 0. dropout ( float , default: 0.1 ) \u2013 The dropout rate applied during training to prevent overfitting. Defaults to 0.1. zinb ( bool , default: True ) \u2013 Whether to use a zero inflated negative binomial distribution. Defaults to True. Source code in scprint/model/decoders.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 def __init__ ( self , d_model : int , nfirst_tokens_to_skip : int = 0 , dropout : float = 0.1 , zinb : bool = True , ): \"\"\" ExprDecoder Decoder for the gene expression prediction. Will output the mean, variance and zero logits, parameters of a zero inflated negative binomial distribution. Args: d_model (int): The dimension of the model. This is the size of the input feature vector. nfirst_tokens_to_skip (int, optional): The number of initial labels to skip in the sequence. Defaults to 0. dropout (float, optional): The dropout rate applied during training to prevent overfitting. Defaults to 0.1. zinb (bool, optional): Whether to use a zero inflated negative binomial distribution. Defaults to True. \"\"\" super ( ExprDecoder , self ) . __init__ () self . nfirst_tokens_to_skip = nfirst_tokens_to_skip self . fc = nn . Sequential ( nn . Linear ( d_model , d_model ), nn . LayerNorm ( d_model ), nn . LeakyReLU (), nn . Dropout ( dropout ), nn . Linear ( d_model , d_model ), nn . LayerNorm ( d_model ), nn . LeakyReLU (), ) self . pred_var_zero = nn . Linear ( d_model , 3 if zinb else 1 ) self . zinb = zinb","title":"ExprDecoder"},{"location":"model/#scprint.model.decoders.ExprDecoder.forward","text":"x is the output of the transformer, (batch, seq_len, d_model) Source code in scprint/model/decoders.py 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 def forward ( self , x : Tensor ) -> Dict [ str , Tensor ]: \"\"\"x is the output of the transformer, (batch, seq_len, d_model)\"\"\" # we don't do it on the labels x = self . fc ( x [:, self . nfirst_tokens_to_skip :, :]) if self . zinb : pred_value , var_value , zero_logits = self . pred_var_zero ( x ) . split ( 1 , dim =- 1 ) # (batch, seq_len) # The sigmoid function is used to map the zero_logits to a probability between 0 and 1. return dict ( mean = F . softmax ( pred_value . squeeze ( - 1 ), dim =- 1 ), disp = torch . exp ( torch . clamp ( var_value . squeeze ( - 1 ), max = 15 )), zero_logits = zero_logits . squeeze ( - 1 ), ) else : pred_value = self . pred_var_zero ( x ) return dict ( mean = F . softmax ( pred_value . squeeze ( - 1 ), dim =- 1 ))","title":"forward"},{"location":"model/#scprint.model.decoders.GraphSDEExprDecoder","text":"Bases: Module Initialize the ExprNeuralSDEDecoder module. Parameters: d_model ( int ) \u2013 The dimension of the model. drift ( Module ) \u2013 The drift component of the SDE. diffusion ( Module ) \u2013 The diffusion component of the SDE. Source code in scprint/model/decoders.py 8 9 10 11 12 13 14 15 16 17 18 19 20 def __init__ ( self , d_model : int , drift : nn . Module , diffusion : nn . Module ): \"\"\" Initialize the ExprNeuralSDEDecoder module. Args: d_model (int): The dimension of the model. drift (nn.Module): The drift component of the SDE. diffusion (nn.Module): The diffusion component of the SDE. \"\"\" super () . __init__ () self . d_model = d_model self . drift = drift self . diffusion = diffusion","title":"GraphSDEExprDecoder"},{"location":"model/#scprint.model.decoders.MVCDecoder","text":"Bases: Module MVCDecoder Decoder for the masked value prediction for cell embeddings. Will use the gene embeddings with the cell embeddings to predict the mean, variance and zero logits Parameters: d_model \u2013 obj: int ): dimension of the gene embedding. arch_style \u2013 obj: str ): architecture style of the decoder, choice from 1. \"inner product\" or 2. \"cell product\" 3. \"concat query\" or 4. \"sum query\". query_activation \u2013 obj: nn.Module ): activation function for the query vectors. Defaults to nn.Sigmoid. hidden_activation \u2013 obj: nn.Module ): activation function for the hidden layers. Defaults to nn.PReLU. Source code in scprint/model/decoders.py 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 def __init__ ( self , d_model : int , arch_style : str = \"inner product\" , tot_labels : int = 1 , query_activation : nn . Module = nn . Sigmoid , hidden_activation : nn . Module = nn . PReLU , ) -> None : \"\"\" MVCDecoder Decoder for the masked value prediction for cell embeddings. Will use the gene embeddings with the cell embeddings to predict the mean, variance and zero logits Args: d_model (:obj:`int`): dimension of the gene embedding. arch_style (:obj:`str`): architecture style of the decoder, choice from 1. \"inner product\" or 2. \"cell product\" 3. \"concat query\" or 4. \"sum query\". query_activation (:obj:`nn.Module`): activation function for the query vectors. Defaults to nn.Sigmoid. hidden_activation (:obj:`nn.Module`): activation function for the hidden layers. Defaults to nn.PReLU. \"\"\" super ( MVCDecoder , self ) . __init__ () if arch_style == \"inner product\" : self . gene2query = nn . Linear ( d_model , d_model ) self . norm = nn . LayerNorm ( d_model ) self . query_activation = query_activation () self . pred_var_zero = nn . Linear ( d_model , d_model * 3 , bias = False ) elif arch_style == \"concat query\" : self . gene2query = nn . Linear ( d_model , d_model ) self . query_activation = query_activation () self . fc1 = nn . Linear ( d_model * ( 1 + tot_labels ), d_model / 2 ) self . hidden_activation = hidden_activation () self . fc2 = nn . Linear ( d_model / 2 , 3 ) elif arch_style == \"sum query\" : self . gene2query = nn . Linear ( d_model , d_model ) self . query_activation = query_activation () self . fc1 = nn . Linear ( d_model , 64 ) self . hidden_activation = hidden_activation () self . fc2 = nn . Linear ( 64 , 3 ) else : raise ValueError ( f \"Unknown arch_style: { arch_style } \" ) self . arch_style = arch_style self . do_detach = arch_style . endswith ( \"detach\" ) self . d_model = d_model","title":"MVCDecoder"},{"location":"model/#scprint.model.decoders.MVCDecoder.forward","text":"Parameters: cell_emb ( Tensor ) \u2013 Tensor, shape (batch, embsize=d_model) gene_embs ( Tensor ) \u2013 Tensor, shape (batch, seq_len, embsize=d_model) Source code in scprint/model/decoders.py 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 def forward ( self , cell_emb : Tensor , gene_embs : Tensor , ) -> Union [ Tensor , Dict [ str , Tensor ]]: \"\"\" Args: cell_emb: Tensor, shape (batch, embsize=d_model) gene_embs: Tensor, shape (batch, seq_len, embsize=d_model) \"\"\" if self . arch_style == \"inner product\" : query_vecs = self . query_activation ( self . norm ( self . gene2query ( gene_embs ))) pred , var , zero_logits = self . pred_var_zero ( query_vecs ) . split ( self . d_model , dim =- 1 ) cell_emb = cell_emb . unsqueeze ( 2 ) pred , var , zero_logits = ( torch . bmm ( pred , cell_emb ) . squeeze ( 2 ), torch . bmm ( var , cell_emb ) . squeeze ( 2 ), torch . bmm ( zero_logits , cell_emb ) . squeeze ( 2 ), ) # zero logits need to based on the cell_emb, because of input exprs elif self . arch_style == \"concat query\" : query_vecs = self . query_activation ( self . gene2query ( gene_embs )) # expand cell_emb to (batch, seq_len, embsize) cell_emb = cell_emb . unsqueeze ( 1 ) . expand ( - 1 , gene_embs . shape [ 1 ], - 1 ) h = self . hidden_activation ( self . fc1 ( torch . cat ([ cell_emb , query_vecs ], dim = 2 )) ) pred , var , zero_logits = self . fc2 ( h ) . split ( 1 , dim =- 1 ) elif self . arch_style == \"sum query\" : query_vecs = self . query_activation ( self . gene2query ( gene_embs )) cell_emb = cell_emb . unsqueeze ( 1 ) h = self . hidden_activation ( self . fc1 ( cell_emb + query_vecs )) pred , var , zero_logits = self . fc2 ( h ) . split ( 1 , dim =- 1 ) return dict ( mvc_mean = F . softmax ( pred , dim =- 1 ), mvc_disp = torch . exp ( torch . clamp ( var , max = 15 )), mvc_zero_logits = zero_logits , )","title":"forward"},{"location":"model/#flashattention","text":"","title":"flashattention"},{"location":"model/#scprint.model.flash_attn.flashformer","text":"","title":"flashformer"},{"location":"model/#scprint.model.flash_attn.flashformer.FlashTransformerEncoder","text":"Bases: Module FlashTransformerEncoder a transformer encoder with flash attention. Parameters: d_model ( int ) \u2013 The dimension of the input vectors. nhead ( int ) \u2013 The number of attention heads. nlayers ( int ) \u2013 The number of layers in the transformer. dropout ( float , default: 0.1 ) \u2013 The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. residual_in_fp32 ( bool , default: True ) \u2013 Whether to force the residual to be in fp32 format. Defaults to True. num_heads_kv ( _type_ , default: None ) \u2013 The number of heads for key/value. Defaults to None. checkpointing ( bool , default: False ) \u2013 Whether to use gradient checkpointing. Defaults to False. fused_dropout_add_ln ( bool , default: False ) \u2013 Whether to fuse dropout, addition and layer normalization operations. Defaults to False. return_residual ( bool , default: False ) \u2013 Whether to return the residual. Defaults to False. prenorm ( bool , default: True ) \u2013 Whether to use pre-normalization. Defaults to True. mlp_ratio ( float , default: 4.0 ) \u2013 The ratio for MLP. Defaults to 4.0. fused_mlp ( bool , default: False ) \u2013 Whether to use fused MLP. Defaults to False. fused_bias_fc ( bool , default: False ) \u2013 Whether to fuse bias and fully connected layers. Defaults to False. sequence_parallel ( bool , default: False ) \u2013 Whether to use sequence parallelism. Defaults to False. drop_path_rate ( float , default: 0.0 ) \u2013 The drop path rate. Defaults to 0.0. weight_init ( str , default: '' ) \u2013 The weight initialization method. Defaults to \"\". Raises: ImportError \u2013 Raised when Triton is not installed but fused_dropout_add_ln is set to True. NotImplementedError \u2013 Raised when an unsupported operation is attempted. Source code in scprint/model/flash_attn/flashformer.py 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 def __init__ ( self , d_model : int , nhead : int , nlayers : int , dropout : float = 0.1 , residual_in_fp32 : bool = True , num_heads_kv : Optional [ int ] = None , checkpointing : bool = False , fused_dropout_add_ln : bool = False , return_residual : bool = False , prenorm : bool = True , mlp_ratio : float = 4.0 , fused_mlp : bool = False , fused_bias_fc : bool = False , sequence_parallel : bool = False , drop_path_rate : float = 0.0 , use_flash_attn : bool = True , weight_init : str = \"\" , ): \"\"\" FlashTransformerEncoder a transformer encoder with flash attention. Args: d_model (int): The dimension of the input vectors. nhead (int): The number of attention heads. nlayers (int): The number of layers in the transformer. dropout (float, optional): The dropout rate to apply to the output of the positional encoding. Defaults to 0.1. residual_in_fp32 (bool, optional): Whether to force the residual to be in fp32 format. Defaults to True. num_heads_kv (_type_, optional): The number of heads for key/value. Defaults to None. checkpointing (bool, optional): Whether to use gradient checkpointing. Defaults to False. fused_dropout_add_ln (bool, optional): Whether to fuse dropout, addition and layer normalization operations. Defaults to False. return_residual (bool, optional): Whether to return the residual. Defaults to False. prenorm (bool, optional): Whether to use pre-normalization. Defaults to True. mlp_ratio (float, optional): The ratio for MLP. Defaults to 4.0. fused_mlp (bool, optional): Whether to use fused MLP. Defaults to False. fused_bias_fc (bool, optional): Whether to fuse bias and fully connected layers. Defaults to False. sequence_parallel (bool, optional): Whether to use sequence parallelism. Defaults to False. drop_path_rate (float, optional): The drop path rate. Defaults to 0.0. weight_init (str, optional): The weight initialization method. Defaults to \"\". Raises: ImportError: Raised when Triton is not installed but fused_dropout_add_ln is set to True. NotImplementedError: Raised when an unsupported operation is attempted. \"\"\" super ( FlashTransformerEncoder , self ) . __init__ () self . blocks = nn . ModuleList () dpr = [ x . item () for x in torch . linspace ( 0 , drop_path_rate , nlayers ) ] # stochastic depth decay rule for i in range ( nlayers ): mlp = create_mlp_cls ( d_model , mlp_ratio , nn . GELU , fused_mlp ) attention = partial ( MHA , num_heads = nhead , dropout = dropout , causal = False , use_flash_attn = use_flash_attn , num_heads_kv = num_heads_kv , checkpointing = checkpointing , fused_bias_fc = fused_bias_fc , layer_idx = i , ) # or use parallelBlock where attn & MLP are done in parallel encoder_layers = Block ( d_model , attention , mlp , prenorm = prenorm , # need to set it here for now although it hinders some performances as it returns the residual and I need to see what to do with it # TD [2022-07-30]: Force residual in fp32, seems to make fp16 training more stable residual_in_fp32 = residual_in_fp32 , sequence_parallel = sequence_parallel , # for more parallelism resid_dropout1 = dropout , resid_dropout2 = dropout , drop_path1 = dpr [ i - 1 ] if i > 0 else 0.0 , drop_path2 = dpr [ i ], fused_dropout_add_ln = fused_dropout_add_ln , return_residual = return_residual , ) self . blocks . append ( encoder_layers ) self . prenorm = prenorm self . dropout = nn . Dropout ( p = dropout ) self . drop_path = StochasticDepth ( p = dpr [ - 1 ], mode = \"row\" ) self . norm = torch . nn . LayerNorm ( d_model , eps = 1e-6 ) self . fused_dropout_add_ln = fused_dropout_add_ln if self . fused_dropout_add_ln and layer_norm_fn is None : raise ImportError ( \"Triton is not installed\" ) if sequence_parallel : # This seems to only be important when doing tensor parallelism across GPUs, to increase even more the context length I guess? # not really necessary here I think raise NotImplementedError ( \"sequence_parallel not implemented yet\" ) self . init_weights ( weight_init )","title":"FlashTransformerEncoder"},{"location":"model/#scprint.model.flash_attn.mha","text":"","title":"mha"},{"location":"model/#scprint.model.flash_attn.mha.CrossAttention","text":"Bases: Module Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. Default to 1/sqrt(d_keys) where d_keys is computed at runtime attention_dropout: The dropout rate to apply to the attention. default to 0.0. Source code in scprint/model/flash_attn/mha.py 245 246 247 248 249 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 ): super () . __init__ () self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout )","title":"CrossAttention"},{"location":"model/#scprint.model.flash_attn.mha.CrossAttention.forward","text":"Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, Sk) Source code in scprint/model/flash_attn/mha.py 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 def forward ( self , q , kv , causal = None , key_padding_mask = None , bias = None ): \"\"\"Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, Sk) \"\"\" batch_size , seqlen_q = q . shape [ 0 ], q . shape [ 1 ] causal = self . causal if causal is None else causal seqlen_k = kv . shape [ 1 ] assert kv . shape [ 0 ] == batch_size and kv . shape [ 4 ] == q . shape [ 3 ] if kv . shape [ 3 ] != q . shape [ 2 ]: # MQA/GQA kv = repeat ( kv , \"... hkv d -> ... (hkv g) d\" , g = q . shape [ 2 ] // kv . shape [ 3 ]) k , v = kv . unbind ( dim = 2 ) softmax_scale = self . softmax_scale or 1.0 / math . sqrt ( q . shape [ - 1 ]) scores = torch . einsum ( \"bthd,bshd->bhts\" , q , k * softmax_scale ) if key_padding_mask is not None : padding_mask = torch . full ( ( batch_size , seqlen_k ), - 10000.0 , dtype = scores . dtype , device = scores . device , ) padding_mask . masked_fill_ ( key_padding_mask , 0.0 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + rearrange ( padding_mask , \"b s -> b 1 1 s\" ) if causal : # causal mask needs to take into account the difference between seqlen_q and seqlen_k row_idx = rearrange ( torch . arange ( seqlen_q , device = q . device , dtype = torch . long ), \"s -> s 1\" ) col_idx = torch . arange ( seqlen_k , device = kv . device , dtype = torch . long ) sk = ( seqlen_k if key_padding_mask is None else rearrange ( key_padding_mask . sum ( - 1 ), \"b -> b 1 1 1\" ) ) causal_mask = col_idx > row_idx + sk - seqlen_q scores = scores . masked_fill ( causal_mask , - 10000.0 ) attention = torch . softmax ( scores , dim =- 1 , dtype = v . dtype ) attention_drop = self . drop ( attention ) output = torch . einsum ( \"bhts,bshd->bthd\" , attention_drop , v ) return output","title":"forward"},{"location":"model/#scprint.model.flash_attn.mha.FlashCrossAttention","text":"Bases: Module Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The dropout rate to apply to the attention (default: 0.0) Source code in scprint/model/flash_attn/mha.py 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 , alibi_slopes = None , deterministic = False , ): \"\"\" Implement the scaled dot product attention with softmax. Args softmax_scale: The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout: The dropout rate to apply to the attention (default: 0.0) \"\"\" super () . __init__ () assert flash_attn_kvpacked_func is not None , \"FlashAttention is not installed\" assert flash_attn_kvpacked_func is not None , \"FlashAttention is not installed\" self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout ) self . register_buffer ( \"alibi_slopes\" , alibi_slopes , persistent = False ) self . deterministic = deterministic","title":"FlashCrossAttention"},{"location":"model/#scprint.model.flash_attn.mha.FlashCrossAttention.forward","text":"Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into q. max_seqlen: int. Maximum sequence length in the batch of q. cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into kv. max_seqlen_k: int. Maximum sequence length in the batch of k and v. Source code in scprint/model/flash_attn/mha.py 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 def forward ( self , q , kv , causal = None , cu_seqlens = None , max_seqlen = None , cu_seqlens_k = None , max_seqlen_k = None , ): \"\"\" Implements the multihead softmax attention. Args q: The tensor containing the query. (B, Sq, H, D) kv: The tensor containing the key and value. (B, Sk, 2, H_k, D) causal: if passed, will override self.causal cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into q. max_seqlen: int. Maximum sequence length in the batch of q. cu_seqlens_k: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into kv. max_seqlen_k: int. Maximum sequence length in the batch of k and v. \"\"\" assert q . dtype in [ torch . float16 , torch . bfloat16 ] assert q . is_cuda and kv . is_cuda causal = self . causal if causal is None else causal batch_size , seqlen_q = q . shape [ 0 ], q . shape [ 1 ] assert kv . shape [ 0 ] == batch_size and kv . shape [ 4 ] == q . shape [ 3 ] return flash_attn_kvpacked_func ( q , kv , None , # self.drop.p if self.training else 0.0, causal , self . softmax_scale , # alibi_slopes=self.alibi_slopes, # deterministic=self.deterministic, )","title":"forward"},{"location":"model/#scprint.model.flash_attn.mha.FlashSelfAttention","text":"Bases: Module Implement the scaled dot product attention with softmax. Parameters: softmax_scale ( float , default: None ) \u2013 The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout ( float , default: 0.0 ) \u2013 The dropout rate to apply to the attention (default: 0.0) causal ( bool , default: False ) \u2013 Whether to use causal attention. Defaults to False. Source code in scprint/model/flash_attn/mha.py 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 def __init__ ( self , causal : bool = False , softmax_scale : Optional [ float ] = None , attention_dropout : float = 0.0 , alibi_slopes : Optional [ Any ] = None , deterministic : bool = False , use_triton : bool = False , ): \"\"\"Implement the scaled dot product attention with softmax. Args: softmax_scale (float, optional): The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout (float, optional): The dropout rate to apply to the attention (default: 0.0) causal (bool, optional): Whether to use causal attention. Defaults to False. \"\"\" super () . __init__ () if flash_attn_qkvpacked_func is None : print ( \"FlashAttention is not installed, using triton instead\" ) use_triton = True self . use_triton = use_triton self . causal = causal self . softmax_scale = softmax_scale","title":"FlashSelfAttention"},{"location":"model/#scprint.model.flash_attn.mha.FlashSelfAttention.forward","text":"Implements the multihead softmax attention. Args qkv (Tensor): The tensor containing the query, key, and value. If cu_seqlens is None and max_seqlen is None, then qkv has shape (B, S, 3, H, D). If cu_seqlens is not None and max_seqlen is not None, then qkv has shape (total, 3, H, D), where total is the sum of the sequence lengths in the batch. causal (bool): if passed, will override self.causal cu_seqlens (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into qkv. max_seqlen (int). Maximum sequence length in the batch. Returns: out: (total, H, D) if cu_seqlens is not None and max_seqlen is not None, else (B, S, H, D). Source code in scprint/model/flash_attn/mha.py 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 def forward ( self , qkv : torch . Tensor , causal : Optional [ bool ] = None , cu_seqlens : Optional [ torch . Tensor ] = None , max_seqlen : Optional [ int ] = None , cu_seqlens_k : Optional [ torch . Tensor ] = None , max_seqlen_k : Optional [ int ] = None , bias : Optional [ torch . Tensor ] = None , ** kwargs , ): \"\"\"Implements the multihead softmax attention. Args qkv (Tensor): The tensor containing the query, key, and value. If cu_seqlens is None and max_seqlen is None, then qkv has shape (B, S, 3, H, D). If cu_seqlens is not None and max_seqlen is not None, then qkv has shape (total, 3, H, D), where total is the sum of the sequence lengths in the batch. causal (bool): if passed, will override self.causal cu_seqlens (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into qkv. max_seqlen (int). Maximum sequence length in the batch. Returns: out: (total, H, D) if cu_seqlens is not None and max_seqlen is not None, else (B, S, H, D). \"\"\" assert qkv . dtype in [ torch . float16 , torch . bfloat16 ] assert qkv . is_cuda causal = self . causal if causal is None else causal if self . use_triton : raise NotImplementedError ( \"OpenAI's flashattention is not implemented\" ) if qkv . stride ( - 1 ) != 1 : qkv = qkv . contiguous () # return triton_attention( # qkv[:, :, 0], # qkv[:, :, 1], # qkv[:, :, 2], # bias, # causal, # self.softmax_scale, # ) else : return flash_attn_qkvpacked_func ( qkv , bias , # self.drop.p if self.training else 0.0, causal , self . softmax_scale , )","title":"forward"},{"location":"model/#scprint.model.flash_attn.mha.LinearResidual","text":"Bases: Linear Wrap nn.Linear to return the residual as well. For compatibility with FusedDense.","title":"LinearResidual"},{"location":"model/#scprint.model.flash_attn.mha.MHA","text":"Bases: Module MHA Multi-head self-attention and cross-attention Parameters: num_heads_kv ( int , default: None ) \u2013 can be used to toggle MQA / GQA. If None, use num_heads. return_residual ( bool , default: False ) \u2013 whether to return the input x along with the output. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. checkpointing ( bool , default: False ) \u2013 whether to use checkpointing to save memory. Defaults to False. num_heads_kv ( int , default: None ) \u2013 can be used to toggle MQA / GQA. If None, use num_heads. cross_attn ( bool , default: False ) \u2013 whether to use cross-attention. Defaults to False. qkv_proj_bias ( bool , default: True ) \u2013 whether to use bias in the query, key, value projection. Defaults to True. out_proj_bias ( bool , default: True ) \u2013 whether to use bias in the output projection. Defaults to True. dropout ( float , default: 0.0 ) \u2013 dropout rate. Defaults to 0.0. softmax_scale ( float , default: None ) \u2013 The temperature to use for the softmax attention. causal ( bool , default: False ) \u2013 whether to use causal attention. Defaults to False. layer_idx ( int , default: None ) \u2013 layer index for inference cache. Defaults to None. dwconv ( bool , default: False ) \u2013 whether to use depthwise convolution. Defaults to False. fused_bias_fc ( bool , default: False ) \u2013 whether to use fused_bias_fc. Defaults to False. use_flash_attn ( bool , default: False ) \u2013 whether to use FlashAttention. Defaults to False. device ( device , default: None ) \u2013 device. Defaults to None. dtype ( dtype , default: None ) \u2013 dtype. Defaults to None. Source code in scprint/model/flash_attn/mha.py 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 def __init__ ( self , embed_dim : int , num_heads : int , num_heads_kv : Optional [ int ] = None , cross_attn : bool = False , qkv_proj_bias : bool = True , out_proj_bias : bool = True , dropout : float = 0.0 , softmax_scale : Optional [ float ] = None , causal : bool = False , layer_idx : Optional [ int ] = None , dwconv : bool = False , rotary_emb_dim : int = 0 , rotary_emb_base : float = 10000.0 , rotary_emb_scale_base : Optional [ float ] = None , rotary_emb_interleaved : bool = False , use_alibi : bool = False , fused_bias_fc : bool = False , use_flash_attn : bool = False , return_residual : bool = False , checkpointing : bool = False , device : Optional [ torch . device ] = None , dtype : Optional [ torch . dtype ] = None , ) -> None : \"\"\" MHA Multi-head self-attention and cross-attention Args: embed_dim num_heads_kv (int): can be used to toggle MQA / GQA. If None, use num_heads. return_residual (bool, optional): whether to return the input x along with the output. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. checkpointing (bool, optional): whether to use checkpointing to save memory. Defaults to False. num_heads_kv (int, optional): can be used to toggle MQA / GQA. If None, use num_heads. cross_attn (bool, optional): whether to use cross-attention. Defaults to False. qkv_proj_bias (bool, optional): whether to use bias in the query, key, value projection. Defaults to True. out_proj_bias (bool, optional): whether to use bias in the output projection. Defaults to True. dropout (float, optional): dropout rate. Defaults to 0.0. softmax_scale (float, optional): The temperature to use for the softmax attention. causal (bool, optional): whether to use causal attention. Defaults to False. layer_idx (int, optional): layer index for inference cache. Defaults to None. dwconv (bool, optional): whether to use depthwise convolution. Defaults to False. fused_bias_fc (bool, optional): whether to use fused_bias_fc. Defaults to False. use_flash_attn (bool, optional): whether to use FlashAttention. Defaults to False. device (torch.device, optional): device. Defaults to None. dtype (torch.dtype, optional): dtype. Defaults to None. \"\"\" factory_kwargs = { \"device\" : device , \"dtype\" : dtype } super () . __init__ () self . embed_dim = embed_dim self . cross_attn = cross_attn self . causal = causal self . layer_idx = layer_idx self . dwconv = dwconv self . rotary_emb_dim = rotary_emb_dim self . use_flash_attn = use_flash_attn if self . use_flash_attn and ( flash_attn_kvpacked_func is None ): print ( \"you requested flash transformer but it requires the flash package which is not installed\" ) print ( \"falling back to regular transformer...\" ) self . use_flash_attn = False # NOT flash transformer using the special tritton kernel # or parallelMHA (add the process group thing and faster) self . return_residual = return_residual self . checkpointing = checkpointing alibi_slopes = None self . num_heads = num_heads self . num_heads_kv = num_heads_kv if num_heads_kv is not None else num_heads assert ( self . num_heads % self . num_heads_kv == 0 ), \"num_heads must be divisible by num_heads_kv\" assert ( self . embed_dim % num_heads == 0 ), \"embed_dim must be divisible by num_heads\" self . head_dim = self . embed_dim // num_heads qkv_dim = self . head_dim * ( self . num_heads + 2 * self . num_heads_kv ) kv_dim = 2 * self . head_dim * self . num_heads_kv if self . rotary_emb_dim > 0 : assert ( not cross_attn ), \"MHA with rotary embedding does not support cross-attention yet\" assert RotaryEmbedding is not None , \"rotary_emb is not installed\" self . rotary_emb = RotaryEmbedding ( self . rotary_emb_dim , base = rotary_emb_base , scale_base = rotary_emb_scale_base , interleaved = rotary_emb_interleaved , device = device , ) if fused_bias_fc and FusedDense is None : raise ImportError ( \"fused_dense is not installed\" ) linear_cls = nn . Linear if not fused_bias_fc else FusedDense linear_resid_cls = ( LinearResidual if not fused_bias_fc else partial ( FusedDense , return_residual = True ) ) wqkv_cls = linear_cls if not self . return_residual else linear_resid_cls inner_attn_cls = ( partial ( FlashSelfAttention , alibi_slopes = alibi_slopes ) if self . use_flash_attn else SelfAttention ) inner_cross_attn_cls = ( partial ( FlashCrossAttention , alibi_slopes = alibi_slopes ) if self . use_flash_attn else CrossAttention ) if not self . cross_attn : self . Wqkv = wqkv_cls ( embed_dim , qkv_dim , bias = qkv_proj_bias , ** factory_kwargs ) else : self . Wq = linear_cls ( embed_dim , embed_dim , bias = qkv_proj_bias , ** factory_kwargs ) self . Wkv = wqkv_cls ( embed_dim , kv_dim , bias = qkv_proj_bias , ** factory_kwargs ) if self . dwconv : if self . num_heads_kv == self . num_heads : self . dwconv_qkv = nn . Conv1d ( qkv_dim , qkv_dim , kernel_size = 3 , padding = 2 , groups = qkv_dim ) else : self . dwconv_q = nn . Conv1d ( embed_dim , embed_dim , kernel_size = 3 , padding = 2 , groups = embed_dim ) self . dwconv_kv = nn . Conv1d ( kv_dim , kv_dim , kernel_size = 3 , padding = 2 , groups = kv_dim ) self . inner_attn = inner_attn_cls ( causal = causal , softmax_scale = softmax_scale , attention_dropout = dropout , ) self . inner_cross_attn = inner_cross_attn_cls ( causal = causal , softmax_scale = softmax_scale , attention_dropout = dropout ) self . out_proj = linear_cls ( embed_dim , embed_dim , bias = out_proj_bias , ** factory_kwargs )","title":"MHA"},{"location":"model/#scprint.model.flash_attn.mha.MHA.forward","text":"Parameters: x ( Tensor ) \u2013 (batch, seqlen, hidden_dim) (where hidden_dim = num heads * head dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the is the sum of the sequence lengths in the batch. x_kv ( Optional [ Tensor ] , default: None ) \u2013 (batch, seqlen, hidden_dim), only applicable for cross-attention. If None, use x. cu_seqlens ( Optional [ Tensor ] , default: None ) \u2013 (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into x. Only applicable when using FlashAttention. max_seqlen ( Optional [ int ] , default: None ) \u2013 int. Maximum sequence length in the batch. key_padding_mask ( Optional [ Tensor ] , default: None ) \u2013 boolean mask, True means to keep, False means to mask out. (batch, seqlen). Only applicable when not using FlashAttention. mixer_subset ( Optional [ Tensor ] , default: None ) \u2013 for cross-attention only. If not None, will take a subset of x before applying the query projection. Useful for e.g., ViT where we only care about the CLS token in the last layer. inference_params ( Optional [ dict ] , default: None ) \u2013 for generation. Adapted from Megatron-LM (and Apex) https \u2013 //github.com/NVIDIA/apex/blob/3ff1a10f72ec07067c4e44759442329804ac5162/apex/transformer/testing/standalone_transformer_lm.py#L470 return_qkv ( bool , default: False ) \u2013 whether to return the qkv tensor. Defaults to False. Returns: out \u2013 (batch, seqlen, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the sum of the sequence lengths in the batch. qkv \u2013 (batch, seqlen, 3, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, 3, hidden_dim) where total is the sum of the sequence lengths in the batch. Source code in scprint/model/flash_attn/mha.py 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 def forward ( self , x : torch . Tensor , x_kv : Optional [ torch . Tensor ] = None , key_padding_mask : Optional [ torch . Tensor ] = None , cu_seqlens : Optional [ torch . Tensor ] = None , max_seqlen : Optional [ int ] = None , mixer_subset : Optional [ torch . Tensor ] = None , inference_params : Optional [ dict ] = None , return_qkv : bool = False , ** kwargs , ): \"\"\" Args: x: (batch, seqlen, hidden_dim) (where hidden_dim = num heads * head dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the is the sum of the sequence lengths in the batch. x_kv: (batch, seqlen, hidden_dim), only applicable for cross-attention. If None, use x. cu_seqlens: (batch_size + 1,), dtype torch.int32. The cumulative sequence lengths of the sequences in the batch, used to index into x. Only applicable when using FlashAttention. max_seqlen: int. Maximum sequence length in the batch. key_padding_mask: boolean mask, True means to keep, False means to mask out. (batch, seqlen). Only applicable when not using FlashAttention. mixer_subset: for cross-attention only. If not None, will take a subset of x before applying the query projection. Useful for e.g., ViT where we only care about the CLS token in the last layer. inference_params: for generation. Adapted from Megatron-LM (and Apex) https://github.com/NVIDIA/apex/blob/3ff1a10f72ec07067c4e44759442329804ac5162/apex/transformer/testing/standalone_transformer_lm.py#L470 return_qkv: whether to return the qkv tensor. Defaults to False. Returns: out: (batch, seqlen, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, hidden_dim) where total is the sum of the sequence lengths in the batch. qkv: (batch, seqlen, 3, hidden_dim) if cu_seqlens is None and max_seqlen is None, else (total, 3, hidden_dim) where total is the sum of the sequence lengths in the batch. \"\"\" if cu_seqlens is not None : assert max_seqlen is not None assert key_padding_mask is None assert self . use_flash_attn assert not self . dwconv assert self . rotary_emb_dim == 0 if key_padding_mask is not None : assert cu_seqlens is None assert max_seqlen is None assert not self . use_flash_attn if inference_params is not None : assert key_padding_mask is None assert cu_seqlens is None and max_seqlen is None assert not self . dwconv kwargs = ( {} # \"cu_seqlens\": cu_seqlens, \"max_seqlen\": max_seqlen, **kwargs} if self . use_flash_attn else { \"key_padding_mask\" : key_padding_mask , ** kwargs } ) seqlen_offset = ( 0 if inference_params is None else ( inference_params . lengths_per_sample if inference_params . lengths_per_sample is not None else inference_params . seqlen_offset ) ) rotary_max_seqlen = ( inference_params . max_seqlen if inference_params is not None else None ) batch , seqlen = x . shape [: 2 ] if not self . cross_attn and self . num_heads_kv == self . num_heads : assert x_kv is None and mixer_subset is None if not self . return_residual : qkv = self . Wqkv ( x ) # .to(torch.float16, device=\"cuda\") else : qkv , x = self . Wqkv ( x ) if self . dwconv : qkv = rearrange ( self . dwconv_qkv ( rearrange ( qkv , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () qkv = rearrange ( qkv , \"... (three h d) -> ... three h d\" , three = 3 , d = self . head_dim ) if ( inference_params is None or inference_params . seqlen_offset == 0 or ( self . rotary_emb_dim == 0 or self . rotary_emb_dim % 16 != 0 ) or not self . use_flash_attn ): if self . rotary_emb_dim > 0 : qkv = self . rotary_emb ( qkv , seqlen_offset = seqlen_offset , max_seqlen = rotary_max_seqlen ) if inference_params is None : if not self . checkpointing : context = self . inner_attn ( qkv , ** kwargs ) else : context = torch . utils . checkpoint . checkpoint ( self . inner_attn , qkv , ** kwargs ) else : context = self . _update_kvcache_attention ( qkv [:, :, 0 ], qkv [:, :, 1 :], inference_params ) else : context = self . _apply_rotary_update_kvcache_attention ( qkv [:, :, 0 ], qkv [:, :, 1 :], inference_params ) else : if self . cross_attn : if not self . return_residual : q = self . Wq ( x if mixer_subset is None else x [:, mixer_subset ]) kv = self . Wkv ( x_kv if x_kv is not None else x ) else : if x_kv is not None : kv , x_kv = self . Wkv ( x_kv ) else : kv , x = self . Wkv ( x ) q = self . Wq ( x if mixer_subset is None else x [:, mixer_subset ]) else : assert self . num_heads_kv != self . num_heads if not self . return_residual : qkv = self . Wqkv ( x ) else : qkv , x = self . Wqkv ( x ) q = qkv [ ... , : self . num_heads * self . head_dim ] kv = qkv [ ... , self . num_heads * self . head_dim :] q = rearrange ( q , \"... (h d) -> ... h d\" , d = self . head_dim ) kv = rearrange ( kv , \"... (two hkv d) -> ... two hkv d\" , two = 2 , d = self . head_dim ) if self . dwconv : q = rearrange ( self . dwconv_q ( rearrange ( q , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () kv = rearrange ( self . dwconv_kv ( rearrange ( kv , \"b s d -> b d s\" ))[ ... , : - 2 ], \"b d s -> b s d\" , ) . contiguous () if ( inference_params is None or inference_params . seqlen_offset == 0 or ( self . rotary_emb_dim == 0 or self . rotary_emb_dim % 16 != 0 ) or not self . use_flash_attn ): if self . rotary_emb_dim > 0 : q , kv = self . rotary_emb ( q , kv , seqlen_offset = seqlen_offset , max_seqlen = rotary_max_seqlen ) if inference_params is None : if not self . checkpointing : context = self . inner_cross_attn ( q , kv , ** kwargs ) else : context = torch . utils . checkpoint . checkpoint ( self . inner_cross_attn , q , kv , ** kwargs ) else : context = self . _update_kvcache_attention ( q , kv , inference_params ) else : context = self . _apply_rotary_update_kvcache_attention ( q , kv , inference_params ) out = self . out_proj ( rearrange ( context , \"... h d -> ... (h d)\" )) if return_qkv : return out if not self . return_residual else ( out , x ), qkv else : return out if not self . return_residual else ( out , x )","title":"forward"},{"location":"model/#scprint.model.flash_attn.mha.SelfAttention","text":"Bases: Module Implement the scaled dot product attention with softmax. Parameters: softmax_scale \u2013 The temperature to use for the softmax attention. (default: 1/sqrt(d_keys) where d_keys is computed at runtime) attention_dropout \u2013 The dropout rate to apply to the attention (default: 0.0) Source code in scprint/model/flash_attn/mha.py 195 196 197 198 199 def __init__ ( self , causal = False , softmax_scale = None , attention_dropout = 0.0 ): super () . __init__ () self . causal = causal self . softmax_scale = softmax_scale self . drop = nn . Dropout ( attention_dropout )","title":"SelfAttention"},{"location":"model/#scprint.model.flash_attn.mha.SelfAttention.forward","text":"Implements the multihead softmax attention. Parameters: qkv \u2013 The tensor containing the query, key, and value. (B, S, 3, H, D) causal \u2013 if passed, will override self.causal key_padding_mask \u2013 boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, S) Source code in scprint/model/flash_attn/mha.py 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 def forward ( self , qkv , causal = None , key_padding_mask = None , bias = None ): \"\"\" Implements the multihead softmax attention. Args: qkv: The tensor containing the query, key, and value. (B, S, 3, H, D) causal: if passed, will override self.causal key_padding_mask: boolean mask to apply to the attention weights. True means to keep, False means to mask out. (B, S) \"\"\" batch_size , seqlen = qkv . shape [ 0 ], qkv . shape [ 1 ] causal = self . causal if causal is None else causal q , k , v = qkv . unbind ( dim = 2 ) softmax_scale = self . softmax_scale or 1.0 / math . sqrt ( q . shape [ - 1 ]) scores = torch . einsum ( \"bthd,bshd->bhts\" , q , k * softmax_scale ) if key_padding_mask is not None : padding_mask = torch . full ( ( batch_size , seqlen ), - 10000.0 , dtype = scores . dtype , device = scores . device ) padding_mask . masked_fill_ ( key_padding_mask , 0.0 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + rearrange ( padding_mask , \"b s -> b 1 1 s\" ) if causal : # \"triu_tril_cuda_template\" not implemented for 'BFloat16' # So we have to construct the mask in float causal_mask = torch . triu ( torch . full (( seqlen , seqlen ), - 10000.0 , device = scores . device ), 1 ) # TD [2022-09-30]: Adding is faster than masked_fill_ (idk why, just better kernel I guess) scores = scores + causal_mask . to ( dtype = scores . dtype ) attention = torch . softmax ( scores , dim =- 1 , dtype = v . dtype ) attention_drop = self . drop ( attention ) output = torch . einsum ( \"bhts,bshd->bthd\" , attention_drop , v ) return output","title":"forward"},{"location":"model/#scprint.model.flash_attn.mlp","text":"","title":"mlp"},{"location":"model/#scprint.model.flash_attn.mlp.Mlp","text":"Bases: Module Multi-layer perceptron (MLP) module. Parameters: in_features ( int ) \u2013 Size of each input sample. hidden_features ( Optional [ int ] , default: None ) \u2013 Size of the hidden layer. Defaults to 4 * in_features. out_features ( Optional [ int ] , default: None ) \u2013 Size of each output sample. Defaults to in_features. activation ( Callable [[ Tensor ], Tensor ] , default: gelu ) \u2013 Activation function. Defaults to F.gelu. bias1 ( bool , default: True ) \u2013 If set to False, the first linear layer will not learn an additive bias. Defaults to True. bias2 ( bool , default: True ) \u2013 If set to False, the second linear layer will not learn an additive bias. Defaults to True. return_residual ( bool , default: False ) \u2013 If set to True, the forward method will return a tuple (output, input). Defaults to False. device ( Optional [ device ] , default: None ) \u2013 The desired device of the parameters. Defaults to None. dtype ( Optional [ dtype ] , default: None ) \u2013 The desired data type of the parameters. Defaults to None. Source code in scprint/model/flash_attn/mlp.py 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 def __init__ ( self , in_features : int , hidden_features : Optional [ int ] = None , out_features : Optional [ int ] = None , activation : Callable [[ torch . Tensor ], torch . Tensor ] = F . gelu , bias1 : bool = True , bias2 : bool = True , return_residual : bool = False , device : Optional [ torch . device ] = None , dtype : Optional [ torch . dtype ] = None , ) -> None : \"\"\" Multi-layer perceptron (MLP) module. Args: in_features (int): Size of each input sample. hidden_features (Optional[int], optional): Size of the hidden layer. Defaults to 4 * in_features. out_features (Optional[int], optional): Size of each output sample. Defaults to in_features. activation (Callable[[torch.Tensor], torch.Tensor], optional): Activation function. Defaults to F.gelu. bias1 (bool, optional): If set to False, the first linear layer will not learn an additive bias. Defaults to True. bias2 (bool, optional): If set to False, the second linear layer will not learn an additive bias. Defaults to True. return_residual (bool, optional): If set to True, the forward method will return a tuple (output, input). Defaults to False. device (Optional[torch.device], optional): The desired device of the parameters. Defaults to None. dtype (Optional[torch.dtype], optional): The desired data type of the parameters. Defaults to None. \"\"\" factory_kwargs = { \"device\" : device , \"dtype\" : dtype } super () . __init__ () out_features = out_features if out_features is not None else in_features hidden_features = ( hidden_features if hidden_features is not None else in_features * 4 ) self . return_residual = return_residual self . fc1 = nn . Linear ( in_features , hidden_features , bias = bias1 , ** factory_kwargs ) self . activation = activation self . fc2 = nn . Linear ( hidden_features , out_features , bias = bias2 , ** factory_kwargs )","title":"Mlp"},{"location":"model/#scprint.model.flash_attn.mlp.Mlp.forward","text":"Forward pass of the MLP. Parameters: x ( Tensor ) \u2013 Input tensor. Returns: Union [ Tensor , Tuple [ Tensor , Tensor ]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: Output tensor, or a tuple (output, input) if return_residual is True. Source code in scprint/model/flash_attn/mlp.py 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 def forward ( self , x : torch . Tensor ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , torch . Tensor ]]: \"\"\" Forward pass of the MLP. Args: x (torch.Tensor): Input tensor. Returns: Union[torch.Tensor, Tuple[torch.Tensor, torch.Tensor]]: Output tensor, or a tuple (output, input) if return_residual is True. \"\"\" y = self . fc1 ( x ) y = self . activation ( y ) y = self . fc2 ( y ) return y if not self . return_residual else ( y , x )","title":"forward"},{"location":"model/#scprint.model.flash_attn.block","text":"","title":"block"},{"location":"model/#scprint.model.flash_attn.block.Block","text":"Bases: Module For prenorm=True, this Block has a slightly different structure compared to a regular prenorm Transformer block. The standard block is: LN -> MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add. [Ref: https://arxiv.org/abs/2002.04745] Here we have: Dropout -> Add -> LN -> MHA -> Dropout -> Add -> LN -> MLP, returning both the hidden_states (output of the MLP) and the residual. This is for performance reasons, as we can fuse the dropout, add and LayerNorm. The residual needs to be provided (except for the very first block). For prenorm=False, this Block has the same structure as a regular postnorm Transformer block: MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add -> LN. Parameters: dim ( int ) \u2013 the number of features in the input. mixer_cls ( Optional [ Callable ] , default: None ) \u2013 the class to use for the mixer layer. Defaults to None. mlp_cls ( Optional [ Callable ] , default: None ) \u2013 the class to use for the mlp layer. Defaults to None. norm_cls ( Callable , default: partial ( LayerNorm , eps=1e-06) ) \u2013 the class to use for the layer norm. Defaults to partial(nn.LayerNorm, eps=1e-6). dropout_cls ( Type [ Dropout ] , default: Dropout ) \u2013 the class to use for the dropout. Defaults to nn.Dropout. prenorm ( bool , default: True ) \u2013 whether to use pre-norm or post-norm. Defaults to True. resid_dropout1 ( float , default: 0.0 ) \u2013 the dropout probability for the first dropout layer. Defaults to 0.0. resid_dropout2 ( float , default: 0.0 ) \u2013 the dropout probability for the second dropout layer. Defaults to 0.0. drop_path1 ( float , default: 0.0 ) \u2013 the drop path probability for the first drop path layer. Defaults to 0.0. drop_path2 ( float , default: 0.0 ) \u2013 the drop path probability for the second drop path layer. Defaults to 0.0. fused_dropout_add_ln ( bool , default: False ) \u2013 whether to fuse the dropout, add and layer norm. Defaults to False. return_residual ( bool , default: False ) \u2013 whether each of the sub-layers (mixer and mlp) will return the residual. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. residual_in_fp32 ( bool , default: False ) \u2013 whether to keep the residual in fp32. This is for performance reason: for post-norm architecture, keeping the residual in fp32 allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. sequence_parallel ( bool , default: False ) \u2013 whether to use sequence parallelism. Defaults to False. mark_shared_params ( bool , default: False ) \u2013 whether to mark the norm parameters as \"shared_params\". This is useful when we want to sync the norm parameters across workers. Defaults to False. Source code in scprint/model/flash_attn/block.py 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 def __init__ ( self , dim : int , mixer_cls : Optional [ Callable ] = None , mlp_cls : Optional [ Callable ] = None , norm_cls : Callable = partial ( nn . LayerNorm , eps = 1e-6 ), dropout_cls : Type [ nn . Dropout ] = nn . Dropout , prenorm : bool = True , resid_dropout1 : float = 0.0 , resid_dropout2 : float = 0.0 , drop_path1 : float = 0.0 , drop_path2 : float = 0.0 , fused_dropout_add_ln : bool = False , return_residual : bool = False , residual_in_fp32 : bool = False , sequence_parallel : bool = False , mark_shared_params : bool = False , ): \"\"\" For prenorm=True, this Block has a slightly different structure compared to a regular prenorm Transformer block. The standard block is: LN -> MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add. [Ref: https://arxiv.org/abs/2002.04745] Here we have: Dropout -> Add -> LN -> MHA -> Dropout -> Add -> LN -> MLP, returning both the hidden_states (output of the MLP) and the residual. This is for performance reasons, as we can fuse the dropout, add and LayerNorm. The residual needs to be provided (except for the very first block). For prenorm=False, this Block has the same structure as a regular postnorm Transformer block: MHA -> Dropout -> Add -> LN -> MLP -> Dropout -> Add -> LN. Args: dim (int): the number of features in the input. mixer_cls (Optional[Callable], optional): the class to use for the mixer layer. Defaults to None. mlp_cls (Optional[Callable], optional): the class to use for the mlp layer. Defaults to None. norm_cls (Callable, optional): the class to use for the layer norm. Defaults to partial(nn.LayerNorm, eps=1e-6). dropout_cls (Type[nn.Dropout], optional): the class to use for the dropout. Defaults to nn.Dropout. prenorm (bool, optional): whether to use pre-norm or post-norm. Defaults to True. resid_dropout1 (float, optional): the dropout probability for the first dropout layer. Defaults to 0.0. resid_dropout2 (float, optional): the dropout probability for the second dropout layer. Defaults to 0.0. drop_path1 (float, optional): the drop path probability for the first drop path layer. Defaults to 0.0. drop_path2 (float, optional): the drop path probability for the second drop path layer. Defaults to 0.0. fused_dropout_add_ln (bool, optional): whether to fuse the dropout, add and layer norm. Defaults to False. return_residual (bool, optional): whether each of the sub-layers (mixer and mlp) will return the residual. This is for performance reason: for post-norm architecture, returning the input allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. residual_in_fp32 (bool, optional): whether to keep the residual in fp32. This is for performance reason: for post-norm architecture, keeping the residual in fp32 allows us to fuse the backward of nn.Linear with the residual connection. Defaults to False. sequence_parallel (bool, optional): whether to use sequence parallelism. Defaults to False. mark_shared_params (bool, optional): whether to mark the norm parameters as \"shared_params\". This is useful when we want to sync the norm parameters across workers. Defaults to False. \"\"\" super () . __init__ () self . prenorm = prenorm self . fused_dropout_add_ln = fused_dropout_add_ln self . return_residual = return_residual self . residual_in_fp32 = residual_in_fp32 if self . residual_in_fp32 : assert self . prenorm , \"residual_in_fp32 is only compatible with prenorm=True\" if mixer_cls is None : mixer_cls = partial ( MHA , num_heads = dim // 64 ) if mlp_cls is None : mlp_cls = partial ( Mlp , hidden_features = 4 * dim ) self . mixer = mixer_cls ( dim ) self . dropout1 = dropout_cls ( resid_dropout1 ) self . drop_path1 = StochasticDepth ( drop_path1 , mode = \"row\" ) self . norm1 = norm_cls ( dim ) self . mlp = mlp_cls ( dim ) if not isinstance ( self . mlp , nn . Identity ): self . dropout2 = dropout_cls ( resid_dropout2 ) self . drop_path2 = StochasticDepth ( drop_path2 , mode = \"row\" ) self . norm2 = norm_cls ( dim ) if self . fused_dropout_add_ln : assert layer_norm_fn is not None , \"Triton is not installed\" assert isinstance ( self . norm1 , ( nn . LayerNorm , RMSNorm )) and isinstance ( self . dropout1 , nn . Dropout ) # TD [2023-01-07]: TODO: During training, if sequence_parallel is False and dropout != 0.0, # then the input to each worker in the tensor parallel group will be different. # This would produce wrong outputs? Somehow we'd need to sync the RNG state across workers. # For now this is not an issue because we always use sequence_parallel=True during training # and only use sequence_parallel=False during inference. # Mark the norm parameters as \"sequence_parallel\" so that we run all-reduce on their grads. if sequence_parallel : for p in self . norm1 . parameters (): p . _sequence_parallel = True if hasattr ( self , \"norm2\" ): for p in self . norm2 . parameters (): p . _sequence_parallel = True # Mark the norm parameters as \"shared_params\" so that we sync their values at init. if mark_shared_params : for p in self . norm1 . parameters (): p . _shared_params = True if hasattr ( self , \"norm2\" ): for p in self . norm2 . parameters (): p . _shared_params = True","title":"Block"},{"location":"model/#scprint.model.flash_attn.block.Block.forward","text":"Pass the input through the encoder layer. Parameters: hidden_states ( Tensor ) \u2013 The sequence to be passed to the encoder layer. This is a required argument. residual ( Optional [ Tensor ] , default: None ) \u2013 This argument is used differently based on the normalization method. If postnorm is used, residual should be None. If prenorm is used, hidden_states is updated as Attn/MLP(LN(residual)). mixer_subset ( Optional [ Tensor ] , default: None ) \u2013 This argument is used only for cross-attention. If not None, a subset of the input sequence 'x' is taken before applying the query projection. This is particularly useful for models like ViT where only the CLS token in the last layer is of interest. mixer_kwargs ( Optional [ Dict [ str , Any ]] , default: None ) \u2013 This argument is used only for cross-attention. It is a dictionary of additional arguments to be passed to the mixer. return_qkv ( bool , default: False ) \u2013 If True, the function will return the query, key, and value tensors. Returns: \u2013 Tensor or Tuple[Tensor, Tensor]: The output tensor of the encoder layer. \u2013 If return_qkv is True, the function will return a tuple of the output tensor and the query, key, and value tensors. Source code in scprint/model/flash_attn/block.py 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 def forward ( self , hidden_states : Tensor , residual : Optional [ Tensor ] = None , bias : Optional [ Tensor ] = None , src_mask : Optional [ Tensor ] = None , is_causal : Optional [ bool ] = None , src_key_padding_mask : Optional [ Tensor ] = None , mixer_subset : Optional [ Tensor ] = None , mixer_kwargs : Optional [ Dict [ str , Any ]] = None , return_qkv : bool = False , ): r \"\"\"Pass the input through the encoder layer. Args: hidden_states (Tensor): The sequence to be passed to the encoder layer. This is a required argument. residual (Optional[Tensor]): This argument is used differently based on the normalization method. If postnorm is used, residual should be None. If prenorm is used, hidden_states is updated as Attn/MLP(LN(residual)). mixer_subset: This argument is used only for cross-attention. If not None, a subset of the input sequence 'x' is taken before applying the query projection. This is particularly useful for models like ViT where only the CLS token in the last layer is of interest. mixer_kwargs: This argument is used only for cross-attention. It is a dictionary of additional arguments to be passed to the mixer. return_qkv: If True, the function will return the query, key, and value tensors. Returns: Tensor or Tuple[Tensor, Tensor]: The output tensor of the encoder layer. If return_qkv is True, the function will return a tuple of the output tensor and the query, key, and value tensors. \"\"\" if self . prenorm : if not self . fused_dropout_add_ln : dropped = self . drop_path1 ( self . dropout1 ( hidden_states )) residual = ( dropped + residual ) if residual is not None else dropped hidden_states = self . norm1 ( residual . to ( dtype = self . norm1 . weight . dtype )) if self . residual_in_fp32 : residual = residual . to ( torch . float32 ) else : if self . drop_path1 . p == 0 or not self . training : rowscale1 = None else : rowscale1 = self . drop_path1 ( torch . ones ( hidden_states . shape [: - 1 ], device = hidden_states . device , dtype = hidden_states . dtype , ) ) hidden_states , residual = layer_norm_fn ( hidden_states , self . norm1 . weight , self . norm1 . bias , residual = residual , eps = self . norm1 . eps , dropout_p = self . dropout1 . p if self . training else 0.0 , rowscale = rowscale1 , prenorm = True , residual_in_fp32 = self . residual_in_fp32 , is_rms_norm = isinstance ( self . norm1 , RMSNorm ), ) if mixer_kwargs is None : mixer_kwargs = {} if mixer_subset is not None : mixer_kwargs [ \"mixer_subset\" ] = mixer_subset hidden_states = self . mixer ( hidden_states , return_qkv = return_qkv , bias = bias , ** mixer_kwargs ) if return_qkv : qkv = hidden_states [ 1 ] hidden_states = hidden_states [ 0 ] if mixer_subset is not None : residual = residual [:, mixer_subset ] if not isinstance ( self . mlp , nn . Identity ): if not self . fused_dropout_add_ln : dropped = self . drop_path2 ( self . dropout2 ( hidden_states )) residual = ( dropped + residual ) if residual is not None else dropped hidden_states = self . norm2 ( residual . to ( dtype = self . norm2 . weight . dtype ) ) if self . residual_in_fp32 : residual = residual . to ( torch . float32 ) else : if self . drop_path2 . p == 0 or not self . training : rowscale2 = None else : rowscale2 = self . drop_path2 ( torch . ones ( hidden_states . shape [: - 1 ], device = hidden_states . device , dtype = hidden_states . dtype , ) ) hidden_states , residual = layer_norm_fn ( hidden_states , self . norm2 . weight , self . norm2 . bias , residual = residual , eps = self . norm2 . eps , dropout_p = self . dropout2 . p if self . training else 0.0 , rowscale = rowscale2 , prenorm = True , residual_in_fp32 = self . residual_in_fp32 , is_rms_norm = isinstance ( self . norm2 , RMSNorm ), ) hidden_states = self . mlp ( hidden_states ) return ( ( hidden_states , residual ) if not return_qkv else ( hidden_states , residual , qkv , ) ) # if not prenorm (disregard for scPRINT) else : assert residual is None mixer_out = self . mixer ( hidden_states , return_qkv = return_qkv , bias = bias , ** ( mixer_kwargs if mixer_kwargs is not None else {}) ) if return_qkv : qkv = mixer_out [ - 1 ] mixer_out = mixer_out [: - 1 ] if self . return_residual : # mixer out is actually a pair here mixer_out , hidden_states = mixer_out if not self . fused_dropout_add_ln : hidden_states = self . norm1 ( ( self . drop_path1 ( self . dropout1 ( mixer_out )) + hidden_states ) . to ( dtype = self . norm1 . weight . dtype ) ) else : if self . drop_path1 . p == 0 or not self . training : rowscale1 = None else : rowscale1 = self . drop_path1 ( torch . ones ( mixer_out . shape [: - 1 ], device = mixer_out . device , dtype = mixer_out . dtype , ) ) hidden_states = layer_norm_fn ( mixer_out , self . norm1 . weight , self . norm1 . bias , residual = hidden_states , eps = self . norm1 . eps , dropout_p = self . dropout1 . p if self . training else 0.0 , rowscale = rowscale1 , prenorm = False , is_rms_norm = isinstance ( self . norm1 , RMSNorm ), ) if not isinstance ( self . mlp , nn . Identity ): mlp_out = self . mlp ( hidden_states ) if self . return_residual : # mlp out is actually a pair here mlp_out , hidden_states = mlp_out if not self . fused_dropout_add_ln : hidden_states = self . norm2 ( ( self . drop_path2 ( self . dropout2 ( mlp_out )) + hidden_states ) . to ( dtype = self . norm2 . weight . dtype ) ) else : if self . drop_path2 . p == 0 or not self . training : rowscale2 = None else : rowscale2 = self . drop_path2 ( torch . ones ( mlp_out . shape [: - 1 ], device = mlp_out . device , dtype = mlp_out . dtype , ) ) hidden_states = layer_norm_fn ( mlp_out , self . norm2 . weight , self . norm2 . bias , residual = hidden_states , eps = self . norm2 . eps , dropout_p = self . dropout2 . p if self . training else 0.0 , rowscale = rowscale2 , prenorm = False , is_rms_norm = isinstance ( self . norm2 , RMSNorm ), ) return hidden_states if not return_qkv else ( hidden_states , qkv )","title":"forward"},{"location":"model/#scprint.model.flash_attn.flashattention","text":"Experimental implementation of FlashAttention in Triton. Tested with triton==2.0.0.dev20221202. Triton 2.0 has a new backend (MLIR) but seems like it doesn't yet work for head dimensions other than 64: https://github.com/openai/triton/blob/d376020f90002757eea3ea9475d4f7cfc2ec5ead/python/triton/ops/flash_attention.py#L207 We'll update this implementation with the new Triton backend once this is fixed. We use the FlashAttention implementation from Phil Tillet a starting point. https://github.com/openai/triton/blob/master/python/tutorials/06-fused-attention.py Changes: - Implement both causal and non-causal attention. - Implement both self-attention and cross-attention. - Support arbitrary seqlens (not just multiples of 128), for both forward and backward. - Support all head dimensions up to 128 (not just 16, 32, 64, 128), for both forward and backward. - Support attention bias. - Speed up the forward pass a bit, and only store the LSE instead of m and l. - Make the backward for d=128 much faster by reducing register spilling. - Optionally parallelize the backward pass across seqlen_k, to deal with the case of small batch size * nheads. Caution: - This is an experimental implementation. The forward pass should be quite robust but I'm not 100% sure that the backward pass doesn't have race conditions (due to the Triton compiler). - This implementation has only been tested on A100. - If you plan to use headdim other than 64 and 128, you should test for race conditions (due to the Triton compiler), as done in tests/test_flash_attn.py \"test_flash_attn_triton_race_condition\". I've tested and fixed many race conditions for different head dimensions (40, 48, 64, 128, 80, 88, 96), but I'm still not 100% confident that there are none left for other head dimensions. Differences between this Triton version and the CUDA version: - Triton version doesn't support dropout. - Triton forward is generally faster than CUDA forward, while Triton backward is generally slower than CUDA backward. Overall Triton forward + backward is slightly slower than CUDA forward + backward. - Triton version doesn't support different sequence lengths in a batch (i.e., RaggedTensor/NestedTensor). - Triton version supports attention bias, while CUDA version doesn't.","title":"flashattention"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnFunc","text":"Bases: Function","title":"FlashAttnFunc"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnFunc.forward","text":"Perform the forward pass of FlashAttention. Parameters: q ( Tensor ) \u2013 Query tensor of shape (batch_size, seqlen_q, nheads, headdim). k ( Tensor ) \u2013 Key tensor of shape (batch_size, seqlen_k, nheads, headdim). v ( Tensor ) \u2013 Value tensor of shape (batch_size, seqlen_k, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor, shape broadcastible to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Scaling factor for the softmax operation. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 @staticmethod def forward ( ctx : torch . autograd . Function , q : torch . Tensor , k : torch . Tensor , v : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Perform the forward pass of FlashAttention. Args: q (torch.Tensor): Query tensor of shape (batch_size, seqlen_q, nheads, headdim). k (torch.Tensor): Key tensor of shape (batch_size, seqlen_k, nheads, headdim). v (torch.Tensor): Value tensor of shape (batch_size, seqlen_k, nheads, headdim). bias (Optional[torch.Tensor]): Bias tensor, shape broadcastible to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Scaling factor for the softmax operation. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous q , k , v = [ x if x . stride ( - 1 ) == 1 else x . contiguous () for x in [ q , k , v ]] o , lse , ctx . softmax_scale = _flash_attn_forward ( q , k , v , bias = bias , causal = causal , softmax_scale = softmax_scale ) ctx . save_for_backward ( q , k , v , o , lse , bias ) ctx . causal = causal return o","title":"forward"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnKVPackedFunc","text":"Bases: Function","title":"FlashAttnKVPackedFunc"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnKVPackedFunc.forward","text":"Perform the forward pass of FlashAttention with packed key and value tensors. Parameters: q ( Tensor ) \u2013 Query tensor of shape (batch, seqlen_q, nheads, headdim). kv ( Tensor ) \u2013 Key and value tensor of shape (batch, seqlen_k, 2, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor, shape broadcastable to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Scaling factor for the softmax operation. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 @staticmethod def forward ( ctx , q : torch . Tensor , kv : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Perform the forward pass of FlashAttention with packed key and value tensors. Args: q (torch.Tensor): Query tensor of shape (batch, seqlen_q, nheads, headdim). kv (torch.Tensor): Key and value tensor of shape (batch, seqlen_k, 2, nheads, headdim). bias (Optional[torch.Tensor]): Bias tensor, shape broadcastable to (batch, nheads, seqlen_q, seqlen_k). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen_k). ALiBi mask for non-causal would have shape (1, nheads, seqlen_q, seqlen_k). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Scaling factor for the softmax operation. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous q , kv = [ x if x . stride ( - 1 ) == 1 else x . contiguous () for x in [ q , kv ]] o , lse , ctx . softmax_scale = _flash_attn_forward ( q , kv [:, :, 0 ], kv [:, :, 1 ], bias = bias , causal = causal , softmax_scale = softmax_scale , ) ctx . save_for_backward ( q , kv , o , lse , bias ) ctx . causal = causal return o","title":"forward"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnQKVPackedFunc","text":"Bases: Function","title":"FlashAttnQKVPackedFunc"},{"location":"model/#scprint.model.flash_attn.flashattention.FlashAttnQKVPackedFunc.forward","text":"Forward pass for FlashAttention. Parameters: ctx ( Function ) \u2013 The context object to save information for backward computation. qkv ( Tensor ) \u2013 Input tensor of shape (batch, seqlen, 3, nheads, headdim). bias ( Optional [ Tensor ] , default: None ) \u2013 Optional bias tensor, shape broadcastible to (batch, nheads, seqlen, seqlen). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen). ALiBi mask for non-causal would have shape (1, nheads, seqlen, seqlen). causal ( bool , default: False ) \u2013 Whether to apply causal masking. Default is False. softmax_scale ( Optional [ float ] , default: None ) \u2013 Optional scaling factor for softmax. Default is None. Returns: Tensor \u2013 torch.Tensor: Output tensor after applying FlashAttention. Source code in scprint/model/flash_attn/flashattention.py 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 @staticmethod def forward ( ctx : torch . autograd . Function , qkv : torch . Tensor , bias : Optional [ torch . Tensor ] = None , causal : bool = False , softmax_scale : Optional [ float ] = None , ) -> torch . Tensor : \"\"\" Forward pass for FlashAttention. Args: ctx (torch.autograd.Function): The context object to save information for backward computation. qkv (torch.Tensor): Input tensor of shape (batch, seqlen, 3, nheads, headdim). bias (Optional[torch.Tensor]): Optional bias tensor, shape broadcastible to (batch, nheads, seqlen, seqlen). For example, ALiBi mask for causal would have shape (1, nheads, 1, seqlen). ALiBi mask for non-causal would have shape (1, nheads, seqlen, seqlen). causal (bool): Whether to apply causal masking. Default is False. softmax_scale (Optional[float]): Optional scaling factor for softmax. Default is None. Returns: torch.Tensor: Output tensor after applying FlashAttention. \"\"\" # Make sure that the last dimension is contiguous if qkv . stride ( - 1 ) != 1 : qkv = qkv . contiguous () o , lse , ctx . softmax_scale = _flash_attn_forward ( qkv [:, :, 0 ], qkv [:, :, 1 ], qkv [:, :, 2 ], bias = bias , causal = causal , softmax_scale = softmax_scale , ) ctx . save_for_backward ( qkv , o , lse , bias ) ctx . causal = causal return o","title":"forward"},{"location":"model/#scprint.model.flash_attn.activations","text":"","title":"activations"},{"location":"model/#scprint.model.flash_attn.activations.bias_gelu_back","text":"Assume that y has shape (B, D) and bias has shape (D) Source code in scprint/model/flash_attn/activations.py 24 25 26 27 28 29 30 31 32 33 34 @torch . jit . script def bias_gelu_back ( g , y , bias ): \"\"\"Assume that y has shape (B, D) and bias has shape (D)\"\"\" x = bias + y tanh_out = torch . tanh ( 0.79788456 * x * ( 1 + 0.044715 * x * x )) # sqrt(2/pi) * 3 * 0.044715 -> 0.1070322243 ff = 0.5 * x * ( ( 1 - tanh_out * tanh_out ) * ( 0.79788456 + 0.1070322243 * x * x ) ) + 0.5 * ( 1 + tanh_out ) grad_y = ff * g return grad_y . to ( dtype = y . dtype ), grad_y . sum ( dim = ( 0 ), dtype = bias . dtype )","title":"bias_gelu_back"},{"location":"model/#scprint.model.flash_attn.layer_norm","text":"","title":"layer_norm"},{"location":"model/#scprint.model.flash_attn.layer_norm.layer_norm_ref","text":"Reference implementation of Layer Normalization with optional dropout and residual connections. Parameters: x ( Tensor ) \u2013 Input tensor. weight ( Tensor ) \u2013 Weight tensor for normalization. bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor for normalization. residual ( Optional [ Tensor ] , default: None ) \u2013 Residual tensor to be added to the input. x1 ( Optional [ Tensor ] , default: None ) \u2013 Additional input tensor for parallel LayerNorm. weight1 ( Optional [ Tensor ] , default: None ) \u2013 Additional weight tensor for parallel LayerNorm. bias1 ( Optional [ Tensor ] , default: None ) \u2013 Additional bias tensor for parallel LayerNorm. eps ( float , default: 1e-06 ) \u2013 Epsilon value to avoid division by zero. dropout_p ( float , default: 0.0 ) \u2013 Dropout probability. rowscale ( Optional [ Tensor ] , default: None ) \u2013 Row scaling tensor. prenorm ( bool , default: False ) \u2013 Whether to return the prenormalized output. dropout_mask ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the input tensor. dropout_mask1 ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the additional input tensor. upcast ( bool , default: False ) \u2013 Whether to upcast the input tensors to float. Returns: Union [ Tensor , Tuple [ Tensor , ...]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). Source code in scprint/model/flash_attn/layer_norm.py 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 def layer_norm_ref ( x : torch . Tensor , weight : torch . Tensor , bias : Optional [ torch . Tensor ] = None , residual : Optional [ torch . Tensor ] = None , x1 : Optional [ torch . Tensor ] = None , weight1 : Optional [ torch . Tensor ] = None , bias1 : Optional [ torch . Tensor ] = None , eps : float = 1e-6 , dropout_p : float = 0.0 , rowscale : Optional [ torch . Tensor ] = None , prenorm : bool = False , dropout_mask : Optional [ torch . Tensor ] = None , dropout_mask1 : Optional [ torch . Tensor ] = None , upcast : bool = False , ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , ... ]]: \"\"\" Reference implementation of Layer Normalization with optional dropout and residual connections. Args: x (torch.Tensor): Input tensor. weight (torch.Tensor): Weight tensor for normalization. bias (Optional[torch.Tensor]): Bias tensor for normalization. residual (Optional[torch.Tensor]): Residual tensor to be added to the input. x1 (Optional[torch.Tensor]): Additional input tensor for parallel LayerNorm. weight1 (Optional[torch.Tensor]): Additional weight tensor for parallel LayerNorm. bias1 (Optional[torch.Tensor]): Additional bias tensor for parallel LayerNorm. eps (float): Epsilon value to avoid division by zero. dropout_p (float): Dropout probability. rowscale (Optional[torch.Tensor]): Row scaling tensor. prenorm (bool): Whether to return the prenormalized output. dropout_mask (Optional[torch.Tensor]): Dropout mask for the input tensor. dropout_mask1 (Optional[torch.Tensor]): Dropout mask for the additional input tensor. upcast (bool): Whether to upcast the input tensors to float. Returns: Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). \"\"\" dtype = x . dtype if upcast : x = x . float () weight = weight . float () bias = bias . float () if bias is not None else None residual = residual . float () if residual is not None else residual x1 = x1 . float () if x1 is not None else None weight1 = weight1 . float () if weight1 is not None else None bias1 = bias1 . float () if bias1 is not None else None if x1 is not None : assert rowscale is None , \"rowscale is not supported with parallel LayerNorm\" if rowscale is not None : x = x * rowscale [ ... , None ] if dropout_p > 0.0 : if dropout_mask is not None : x = x . masked_fill ( ~ dropout_mask , 0.0 ) / ( 1.0 - dropout_p ) else : x = F . dropout ( x , p = dropout_p ) if x1 is not None : if dropout_mask1 is not None : x1 = x1 . masked_fill ( ~ dropout_mask1 , 0.0 ) / ( 1.0 - dropout_p ) else : x1 = F . dropout ( x1 , p = dropout_p ) if x1 is not None : x = x + x1 if residual is not None : x = ( x + residual ) . to ( x . dtype ) out = F . layer_norm ( x . to ( weight . dtype ), x . shape [ - 1 :], weight = weight , bias = bias , eps = eps ) . to ( dtype ) if weight1 is None : return out if not prenorm else ( out , x ) else : out1 = F . layer_norm ( x . to ( weight1 . dtype ), x . shape [ - 1 :], weight = weight1 , bias = bias1 , eps = eps ) . to ( dtype ) return ( out , out1 ) if not prenorm else ( out , out1 , x )","title":"layer_norm_ref"},{"location":"model/#scprint.model.flash_attn.layer_norm.rms_norm_ref","text":"Reference implementation of RMS Normalization with optional dropout and residual connections. Parameters: x ( Tensor ) \u2013 Input tensor. weight ( Tensor ) \u2013 Weight tensor for normalization. bias ( Optional [ Tensor ] , default: None ) \u2013 Bias tensor for normalization. residual ( Optional [ Tensor ] , default: None ) \u2013 Residual tensor to be added to the input. x1 ( Optional [ Tensor ] , default: None ) \u2013 Additional input tensor for parallel RMSNorm. weight1 ( Optional [ Tensor ] , default: None ) \u2013 Additional weight tensor for parallel RMSNorm. bias1 ( Optional [ Tensor ] , default: None ) \u2013 Additional bias tensor for parallel RMSNorm. eps ( float , default: 1e-06 ) \u2013 Epsilon value to avoid division by zero. dropout_p ( float , default: 0.0 ) \u2013 Dropout probability. rowscale ( Optional [ Tensor ] , default: None ) \u2013 Row scaling tensor. prenorm ( bool , default: False ) \u2013 Whether to return the prenormalized output. dropout_mask ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the input tensor. dropout_mask1 ( Optional [ Tensor ] , default: None ) \u2013 Dropout mask for the additional input tensor. upcast ( bool , default: False ) \u2013 Whether to upcast the input tensors to float. Returns: Union [ Tensor , Tuple [ Tensor , ...]] \u2013 Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). Source code in scprint/model/flash_attn/layer_norm.py 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 def rms_norm_ref ( x : torch . Tensor , weight : torch . Tensor , bias : Optional [ torch . Tensor ] = None , residual : Optional [ torch . Tensor ] = None , x1 : Optional [ torch . Tensor ] = None , weight1 : Optional [ torch . Tensor ] = None , bias1 : Optional [ torch . Tensor ] = None , eps : float = 1e-6 , dropout_p : float = 0.0 , rowscale : Optional [ torch . Tensor ] = None , prenorm : bool = False , dropout_mask : Optional [ torch . Tensor ] = None , dropout_mask1 : Optional [ torch . Tensor ] = None , upcast : bool = False , ) -> Union [ torch . Tensor , Tuple [ torch . Tensor , ... ]]: \"\"\" Reference implementation of RMS Normalization with optional dropout and residual connections. Args: x (torch.Tensor): Input tensor. weight (torch.Tensor): Weight tensor for normalization. bias (Optional[torch.Tensor]): Bias tensor for normalization. residual (Optional[torch.Tensor]): Residual tensor to be added to the input. x1 (Optional[torch.Tensor]): Additional input tensor for parallel RMSNorm. weight1 (Optional[torch.Tensor]): Additional weight tensor for parallel RMSNorm. bias1 (Optional[torch.Tensor]): Additional bias tensor for parallel RMSNorm. eps (float): Epsilon value to avoid division by zero. dropout_p (float): Dropout probability. rowscale (Optional[torch.Tensor]): Row scaling tensor. prenorm (bool): Whether to return the prenormalized output. dropout_mask (Optional[torch.Tensor]): Dropout mask for the input tensor. dropout_mask1 (Optional[torch.Tensor]): Dropout mask for the additional input tensor. upcast (bool): Whether to upcast the input tensors to float. Returns: Union[torch.Tensor, Tuple[torch.Tensor, ...]]: Normalized output tensor(s). \"\"\" dtype = x . dtype if upcast : x = x . float () weight = weight . float () bias = bias . float () if bias is not None else None residual = residual . float () if residual is not None else residual x1 = x1 . float () if x1 is not None else None weight1 = weight1 . float () if weight1 is not None else None bias1 = bias1 . float () if bias1 is not None else None if x1 is not None : assert rowscale is None , \"rowscale is not supported with parallel LayerNorm\" if rowscale is not None : x = x * rowscale [ ... , None ] if dropout_p > 0.0 : if dropout_mask is not None : x = x . masked_fill ( ~ dropout_mask , 0.0 ) / ( 1.0 - dropout_p ) else : x = F . dropout ( x , p = dropout_p ) if x1 is not None : if dropout_mask1 is not None : x1 = x1 . masked_fill ( ~ dropout_mask1 , 0.0 ) / ( 1.0 - dropout_p ) else : x1 = F . dropout ( x1 , p = dropout_p ) if x1 is not None : x = x + x1 if residual is not None : x = ( x + residual ) . to ( x . dtype ) rstd = 1 / torch . sqrt (( x . square ()) . mean ( dim =- 1 , keepdim = True ) + eps ) out = (( x * rstd * weight ) + bias if bias is not None else ( x * rstd * weight )) . to ( dtype ) if weight1 is None : return out if not prenorm else ( out , x ) else : out1 = ( ( x * rstd * weight1 ) + bias1 if bias1 is not None else ( x * rstd * weight1 ) ) . to ( dtype ) return ( out , out1 ) if not prenorm else ( out , out1 , x )","title":"rms_norm_ref"},{"location":"pretrain/","text":"Pre-training scPRINT scPRINT is a large model that can be pre-trained on a large dataset of single cell data. This pre-training is quite efficient for scPRINT and smaller models can be pretrained on any hardware with a 20GB NVIDIA GPU. Setup of the database To perform pretraining you will need a large dataset. We recommend using the laminDB to assemble such a large database of dataset and to use our scdataloader package to perform the data loading to the model. In addition, you will need to preprocess your datasets. To make sure that the fields are all here, the genes are in the right format, the raw counts are used, etc... We recommend using the Preprocessor class of the scdataloader package. Moreover scdataloader works with a set of ontologies. To install these, use the function populate_my_ontologies from the scdataloader package. If you do not have your own database of anndatas, we recommend the cellxgene database and our associated helper function to download and preprocess all of cellxgene in a single command with scdataloader . Finally you might want to generate gene embeddings to use with scPRINT instead of learning these tokens from scratch. For this you can use the gene_embedders module of scPRINT, which usage is detailed in the notebooks/generate_gene_embeddings.ipynb notebook. Pre-training to pretrain scPRINT we strongly recommend using command line as it can take multiple days (and using some HPC plateform like slurm or others). If on your own machine, use something like screen at least \ud83d\ude09. Most of the pre-training usage follows from pytorch lightning with scprint fit you will launch a training run. It will populate both the datamodule (see scdataloader ), the model (see model.py ), the trainer (see pytorch lightning ) and the various callbacks. But you might want to use additional parameters. For this, you can use the config folder and the yaml files in it. These files are used to store the main hyperparameters of the model and the training scheme. More hyperparameters are given to the scPRINT model via a Trainer callback I created (see trainer/trainer.py ). This is used to specify parameters to scPRINT that are used solely during training and are not part of the model definition itself, like lr, schedulers, optimizers, etc.. I use a callback as it is how pytorch lightning requires us to send training parameters to the model. Thus a full command line to train scPRINT on a slurm cluster might look like this: conda activate scprint ### slurm level stuff module load cuda/11.7 srun -p gpu #gpu partition -q gpu #gpu queue --gres=gpu:A40:4,gmem:40G #gpu type (4 A40 with 40GB of GPU mem) --cpus-per-task 16 --mem-per-gpu 90G #RAM per GPU --ntasks-per-node=1 #### # actuall scprint command scprint fit --config config/base.yml #base config file (see below) --config config/pretrain_large.yml #the differences when training a large model --model.nhead 8 # changing this parameter from the large model directly in command line (cannot do 4 heads of 128dim with A40 GPUs...) --scprint_training.name o2uniqsx #an id for the model (not needed but useful) --trainer.strategy auto #here the strategy selected will be \"ddp_find_unused_parameters_true\" with the base yaml file containing: # general params project: scprint_scale #project name for saving data and wandb seed_everything: 42 ckpt_path: null #we don't have a checkpoint weights as we train from scratch set_float32_matmul_precision: True wandblog: all #we use wandb here log_freq: 200 log_graph: True trainer: #training level params precision: 16-mixed #we use mixed precision 16bit for training gradient_clip_val: 100 #needed log_every_n_steps: 100 .... logger: #we can add multiple loggers (see below) - class_path: lightning.pytorch.loggers.WandbLogger callbacks: #you can create your own callback and add it here or use lightning's callbacks - class_path: lightning.pytorch.callbacks.StochasticWeightAveraging init_args: swa_lrs: 0.03 ... model: # model params dropout: 0.1 transformer: flash #flashattention is used mvc_decoder: inner product residual_in_fp32: True ... data: #datamodule params organisms: #we will use these 2 species - NCBITaxon:9606 - NCBITaxon:10090 gene_position_tolerance: 10_000 #gene location: if genes are closer than 10kb, they are considered as the same location gene_embeddings: ./data/main/gene_embeddings.parquet #the embeddings of genes (see above ) collection_name: all no zhang13M # the name of the laminDB collection we will use how: random expr # how we collate the expression data (here random expressed genes) max_len: 2200 #how many genes we use in the model context during training weight_scaler: 50 #how do we scale the weighted random sampling procedure (see our manuscript) ... We use wanDB in our case and our previous wandb training runs are available here , however scPRINT and pytorch lightning support a breadth of logging tools: see loggers . We use slurm in our usecase here but scPRINT and pytorch lightning has been made to work in a breadth of environments e.g. . Fine-tuning For now scPRINT doesn't have a fine-tuning script. But PRs are very welcome on using LoRA and its alternatives to fine-tune scPRINT on novel tasks!","title":"pre-training"},{"location":"pretrain/#pre-training-scprint","text":"scPRINT is a large model that can be pre-trained on a large dataset of single cell data. This pre-training is quite efficient for scPRINT and smaller models can be pretrained on any hardware with a 20GB NVIDIA GPU.","title":"Pre-training scPRINT"},{"location":"pretrain/#setup-of-the-database","text":"To perform pretraining you will need a large dataset. We recommend using the laminDB to assemble such a large database of dataset and to use our scdataloader package to perform the data loading to the model. In addition, you will need to preprocess your datasets. To make sure that the fields are all here, the genes are in the right format, the raw counts are used, etc... We recommend using the Preprocessor class of the scdataloader package. Moreover scdataloader works with a set of ontologies. To install these, use the function populate_my_ontologies from the scdataloader package. If you do not have your own database of anndatas, we recommend the cellxgene database and our associated helper function to download and preprocess all of cellxgene in a single command with scdataloader . Finally you might want to generate gene embeddings to use with scPRINT instead of learning these tokens from scratch. For this you can use the gene_embedders module of scPRINT, which usage is detailed in the notebooks/generate_gene_embeddings.ipynb notebook.","title":"Setup of the database"},{"location":"pretrain/#pre-training","text":"to pretrain scPRINT we strongly recommend using command line as it can take multiple days (and using some HPC plateform like slurm or others). If on your own machine, use something like screen at least \ud83d\ude09. Most of the pre-training usage follows from pytorch lightning with scprint fit you will launch a training run. It will populate both the datamodule (see scdataloader ), the model (see model.py ), the trainer (see pytorch lightning ) and the various callbacks. But you might want to use additional parameters. For this, you can use the config folder and the yaml files in it. These files are used to store the main hyperparameters of the model and the training scheme. More hyperparameters are given to the scPRINT model via a Trainer callback I created (see trainer/trainer.py ). This is used to specify parameters to scPRINT that are used solely during training and are not part of the model definition itself, like lr, schedulers, optimizers, etc.. I use a callback as it is how pytorch lightning requires us to send training parameters to the model. Thus a full command line to train scPRINT on a slurm cluster might look like this: conda activate scprint ### slurm level stuff module load cuda/11.7 srun -p gpu #gpu partition -q gpu #gpu queue --gres=gpu:A40:4,gmem:40G #gpu type (4 A40 with 40GB of GPU mem) --cpus-per-task 16 --mem-per-gpu 90G #RAM per GPU --ntasks-per-node=1 #### # actuall scprint command scprint fit --config config/base.yml #base config file (see below) --config config/pretrain_large.yml #the differences when training a large model --model.nhead 8 # changing this parameter from the large model directly in command line (cannot do 4 heads of 128dim with A40 GPUs...) --scprint_training.name o2uniqsx #an id for the model (not needed but useful) --trainer.strategy auto #here the strategy selected will be \"ddp_find_unused_parameters_true\" with the base yaml file containing: # general params project: scprint_scale #project name for saving data and wandb seed_everything: 42 ckpt_path: null #we don't have a checkpoint weights as we train from scratch set_float32_matmul_precision: True wandblog: all #we use wandb here log_freq: 200 log_graph: True trainer: #training level params precision: 16-mixed #we use mixed precision 16bit for training gradient_clip_val: 100 #needed log_every_n_steps: 100 .... logger: #we can add multiple loggers (see below) - class_path: lightning.pytorch.loggers.WandbLogger callbacks: #you can create your own callback and add it here or use lightning's callbacks - class_path: lightning.pytorch.callbacks.StochasticWeightAveraging init_args: swa_lrs: 0.03 ... model: # model params dropout: 0.1 transformer: flash #flashattention is used mvc_decoder: inner product residual_in_fp32: True ... data: #datamodule params organisms: #we will use these 2 species - NCBITaxon:9606 - NCBITaxon:10090 gene_position_tolerance: 10_000 #gene location: if genes are closer than 10kb, they are considered as the same location gene_embeddings: ./data/main/gene_embeddings.parquet #the embeddings of genes (see above ) collection_name: all no zhang13M # the name of the laminDB collection we will use how: random expr # how we collate the expression data (here random expressed genes) max_len: 2200 #how many genes we use in the model context during training weight_scaler: 50 #how do we scale the weighted random sampling procedure (see our manuscript) ... We use wanDB in our case and our previous wandb training runs are available here , however scPRINT and pytorch lightning support a breadth of logging tools: see loggers . We use slurm in our usecase here but scPRINT and pytorch lightning has been made to work in a breadth of environments e.g. .","title":"Pre-training"},{"location":"pretrain/#fine-tuning","text":"For now scPRINT doesn't have a fine-tuning script. But PRs are very welcome on using LoRA and its alternatives to fine-tune scPRINT on novel tasks!","title":"Fine-tuning"},{"location":"structure/","text":"structure gene embedders Function to get embeddings from a set of genes, given their ensembl ids. For now use 2 different models: RNABert : for non coding genes ESM2 : for protein coding genes given ids, a fasta file, will use the models to compute an embedding of each gene. This could be potentially applied to genes with mutations and from different species. data_loaders From scDataloader. (see more in the available readmes and website https://jkobject.com/scDataLoader) For now can work with either one to many AnnData's or a laminDB Collection of AnnDatas allows you to preprocess your anndatas too. They can be stored locally or remotely stores them in a Dataset class. Creates the DataLoaders from a Datamodule Class. Collates the results using a Collator function. model Extends from lightning data module to implement all the necessary functions to do: training validation testing prediction (inference) is subdivided into multiple parts: encoder transformer decoder trainer & cli the model uses lightning's training toolkit and CLI tools. to use CLI, just call scprint ... (will call the __main__.py function). Additional, training-specific informations are passed to the model using the trainer.py function. specific training schemes are available under the config folder as yaml files. Moreover the model can be trained on multiple compute types. SLURM scripts are available under the slurm folder. tasks Implement different tasks that a pretrained model would perform. for now: GRN prediction: given a single cell dataset and a group (cell type, cluster, ...) will output a GRnnData completed with a predicted GRN from the attention of the model. denoising: from a single cell dataset, will modify the count matrices to predict what it would have looked like if it had been sequenced deeper, according to the model. embedding: from a single cell dataset, will create embeddings (low dimensional representations) of each cells, as well as prediction of the cell labels the model has been trained on (cell type, disease, ethnicity, sex...). It will also output a umap and predicted expression from the zinb, post bottleneck (similar to a VAE decoder prediction)","title":"structure"},{"location":"structure/#structure","text":"","title":"structure"},{"location":"structure/#gene-embedders","text":"Function to get embeddings from a set of genes, given their ensembl ids. For now use 2 different models: RNABert : for non coding genes ESM2 : for protein coding genes given ids, a fasta file, will use the models to compute an embedding of each gene. This could be potentially applied to genes with mutations and from different species.","title":"gene embedders"},{"location":"structure/#data_loaders","text":"From scDataloader. (see more in the available readmes and website https://jkobject.com/scDataLoader) For now can work with either one to many AnnData's or a laminDB Collection of AnnDatas allows you to preprocess your anndatas too. They can be stored locally or remotely stores them in a Dataset class. Creates the DataLoaders from a Datamodule Class. Collates the results using a Collator function.","title":"data_loaders"},{"location":"structure/#model","text":"Extends from lightning data module to implement all the necessary functions to do: training validation testing prediction (inference) is subdivided into multiple parts: encoder transformer decoder","title":"model"},{"location":"structure/#trainer-cli","text":"the model uses lightning's training toolkit and CLI tools. to use CLI, just call scprint ... (will call the __main__.py function). Additional, training-specific informations are passed to the model using the trainer.py function. specific training schemes are available under the config folder as yaml files. Moreover the model can be trained on multiple compute types. SLURM scripts are available under the slurm folder.","title":"trainer & cli"},{"location":"structure/#tasks","text":"Implement different tasks that a pretrained model would perform. for now: GRN prediction: given a single cell dataset and a group (cell type, cluster, ...) will output a GRnnData completed with a predicted GRN from the attention of the model. denoising: from a single cell dataset, will modify the count matrices to predict what it would have looked like if it had been sequenced deeper, according to the model. embedding: from a single cell dataset, will create embeddings (low dimensional representations) of each cells, as well as prediction of the cell labels the model has been trained on (cell type, disease, ethnicity, sex...). It will also output a umap and predicted expression from the zinb, post bottleneck (similar to a VAE decoder prediction)","title":"tasks"},{"location":"tasks/","text":"Documentation for the tasks scprint.tasks.cell_emb Embedder Embedder a class to embed and annotate cells using a model Parameters: batch_size ( int , default: 64 ) \u2013 The size of the batches to be used in the DataLoader. Defaults to 64. num_workers ( int , default: 8 ) \u2013 The number of worker processes to use for data loading. Defaults to 8. how ( str , default: 'random expr' ) \u2013 The method to be used for selecting valid genes. Defaults to \"most expr\". max_len ( int , default: 2000 ) \u2013 The maximum length of the gene sequence. Defaults to 1000. add_zero_genes ( int , default: 0 ) \u2013 The number of zero genes to add to the gene sequence. Defaults to 100. precision ( str , default: '16-mixed' ) \u2013 The precision to be used in the Trainer. Defaults to \"16-mixed\". pred_embedding ( List [ str ] , default: ['cell_type_ontology_term_id', 'disease_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'sex_ontology_term_id'] ) \u2013 The list of labels to be used for plotting embeddings. Defaults to [ \"cell_type_ontology_term_id\", \"disease_ontology_term_id\", \"self_reported_ethnicity_ontology_term_id\", \"sex_ontology_term_id\", ]. doclass ( bool , default: True ) \u2013 Whether to perform classification. Defaults to True. doplot ( bool , default: True ) \u2013 Whether to generate plots. Defaults to True. keep_all_cls_pred ( bool , default: False ) \u2013 Whether to keep all class predictions. Defaults to False. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. output_expression ( str , default: 'none' ) \u2013 The method to output expression data. Options are \"none\", \"all\", \"sample\". Defaults to \"none\". Source code in scprint/tasks/cell_emb.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 def __init__ ( self , batch_size : int = 64 , num_workers : int = 8 , how : str = \"random expr\" , max_len : int = 2000 , doclass : bool = True , add_zero_genes : int = 0 , precision : str = \"16-mixed\" , pred_embedding : List [ str ] = [ \"cell_type_ontology_term_id\" , \"disease_ontology_term_id\" , \"self_reported_ethnicity_ontology_term_id\" , \"sex_ontology_term_id\" , ], plot_corr_size : int = 64 , doplot : bool = True , keep_all_cls_pred : bool = False , devices : List [ int ] = [ 0 ], dtype : torch . dtype = torch . float16 , output_expression : str = \"none\" , ): \"\"\" Embedder a class to embed and annotate cells using a model Args: batch_size (int, optional): The size of the batches to be used in the DataLoader. Defaults to 64. num_workers (int, optional): The number of worker processes to use for data loading. Defaults to 8. how (str, optional): The method to be used for selecting valid genes. Defaults to \"most expr\". max_len (int, optional): The maximum length of the gene sequence. Defaults to 1000. add_zero_genes (int, optional): The number of zero genes to add to the gene sequence. Defaults to 100. precision (str, optional): The precision to be used in the Trainer. Defaults to \"16-mixed\". pred_embedding (List[str], optional): The list of labels to be used for plotting embeddings. Defaults to [ \"cell_type_ontology_term_id\", \"disease_ontology_term_id\", \"self_reported_ethnicity_ontology_term_id\", \"sex_ontology_term_id\", ]. doclass (bool, optional): Whether to perform classification. Defaults to True. doplot (bool, optional): Whether to generate plots. Defaults to True. keep_all_cls_pred (bool, optional): Whether to keep all class predictions. Defaults to False. devices (List[int], optional): List of device IDs to use. Defaults to [0]. dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. output_expression (str, optional): The method to output expression data. Options are \"none\", \"all\", \"sample\". Defaults to \"none\". \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . how = how self . max_len = max_len self . add_zero_genes = add_zero_genes self . pred_embedding = pred_embedding self . keep_all_cls_pred = keep_all_cls_pred self . plot_corr_size = plot_corr_size self . precision = precision self . doplot = doplot self . doclass = doclass self . trainer = Trainer ( precision = precision , devices = devices ) self . output_expression = output_expression __call__ call function to call the embedding Parameters: model ( Module ) \u2013 The scPRINT model to be used for embedding and annotation. adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. cache ( bool , default: False ) \u2013 Whether to use cached results if available. Defaults to False. Raises: ValueError \u2013 If the model does not have a logger attribute. ValueError \u2013 If the model does not have a global_step attribute. Returns: AnnData \u2013 The annotated data matrix with embedded cell representations. \u2013 List[str]: List of gene names used in the embedding. \u2013 np.ndarray: The predicted expression values if output_expression is not \"none\". dict \u2013 Additional metrics and information from the embedding process. Source code in scprint/tasks/cell_emb.py 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 def __call__ ( self , model : torch . nn . Module , adata : AnnData , cache = False ): \"\"\" __call__ function to call the embedding Args: model (torch.nn.Module): The scPRINT model to be used for embedding and annotation. adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. cache (bool, optional): Whether to use cached results if available. Defaults to False. Raises: ValueError: If the model does not have a logger attribute. ValueError: If the model does not have a global_step attribute. Returns: AnnData: The annotated data matrix with embedded cell representations. List[str]: List of gene names used in the embedding. np.ndarray: The predicted expression values if output_expression is not \"none\". dict: Additional metrics and information from the embedding process. \"\"\" # one of \"all\" \"sample\" \"none\" try : mdir = ( model . logger . save_dir if model . logger . save_dir is not None else \"data\" ) except : mdir = \"data\" try : file = ( mdir + \"/step_\" + str ( model . global_step ) + \"_predict_part_\" + str ( model . counter ) + \"_\" + str ( model . global_rank ) + \".h5ad\" ) hasfile = os . path . exists ( file ) except : hasfile = False if not cache or not hasfile : model . predict_mode = \"none\" model . keep_all_cls_pred = self . keep_all_cls_pred # Add at least the organism you are working with if self . how == \"most var\" : sc . pp . highly_variable_genes ( adata , flavor = \"seurat_v3\" , n_top_genes = self . max_len ) curr_genes = adata . var . index [ adata . var . highly_variable ] adataset = SimpleAnnDataset ( adata , obs_to_output = [ \"organism_ontology_term_id\" ] ) col = Collator ( organisms = model . organisms , valid_genes = model . genes , how = self . how if self . how != \"most var\" else \"some\" , max_len = self . max_len , add_zero_genes = self . add_zero_genes , genelist = [] if self . how != \"most var\" else curr_genes , ) dataloader = DataLoader ( adataset , collate_fn = col , batch_size = self . batch_size , num_workers = self . num_workers , shuffle = False , ) model . eval () model . on_predict_epoch_start () device = model . device . type model . doplot = self . doplot with torch . no_grad (), torch . autocast ( device_type = device , dtype = torch . float16 ): for batch in tqdm ( dataloader ): gene_pos , expression , depth = ( batch [ \"genes\" ] . to ( device ), batch [ \"x\" ] . to ( device ), batch [ \"depth\" ] . to ( device ), ) model . _predict ( gene_pos , expression , depth , predict_mode = \"none\" , pred_embedding = self . pred_embedding , ) torch . cuda . empty_cache () model . log_adata ( name = \"predict_part_\" + str ( model . counter )) try : mdir = ( model . logger . save_dir if model . logger . save_dir is not None else \"data\" ) except : mdir = \"data\" file = ( mdir + \"/step_\" + str ( model . global_step ) + \"_\" + model . name + \"_predict_part_\" + str ( model . counter ) + \"_\" + str ( model . global_rank ) + \".h5ad\" ) pred_adata = sc . read_h5ad ( file ) if self . output_expression == \"all\" : adata . obsm [ \"scprint_mu\" ] = model . expr_pred [ 0 ] adata . obsm [ \"scprint_theta\" ] = model . expr_pred [ 1 ] adata . obsm [ \"scprint_pi\" ] = model . expr_pred [ 2 ] adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () elif self . output_expression == \"sample\" : adata . obsm [ \"scprint_expr\" ] = ( utils . zinb_sample ( model . expr_pred [ 0 ], model . expr_pred [ 1 ], model . expr_pred [ 2 ], ) . cpu () . numpy () ) adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () elif self . output_expression == \"old\" : expr = np . array ( model . expr_pred [ 0 ]) expr [ np . random . binomial ( 1 , p = np . array ( torch . nn . functional . sigmoid ( model . expr_pred [ 2 ] . to ( torch . float32 ) ) ), ) . astype ( bool ) ] = 0 expr [ expr <= 0.3 ] = 0 expr [( expr >= 0.3 ) & ( expr <= 1 )] = 1 adata . obsm [ \"scprint_expr\" ] = expr . astype ( int ) adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () else : pass pred_adata . obs . index = adata . obs . index adata . obsm [ \"scprint_umap\" ] = pred_adata . obsm [ \"X_umap\" ] # adata.obsm[\"scprint_leiden\"] = pred_adata.obsm[\"leiden\"] adata . obsm [ \"scprint\" ] = pred_adata . X pred_adata . obs . index = adata . obs . index adata . obs = pd . concat ([ adata . obs , pred_adata . obs ], axis = 1 ) if self . keep_all_cls_pred : allclspred = model . pred columns = [] for cl in model . classes : n = model . label_counts [ cl ] columns += [ model . label_decoders [ cl ][ i ] for i in range ( n )] allclspred = pd . DataFrame ( allclspred , columns = columns , index = adata . obs . index ) adata . obs = pd . concat ( adata . obs , allclspred ) metrics = {} if self . doclass and not self . keep_all_cls_pred : for cl in model . classes : res = [] if cl not in adata . obs . columns : continue class_topred = model . label_decoders [ cl ] . values () if cl in model . labels_hierarchy : # class_groupings = { # k: [ # i.ontology_id # for i in bt.CellType.filter(k).first().children.all() # ] # for k in set(adata.obs[cl].unique()) - set(class_topred) # } cur_labels_hierarchy = { model . label_decoders [ cl ][ k ]: [ model . label_decoders [ cl ][ i ] for i in v ] for k , v in model . labels_hierarchy [ cl ] . items () } else : cur_labels_hierarchy = {} for pred , true in adata . obs [[ \"pred_\" + cl , cl ]] . values : if pred == true : res . append ( True ) continue if len ( cur_labels_hierarchy ) > 0 : if true in cur_labels_hierarchy : res . append ( pred in cur_labels_hierarchy [ true ]) continue elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) # else true is unknown # else we pass if len ( res ) == 0 : # true was always unknown res = [ 1 ] if self . doplot : print ( \" \" , cl ) print ( \" accuracy:\" , sum ( res ) / len ( res )) print ( \" \" ) metrics . update ({ cl + \"_accuracy\" : sum ( res ) / len ( res )}) # m = self.compute_reconstruction(adata, plot_corr_size=self.plot_corr_size) # metrics.update(m) return adata , metrics compute_classification Compute classification metrics for the given annotated data. Parameters: adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. classes ( List [ str ] ) \u2013 List of class labels to be used for classification. label_decoders ( Dict [ str , Any ] ) \u2013 Dictionary of label decoders for each class. labels_hierarchy ( Dict [ str , Any ] ) \u2013 Dictionary representing the hierarchy of labels. metric_type ( List [ str ] , default: ['macro', 'micro', 'weighted'] ) \u2013 List of metric types to compute. Defaults to [\"macro\", \"micro\", \"weighted\"]. Returns: Dict [ str , Dict [ str , float ]] \u2013 Dict[str, Dict[str, float]]: A dictionary containing classification metrics for each class. Source code in scprint/tasks/cell_emb.py 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 def compute_classification ( adata : AnnData , classes : List [ str ], label_decoders : Dict [ str , Any ], labels_hierarchy : Dict [ str , Any ], metric_type : List [ str ] = [ \"macro\" , \"micro\" , \"weighted\" ], ) -> Dict [ str , Dict [ str , float ]]: \"\"\" Compute classification metrics for the given annotated data. Args: adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. classes (List[str]): List of class labels to be used for classification. label_decoders (Dict[str, Any]): Dictionary of label decoders for each class. labels_hierarchy (Dict[str, Any]): Dictionary representing the hierarchy of labels. metric_type (List[str], optional): List of metric types to compute. Defaults to [\"macro\", \"micro\", \"weighted\"]. Returns: Dict[str, Dict[str, float]]: A dictionary containing classification metrics for each class. \"\"\" metrics = {} for label in classes : res = [] if label not in adata . obs . columns : continue labels_topred = label_decoders [ label ] . values () if label in labels_hierarchy : parentdf = ( bt . CellType . filter () . df ( include = [ \"parents__ontology_id\" ]) . set_index ( \"ontology_id\" )[[ \"parents__ontology_id\" ]] ) parentdf . parents__ontology_id = parentdf . parents__ontology_id . astype ( str ) class_groupings = { k : get_descendants ( k , parentdf ) for k in set ( adata . obs [ label ] . unique ()) } for pred , true in adata . obs [[ \"pred_\" + label , label ]] . values : if pred == true : res . append ( true ) continue if label in labels_hierarchy : if true in class_groupings : res . append ( true if pred in class_groupings [ true ] else \"\" ) continue elif true not in labels_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true not in labels_topred : raise ValueError ( f \"true label { true } not in available classes\" ) res . append ( \"\" ) metrics [ label ] = {} metrics [ label ][ \"accuracy\" ] = np . mean ( np . array ( res ) == adata . obs [ label ] . values ) for x in metric_type : metrics [ label ][ x ] = f1_score ( np . array ( res ), adata . obs [ label ] . values , average = x ) return metrics compute_corr Compute the correlation between the output and target matrices. Parameters: out ( ndarray ) \u2013 The output matrix. to ( ndarray ) \u2013 The target matrix. doplot ( bool , default: True ) \u2013 Whether to generate a plot of the correlation coefficients. Defaults to True. compute_mean_regress ( bool , default: False ) \u2013 Whether to compute mean regression. Defaults to False. plot_corr_size ( int , default: 64 ) \u2013 The size of the plot for correlation. Defaults to 64. Returns: dict ( dict ) \u2013 A dictionary containing the computed metrics. Source code in scprint/tasks/cell_emb.py 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 def compute_corr ( out : np . ndarray , to : np . ndarray , doplot : bool = True , compute_mean_regress : bool = False , plot_corr_size : int = 64 , ) -> dict : \"\"\" Compute the correlation between the output and target matrices. Args: out (np.ndarray): The output matrix. to (np.ndarray): The target matrix. doplot (bool, optional): Whether to generate a plot of the correlation coefficients. Defaults to True. compute_mean_regress (bool, optional): Whether to compute mean regression. Defaults to False. plot_corr_size (int, optional): The size of the plot for correlation. Defaults to 64. Returns: dict: A dictionary containing the computed metrics. \"\"\" metrics = {} corr_coef , p_value = spearmanr ( out , to . T , ) corr_coef [ p_value > 0.05 ] = 0 # corr_coef[] # only on non zero values, # compare a1-b1 corr with a1-b(n) corr. should be higher # Plot correlation coefficient val = plot_corr_size + 2 if compute_mean_regress else plot_corr_size metrics . update ( { \"recons_corr\" : np . mean ( corr_coef [ val :, : plot_corr_size ] . diagonal ())} ) if compute_mean_regress : metrics . update ( { \"mean_regress\" : np . mean ( corr_coef [ plot_corr_size : plot_corr_size + 2 , : plot_corr_size , ] . flatten () ) } ) if doplot : plt . figure ( figsize = ( 10 , 5 )) plt . imshow ( corr_coef , cmap = \"coolwarm\" , interpolation = \"none\" , vmin =- 1 , vmax = 1 ) plt . colorbar () plt . title ( 'Correlation Coefficient of expr and i[\"x\"]' ) plt . show () return metrics default_benchmark Run the default benchmark for embedding and annotation using the scPRINT model. Parameters: model ( Module ) \u2013 The scPRINT model to be used for embedding and annotation. default_dataset ( str , default: 'pancreas' ) \u2013 The default dataset to use for benchmarking. Options are \"pancreas\", \"lung\", or a path to a dataset. Defaults to \"pancreas\". do_class ( bool , default: True ) \u2013 Whether to perform classification. Defaults to True. coarse ( bool , default: False ) \u2013 Whether to use coarse cell type annotations. Defaults to False. Returns: dict ( dict ) \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/cell_emb.py 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 def default_benchmark ( model : torch . nn . Module , default_dataset : str = \"pancreas\" , do_class : bool = True , coarse : bool = False , ) -> dict : \"\"\" Run the default benchmark for embedding and annotation using the scPRINT model. Args: model (torch.nn.Module): The scPRINT model to be used for embedding and annotation. default_dataset (str, optional): The default dataset to use for benchmarking. Options are \"pancreas\", \"lung\", or a path to a dataset. Defaults to \"pancreas\". do_class (bool, optional): Whether to perform classification. Defaults to True. coarse (bool, optional): Whether to use coarse cell type annotations. Defaults to False. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" if default_dataset == \"pancreas\" : adata = sc . read ( FILE_LOC + \"/../../data/pancreas_atlas.h5ad\" , backup_url = \"https://figshare.com/ndownloader/files/24539828\" , ) adata . obs [ \"cell_type_ontology_term_id\" ] = adata . obs [ \"celltype\" ] . replace ( COARSE if coarse else FINE ) adata . obs [ \"assay_ontology_term_id\" ] = adata . obs [ \"tech\" ] . replace ( COARSE if coarse else FINE ) elif default_dataset == \"lung\" : adata = sc . read ( FILE_LOC + \"/../../data/lung_atlas.h5ad\" , backup_url = \"https://figshare.com/ndownloader/files/24539942\" , ) adata . obs [ \"cell_type_ontology_term_id\" ] = adata . obs [ \"cell_type\" ] . replace ( COARSE if coarse else FINE ) else : adata = sc . read_h5ad ( default_dataset ) adata . obs [ \"batch\" ] = adata . obs [ \"assay_ontology_term_id\" ] adata . obs [ \"cell_type\" ] = adata . obs [ \"cell_type_ontology_term_id\" ] preprocessor = Preprocessor ( use_layer = \"counts\" , is_symbol = True , force_preprocess = True , skip_validate = True , do_postp = False , ) adata . obs [ \"organism_ontology_term_id\" ] = \"NCBITaxon:9606\" adata = preprocessor ( adata . copy ()) embedder = Embedder ( pred_embedding = [ \"cell_type_ontology_term_id\" ], doclass = ( default_dataset not in [ \"pancreas\" , \"lung\" ]), devices = 1 , ) embed_adata , metrics = embedder ( model , adata . copy ()) bm = Benchmarker ( embed_adata , batch_key = \"tech\" if default_dataset == \"pancreas\" else \"batch\" , label_key = \"celltype\" if default_dataset == \"pancreas\" else \"cell_type\" , embedding_obsm_keys = [ \"scprint\" ], n_jobs = 6 , ) bm . benchmark () metrics . update ({ \"scib\" : bm . get_results ( min_max_scale = False ) . T . to_dict ()[ \"scprint\" ]}) metrics [ \"classif\" ] = compute_classification ( embed_adata , model . classes , model . label_decoders , model . labels_hierarchy ) return metrics scprint.tasks.grn GNInfer GNInfer a class to infer gene regulatory networks from a dataset using a scPRINT model. Parameters: layer ( Optional [ list [ int ]] , default: None ) \u2013 List of layers to use for the inference. Defaults to None. batch_size ( int , default: 64 ) \u2013 Batch size for processing. Defaults to 64. num_workers ( int , default: 8 ) \u2013 Number of workers for data loading. Defaults to 8. drop_unexpressed ( bool , default: False ) \u2013 Whether to drop unexpressed genes. Defaults to False. num_genes ( int , default: 3000 ) \u2013 Number of genes to consider. Defaults to 3000. precision ( str , default: '16-mixed' ) \u2013 Precision type for computations. Defaults to \"16-mixed\". cell_type_col ( str , default: 'cell_type' ) \u2013 Column name for cell type information. Defaults to \"cell_type\". how ( str , default: 'random expr' ) \u2013 Method to select genes. Options are \"random expr\", \"most var within\", \"most var across\", \"given\". Defaults to \"random expr\". preprocess ( str , default: 'softmax' ) \u2013 Preprocessing method. Options are \"softmax\", \"sinkhorn\", \"none\". Defaults to \"softmax\". head_agg ( str , default: 'mean' ) \u2013 Aggregation method for heads. Options are \"mean\", \"sum\", \"none\". Defaults to \"mean\". filtration ( str , default: 'thresh' ) \u2013 Filtration method for the adjacency matrix. Options are \"thresh\", \"top-k\", \"mst\", \"known\", \"none\". Defaults to \"thresh\". k ( int , default: 10 ) \u2013 Number of top connections to keep if filtration is \"top-k\". Defaults to 10. apc ( bool , default: False ) \u2013 Whether to apply Average Product Correction. Defaults to False. known_grn ( optional , default: None ) \u2013 Known gene regulatory network to use as a reference. Defaults to None. symmetrize ( bool , default: False ) \u2013 Whether to symmetrize the adjacency matrix. Defaults to False. doplot ( bool , default: True ) \u2013 Whether to generate plots. Defaults to True. max_cells ( int , default: 0 ) \u2013 Maximum number of cells to consider. Defaults to 0. forward_mode ( str , default: 'none' ) \u2013 Mode for forward pass. Defaults to \"none\". genes ( list , default: [] ) \u2013 List of genes to consider. Defaults to an empty list. loc ( str , default: './' ) \u2013 Location to save results. Defaults to \"./\". dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. locname ( str , default: '' ) \u2013 Name for the location. Defaults to an empty string. Source code in scprint/tasks/grn.py 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 def __init__ ( self , layer : Optional [ List [ int ]] = None , batch_size : int = 64 , num_workers : int = 8 , drop_unexpressed : bool = False , num_genes : int = 3000 , precision : str = \"16-mixed\" , cell_type_col : str = \"cell_type\" , how : str = \"random expr\" , # random expr, most var within, most var across, given preprocess : str = \"softmax\" , # sinkhorn, softmax, none head_agg : str = \"mean\" , # mean, sum, none filtration : str = \"thresh\" , # thresh, top-k, mst, known, none k : int = 10 , apc : bool = False , known_grn : Optional [ any ] = None , symmetrize : bool = False , doplot : bool = True , max_cells : int = 0 , forward_mode : str = \"none\" , genes : List [ str ] = [], loc : str = \"./\" , dtype : torch . dtype = torch . float16 , devices : List [ int ] = [ 0 ], locname : str = \"\" , ): \"\"\" GNInfer a class to infer gene regulatory networks from a dataset using a scPRINT model. Args: layer (Optional[list[int]], optional): List of layers to use for the inference. Defaults to None. batch_size (int, optional): Batch size for processing. Defaults to 64. num_workers (int, optional): Number of workers for data loading. Defaults to 8. drop_unexpressed (bool, optional): Whether to drop unexpressed genes. Defaults to False. num_genes (int, optional): Number of genes to consider. Defaults to 3000. precision (str, optional): Precision type for computations. Defaults to \"16-mixed\". cell_type_col (str, optional): Column name for cell type information. Defaults to \"cell_type\". how (str, optional): Method to select genes. Options are \"random expr\", \"most var within\", \"most var across\", \"given\". Defaults to \"random expr\". preprocess (str, optional): Preprocessing method. Options are \"softmax\", \"sinkhorn\", \"none\". Defaults to \"softmax\". head_agg (str, optional): Aggregation method for heads. Options are \"mean\", \"sum\", \"none\". Defaults to \"mean\". filtration (str, optional): Filtration method for the adjacency matrix. Options are \"thresh\", \"top-k\", \"mst\", \"known\", \"none\". Defaults to \"thresh\". k (int, optional): Number of top connections to keep if filtration is \"top-k\". Defaults to 10. apc (bool, optional): Whether to apply Average Product Correction. Defaults to False. known_grn (optional): Known gene regulatory network to use as a reference. Defaults to None. symmetrize (bool, optional): Whether to symmetrize the adjacency matrix. Defaults to False. doplot (bool, optional): Whether to generate plots. Defaults to True. max_cells (int, optional): Maximum number of cells to consider. Defaults to 0. forward_mode (str, optional): Mode for forward pass. Defaults to \"none\". genes (list, optional): List of genes to consider. Defaults to an empty list. loc (str, optional): Location to save results. Defaults to \"./\". dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. devices (List[int], optional): List of device IDs to use. Defaults to [0]. locname (str, optional): Name for the location. Defaults to an empty string. \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . layer = layer self . locname = locname self . how = how assert self . how in [ \"most var within\" , \"most var across\" , \"random expr\" , \"given\" , ], \"how must be one of 'most var within', 'most var across', 'random expr', 'given'\" self . num_genes = num_genes self . preprocess = preprocess self . cell_type_col = cell_type_col self . filtration = filtration self . doplot = doplot self . genes = genes self . apc = apc self . dtype = dtype self . forward_mode = forward_mode self . k = k self . symmetrize = symmetrize self . known_grn = known_grn self . head_agg = head_agg self . max_cells = max_cells self . curr_genes = None self . drop_unexpressed = drop_unexpressed self . precision = precision __call__ call runs the method Parameters: model ( Module ) \u2013 The model to be used for generating the network adata ( AnnData ) \u2013 Annotated data matrix of shape n_obs \u00d7 n_vars . n_obs is the number of cells and n_vars is the number of genes. cell_type ( str , default: None ) \u2013 Specific cell type to filter the data. Defaults to None. Returns: AnnData \u2013 Annotated data matrix with predictions and annotations. \u2013 np.ndarray: Filtered adjacency matrix. Source code in scprint/tasks/grn.py 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 def __call__ ( self , model : torch . nn . Module , adata : AnnData , cell_type = None ): \"\"\" __call__ runs the method Args: model (torch.nn.Module): The model to be used for generating the network adata (AnnData): Annotated data matrix of shape `n_obs` \u00d7 `n_vars`. `n_obs` is the number of cells and `n_vars` is the number of genes. cell_type (str, optional): Specific cell type to filter the data. Defaults to None. Returns: AnnData: Annotated data matrix with predictions and annotations. np.ndarray: Filtered adjacency matrix. \"\"\" # Add at least the organism you are working with if self . layer is None : self . layer = list ( range ( model . nlayers )) subadata = self . predict ( model , adata , self . layer , cell_type ) adjacencies = self . aggregate ( model . attn . get (), model . genes ) if self . head_agg == \"none\" : return self . save ( adjacencies [ 8 :, 8 :, :], subadata ) else : return self . save ( self . filter ( adjacencies )[ 8 :, 8 :], subadata ) default_benchmark default_benchmark function to run the default scPRINT GRN benchmark Parameters: model ( Any ) \u2013 The scPRINT model to be used for the benchmark. default_dataset ( str , default: 'sroy' ) \u2013 The default dataset to use for benchmarking. Defaults to \"sroy\". cell_types ( List [ str ] , default: ['kidney distal convoluted tubule epithelial cell', 'kidney loop of Henle thick ascending limb epithelial cell', 'kidney collecting duct principal cell', 'mesangial cell', 'blood vessel smooth muscle cell', 'podocyte', 'macrophage', 'leukocyte', 'kidney interstitial fibroblast', 'endothelial cell'] ) \u2013 List of cell types to include in the benchmark. Defaults to [ \"kidney distal convoluted tubule epithelial cell\", \"kidney loop of Henle thick ascending limb epithelial cell\", \"kidney collecting duct principal cell\", \"mesangial cell\", \"blood vessel smooth muscle cell\", \"podocyte\", \"macrophage\", \"leukocyte\", \"kidney interstitial fibroblast\", \"endothelial cell\", maxlayers ( int , default: 16 ) \u2013 Maximum number of layers to use from the model. Defaults to 16. maxgenes ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. batch_size ( int , default: 32 ) \u2013 Batch size for processing. Defaults to 32. maxcells ( int , default: 1024 ) \u2013 Maximum number of cells to consider. Defaults to 1024. Returns: dict \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/grn.py 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 def default_benchmark ( model : Any , default_dataset : str = \"sroy\" , cell_types : List [ str ] = [ \"kidney distal convoluted tubule epithelial cell\" , \"kidney loop of Henle thick ascending limb epithelial cell\" , \"kidney collecting duct principal cell\" , \"mesangial cell\" , \"blood vessel smooth muscle cell\" , \"podocyte\" , \"macrophage\" , \"leukocyte\" , \"kidney interstitial fibroblast\" , \"endothelial cell\" , ], maxlayers : int = 16 , maxgenes : int = 5000 , batch_size : int = 32 , maxcells : int = 1024 , ): \"\"\" default_benchmark function to run the default scPRINT GRN benchmark Args: model (Any): The scPRINT model to be used for the benchmark. default_dataset (str, optional): The default dataset to use for benchmarking. Defaults to \"sroy\". cell_types (List[str], optional): List of cell types to include in the benchmark. Defaults to [ \"kidney distal convoluted tubule epithelial cell\", \"kidney loop of Henle thick ascending limb epithelial cell\", \"kidney collecting duct principal cell\", \"mesangial cell\", \"blood vessel smooth muscle cell\", \"podocyte\", \"macrophage\", \"leukocyte\", \"kidney interstitial fibroblast\", \"endothelial cell\", ]. maxlayers (int, optional): Maximum number of layers to use from the model. Defaults to 16. maxgenes (int, optional): Maximum number of genes to consider. Defaults to 5000. batch_size (int, optional): Batch size for processing. Defaults to 32. maxcells (int, optional): Maximum number of cells to consider. Defaults to 1024. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" metrics = {} layers = list ( range ( model . nlayers ))[ max ( 0 , model . nlayers - maxlayers ) :] clf_omni = None if default_dataset == \"sroy\" : preprocessor = Preprocessor ( is_symbol = True , force_preprocess = True , skip_validate = True , do_postp = False , min_valid_genes_id = 5000 , min_dataset_size = 64 , ) clf_self = None todo = [ ( \"han\" , \"human\" , \"full\" ), ( \"mine\" , \"human\" , \"full\" ), ( \"han\" , \"human\" , \"chip\" ), ( \"han\" , \"human\" , \"ko\" ), ( \"tran\" , \"mouse\" , \"full\" ), ( \"zhao\" , \"mouse\" , \"full\" ), ( \"tran\" , \"mouse\" , \"chip\" ), ( \"tran\" , \"mouse\" , \"ko\" ), ] for da , spe , gt in todo : if gt != \"full\" : continue print ( da + \"_\" + gt ) preadata = get_sroy_gt ( get = da , species = spe , gt = gt ) adata = preprocessor ( preadata . copy ()) grn_inferer = GNInfer ( layer = layers , how = \"most var within\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_genes = maxgenes , num_workers = 8 , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata ) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . var [ \"ensembl_id\" ] = grn . var . index grn . var [ \"symbol\" ] = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T if spe == \"human\" : metrics [ \"mean_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () ## OMNI if clf_omni is None : grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.9 , class_weight = { 1 : 800 , 0 : 1 }, shuffle = True , return_full = False , ) joblib . dump ( clf_omni , \"clf_omni.pkl\" ) metrics [ \"omni_classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) if spe == \"human\" : metrics [ \"omni_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = True ) . scprint_benchmark () grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"omni_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) ## SELF if clf_self is None : grn . varp [ \"GRN\" ] = np . transpose ( grn . varp [ \"all\" ], ( 1 , 0 , 2 )) _ , m , clf_self = train_classifier ( grn , other = preadata , C = 1 , train_size = 0.5 , class_weight = { 1 : 40 , 0 : 1 }, shuffle = False , return_full = False , ) metrics [ \"self_classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"self_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) if spe == \"human\" : grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"self_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = True ) . scprint_benchmark () ## chip / ko if ( da , spe , \"chip\" ) in todo : preadata = get_sroy_gt ( get = da , species = spe , gt = \"chip\" ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"omni_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"self_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) if ( da , spe , \"ko\" ) in todo : preadata = get_sroy_gt ( get = da , species = spe , gt = \"ko\" ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"omni_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"self_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) del grn elif default_dataset == \"gwps\" : if not os . path . exists ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ): adata = get_perturb_gt () adata . write_h5ad ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ) else : adata = read_h5ad ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ) preprocessor = Preprocessor ( force_preprocess = True , skip_validate = True , do_postp = False , min_valid_genes_id = maxgenes , min_dataset_size = 64 , ) nadata = preprocessor ( adata . copy ()) adata . var [ \"isTF\" ] = False adata . var . loc [ adata . var . gene_name . isin ( grnutils . TF ), \"isTF\" ] = True adata . var [ \"isTF\" ] . sum () grn_inferer = GNInfer ( layer = layers , how = \"most var within\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_genes = maxgenes , max_cells = maxcells , doplot = False , num_workers = 8 , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , nadata ) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) grn . var [ \"ensembl_id\" ] = grn . var . index grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) metrics [ \"mean_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] grn . var . index = grn . var [ \"ensembl_id\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.9 , class_weight = { 1 : 800 , 0 : 1 }, shuffle = True , doplot = False , return_full = False , use_col = \"gene_name\" , ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"omni\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) metrics [ \"omni_classifier\" ] = m grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"omni_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () grn . varp [ \"GRN\" ] = np . transpose ( grn . varp [ \"all\" ], ( 1 , 0 , 2 )) grn . var . index = grn . var [ \"ensembl_id\" ] _ , m , clf_self = train_classifier ( grn , other = adata , C = 1 , train_size = 0.5 , class_weight = { 1 : 40 , 0 : 1 }, doplot = False , shuffle = False , return_full = False , use_col = \"ensembl_id\" , ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"self\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) metrics [ \"self_classifier\" ] = m grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"self_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () else : # max_genes=4000 adata = sc . read_h5ad ( default_dataset ) adata . var [ \"isTF\" ] = False adata . var . loc [ adata . var . symbol . isin ( grnutils . TF ), \"isTF\" ] = True for celltype in cell_types : print ( celltype ) grn_inferer = GNInfer ( layer = layers , how = \"random expr\" , preprocess = \"softmax\" , head_agg = \"max\" , filtration = \"none\" , forward_mode = \"none\" , num_workers = 8 , num_genes = 2200 , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata [ adata . X . sum ( 1 ) > 500 ], cell_type = celltype ) grn . var . index = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) metrics [ celltype + \"_scprint\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () del grn gc . collect () grn_inferer = GNInfer ( layer = layers , how = \"most var across\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_workers = 8 , num_genes = maxgenes , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata [ adata . X . sum ( 1 ) > 500 ], cell_type = celltype ) grn . var . index = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . mean ( - 1 ) metrics [ celltype + \"_scprint_mean\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () if clf_omni is None : grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.6 , max_iter = 300 , class_weight = { 1 : 800 , 0 : 1 }, return_full = False , shuffle = True , doplot = False , ) joblib . dump ( clf_omni , \"clf_omni.pkl\" ) metrics [ \"classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) metrics [ celltype + \"_scprint_class\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () del grn gc . collect () return metrics scprint.tasks.denoise Denoiser Denoiser class for denoising scRNA-seq data using a scPRINT model Parameters: batch_size ( int , default: 10 ) \u2013 Batch size for processing. Defaults to 10. num_workers ( int , default: 1 ) \u2013 Number of workers for data loading. Defaults to 1. max_len ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. precision ( str , default: '16-mixed' ) \u2013 Precision type for computations. Defaults to \"16-mixed\". how ( str , default: 'most var' ) \u2013 Method to select genes. Options are \"most var\". Defaults to \"most var\". plot_corr_size ( int , default: 10000 ) \u2013 Number of cells to use for plotting correlation. Defaults to 10000. doplot ( bool , default: False ) \u2013 Whether to generate plots. Defaults to False. predict_depth_mult ( int , default: 4 ) \u2013 Multiplier for prediction depth. Defaults to 4. downsample ( Optional [ float ] , default: None ) \u2013 Fraction of data to downsample. Defaults to None. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. Source code in scprint/tasks/denoise.py 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 def __init__ ( self , batch_size : int = 10 , num_workers : int = 1 , max_len : int = 5_000 , precision : str = \"16-mixed\" , how : str = \"most var\" , plot_corr_size : int = 10_000 , doplot : bool = False , predict_depth_mult : int = 4 , downsample : Optional [ float ] = None , devices : List [ int ] = [ 0 ], dtype : torch . dtype = torch . float16 , ): \"\"\" Denoiser class for denoising scRNA-seq data using a scPRINT model Args: batch_size (int, optional): Batch size for processing. Defaults to 10. num_workers (int, optional): Number of workers for data loading. Defaults to 1. max_len (int, optional): Maximum number of genes to consider. Defaults to 5000. precision (str, optional): Precision type for computations. Defaults to \"16-mixed\". how (str, optional): Method to select genes. Options are \"most var\". Defaults to \"most var\". plot_corr_size (int, optional): Number of cells to use for plotting correlation. Defaults to 10000. doplot (bool, optional): Whether to generate plots. Defaults to False. predict_depth_mult (int, optional): Multiplier for prediction depth. Defaults to 4. downsample (Optional[float], optional): Fraction of data to downsample. Defaults to None. devices (List[int], optional): List of device IDs to use. Defaults to [0]. dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . max_len = max_len self . plot_corr_size = plot_corr_size self . doplot = doplot self . predict_depth_mult = predict_depth_mult self . how = how self . downsample = downsample self . precision = precision self . dtype = dtype __call__ call calling the function Parameters: model ( Module ) \u2013 The scPRINT model to be used for denoising. adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. Returns: AnnData \u2013 The denoised annotated data matrix. Source code in scprint/tasks/denoise.py 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 def __call__ ( self , model : torch . nn . Module , adata : AnnData ): \"\"\" __call__ calling the function Args: model (torch.nn.Module): The scPRINT model to be used for denoising. adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. Returns: AnnData: The denoised annotated data matrix. \"\"\" if os . path . exists ( \"collator_output.txt\" ): os . remove ( \"collator_output.txt\" ) random_indices = None if self . plot_corr_size < adata . shape [ 0 ]: random_indices = np . random . randint ( low = 0 , high = adata . shape [ 0 ], size = self . plot_corr_size ) adataset = SimpleAnnDataset ( adata [ random_indices ], obs_to_output = [ \"organism_ontology_term_id\" ] ) else : adataset = SimpleAnnDataset ( adata , obs_to_output = [ \"organism_ontology_term_id\" ] ) if self . how == \"most var\" : sc . pp . highly_variable_genes ( adata , flavor = \"seurat_v3\" , n_top_genes = self . max_len , span = 0.99 ) genelist = adata . var . index [ adata . var . highly_variable ] print ( len ( genelist )) col = Collator ( organisms = model . organisms , valid_genes = model . genes , max_len = self . max_len , how = \"some\" if self . how == \"most var\" else self . how , genelist = genelist if self . how == \"most var\" else [], downsample = self . downsample , save_output = True , ) dataloader = DataLoader ( adataset , collate_fn = col , batch_size = self . batch_size , num_workers = self . num_workers , shuffle = False , ) model . doplot = self . doplot model . on_predict_epoch_start () model . eval () device = model . device . type with torch . no_grad (), torch . autocast ( device_type = device , dtype = self . dtype ): for batch in tqdm ( dataloader ): gene_pos , expression , depth = ( batch [ \"genes\" ] . to ( device ), batch [ \"x\" ] . to ( device ), batch [ \"depth\" ] . to ( device ), ) model . _predict ( gene_pos , expression , depth , predict_mode = \"denoise\" , depth_mult = self . predict_depth_mult , ) torch . cuda . empty_cache () self . genes = ( model . pos . cpu () . numpy () if self . how != \"most var\" else list ( set ( model . genes ) & set ( genelist )) ) tokeep = None metrics = None if self . downsample is not None : reco = model . expr_pred [ 0 ] reco = reco . cpu () . numpy () tokeep = np . isnan ( reco ) . sum ( 1 ) == 0 reco = reco [ tokeep ] noisy = np . loadtxt ( \"collator_output.txt\" )[ tokeep ] if random_indices is not None : true = adata . X [ random_indices ][ tokeep ] else : true = adata . X [ tokeep ] true = true . toarray () if issparse ( true ) else true if self . how == \"most var\" : true = true [:, adata . var . index . isin ( self . genes )] # noisy[true==0]=0 else : true = np . vstack ( [ true [ i , adata . var . index . get_indexer ( np . array ( model . genes )[ val ]), ] . copy () for i , val in enumerate ( self . genes ) ] ) # reco[true==0] = 0 # import pdb # pdb.set_trace() # reco[reco!=0] = 2 # corr_coef = np.corrcoef( # np.vstack([reco[true!=0], noisy[true!=0], true[true!=0]]) # ) corr_coef , p_value = spearmanr ( np . vstack ([ reco [ true != 0 ], noisy [ true != 0 ], true [ true != 0 ]]) . T ) metrics = { \"reco2noisy\" : corr_coef [ 0 , 1 ], \"reco2full\" : corr_coef [ 0 , 2 ], \"noisy2full\" : corr_coef [ 1 , 2 ], } # corr_coef[p_value > 0.05] = 0 # if self.doplot: # plt.figure(figsize=(10, 5)) # plt.imshow( # corr_coef, cmap=\"coolwarm\", interpolation=\"none\", vmin=-1, vmax=1 # ) # plt.colorbar() # plt.title(\"Expression Correlation Coefficient\") # plt.show() # metrics = { # \"reco2noisy\": np.mean( # corr_coef[ # self.plot_corr_size : self.plot_corr_size * 2, : self.plot_corr_size # ].diagonal() # ), # \"reco2full\": np.mean( # corr_coef[self.plot_corr_size * 2 :, : self.plot_corr_size].diagonal() # ), # \"noisy2full\": np.mean( # corr_coef[ # self.plot_corr_size * 2 :, # self.plot_corr_size : self.plot_corr_size * 2, # ].diagonal() # ), # } return ( metrics , ( random_indices [ tokeep ] if random_indices is not None and tokeep is not None else random_indices ), self . genes , ( model . expr_pred [ 0 ][ tokeep ] . cpu () . numpy () if tokeep is not None else model . expr_pred [ 0 ] . cpu () . numpy () ), ) default_benchmark default_benchmark function used to run the default denoising benchmark of scPRINT Parameters: model ( Any ) \u2013 The scPRINT model to be used for the benchmark. default_dataset ( str , default: FILE_DIR + '/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad' ) \u2013 Path to the default dataset to use for benchmarking. Defaults to FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\". max_len ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. Returns: dict \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/denoise.py 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 def default_benchmark ( model : Any , default_dataset : str = FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\" , max_len : int = 5000 , ): \"\"\" default_benchmark function used to run the default denoising benchmark of scPRINT Args: model (Any): The scPRINT model to be used for the benchmark. default_dataset (str, optional): Path to the default dataset to use for benchmarking. Defaults to FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\". max_len (int, optional): Maximum number of genes to consider. Defaults to 5000. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" adata = sc . read_h5ad ( default_dataset ) denoise = Denoiser ( model , batch_size = 40 , max_len = max_len , plot_corr_size = 10_000 , doplot = False , num_workers = 8 , predict_depth_mult = 10 , downsample = 0.7 , devices = 1 , ) return denoise ( adata )[ 0 ] split_molecules Splits molecules into two (potentially overlapping) groups. :param umis: Array of molecules to split :param data_split: Proportion of molecules to assign to the first group :param overlap_factor: Overlap correction factor, if desired :param random_state: For reproducible sampling :return: umis_X and umis_Y, representing split and ~(1 - split) counts sampled from the input array Source code in scprint/tasks/denoise.py 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 def split_molecules ( umis : np . ndarray , data_split : float , overlap_factor : float = 0.0 , random_state : np . random . RandomState = None , ) -> Tuple [ np . ndarray , np . ndarray ]: \"\"\"Splits molecules into two (potentially overlapping) groups. :param umis: Array of molecules to split :param data_split: Proportion of molecules to assign to the first group :param overlap_factor: Overlap correction factor, if desired :param random_state: For reproducible sampling :return: umis_X and umis_Y, representing ``split`` and ``~(1 - split)`` counts sampled from the input array \"\"\" if random_state is None : random_state = np . random . RandomState () umis_X_disjoint = random_state . binomial ( umis , data_split - overlap_factor ) umis_Y_disjoint = random_state . binomial ( umis - umis_X_disjoint , ( 1 - data_split ) / ( 1 - data_split + overlap_factor ) ) overlap_factor = umis - umis_X_disjoint - umis_Y_disjoint umis_X = umis_X_disjoint + overlap_factor umis_Y = umis_Y_disjoint + overlap_factor return umis_X , umis_Y","title":"tasks"},{"location":"tasks/#documentation-for-the-tasks","text":"","title":"Documentation for the tasks"},{"location":"tasks/#scprint.tasks.cell_emb","text":"","title":"cell_emb"},{"location":"tasks/#scprint.tasks.cell_emb.Embedder","text":"Embedder a class to embed and annotate cells using a model Parameters: batch_size ( int , default: 64 ) \u2013 The size of the batches to be used in the DataLoader. Defaults to 64. num_workers ( int , default: 8 ) \u2013 The number of worker processes to use for data loading. Defaults to 8. how ( str , default: 'random expr' ) \u2013 The method to be used for selecting valid genes. Defaults to \"most expr\". max_len ( int , default: 2000 ) \u2013 The maximum length of the gene sequence. Defaults to 1000. add_zero_genes ( int , default: 0 ) \u2013 The number of zero genes to add to the gene sequence. Defaults to 100. precision ( str , default: '16-mixed' ) \u2013 The precision to be used in the Trainer. Defaults to \"16-mixed\". pred_embedding ( List [ str ] , default: ['cell_type_ontology_term_id', 'disease_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'sex_ontology_term_id'] ) \u2013 The list of labels to be used for plotting embeddings. Defaults to [ \"cell_type_ontology_term_id\", \"disease_ontology_term_id\", \"self_reported_ethnicity_ontology_term_id\", \"sex_ontology_term_id\", ]. doclass ( bool , default: True ) \u2013 Whether to perform classification. Defaults to True. doplot ( bool , default: True ) \u2013 Whether to generate plots. Defaults to True. keep_all_cls_pred ( bool , default: False ) \u2013 Whether to keep all class predictions. Defaults to False. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. output_expression ( str , default: 'none' ) \u2013 The method to output expression data. Options are \"none\", \"all\", \"sample\". Defaults to \"none\". Source code in scprint/tasks/cell_emb.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 def __init__ ( self , batch_size : int = 64 , num_workers : int = 8 , how : str = \"random expr\" , max_len : int = 2000 , doclass : bool = True , add_zero_genes : int = 0 , precision : str = \"16-mixed\" , pred_embedding : List [ str ] = [ \"cell_type_ontology_term_id\" , \"disease_ontology_term_id\" , \"self_reported_ethnicity_ontology_term_id\" , \"sex_ontology_term_id\" , ], plot_corr_size : int = 64 , doplot : bool = True , keep_all_cls_pred : bool = False , devices : List [ int ] = [ 0 ], dtype : torch . dtype = torch . float16 , output_expression : str = \"none\" , ): \"\"\" Embedder a class to embed and annotate cells using a model Args: batch_size (int, optional): The size of the batches to be used in the DataLoader. Defaults to 64. num_workers (int, optional): The number of worker processes to use for data loading. Defaults to 8. how (str, optional): The method to be used for selecting valid genes. Defaults to \"most expr\". max_len (int, optional): The maximum length of the gene sequence. Defaults to 1000. add_zero_genes (int, optional): The number of zero genes to add to the gene sequence. Defaults to 100. precision (str, optional): The precision to be used in the Trainer. Defaults to \"16-mixed\". pred_embedding (List[str], optional): The list of labels to be used for plotting embeddings. Defaults to [ \"cell_type_ontology_term_id\", \"disease_ontology_term_id\", \"self_reported_ethnicity_ontology_term_id\", \"sex_ontology_term_id\", ]. doclass (bool, optional): Whether to perform classification. Defaults to True. doplot (bool, optional): Whether to generate plots. Defaults to True. keep_all_cls_pred (bool, optional): Whether to keep all class predictions. Defaults to False. devices (List[int], optional): List of device IDs to use. Defaults to [0]. dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. output_expression (str, optional): The method to output expression data. Options are \"none\", \"all\", \"sample\". Defaults to \"none\". \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . how = how self . max_len = max_len self . add_zero_genes = add_zero_genes self . pred_embedding = pred_embedding self . keep_all_cls_pred = keep_all_cls_pred self . plot_corr_size = plot_corr_size self . precision = precision self . doplot = doplot self . doclass = doclass self . trainer = Trainer ( precision = precision , devices = devices ) self . output_expression = output_expression","title":"Embedder"},{"location":"tasks/#scprint.tasks.cell_emb.Embedder.__call__","text":"call function to call the embedding Parameters: model ( Module ) \u2013 The scPRINT model to be used for embedding and annotation. adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. cache ( bool , default: False ) \u2013 Whether to use cached results if available. Defaults to False. Raises: ValueError \u2013 If the model does not have a logger attribute. ValueError \u2013 If the model does not have a global_step attribute. Returns: AnnData \u2013 The annotated data matrix with embedded cell representations. \u2013 List[str]: List of gene names used in the embedding. \u2013 np.ndarray: The predicted expression values if output_expression is not \"none\". dict \u2013 Additional metrics and information from the embedding process. Source code in scprint/tasks/cell_emb.py 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 def __call__ ( self , model : torch . nn . Module , adata : AnnData , cache = False ): \"\"\" __call__ function to call the embedding Args: model (torch.nn.Module): The scPRINT model to be used for embedding and annotation. adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. cache (bool, optional): Whether to use cached results if available. Defaults to False. Raises: ValueError: If the model does not have a logger attribute. ValueError: If the model does not have a global_step attribute. Returns: AnnData: The annotated data matrix with embedded cell representations. List[str]: List of gene names used in the embedding. np.ndarray: The predicted expression values if output_expression is not \"none\". dict: Additional metrics and information from the embedding process. \"\"\" # one of \"all\" \"sample\" \"none\" try : mdir = ( model . logger . save_dir if model . logger . save_dir is not None else \"data\" ) except : mdir = \"data\" try : file = ( mdir + \"/step_\" + str ( model . global_step ) + \"_predict_part_\" + str ( model . counter ) + \"_\" + str ( model . global_rank ) + \".h5ad\" ) hasfile = os . path . exists ( file ) except : hasfile = False if not cache or not hasfile : model . predict_mode = \"none\" model . keep_all_cls_pred = self . keep_all_cls_pred # Add at least the organism you are working with if self . how == \"most var\" : sc . pp . highly_variable_genes ( adata , flavor = \"seurat_v3\" , n_top_genes = self . max_len ) curr_genes = adata . var . index [ adata . var . highly_variable ] adataset = SimpleAnnDataset ( adata , obs_to_output = [ \"organism_ontology_term_id\" ] ) col = Collator ( organisms = model . organisms , valid_genes = model . genes , how = self . how if self . how != \"most var\" else \"some\" , max_len = self . max_len , add_zero_genes = self . add_zero_genes , genelist = [] if self . how != \"most var\" else curr_genes , ) dataloader = DataLoader ( adataset , collate_fn = col , batch_size = self . batch_size , num_workers = self . num_workers , shuffle = False , ) model . eval () model . on_predict_epoch_start () device = model . device . type model . doplot = self . doplot with torch . no_grad (), torch . autocast ( device_type = device , dtype = torch . float16 ): for batch in tqdm ( dataloader ): gene_pos , expression , depth = ( batch [ \"genes\" ] . to ( device ), batch [ \"x\" ] . to ( device ), batch [ \"depth\" ] . to ( device ), ) model . _predict ( gene_pos , expression , depth , predict_mode = \"none\" , pred_embedding = self . pred_embedding , ) torch . cuda . empty_cache () model . log_adata ( name = \"predict_part_\" + str ( model . counter )) try : mdir = ( model . logger . save_dir if model . logger . save_dir is not None else \"data\" ) except : mdir = \"data\" file = ( mdir + \"/step_\" + str ( model . global_step ) + \"_\" + model . name + \"_predict_part_\" + str ( model . counter ) + \"_\" + str ( model . global_rank ) + \".h5ad\" ) pred_adata = sc . read_h5ad ( file ) if self . output_expression == \"all\" : adata . obsm [ \"scprint_mu\" ] = model . expr_pred [ 0 ] adata . obsm [ \"scprint_theta\" ] = model . expr_pred [ 1 ] adata . obsm [ \"scprint_pi\" ] = model . expr_pred [ 2 ] adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () elif self . output_expression == \"sample\" : adata . obsm [ \"scprint_expr\" ] = ( utils . zinb_sample ( model . expr_pred [ 0 ], model . expr_pred [ 1 ], model . expr_pred [ 2 ], ) . cpu () . numpy () ) adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () elif self . output_expression == \"old\" : expr = np . array ( model . expr_pred [ 0 ]) expr [ np . random . binomial ( 1 , p = np . array ( torch . nn . functional . sigmoid ( model . expr_pred [ 2 ] . to ( torch . float32 ) ) ), ) . astype ( bool ) ] = 0 expr [ expr <= 0.3 ] = 0 expr [( expr >= 0.3 ) & ( expr <= 1 )] = 1 adata . obsm [ \"scprint_expr\" ] = expr . astype ( int ) adata . obsm [ \"scprint_pos\" ] = model . pos . cpu () . numpy () else : pass pred_adata . obs . index = adata . obs . index adata . obsm [ \"scprint_umap\" ] = pred_adata . obsm [ \"X_umap\" ] # adata.obsm[\"scprint_leiden\"] = pred_adata.obsm[\"leiden\"] adata . obsm [ \"scprint\" ] = pred_adata . X pred_adata . obs . index = adata . obs . index adata . obs = pd . concat ([ adata . obs , pred_adata . obs ], axis = 1 ) if self . keep_all_cls_pred : allclspred = model . pred columns = [] for cl in model . classes : n = model . label_counts [ cl ] columns += [ model . label_decoders [ cl ][ i ] for i in range ( n )] allclspred = pd . DataFrame ( allclspred , columns = columns , index = adata . obs . index ) adata . obs = pd . concat ( adata . obs , allclspred ) metrics = {} if self . doclass and not self . keep_all_cls_pred : for cl in model . classes : res = [] if cl not in adata . obs . columns : continue class_topred = model . label_decoders [ cl ] . values () if cl in model . labels_hierarchy : # class_groupings = { # k: [ # i.ontology_id # for i in bt.CellType.filter(k).first().children.all() # ] # for k in set(adata.obs[cl].unique()) - set(class_topred) # } cur_labels_hierarchy = { model . label_decoders [ cl ][ k ]: [ model . label_decoders [ cl ][ i ] for i in v ] for k , v in model . labels_hierarchy [ cl ] . items () } else : cur_labels_hierarchy = {} for pred , true in adata . obs [[ \"pred_\" + cl , cl ]] . values : if pred == true : res . append ( True ) continue if len ( cur_labels_hierarchy ) > 0 : if true in cur_labels_hierarchy : res . append ( pred in cur_labels_hierarchy [ true ]) continue elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) elif true not in class_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true != \"unknown\" : res . append ( False ) # else true is unknown # else we pass if len ( res ) == 0 : # true was always unknown res = [ 1 ] if self . doplot : print ( \" \" , cl ) print ( \" accuracy:\" , sum ( res ) / len ( res )) print ( \" \" ) metrics . update ({ cl + \"_accuracy\" : sum ( res ) / len ( res )}) # m = self.compute_reconstruction(adata, plot_corr_size=self.plot_corr_size) # metrics.update(m) return adata , metrics","title":"__call__"},{"location":"tasks/#scprint.tasks.cell_emb.compute_classification","text":"Compute classification metrics for the given annotated data. Parameters: adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. classes ( List [ str ] ) \u2013 List of class labels to be used for classification. label_decoders ( Dict [ str , Any ] ) \u2013 Dictionary of label decoders for each class. labels_hierarchy ( Dict [ str , Any ] ) \u2013 Dictionary representing the hierarchy of labels. metric_type ( List [ str ] , default: ['macro', 'micro', 'weighted'] ) \u2013 List of metric types to compute. Defaults to [\"macro\", \"micro\", \"weighted\"]. Returns: Dict [ str , Dict [ str , float ]] \u2013 Dict[str, Dict[str, float]]: A dictionary containing classification metrics for each class. Source code in scprint/tasks/cell_emb.py 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 def compute_classification ( adata : AnnData , classes : List [ str ], label_decoders : Dict [ str , Any ], labels_hierarchy : Dict [ str , Any ], metric_type : List [ str ] = [ \"macro\" , \"micro\" , \"weighted\" ], ) -> Dict [ str , Dict [ str , float ]]: \"\"\" Compute classification metrics for the given annotated data. Args: adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. classes (List[str]): List of class labels to be used for classification. label_decoders (Dict[str, Any]): Dictionary of label decoders for each class. labels_hierarchy (Dict[str, Any]): Dictionary representing the hierarchy of labels. metric_type (List[str], optional): List of metric types to compute. Defaults to [\"macro\", \"micro\", \"weighted\"]. Returns: Dict[str, Dict[str, float]]: A dictionary containing classification metrics for each class. \"\"\" metrics = {} for label in classes : res = [] if label not in adata . obs . columns : continue labels_topred = label_decoders [ label ] . values () if label in labels_hierarchy : parentdf = ( bt . CellType . filter () . df ( include = [ \"parents__ontology_id\" ]) . set_index ( \"ontology_id\" )[[ \"parents__ontology_id\" ]] ) parentdf . parents__ontology_id = parentdf . parents__ontology_id . astype ( str ) class_groupings = { k : get_descendants ( k , parentdf ) for k in set ( adata . obs [ label ] . unique ()) } for pred , true in adata . obs [[ \"pred_\" + label , label ]] . values : if pred == true : res . append ( true ) continue if label in labels_hierarchy : if true in class_groupings : res . append ( true if pred in class_groupings [ true ] else \"\" ) continue elif true not in labels_topred : raise ValueError ( f \"true label { true } not in available classes\" ) elif true not in labels_topred : raise ValueError ( f \"true label { true } not in available classes\" ) res . append ( \"\" ) metrics [ label ] = {} metrics [ label ][ \"accuracy\" ] = np . mean ( np . array ( res ) == adata . obs [ label ] . values ) for x in metric_type : metrics [ label ][ x ] = f1_score ( np . array ( res ), adata . obs [ label ] . values , average = x ) return metrics","title":"compute_classification"},{"location":"tasks/#scprint.tasks.cell_emb.compute_corr","text":"Compute the correlation between the output and target matrices. Parameters: out ( ndarray ) \u2013 The output matrix. to ( ndarray ) \u2013 The target matrix. doplot ( bool , default: True ) \u2013 Whether to generate a plot of the correlation coefficients. Defaults to True. compute_mean_regress ( bool , default: False ) \u2013 Whether to compute mean regression. Defaults to False. plot_corr_size ( int , default: 64 ) \u2013 The size of the plot for correlation. Defaults to 64. Returns: dict ( dict ) \u2013 A dictionary containing the computed metrics. Source code in scprint/tasks/cell_emb.py 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 def compute_corr ( out : np . ndarray , to : np . ndarray , doplot : bool = True , compute_mean_regress : bool = False , plot_corr_size : int = 64 , ) -> dict : \"\"\" Compute the correlation between the output and target matrices. Args: out (np.ndarray): The output matrix. to (np.ndarray): The target matrix. doplot (bool, optional): Whether to generate a plot of the correlation coefficients. Defaults to True. compute_mean_regress (bool, optional): Whether to compute mean regression. Defaults to False. plot_corr_size (int, optional): The size of the plot for correlation. Defaults to 64. Returns: dict: A dictionary containing the computed metrics. \"\"\" metrics = {} corr_coef , p_value = spearmanr ( out , to . T , ) corr_coef [ p_value > 0.05 ] = 0 # corr_coef[] # only on non zero values, # compare a1-b1 corr with a1-b(n) corr. should be higher # Plot correlation coefficient val = plot_corr_size + 2 if compute_mean_regress else plot_corr_size metrics . update ( { \"recons_corr\" : np . mean ( corr_coef [ val :, : plot_corr_size ] . diagonal ())} ) if compute_mean_regress : metrics . update ( { \"mean_regress\" : np . mean ( corr_coef [ plot_corr_size : plot_corr_size + 2 , : plot_corr_size , ] . flatten () ) } ) if doplot : plt . figure ( figsize = ( 10 , 5 )) plt . imshow ( corr_coef , cmap = \"coolwarm\" , interpolation = \"none\" , vmin =- 1 , vmax = 1 ) plt . colorbar () plt . title ( 'Correlation Coefficient of expr and i[\"x\"]' ) plt . show () return metrics","title":"compute_corr"},{"location":"tasks/#scprint.tasks.cell_emb.default_benchmark","text":"Run the default benchmark for embedding and annotation using the scPRINT model. Parameters: model ( Module ) \u2013 The scPRINT model to be used for embedding and annotation. default_dataset ( str , default: 'pancreas' ) \u2013 The default dataset to use for benchmarking. Options are \"pancreas\", \"lung\", or a path to a dataset. Defaults to \"pancreas\". do_class ( bool , default: True ) \u2013 Whether to perform classification. Defaults to True. coarse ( bool , default: False ) \u2013 Whether to use coarse cell type annotations. Defaults to False. Returns: dict ( dict ) \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/cell_emb.py 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 def default_benchmark ( model : torch . nn . Module , default_dataset : str = \"pancreas\" , do_class : bool = True , coarse : bool = False , ) -> dict : \"\"\" Run the default benchmark for embedding and annotation using the scPRINT model. Args: model (torch.nn.Module): The scPRINT model to be used for embedding and annotation. default_dataset (str, optional): The default dataset to use for benchmarking. Options are \"pancreas\", \"lung\", or a path to a dataset. Defaults to \"pancreas\". do_class (bool, optional): Whether to perform classification. Defaults to True. coarse (bool, optional): Whether to use coarse cell type annotations. Defaults to False. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" if default_dataset == \"pancreas\" : adata = sc . read ( FILE_LOC + \"/../../data/pancreas_atlas.h5ad\" , backup_url = \"https://figshare.com/ndownloader/files/24539828\" , ) adata . obs [ \"cell_type_ontology_term_id\" ] = adata . obs [ \"celltype\" ] . replace ( COARSE if coarse else FINE ) adata . obs [ \"assay_ontology_term_id\" ] = adata . obs [ \"tech\" ] . replace ( COARSE if coarse else FINE ) elif default_dataset == \"lung\" : adata = sc . read ( FILE_LOC + \"/../../data/lung_atlas.h5ad\" , backup_url = \"https://figshare.com/ndownloader/files/24539942\" , ) adata . obs [ \"cell_type_ontology_term_id\" ] = adata . obs [ \"cell_type\" ] . replace ( COARSE if coarse else FINE ) else : adata = sc . read_h5ad ( default_dataset ) adata . obs [ \"batch\" ] = adata . obs [ \"assay_ontology_term_id\" ] adata . obs [ \"cell_type\" ] = adata . obs [ \"cell_type_ontology_term_id\" ] preprocessor = Preprocessor ( use_layer = \"counts\" , is_symbol = True , force_preprocess = True , skip_validate = True , do_postp = False , ) adata . obs [ \"organism_ontology_term_id\" ] = \"NCBITaxon:9606\" adata = preprocessor ( adata . copy ()) embedder = Embedder ( pred_embedding = [ \"cell_type_ontology_term_id\" ], doclass = ( default_dataset not in [ \"pancreas\" , \"lung\" ]), devices = 1 , ) embed_adata , metrics = embedder ( model , adata . copy ()) bm = Benchmarker ( embed_adata , batch_key = \"tech\" if default_dataset == \"pancreas\" else \"batch\" , label_key = \"celltype\" if default_dataset == \"pancreas\" else \"cell_type\" , embedding_obsm_keys = [ \"scprint\" ], n_jobs = 6 , ) bm . benchmark () metrics . update ({ \"scib\" : bm . get_results ( min_max_scale = False ) . T . to_dict ()[ \"scprint\" ]}) metrics [ \"classif\" ] = compute_classification ( embed_adata , model . classes , model . label_decoders , model . labels_hierarchy ) return metrics","title":"default_benchmark"},{"location":"tasks/#scprint.tasks.grn","text":"","title":"grn"},{"location":"tasks/#scprint.tasks.grn.GNInfer","text":"GNInfer a class to infer gene regulatory networks from a dataset using a scPRINT model. Parameters: layer ( Optional [ list [ int ]] , default: None ) \u2013 List of layers to use for the inference. Defaults to None. batch_size ( int , default: 64 ) \u2013 Batch size for processing. Defaults to 64. num_workers ( int , default: 8 ) \u2013 Number of workers for data loading. Defaults to 8. drop_unexpressed ( bool , default: False ) \u2013 Whether to drop unexpressed genes. Defaults to False. num_genes ( int , default: 3000 ) \u2013 Number of genes to consider. Defaults to 3000. precision ( str , default: '16-mixed' ) \u2013 Precision type for computations. Defaults to \"16-mixed\". cell_type_col ( str , default: 'cell_type' ) \u2013 Column name for cell type information. Defaults to \"cell_type\". how ( str , default: 'random expr' ) \u2013 Method to select genes. Options are \"random expr\", \"most var within\", \"most var across\", \"given\". Defaults to \"random expr\". preprocess ( str , default: 'softmax' ) \u2013 Preprocessing method. Options are \"softmax\", \"sinkhorn\", \"none\". Defaults to \"softmax\". head_agg ( str , default: 'mean' ) \u2013 Aggregation method for heads. Options are \"mean\", \"sum\", \"none\". Defaults to \"mean\". filtration ( str , default: 'thresh' ) \u2013 Filtration method for the adjacency matrix. Options are \"thresh\", \"top-k\", \"mst\", \"known\", \"none\". Defaults to \"thresh\". k ( int , default: 10 ) \u2013 Number of top connections to keep if filtration is \"top-k\". Defaults to 10. apc ( bool , default: False ) \u2013 Whether to apply Average Product Correction. Defaults to False. known_grn ( optional , default: None ) \u2013 Known gene regulatory network to use as a reference. Defaults to None. symmetrize ( bool , default: False ) \u2013 Whether to symmetrize the adjacency matrix. Defaults to False. doplot ( bool , default: True ) \u2013 Whether to generate plots. Defaults to True. max_cells ( int , default: 0 ) \u2013 Maximum number of cells to consider. Defaults to 0. forward_mode ( str , default: 'none' ) \u2013 Mode for forward pass. Defaults to \"none\". genes ( list , default: [] ) \u2013 List of genes to consider. Defaults to an empty list. loc ( str , default: './' ) \u2013 Location to save results. Defaults to \"./\". dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. locname ( str , default: '' ) \u2013 Name for the location. Defaults to an empty string. Source code in scprint/tasks/grn.py 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 def __init__ ( self , layer : Optional [ List [ int ]] = None , batch_size : int = 64 , num_workers : int = 8 , drop_unexpressed : bool = False , num_genes : int = 3000 , precision : str = \"16-mixed\" , cell_type_col : str = \"cell_type\" , how : str = \"random expr\" , # random expr, most var within, most var across, given preprocess : str = \"softmax\" , # sinkhorn, softmax, none head_agg : str = \"mean\" , # mean, sum, none filtration : str = \"thresh\" , # thresh, top-k, mst, known, none k : int = 10 , apc : bool = False , known_grn : Optional [ any ] = None , symmetrize : bool = False , doplot : bool = True , max_cells : int = 0 , forward_mode : str = \"none\" , genes : List [ str ] = [], loc : str = \"./\" , dtype : torch . dtype = torch . float16 , devices : List [ int ] = [ 0 ], locname : str = \"\" , ): \"\"\" GNInfer a class to infer gene regulatory networks from a dataset using a scPRINT model. Args: layer (Optional[list[int]], optional): List of layers to use for the inference. Defaults to None. batch_size (int, optional): Batch size for processing. Defaults to 64. num_workers (int, optional): Number of workers for data loading. Defaults to 8. drop_unexpressed (bool, optional): Whether to drop unexpressed genes. Defaults to False. num_genes (int, optional): Number of genes to consider. Defaults to 3000. precision (str, optional): Precision type for computations. Defaults to \"16-mixed\". cell_type_col (str, optional): Column name for cell type information. Defaults to \"cell_type\". how (str, optional): Method to select genes. Options are \"random expr\", \"most var within\", \"most var across\", \"given\". Defaults to \"random expr\". preprocess (str, optional): Preprocessing method. Options are \"softmax\", \"sinkhorn\", \"none\". Defaults to \"softmax\". head_agg (str, optional): Aggregation method for heads. Options are \"mean\", \"sum\", \"none\". Defaults to \"mean\". filtration (str, optional): Filtration method for the adjacency matrix. Options are \"thresh\", \"top-k\", \"mst\", \"known\", \"none\". Defaults to \"thresh\". k (int, optional): Number of top connections to keep if filtration is \"top-k\". Defaults to 10. apc (bool, optional): Whether to apply Average Product Correction. Defaults to False. known_grn (optional): Known gene regulatory network to use as a reference. Defaults to None. symmetrize (bool, optional): Whether to symmetrize the adjacency matrix. Defaults to False. doplot (bool, optional): Whether to generate plots. Defaults to True. max_cells (int, optional): Maximum number of cells to consider. Defaults to 0. forward_mode (str, optional): Mode for forward pass. Defaults to \"none\". genes (list, optional): List of genes to consider. Defaults to an empty list. loc (str, optional): Location to save results. Defaults to \"./\". dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. devices (List[int], optional): List of device IDs to use. Defaults to [0]. locname (str, optional): Name for the location. Defaults to an empty string. \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . layer = layer self . locname = locname self . how = how assert self . how in [ \"most var within\" , \"most var across\" , \"random expr\" , \"given\" , ], \"how must be one of 'most var within', 'most var across', 'random expr', 'given'\" self . num_genes = num_genes self . preprocess = preprocess self . cell_type_col = cell_type_col self . filtration = filtration self . doplot = doplot self . genes = genes self . apc = apc self . dtype = dtype self . forward_mode = forward_mode self . k = k self . symmetrize = symmetrize self . known_grn = known_grn self . head_agg = head_agg self . max_cells = max_cells self . curr_genes = None self . drop_unexpressed = drop_unexpressed self . precision = precision","title":"GNInfer"},{"location":"tasks/#scprint.tasks.grn.GNInfer.__call__","text":"call runs the method Parameters: model ( Module ) \u2013 The model to be used for generating the network adata ( AnnData ) \u2013 Annotated data matrix of shape n_obs \u00d7 n_vars . n_obs is the number of cells and n_vars is the number of genes. cell_type ( str , default: None ) \u2013 Specific cell type to filter the data. Defaults to None. Returns: AnnData \u2013 Annotated data matrix with predictions and annotations. \u2013 np.ndarray: Filtered adjacency matrix. Source code in scprint/tasks/grn.py 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 def __call__ ( self , model : torch . nn . Module , adata : AnnData , cell_type = None ): \"\"\" __call__ runs the method Args: model (torch.nn.Module): The model to be used for generating the network adata (AnnData): Annotated data matrix of shape `n_obs` \u00d7 `n_vars`. `n_obs` is the number of cells and `n_vars` is the number of genes. cell_type (str, optional): Specific cell type to filter the data. Defaults to None. Returns: AnnData: Annotated data matrix with predictions and annotations. np.ndarray: Filtered adjacency matrix. \"\"\" # Add at least the organism you are working with if self . layer is None : self . layer = list ( range ( model . nlayers )) subadata = self . predict ( model , adata , self . layer , cell_type ) adjacencies = self . aggregate ( model . attn . get (), model . genes ) if self . head_agg == \"none\" : return self . save ( adjacencies [ 8 :, 8 :, :], subadata ) else : return self . save ( self . filter ( adjacencies )[ 8 :, 8 :], subadata )","title":"__call__"},{"location":"tasks/#scprint.tasks.grn.default_benchmark","text":"default_benchmark function to run the default scPRINT GRN benchmark Parameters: model ( Any ) \u2013 The scPRINT model to be used for the benchmark. default_dataset ( str , default: 'sroy' ) \u2013 The default dataset to use for benchmarking. Defaults to \"sroy\". cell_types ( List [ str ] , default: ['kidney distal convoluted tubule epithelial cell', 'kidney loop of Henle thick ascending limb epithelial cell', 'kidney collecting duct principal cell', 'mesangial cell', 'blood vessel smooth muscle cell', 'podocyte', 'macrophage', 'leukocyte', 'kidney interstitial fibroblast', 'endothelial cell'] ) \u2013 List of cell types to include in the benchmark. Defaults to [ \"kidney distal convoluted tubule epithelial cell\", \"kidney loop of Henle thick ascending limb epithelial cell\", \"kidney collecting duct principal cell\", \"mesangial cell\", \"blood vessel smooth muscle cell\", \"podocyte\", \"macrophage\", \"leukocyte\", \"kidney interstitial fibroblast\", \"endothelial cell\", maxlayers ( int , default: 16 ) \u2013 Maximum number of layers to use from the model. Defaults to 16. maxgenes ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. batch_size ( int , default: 32 ) \u2013 Batch size for processing. Defaults to 32. maxcells ( int , default: 1024 ) \u2013 Maximum number of cells to consider. Defaults to 1024. Returns: dict \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/grn.py 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 def default_benchmark ( model : Any , default_dataset : str = \"sroy\" , cell_types : List [ str ] = [ \"kidney distal convoluted tubule epithelial cell\" , \"kidney loop of Henle thick ascending limb epithelial cell\" , \"kidney collecting duct principal cell\" , \"mesangial cell\" , \"blood vessel smooth muscle cell\" , \"podocyte\" , \"macrophage\" , \"leukocyte\" , \"kidney interstitial fibroblast\" , \"endothelial cell\" , ], maxlayers : int = 16 , maxgenes : int = 5000 , batch_size : int = 32 , maxcells : int = 1024 , ): \"\"\" default_benchmark function to run the default scPRINT GRN benchmark Args: model (Any): The scPRINT model to be used for the benchmark. default_dataset (str, optional): The default dataset to use for benchmarking. Defaults to \"sroy\". cell_types (List[str], optional): List of cell types to include in the benchmark. Defaults to [ \"kidney distal convoluted tubule epithelial cell\", \"kidney loop of Henle thick ascending limb epithelial cell\", \"kidney collecting duct principal cell\", \"mesangial cell\", \"blood vessel smooth muscle cell\", \"podocyte\", \"macrophage\", \"leukocyte\", \"kidney interstitial fibroblast\", \"endothelial cell\", ]. maxlayers (int, optional): Maximum number of layers to use from the model. Defaults to 16. maxgenes (int, optional): Maximum number of genes to consider. Defaults to 5000. batch_size (int, optional): Batch size for processing. Defaults to 32. maxcells (int, optional): Maximum number of cells to consider. Defaults to 1024. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" metrics = {} layers = list ( range ( model . nlayers ))[ max ( 0 , model . nlayers - maxlayers ) :] clf_omni = None if default_dataset == \"sroy\" : preprocessor = Preprocessor ( is_symbol = True , force_preprocess = True , skip_validate = True , do_postp = False , min_valid_genes_id = 5000 , min_dataset_size = 64 , ) clf_self = None todo = [ ( \"han\" , \"human\" , \"full\" ), ( \"mine\" , \"human\" , \"full\" ), ( \"han\" , \"human\" , \"chip\" ), ( \"han\" , \"human\" , \"ko\" ), ( \"tran\" , \"mouse\" , \"full\" ), ( \"zhao\" , \"mouse\" , \"full\" ), ( \"tran\" , \"mouse\" , \"chip\" ), ( \"tran\" , \"mouse\" , \"ko\" ), ] for da , spe , gt in todo : if gt != \"full\" : continue print ( da + \"_\" + gt ) preadata = get_sroy_gt ( get = da , species = spe , gt = gt ) adata = preprocessor ( preadata . copy ()) grn_inferer = GNInfer ( layer = layers , how = \"most var within\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_genes = maxgenes , num_workers = 8 , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata ) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . var [ \"ensembl_id\" ] = grn . var . index grn . var [ \"symbol\" ] = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T if spe == \"human\" : metrics [ \"mean_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () ## OMNI if clf_omni is None : grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.9 , class_weight = { 1 : 800 , 0 : 1 }, shuffle = True , return_full = False , ) joblib . dump ( clf_omni , \"clf_omni.pkl\" ) metrics [ \"omni_classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) if spe == \"human\" : metrics [ \"omni_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = True ) . scprint_benchmark () grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"omni_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) ## SELF if clf_self is None : grn . varp [ \"GRN\" ] = np . transpose ( grn . varp [ \"all\" ], ( 1 , 0 , 2 )) _ , m , clf_self = train_classifier ( grn , other = preadata , C = 1 , train_size = 0.5 , class_weight = { 1 : 40 , 0 : 1 }, shuffle = False , return_full = False , ) metrics [ \"self_classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"self_\" + da + \"_\" + gt ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) if spe == \"human\" : grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"self_\" + da + \"_\" + gt + \"_base\" ] = BenGRN ( grn , do_auc = True , doplot = True ) . scprint_benchmark () ## chip / ko if ( da , spe , \"chip\" ) in todo : preadata = get_sroy_gt ( get = da , species = spe , gt = \"chip\" ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"omni_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"self_\" + da + \"_\" + \"chip\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) if ( da , spe , \"ko\" ) in todo : preadata = get_sroy_gt ( get = da , species = spe , gt = \"ko\" ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"omni_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) grn . varp [ \"GRN\" ] = ( grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T ) metrics [ \"self_\" + da + \"_\" + \"ko\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = preadata ) del grn elif default_dataset == \"gwps\" : if not os . path . exists ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ): adata = get_perturb_gt () adata . write_h5ad ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ) else : adata = read_h5ad ( FILEDIR + \"/../../data/perturb_gt.h5ad\" ) preprocessor = Preprocessor ( force_preprocess = True , skip_validate = True , do_postp = False , min_valid_genes_id = maxgenes , min_dataset_size = 64 , ) nadata = preprocessor ( adata . copy ()) adata . var [ \"isTF\" ] = False adata . var . loc [ adata . var . gene_name . isin ( grnutils . TF ), \"isTF\" ] = True adata . var [ \"isTF\" ] . sum () grn_inferer = GNInfer ( layer = layers , how = \"most var within\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_genes = maxgenes , max_cells = maxcells , doplot = False , num_workers = 8 , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , nadata ) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) . T metrics [ \"mean\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) grn . var [ \"ensembl_id\" ] = grn . var . index grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] . mean ( - 1 ) metrics [ \"mean_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] grn . var . index = grn . var [ \"ensembl_id\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.9 , class_weight = { 1 : 800 , 0 : 1 }, shuffle = True , doplot = False , return_full = False , use_col = \"gene_name\" , ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"omni\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) metrics [ \"omni_classifier\" ] = m grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"omni_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () grn . varp [ \"GRN\" ] = np . transpose ( grn . varp [ \"all\" ], ( 1 , 0 , 2 )) grn . var . index = grn . var [ \"ensembl_id\" ] _ , m , clf_self = train_classifier ( grn , other = adata , C = 1 , train_size = 0.5 , class_weight = { 1 : 40 , 0 : 1 }, doplot = False , shuffle = False , return_full = False , use_col = \"ensembl_id\" , ) grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_self . coef_ [ 0 ] > 0 ] . mean ( - 1 ) . T metrics [ \"self\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . compare_to ( other = adata ) metrics [ \"self_classifier\" ] = m grn . var . index = grn . var [ \"symbol\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . T metrics [ \"self_base\" ] = BenGRN ( grn , do_auc = True , doplot = False ) . scprint_benchmark () else : # max_genes=4000 adata = sc . read_h5ad ( default_dataset ) adata . var [ \"isTF\" ] = False adata . var . loc [ adata . var . symbol . isin ( grnutils . TF ), \"isTF\" ] = True for celltype in cell_types : print ( celltype ) grn_inferer = GNInfer ( layer = layers , how = \"random expr\" , preprocess = \"softmax\" , head_agg = \"max\" , filtration = \"none\" , forward_mode = \"none\" , num_workers = 8 , num_genes = 2200 , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata [ adata . X . sum ( 1 ) > 500 ], cell_type = celltype ) grn . var . index = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) metrics [ celltype + \"_scprint\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () del grn gc . collect () grn_inferer = GNInfer ( layer = layers , how = \"most var across\" , preprocess = \"softmax\" , head_agg = \"none\" , filtration = \"none\" , forward_mode = \"none\" , num_workers = 8 , num_genes = maxgenes , max_cells = maxcells , doplot = False , batch_size = batch_size , devices = 1 , ) grn = grn_inferer ( model , adata [ adata . X . sum ( 1 ) > 500 ], cell_type = celltype ) grn . var . index = make_index_unique ( grn . var [ \"symbol\" ] . astype ( str )) grn . varp [ \"all\" ] = grn . varp [ \"GRN\" ] grn . varp [ \"GRN\" ] = grn . varp [ \"GRN\" ] . mean ( - 1 ) metrics [ celltype + \"_scprint_mean\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () if clf_omni is None : grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ] _ , m , clf_omni = train_classifier ( grn , C = 1 , train_size = 0.6 , max_iter = 300 , class_weight = { 1 : 800 , 0 : 1 }, return_full = False , shuffle = True , doplot = False , ) joblib . dump ( clf_omni , \"clf_omni.pkl\" ) metrics [ \"classifier\" ] = m grn . varp [ \"GRN\" ] = grn . varp [ \"all\" ][:, :, clf_omni . coef_ [ 0 ] > 0 ] . mean ( - 1 ) metrics [ celltype + \"_scprint_class\" ] = BenGRN ( grn , doplot = False ) . scprint_benchmark () del grn gc . collect () return metrics","title":"default_benchmark"},{"location":"tasks/#scprint.tasks.denoise","text":"","title":"denoise"},{"location":"tasks/#scprint.tasks.denoise.Denoiser","text":"Denoiser class for denoising scRNA-seq data using a scPRINT model Parameters: batch_size ( int , default: 10 ) \u2013 Batch size for processing. Defaults to 10. num_workers ( int , default: 1 ) \u2013 Number of workers for data loading. Defaults to 1. max_len ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. precision ( str , default: '16-mixed' ) \u2013 Precision type for computations. Defaults to \"16-mixed\". how ( str , default: 'most var' ) \u2013 Method to select genes. Options are \"most var\". Defaults to \"most var\". plot_corr_size ( int , default: 10000 ) \u2013 Number of cells to use for plotting correlation. Defaults to 10000. doplot ( bool , default: False ) \u2013 Whether to generate plots. Defaults to False. predict_depth_mult ( int , default: 4 ) \u2013 Multiplier for prediction depth. Defaults to 4. downsample ( Optional [ float ] , default: None ) \u2013 Fraction of data to downsample. Defaults to None. devices ( List [ int ] , default: [0] ) \u2013 List of device IDs to use. Defaults to [0]. dtype ( dtype , default: float16 ) \u2013 Data type for computations. Defaults to torch.float16. Source code in scprint/tasks/denoise.py 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 def __init__ ( self , batch_size : int = 10 , num_workers : int = 1 , max_len : int = 5_000 , precision : str = \"16-mixed\" , how : str = \"most var\" , plot_corr_size : int = 10_000 , doplot : bool = False , predict_depth_mult : int = 4 , downsample : Optional [ float ] = None , devices : List [ int ] = [ 0 ], dtype : torch . dtype = torch . float16 , ): \"\"\" Denoiser class for denoising scRNA-seq data using a scPRINT model Args: batch_size (int, optional): Batch size for processing. Defaults to 10. num_workers (int, optional): Number of workers for data loading. Defaults to 1. max_len (int, optional): Maximum number of genes to consider. Defaults to 5000. precision (str, optional): Precision type for computations. Defaults to \"16-mixed\". how (str, optional): Method to select genes. Options are \"most var\". Defaults to \"most var\". plot_corr_size (int, optional): Number of cells to use for plotting correlation. Defaults to 10000. doplot (bool, optional): Whether to generate plots. Defaults to False. predict_depth_mult (int, optional): Multiplier for prediction depth. Defaults to 4. downsample (Optional[float], optional): Fraction of data to downsample. Defaults to None. devices (List[int], optional): List of device IDs to use. Defaults to [0]. dtype (torch.dtype, optional): Data type for computations. Defaults to torch.float16. \"\"\" self . batch_size = batch_size self . num_workers = num_workers self . max_len = max_len self . plot_corr_size = plot_corr_size self . doplot = doplot self . predict_depth_mult = predict_depth_mult self . how = how self . downsample = downsample self . precision = precision self . dtype = dtype","title":"Denoiser"},{"location":"tasks/#scprint.tasks.denoise.Denoiser.__call__","text":"call calling the function Parameters: model ( Module ) \u2013 The scPRINT model to be used for denoising. adata ( AnnData ) \u2013 The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. Returns: AnnData \u2013 The denoised annotated data matrix. Source code in scprint/tasks/denoise.py 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 def __call__ ( self , model : torch . nn . Module , adata : AnnData ): \"\"\" __call__ calling the function Args: model (torch.nn.Module): The scPRINT model to be used for denoising. adata (AnnData): The annotated data matrix of shape n_obs x n_vars. Rows correspond to cells and columns to genes. Returns: AnnData: The denoised annotated data matrix. \"\"\" if os . path . exists ( \"collator_output.txt\" ): os . remove ( \"collator_output.txt\" ) random_indices = None if self . plot_corr_size < adata . shape [ 0 ]: random_indices = np . random . randint ( low = 0 , high = adata . shape [ 0 ], size = self . plot_corr_size ) adataset = SimpleAnnDataset ( adata [ random_indices ], obs_to_output = [ \"organism_ontology_term_id\" ] ) else : adataset = SimpleAnnDataset ( adata , obs_to_output = [ \"organism_ontology_term_id\" ] ) if self . how == \"most var\" : sc . pp . highly_variable_genes ( adata , flavor = \"seurat_v3\" , n_top_genes = self . max_len , span = 0.99 ) genelist = adata . var . index [ adata . var . highly_variable ] print ( len ( genelist )) col = Collator ( organisms = model . organisms , valid_genes = model . genes , max_len = self . max_len , how = \"some\" if self . how == \"most var\" else self . how , genelist = genelist if self . how == \"most var\" else [], downsample = self . downsample , save_output = True , ) dataloader = DataLoader ( adataset , collate_fn = col , batch_size = self . batch_size , num_workers = self . num_workers , shuffle = False , ) model . doplot = self . doplot model . on_predict_epoch_start () model . eval () device = model . device . type with torch . no_grad (), torch . autocast ( device_type = device , dtype = self . dtype ): for batch in tqdm ( dataloader ): gene_pos , expression , depth = ( batch [ \"genes\" ] . to ( device ), batch [ \"x\" ] . to ( device ), batch [ \"depth\" ] . to ( device ), ) model . _predict ( gene_pos , expression , depth , predict_mode = \"denoise\" , depth_mult = self . predict_depth_mult , ) torch . cuda . empty_cache () self . genes = ( model . pos . cpu () . numpy () if self . how != \"most var\" else list ( set ( model . genes ) & set ( genelist )) ) tokeep = None metrics = None if self . downsample is not None : reco = model . expr_pred [ 0 ] reco = reco . cpu () . numpy () tokeep = np . isnan ( reco ) . sum ( 1 ) == 0 reco = reco [ tokeep ] noisy = np . loadtxt ( \"collator_output.txt\" )[ tokeep ] if random_indices is not None : true = adata . X [ random_indices ][ tokeep ] else : true = adata . X [ tokeep ] true = true . toarray () if issparse ( true ) else true if self . how == \"most var\" : true = true [:, adata . var . index . isin ( self . genes )] # noisy[true==0]=0 else : true = np . vstack ( [ true [ i , adata . var . index . get_indexer ( np . array ( model . genes )[ val ]), ] . copy () for i , val in enumerate ( self . genes ) ] ) # reco[true==0] = 0 # import pdb # pdb.set_trace() # reco[reco!=0] = 2 # corr_coef = np.corrcoef( # np.vstack([reco[true!=0], noisy[true!=0], true[true!=0]]) # ) corr_coef , p_value = spearmanr ( np . vstack ([ reco [ true != 0 ], noisy [ true != 0 ], true [ true != 0 ]]) . T ) metrics = { \"reco2noisy\" : corr_coef [ 0 , 1 ], \"reco2full\" : corr_coef [ 0 , 2 ], \"noisy2full\" : corr_coef [ 1 , 2 ], } # corr_coef[p_value > 0.05] = 0 # if self.doplot: # plt.figure(figsize=(10, 5)) # plt.imshow( # corr_coef, cmap=\"coolwarm\", interpolation=\"none\", vmin=-1, vmax=1 # ) # plt.colorbar() # plt.title(\"Expression Correlation Coefficient\") # plt.show() # metrics = { # \"reco2noisy\": np.mean( # corr_coef[ # self.plot_corr_size : self.plot_corr_size * 2, : self.plot_corr_size # ].diagonal() # ), # \"reco2full\": np.mean( # corr_coef[self.plot_corr_size * 2 :, : self.plot_corr_size].diagonal() # ), # \"noisy2full\": np.mean( # corr_coef[ # self.plot_corr_size * 2 :, # self.plot_corr_size : self.plot_corr_size * 2, # ].diagonal() # ), # } return ( metrics , ( random_indices [ tokeep ] if random_indices is not None and tokeep is not None else random_indices ), self . genes , ( model . expr_pred [ 0 ][ tokeep ] . cpu () . numpy () if tokeep is not None else model . expr_pred [ 0 ] . cpu () . numpy () ), )","title":"__call__"},{"location":"tasks/#scprint.tasks.denoise.default_benchmark","text":"default_benchmark function used to run the default denoising benchmark of scPRINT Parameters: model ( Any ) \u2013 The scPRINT model to be used for the benchmark. default_dataset ( str , default: FILE_DIR + '/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad' ) \u2013 Path to the default dataset to use for benchmarking. Defaults to FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\". max_len ( int , default: 5000 ) \u2013 Maximum number of genes to consider. Defaults to 5000. Returns: dict \u2013 A dictionary containing the benchmark metrics. Source code in scprint/tasks/denoise.py 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 def default_benchmark ( model : Any , default_dataset : str = FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\" , max_len : int = 5000 , ): \"\"\" default_benchmark function used to run the default denoising benchmark of scPRINT Args: model (Any): The scPRINT model to be used for the benchmark. default_dataset (str, optional): Path to the default dataset to use for benchmarking. Defaults to FILE_DIR + \"/../../data/r4iCehg3Tw5IbCLiCIbl.h5ad\". max_len (int, optional): Maximum number of genes to consider. Defaults to 5000. Returns: dict: A dictionary containing the benchmark metrics. \"\"\" adata = sc . read_h5ad ( default_dataset ) denoise = Denoiser ( model , batch_size = 40 , max_len = max_len , plot_corr_size = 10_000 , doplot = False , num_workers = 8 , predict_depth_mult = 10 , downsample = 0.7 , devices = 1 , ) return denoise ( adata )[ 0 ]","title":"default_benchmark"},{"location":"tasks/#scprint.tasks.denoise.split_molecules","text":"Splits molecules into two (potentially overlapping) groups. :param umis: Array of molecules to split :param data_split: Proportion of molecules to assign to the first group :param overlap_factor: Overlap correction factor, if desired :param random_state: For reproducible sampling :return: umis_X and umis_Y, representing split and ~(1 - split) counts sampled from the input array Source code in scprint/tasks/denoise.py 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 def split_molecules ( umis : np . ndarray , data_split : float , overlap_factor : float = 0.0 , random_state : np . random . RandomState = None , ) -> Tuple [ np . ndarray , np . ndarray ]: \"\"\"Splits molecules into two (potentially overlapping) groups. :param umis: Array of molecules to split :param data_split: Proportion of molecules to assign to the first group :param overlap_factor: Overlap correction factor, if desired :param random_state: For reproducible sampling :return: umis_X and umis_Y, representing ``split`` and ``~(1 - split)`` counts sampled from the input array \"\"\" if random_state is None : random_state = np . random . RandomState () umis_X_disjoint = random_state . binomial ( umis , data_split - overlap_factor ) umis_Y_disjoint = random_state . binomial ( umis - umis_X_disjoint , ( 1 - data_split ) / ( 1 - data_split + overlap_factor ) ) overlap_factor = umis - umis_X_disjoint - umis_Y_disjoint umis_X = umis_X_disjoint + overlap_factor umis_Y = umis_Y_disjoint + overlap_factor return umis_X , umis_Y","title":"split_molecules"},{"location":"usage/","text":"scPRINT usage scPRINT can be used to denoise / embed (& predict labels) / infer gene networks on single-cell data. Example of doing these tasks on a dataset is given in our manuscript and the example notebooks . But in a nutshell, here is the most minimal example of how scPRINT works: once you have loaded an anndata object, make sure you preprocess it so everything is checked out. (number of genes mentioned, gene format, raw counts used, etc...) more information on the Preprocessor is available in the scDataLoader package () Then you can denoise / embed / infer gn on this anndata using scPRINT and its helper classes. These classes follow a similar pattern to the trainer class in pytorch-lightning. Here is an example for denoising: from scprint import scPrint from scdataloader import Preprocessor import scanpy as sc from scprint.tasks import Denoiser #better to do it in lower precision import torch torch.set_float32_matmul_precision('medium') adata = sc.read_h5ad(\"../data/temp.h5ad\") #make sure we have this metadata adata.obs['organism_ontology_term_id'] = \"NCBITaxon:9606\" # load the model model = scPrint.load_from_checkpoint('../data/temp/last.ckpt', precpt_gene_emb=None) # preprocess to make sure it looks good preprocessor = Preprocessor(do_postp=False) adata = preprocessor(adata) #instanciate the denoiser with params (see the class in tasks/denoiser.py) how=\"most var\" denoiser = Denoiser( model, batch_size=20, max_len=2000, plot_corr_size=100_000, doplot=False, num_workers=1, predict_depth_mult=10, how=how, dtype=torch.bfloat16, ) #denoise metrics, idxs, genes, expr = denoise(model, adata) print(metrics) # apply the denoising to the anndata adata.layers['before'] = adata.X.copy() adata.X = adata.X.tolil() idxs = idxs if idxs is not None else range(adata.shape[0]) for i, idx in enumerate(idxs): adata.X[ idx, adata.var.index.get_indexer( np.array(model.genes)[genes[i]] if how != \"most var\" else genes ), ] = expr_pred[i] adata.X = adata.X.tocsr() But you can do the same thing with a bash command line: $ scprint denoise --ckpt_path ../data/temp/last.ckpt --adata ../data/temp.h5ad --how \"most var\" --dtype \"torch.bfloat16\" --batch_size 20 --max_len 2000 --plot_corr_size 100000 --num_workers 1 --predict_depth_mult 10 --doplot false --species \"NCBITaxon:9606\" However in this context you might have somewhat less options for the preprocessing of the anndataset. However, all parameters of the denoiser, embedder and gninfer classes are available in the cli interface as well!","title":"usage example"},{"location":"usage/#scprint-usage","text":"scPRINT can be used to denoise / embed (& predict labels) / infer gene networks on single-cell data. Example of doing these tasks on a dataset is given in our manuscript and the example notebooks . But in a nutshell, here is the most minimal example of how scPRINT works: once you have loaded an anndata object, make sure you preprocess it so everything is checked out. (number of genes mentioned, gene format, raw counts used, etc...) more information on the Preprocessor is available in the scDataLoader package () Then you can denoise / embed / infer gn on this anndata using scPRINT and its helper classes. These classes follow a similar pattern to the trainer class in pytorch-lightning. Here is an example for denoising: from scprint import scPrint from scdataloader import Preprocessor import scanpy as sc from scprint.tasks import Denoiser #better to do it in lower precision import torch torch.set_float32_matmul_precision('medium') adata = sc.read_h5ad(\"../data/temp.h5ad\") #make sure we have this metadata adata.obs['organism_ontology_term_id'] = \"NCBITaxon:9606\" # load the model model = scPrint.load_from_checkpoint('../data/temp/last.ckpt', precpt_gene_emb=None) # preprocess to make sure it looks good preprocessor = Preprocessor(do_postp=False) adata = preprocessor(adata) #instanciate the denoiser with params (see the class in tasks/denoiser.py) how=\"most var\" denoiser = Denoiser( model, batch_size=20, max_len=2000, plot_corr_size=100_000, doplot=False, num_workers=1, predict_depth_mult=10, how=how, dtype=torch.bfloat16, ) #denoise metrics, idxs, genes, expr = denoise(model, adata) print(metrics) # apply the denoising to the anndata adata.layers['before'] = adata.X.copy() adata.X = adata.X.tolil() idxs = idxs if idxs is not None else range(adata.shape[0]) for i, idx in enumerate(idxs): adata.X[ idx, adata.var.index.get_indexer( np.array(model.genes)[genes[i]] if how != \"most var\" else genes ), ] = expr_pred[i] adata.X = adata.X.tocsr() But you can do the same thing with a bash command line: $ scprint denoise --ckpt_path ../data/temp/last.ckpt --adata ../data/temp.h5ad --how \"most var\" --dtype \"torch.bfloat16\" --batch_size 20 --max_len 2000 --plot_corr_size 100000 --num_workers 1 --predict_depth_mult 10 --doplot false --species \"NCBITaxon:9606\" However in this context you might have somewhat less options for the preprocessing of the anndataset. However, all parameters of the denoiser, embedder and gninfer classes are available in the cli interface as well!","title":"scPRINT usage"},{"location":"utils/","text":"Documentation for the utils modules scprint.utils.sinkhorn SinkhornDistance Bases: Module SinkhornDistance Initialize the SinkhornDistance class Parameters: eps ( float , default: 0.01 ) \u2013 Regularization parameter. Defaults to 1e-2. max_iter ( int , default: 100 ) \u2013 Maximum number of Sinkhorn iterations. Defaults to 100. reduction ( str , default: 'none' ) \u2013 Specifies the reduction to apply to the output. Defaults to \"none\". Source code in scprint/utils/sinkhorn.py 8 9 10 11 12 13 14 15 16 17 18 19 20 def __init__ ( self , eps : float = 1e-2 , max_iter : int = 100 , reduction : str = \"none\" ): \"\"\" SinkhornDistance Initialize the SinkhornDistance class Args: eps (float, optional): Regularization parameter. Defaults to 1e-2. max_iter (int, optional): Maximum number of Sinkhorn iterations. Defaults to 100. reduction (str, optional): Specifies the reduction to apply to the output. Defaults to \"none\". \"\"\" super ( SinkhornDistance , self ) . __init__ () self . eps = eps self . max_iter = max_iter self . reduction = reduction M Modified cost for logarithmic updates Source code in scprint/utils/sinkhorn.py 99 100 101 102 def M ( self , C , u , v ): \"Modified cost for logarithmic updates\" \"\"\"$M_{ij} = (-c_{ij} + u_i + v_j) / epsilon$\"\"\" return ( - C + u . unsqueeze ( - 1 ) + v . unsqueeze ( 1 )) / self . eps ave staticmethod Barycenter subroutine, used by kinetic acceleration through extrapolation. Source code in scprint/utils/sinkhorn.py 104 105 106 107 @staticmethod def ave ( u , u1 , tau ): \"Barycenter subroutine, used by kinetic acceleration through extrapolation.\" return tau * u + ( 1 - tau ) * u1 forward forward Compute the Sinkhorn distance between two measures with cost matrix c Parameters: c ( Tensor ) \u2013 The cost matrix between the two measures. Returns: \u2013 torch.Tensor: The computed Sinkhorn distance. Source code in scprint/utils/sinkhorn.py 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 def forward ( self , c : torch . Tensor ): \"\"\" forward Compute the Sinkhorn distance between two measures with cost matrix c Args: c (torch.Tensor): The cost matrix between the two measures. Returns: torch.Tensor: The computed Sinkhorn distance. \"\"\" C = - c x_points = C . shape [ - 2 ] batch_size = C . shape [ 0 ] # both marginals are fixed with equal weights mu = ( torch . empty ( batch_size , x_points , dtype = C . dtype , requires_grad = False , device = C . device , ) . fill_ ( 1.0 / x_points ) . squeeze () ) nu = ( torch . empty ( batch_size , x_points , dtype = C . dtype , requires_grad = False , device = C . device , ) . fill_ ( 1.0 / x_points ) . squeeze () ) u = torch . zeros_like ( mu ) v = torch . zeros_like ( nu ) # Stopping criterion thresh = 1e-12 # Sinkhorn iterations for i in range ( self . max_iter ): if i % 2 == 0 : u1 = u # useful to check the update u = ( self . eps * ( torch . log ( mu ) - torch . logsumexp ( self . M ( C , u , v ), dim =- 1 )) + u ) err = ( u - u1 ) . abs () . sum ( - 1 ) . mean () else : v = ( self . eps * ( torch . log ( nu ) - torch . logsumexp ( self . M ( C , u , v ) . transpose ( - 2 , - 1 ), dim =- 1 ) ) + v ) v = v . detach () . requires_grad_ ( False ) v [ v > 9 * 1e8 ] = 0.0 v = v . detach () . requires_grad_ ( True ) if err . item () < thresh : break U , V = u , v # Transport plan pi = diag(a)*K*diag(b) pi = torch . exp ( self . M ( C , U , V )) # Sinkhorn distance return pi , C , U , V scprint.utils.utils category_str2int category_str2int converts a list of category strings to a list of category integers. Parameters: category_strs ( List [ str ] ) \u2013 A list of category strings to be converted. Returns: List [ int ] \u2013 List[int]: A list of integers corresponding to the input category strings. Source code in scprint/utils/utils.py 99 100 101 102 103 104 105 106 107 108 109 110 111 def category_str2int ( category_strs : List [ str ]) -> List [ int ]: \"\"\" category_str2int converts a list of category strings to a list of category integers. Args: category_strs (List[str]): A list of category strings to be converted. Returns: List[int]: A list of integers corresponding to the input category strings. \"\"\" set_category_strs = set ( category_strs ) name2id = { name : i for i , name in enumerate ( set_category_strs )} return [ name2id [ name ] for name in category_strs ] createFoldersFor will recursively create folders if needed until having all the folders required to save the file in this filepath Source code in scprint/utils/utils.py 88 89 90 91 92 93 94 95 96 def createFoldersFor ( filepath ): \"\"\" will recursively create folders if needed until having all the folders required to save the file in this filepath \"\"\" prevval = \"\" for val in os . path . expanduser ( filepath ) . split ( \"/\" )[: - 1 ]: prevval += val + \"/\" if not os . path . exists ( prevval ): os . mkdir ( prevval ) fileToList loads an input file with a\\n b\\n.. into a list [a,b,..] Parameters: input_str ( str ) \u2013 The input string to be completed. Returns: str ( list ) \u2013 The completed string with 'complete' appended. Source code in scprint/utils/utils.py 46 47 48 49 50 51 52 53 54 55 56 57 def fileToList ( filename : str , strconv : callable = lambda x : x ) -> list : \"\"\" loads an input file with a\\\\n b\\\\n.. into a list [a,b,..] Args: input_str (str): The input string to be completed. Returns: str: The completed string with 'complete' appended. \"\"\" with open ( filename ) as f : return [ strconv ( val [: - 1 ]) for val in f . readlines ()] get_free_gpu get_free_gpu finds the GPU with the most free memory using nvidia-smi. Returns: int \u2013 The index of the GPU with the most free memory. Source code in scprint/utils/utils.py 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 def get_free_gpu (): \"\"\" get_free_gpu finds the GPU with the most free memory using nvidia-smi. Returns: int: The index of the GPU with the most free memory. \"\"\" import subprocess import sys from io import StringIO import pandas as pd gpu_stats = subprocess . check_output ( [ \"nvidia-smi\" , \"--format=csv\" , \"--query-gpu=memory.used,memory.free\" , ] ) . decode ( \"utf-8\" ) gpu_df = pd . read_csv ( StringIO ( gpu_stats ), names = [ \"memory.used\" , \"memory.free\" ], skiprows = 1 ) print ( \"GPU usage: \\n {} \" . format ( gpu_df )) gpu_df [ \"memory.free\" ] = gpu_df [ \"memory.free\" ] . map ( lambda x : int ( x . rstrip ( \" [MiB]\" ))) idx = gpu_df [ \"memory.free\" ] . idxmax () print ( \"Find free GPU {} with {} free MiB\" . format ( idx , gpu_df . iloc [ idx ][ \"memory.free\" ]) ) return idx get_git_commit get_git_commit gets the current git commit hash. Returns: str \u2013 The current git commit Source code in scprint/utils/utils.py 196 197 198 199 200 201 202 203 def get_git_commit (): \"\"\" get_git_commit gets the current git commit hash. Returns: str: The current git commit \"\"\" return subprocess . check_output ([ \"git\" , \"rev-parse\" , \"HEAD\" ]) . decode ( \"utf-8\" ) . strip () inf_loop wrapper function for endless data loader. Source code in scprint/utils/utils.py 224 225 226 227 def inf_loop ( data_loader ): \"\"\"wrapper function for endless data loader.\"\"\" for loader in repeat ( data_loader ): yield from loader isnotebook check whether excuting in jupyter notebook. Source code in scprint/utils/utils.py 114 115 116 117 118 119 120 121 122 123 124 125 def isnotebook () -> bool : \"\"\"check whether excuting in jupyter notebook.\"\"\" try : shell = get_ipython () . __class__ . __name__ if shell == \"ZMQInteractiveShell\" : return True # Jupyter notebook or qtconsole elif shell == \"TerminalInteractiveShell\" : return True # Terminal running IPython else : return False # Other type (?) except NameError : return False # Probably standard Python interpreter listToFile listToFile loads a list with [a,b,..] into an input file a\\n b\\n.. Parameters: l ( list ) \u2013 The list of elements to be written to the file. filename ( str ) \u2013 The name of the file where the list will be written. strconv ( callable , default: lambda x: str ( x ) ) \u2013 A function to convert each element of the list to a string. Defaults to str. Returns: None \u2013 None Source code in scprint/utils/utils.py 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 def listToFile ( li : list , filename : str , strconv : callable = lambda x : str ( x )) -> None : \"\"\" listToFile loads a list with [a,b,..] into an input file a\\\\n b\\\\n.. Args: l (list): The list of elements to be written to the file. filename (str): The name of the file where the list will be written. strconv (callable, optional): A function to convert each element of the list to a string. Defaults to str. Returns: None \"\"\" with open ( filename , \"w\" ) as f : for item in li : f . write ( \" %s \\n \" % strconv ( item )) load_genes load_genes loads the genes for a given organism. Parameters: organisms ( Union [ str , list ] , default: 'NCBITaxon:9606' ) \u2013 A string or list of strings representing the organism(s) to load genes for. Defaults to \"NCBITaxon:9606\". Returns: \u2013 pd.DataFrame: A DataFrame containing gene information for the specified organism(s). Source code in scprint/utils/utils.py 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 def load_genes ( organisms : Union [ str , list ] = \"NCBITaxon:9606\" ): # \"NCBITaxon:10090\", \"\"\" load_genes loads the genes for a given organism. Args: organisms (Union[str, list], optional): A string or list of strings representing the organism(s) to load genes for. Defaults to \"NCBITaxon:9606\". Returns: pd.DataFrame: A DataFrame containing gene information for the specified organism(s). \"\"\" organismdf = [] if type ( organisms ) is str : organisms = [ organisms ] for organism in organisms : genesdf = bt . Gene . filter ( organism_id = bt . Organism . filter ( ontology_id = organism ) . first () . id ) . df () genesdf = genesdf [ ~ genesdf [ \"public_source_id\" ] . isna ()] genesdf = genesdf . drop_duplicates ( subset = \"ensembl_gene_id\" ) genesdf = genesdf . set_index ( \"ensembl_gene_id\" ) . sort_index () # mitochondrial genes genesdf [ \"mt\" ] = genesdf . symbol . astype ( str ) . str . startswith ( \"MT-\" ) # ribosomal genes genesdf [ \"ribo\" ] = genesdf . symbol . astype ( str ) . str . startswith (( \"RPS\" , \"RPL\" )) # hemoglobin genes. genesdf [ \"hb\" ] = genesdf . symbol . astype ( str ) . str . contains (( \"^HB[^(P)]\" )) genesdf [ \"organism\" ] = organism organismdf . append ( genesdf ) organismdf = pd . concat ( organismdf ) organismdf . drop ( columns = [ \"source_id\" , \"stable_id\" , \"run_id\" , \"created_by_id\" , \"updated_at\" ], inplace = True , ) return organismdf prepare_device setup GPU device if available. get gpu device indices which are used for DataParallel Source code in scprint/utils/utils.py 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 def prepare_device ( n_gpu_use ): \"\"\" setup GPU device if available. get gpu device indices which are used for DataParallel \"\"\" n_gpu = torch . cuda . device_count () if n_gpu_use > 0 and n_gpu == 0 : print ( \"Warning: There's no GPU available on this machine,\" \"training will be performed on CPU.\" ) n_gpu_use = 0 if n_gpu_use > n_gpu : print ( f \"Warning: The number of GPU's configured to use is { n_gpu_use } , but only { n_gpu } are \" \"available on this machine.\" ) n_gpu_use = n_gpu device = torch . device ( \"cuda:0\" if n_gpu_use > 0 else \"cpu\" ) list_ids = list ( range ( n_gpu_use )) return device , list_ids run_command run_command runs a command in the shell and prints the output. Parameters: command ( str ) \u2013 The command to be executed in the shell. Returns: int \u2013 The return code of the command executed. Source code in scprint/utils/utils.py 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def run_command ( command : str , ** kwargs ): \"\"\" run_command runs a command in the shell and prints the output. Args: command (str): The command to be executed in the shell. Returns: int: The return code of the command executed. \"\"\" process = subprocess . Popen ( command , stdout = subprocess . PIPE , ** kwargs ) while True : if process . poll () is not None : break output = process . stdout . readline () if output : print ( output . strip ()) rc = process . poll () return rc set_seed set random seed. Source code in scprint/utils/utils.py 77 78 79 80 81 82 83 def set_seed ( seed : int = 42 ): \"\"\"set random seed.\"\"\" random . seed ( seed ) np . random . seed ( seed ) torch . manual_seed ( seed ) torch . backends . cudnn . deterministic = True torch . backends . cudnn . benchmark = False scprint.utils.get_seq load_fasta_species Downloads and caches FASTA files for a given species from the Ensembl FTP server. Parameters: species ( str , default: 'homo_sapiens' ) \u2013 The species name for which to download FASTA files. Defaults to \"homo_sapiens\". output_path ( str , default: '/tmp/data/fasta/' ) \u2013 The local directory path where the FASTA files will be saved. Defaults to \"/tmp/data/fasta/\". cache ( bool , default: True ) \u2013 If True, use cached files if they exist. If False, re-download the files. Defaults to True. Source code in scprint/utils/get_seq.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 def load_fasta_species ( species : str = \"homo_sapiens\" , output_path : str = \"/tmp/data/fasta/\" , cache : bool = True , ) -> None : \"\"\" Downloads and caches FASTA files for a given species from the Ensembl FTP server. Args: species (str, optional): The species name for which to download FASTA files. Defaults to \"homo_sapiens\". output_path (str, optional): The local directory path where the FASTA files will be saved. Defaults to \"/tmp/data/fasta/\". cache (bool, optional): If True, use cached files if they exist. If False, re-download the files. Defaults to True. \"\"\" ftp = ftplib . FTP ( \"ftp.ensembl.org\" ) ftp . login () ftp . cwd ( \"/pub/release-110/fasta/\" + species + \"/pep/\" ) file = list_files ( ftp , \".all.fa.gz\" )[ 0 ] local_file_path = output_path + file if not os . path . exists ( local_file_path ) or not cache : os . makedirs ( os . path . dirname ( local_file_path ), exist_ok = True ) with open ( local_file_path , \"wb\" ) as local_file : ftp . retrbinary ( \"RETR \" + file , local_file . write ) ftp . cwd ( \"/pub/release-110/fasta/\" + species + \"/ncrna/\" ) file = list_files ( ftp , \".ncrna.fa.gz\" )[ 0 ] local_file_path = output_path + file if not os . path . exists ( local_file_path ) or not cache : with open ( local_file_path , \"wb\" ) as local_file : ftp . retrbinary ( \"RETR \" + file , local_file . write ) ftp . quit () seq Fetch nucleotide or amino acid sequence (FASTA) of a gene (and all its isoforms) or transcript by Ensembl, WormBase, or FlyBase ID. Parameters: ens_ids ( Union [ str , List [ str ]] ) \u2013 One or more Ensembl IDs (passed as string or list of strings). Also supports WormBase and FlyBase IDs. translate ( bool , default: False ) \u2013 Defines whether nucleotide or amino acid sequences are returned. Defaults to False (returns nucleotide sequences). Nucleotide sequences are fetched from the Ensembl REST API server. Amino acid sequences are fetched from the UniProt REST API server. isoforms ( bool , default: False ) \u2013 If True, returns the sequences of all known transcripts. Defaults to False. (Only for gene IDs.) parallel ( bool , default: True ) \u2013 If True, fetches sequences in parallel. Defaults to True. save ( bool , default: False ) \u2013 If True, saves output FASTA to current directory. Defaults to False. transcribe ( bool , default: None ) \u2013 Deprecated. Use 'translate' instead. seqtype ( str , default: None ) \u2013 Deprecated. Use 'translate' instead. verbose ( bool , default: True ) \u2013 If True, prints progress information. Defaults to True. Returns: List [ str ] \u2013 List[str]: A list containing the requested sequences, or a FASTA file if 'save' is True. Raises: ValueError \u2013 If an invalid Ensembl ID is provided. Source code in scprint/utils/get_seq.py 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 def seq ( ens_ids : Union [ str , List [ str ]], translate : bool = False , isoforms : bool = False , parallel : bool = True , save : bool = False , transcribe : Optional [ bool ] = None , seqtype : Optional [ str ] = None , verbose : bool = True , ) -> List [ str ]: \"\"\" Fetch nucleotide or amino acid sequence (FASTA) of a gene (and all its isoforms) or transcript by Ensembl, WormBase, or FlyBase ID. Args: ens_ids (Union[str, List[str]]): One or more Ensembl IDs (passed as string or list of strings). Also supports WormBase and FlyBase IDs. translate (bool, optional): Defines whether nucleotide or amino acid sequences are returned. Defaults to False (returns nucleotide sequences). Nucleotide sequences are fetched from the Ensembl REST API server. Amino acid sequences are fetched from the UniProt REST API server. isoforms (bool, optional): If True, returns the sequences of all known transcripts. Defaults to False. (Only for gene IDs.) parallel (bool, optional): If True, fetches sequences in parallel. Defaults to True. save (bool, optional): If True, saves output FASTA to current directory. Defaults to False. transcribe (bool, optional): Deprecated. Use 'translate' instead. seqtype (str, optional): Deprecated. Use 'translate' instead. verbose (bool, optional): If True, prints progress information. Defaults to True. Returns: List[str]: A list containing the requested sequences, or a FASTA file if 'save' is True. Raises: ValueError: If an invalid Ensembl ID is provided. \"\"\" # Handle deprecated arguments if seqtype : logging . error ( \"'seqtype' argument deprecated! Please use True/False argument 'translate' instead.\" ) return if transcribe : translate = transcribe ## Clean up arguments # Clean up Ensembl IDs # If single Ensembl ID passed as string, convert to list if type ( ens_ids ) is str : ens_ids = [ ens_ids ] # Remove Ensembl ID version if passed ens_ids_clean = [] temp = 0 for ensembl_ID in ens_ids : # But only for Ensembl ID (and not for flybase/wormbase IDs) if ensembl_ID . startswith ( \"ENS\" ): ens_ids_clean . append ( ensembl_ID . split ( \".\" )[ 0 ]) if \".\" in ensembl_ID and temp == 0 : if verbose : logging . info ( \"We noticed that you may have passed a version number with your Ensembl ID. \\n \" \"Please note that gget seq will return information linked to the latest Ensembl ID version.\" ) temp = + 1 else : ens_ids_clean . append ( ensembl_ID ) # Initiate empty 'fasta' fasta = [] ## Fetch nucleotide sequece if translate is False : # Define Ensembl REST API server server = ENSEMBL_REST_API # Define type of returned content from REST content_type = \"application/json\" # Initiate dictionary to save results for all IDs in master_dict = {} # Query REST APIs from https://rest.ensembl.org/ for ensembl_ID in ens_ids_clean : # Create dict to save query results results_dict = { ensembl_ID : {}} # If isoforms False, just fetch sequences of passed Ensembl ID if isoforms is False : # sequence/id/ query: Request sequence by stable identifier query = \"sequence/id/\" + ensembl_ID + \"?\" # Try if query valid try : # Submit query; this will throw RuntimeError if ID not found df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"id\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ({ \"seq\" : df_temp }) if verbose : logging . info ( f \"Requesting nucleotide sequence of { ensembl_ID } from Ensembl.\" ) except RuntimeError : logging . error ( f \"ID { ensembl_ID } not found. Please double-check spelling/arguments and try again.\" ) # If isoforms true, fetch sequences of isoforms instead if isoforms is True : # Get ID type (gene, transcript, ...) using gget info info_df = info ( ensembl_ID , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check if Ensembl ID was found if isinstance ( info_df , type ( None )): logging . warning ( f \"ID ' { ensembl_ID } ' not found. Please double-check spelling/arguments and try again.\" ) continue ens_ID_type = info_df . loc [ ensembl_ID ][ \"object_type\" ] # If the ID is a gene, get the IDs of all its transcripts if ens_ID_type == \"Gene\" : if verbose : logging . info ( f \"Requesting nucleotide sequences of all transcripts of { ensembl_ID } from Ensembl.\" ) for transcipt_id in info_df . loc [ ensembl_ID ][ \"all_transcripts\" ]: # Remove version number for Ensembl IDs (not for flybase/wormbase IDs) if transcipt_id . startswith ( \"ENS\" ): transcipt_id = transcipt_id . split ( \".\" )[ 0 ] # Try if query is valid try : # Define the REST query query = \"sequence/id/\" + transcipt_id + \"?\" # Submit query df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ( { f \" { transcipt_id } \" : df_temp } ) except RuntimeError : logging . error ( f \"ID { transcipt_id } not found. \" \"Please double-check spelling/arguments and try again.\" ) # If isoform true, but ID is not a gene; ignore the isoform parameter else : # Try if query is valid try : # Define the REST query query = \"sequence/id/\" + ensembl_ID + \"?\" # Submit query df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"id\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ({ \"seq\" : df_temp }) logging . info ( f \"Requesting nucleotide sequence of { ensembl_ID } from Ensembl.\" ) logging . warning ( \"The isoform option only applies to gene IDs.\" ) except RuntimeError : logging . error ( f \"ID { ensembl_ID } not found. \" \"Please double-check spelling/arguments and try again.\" ) # Add results to master dict master_dict . update ( results_dict ) # Build FASTA file for ens_ID in master_dict : for key in master_dict [ ens_ID ] . keys (): if key == \"seq\" : fasta . append ( \">\" + ens_ID + \" \" + master_dict [ ens_ID ][ key ][ \"desc\" ]) fasta . append ( master_dict [ ens_ID ][ key ][ \"seq\" ]) else : fasta . append ( \">\" + master_dict [ ens_ID ][ key ][ \"id\" ] + \" \" + master_dict [ ens_ID ][ key ][ \"desc\" ] ) fasta . append ( master_dict [ ens_ID ][ key ][ \"seq\" ]) ## Fetch amino acid sequences from UniProt if translate is True : if isoforms is False : # List to collect transcript IDs trans_ids = [] # Get ID type (gene, transcript, ...) using gget info info_df = info ( ens_ids_clean , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check that Ensembl ID was found missing = set ( ens_ids_clean ) - set ( info_df . index . values ) if len ( missing ) > 0 : logging . warning ( f \" { str ( missing ) } IDs not found. Please double-check spelling/arguments.\" ) ens_ID_type = info_df . loc [ ens_ids_clean [ 0 ]][ \"object_type\" ] # If the ID is a gene, use the ID of its canonical transcript if ens_ID_type == \"Gene\" : # Get ID of canonical transcript for ensembl_ID in info_df . index . values : can_trans = info_df . loc [ ensembl_ID ][ \"canonical_transcript\" ] if ensembl_ID . startswith ( \"ENS\" ): # Remove Ensembl ID version from transcript IDs and append to transcript IDs list temp_trans_id = can_trans . split ( \".\" )[ 0 ] trans_ids . append ( temp_trans_id ) elif ensembl_ID . startswith ( \"WB\" ): # Remove added \".\" at the end of transcript IDs temp_trans_id = \".\" . join ( can_trans . split ( \".\" )[: - 1 ]) # # For WormBase transcript IDs, also remove the version number for submission to UniProt API # temp_trans_id = \".\".join(temp_trans_id1.split(\".\")[:-1]) trans_ids . append ( temp_trans_id ) else : # Remove added \".\" at the end of other transcript IDs temp_trans_id = \".\" . join ( can_trans . split ( \".\" )[: - 1 ]) trans_ids . append ( temp_trans_id ) if verbose : logging . info ( f \"Requesting amino acid sequence of the canonical transcript { temp_trans_id } of gene { ensembl_ID } from UniProt.\" ) # If the ID is a transcript, append the ID directly elif ens_ID_type == \"Transcript\" : # # For WormBase transcript IDs, remove the version number for submission to UniProt API # if ensembl_ID.startswith(\"T\"): # trans_ids.append(\".\".join(ensembl_ID.split(\".\")[:-1])) # else: trans_ids = ens_ids_clean if verbose : logging . info ( f \"Requesting amino acid sequence of { trans_ids } from UniProt.\" ) else : logging . warning ( \"ensembl_IDs not recognized as either a gene or transcript ID. It will not be included in the UniProt query.\" ) # Fetch the amino acid sequences of the transcript Ensembl IDs df_uniprot = get_uniprot_seqs ( UNIPROT_REST_API , trans_ids ) # Add info_df.loc[ensembl_ID] to df_uniprot by joining on \"canonical_transcript\" / \"gene_name\" respectively import pdb pdb . set_trace () info_df . set_index ( \"canonical_transcript\" , inplace = True ) df_uniprot . loc [:, \"gene_id\" ] = info_df . loc [ df_uniprot [ \"query\" ], \"gene_name\" ] . values if isoforms is True : # List to collect transcript IDs trans_ids = [] for ensembl_ID in ens_ids_clean : # Get ID type (gene, transcript, ...) using gget info info_df = info ( ensembl_ID , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check that Ensembl ID was found if isinstance ( info_df , type ( None )): logging . warning ( f \"ID ' { ensembl_ID } ' not found. Please double-check spelling/arguments.\" ) continue ens_ID_type = info_df . loc [ ensembl_ID ][ \"object_type\" ] # If the ID is a gene, get the IDs of all isoforms if ens_ID_type == \"Gene\" : # Get the IDs of all transcripts from the gget info results for transcipt_id in info_df . loc [ ensembl_ID ][ \"all_transcripts\" ]: if ensembl_ID . startswith ( \"ENS\" ): # Append transcript ID (without Ensembl version number) to list of transcripts to fetch trans_ids . append ( transcipt_id . split ( \".\" )[ 0 ]) # elif ensembl_ID.startswith(\"WB\"): # # For WormBase transcript IDs, remove the version number for submission to UniProt API # temp_trans_id = \".\".join(transcipt_id.split(\".\")[:-1]) # trans_ids.append(temp_trans_id) else : # Note: No need to remove the added \".\" at the end of unversioned transcripts here, because \"all_transcripts\" are returned without it trans_ids . append ( transcipt_id ) if verbose : logging . info ( f \"Requesting amino acid sequences of all transcripts of gene { ensembl_ID } from UniProt.\" ) elif ens_ID_type == \"Transcript\" : # # For WormBase transcript IDs, remove the version number for submission to UniProt API # if ensembl_ID.startswith(\"T\"): # trans_ids.append(\".\".join(ensembl_ID.split(\".\")[:-1])) # else: trans_ids . append ( ensembl_ID ) if verbose : logging . info ( f \"Requesting amino acid sequence of { ensembl_ID } from UniProt.\" ) logging . warning ( \"The isoform option only applies to gene IDs.\" ) else : logging . warning ( f \" { ensembl_ID } not recognized as either a gene or transcript ID. It will not be included in the UniProt query.\" ) # Fetch amino acid sequences of all isoforms from the UniProt REST API df_uniprot = get_uniprot_seqs ( UNIPROT_REST_API , trans_ids ) # Check if any results were found if len ( df_uniprot ) < 1 : logging . error ( \"No UniProt amino acid sequences were found for these ID(s).\" ) else : # Build FASTA file from UniProt results for ( uniprot_id , query_ensembl_id , gene_name , organism , sequence_length , uniprot_seq , ) in zip ( df_uniprot [ \"uniprot_id\" ] . values , df_uniprot [ \"query\" ] . values , df_uniprot [ \"gene_name\" ] . values , df_uniprot [ \"gene_id\" ] . values , df_uniprot [ \"organism\" ] . values , df_uniprot [ \"sequence_length\" ] . values , df_uniprot [ \"sequence\" ] . values , ): fasta . append ( \">\" + str ( query_ensembl_id ) + \" uniprot_id: \" + str ( uniprot_id ) + \" ensembl_id: \" + str ( query_ensembl_id ) + \" gene_name: \" + str ( gene_name ) + \" organism: \" + str ( organism ) + \" sequence_length: \" + str ( sequence_length ) ) fasta . append ( str ( uniprot_seq )) # Save if save : file = open ( \"gget_seq_results.fa\" , \"w\" ) for element in fasta : file . write ( element + \" \\n \" ) file . close () # missed samples return ( set ( trans_ids ) - set ( df_uniprot [ \"query\" ] . values )) | set ( missing ) return fasta subset_fasta subset_fasta: creates a new fasta file with only the sequence which names contain one of gene_names Parameters: gene_tosubset ( set ) \u2013 A set of gene names to subset from the original FASTA file. fasta_path ( str ) \u2013 The path to the original FASTA file. subfasta_path ( str , default: './data/fasta/subset.fa' ) \u2013 The path to save the subsetted FASTA file. Defaults to \"./data/fasta/subset.fa\". drop_unknown_seq ( bool , default: True ) \u2013 If True, drop sequences containing unknown amino acids (denoted by '*'). Defaults to True. Returns: set ( set ) \u2013 A set of gene names that were found and included in the subsetted FASTA file. Raises: ValueError \u2013 If a gene name does not start with \"ENS\". Source code in scprint/utils/get_seq.py 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 def subset_fasta ( gene_tosubset : set , fasta_path : str , subfasta_path : str = \"./data/fasta/subset.fa\" , drop_unknown_seq : bool = True , ) -> set : \"\"\" subset_fasta: creates a new fasta file with only the sequence which names contain one of gene_names Args: gene_tosubset (set): A set of gene names to subset from the original FASTA file. fasta_path (str): The path to the original FASTA file. subfasta_path (str, optional): The path to save the subsetted FASTA file. Defaults to \"./data/fasta/subset.fa\". drop_unknown_seq (bool, optional): If True, drop sequences containing unknown amino acids (denoted by '*'). Defaults to True. Returns: set: A set of gene names that were found and included in the subsetted FASTA file. Raises: ValueError: If a gene name does not start with \"ENS\". \"\"\" dup = set () weird = 0 genes_found = set () gene_tosubset = set ( gene_tosubset ) with open ( fasta_path , \"r\" ) as original_fasta , open ( subfasta_path , \"w\" ) as subset_fasta : for record in SeqIO . parse ( original_fasta , \"fasta\" ): gene_name = ( record . description . split ( \" gene:\" )[ 1 ] . split ( \" transcript\" )[ 0 ] . split ( \".\" )[ 0 ] ) if gene_name in gene_tosubset : if drop_unknown_seq : if \"*\" in record . seq : weird += 1 continue if not gene_name . startswith ( \"ENS\" ): raise ValueError ( \"issue\" , gene_name ) if gene_name in genes_found : dup . add ( gene_name ) continue record . description = \"\" record . id = gene_name SeqIO . write ( record , subset_fasta , \"fasta\" ) genes_found . add ( gene_name ) print ( len ( dup ), \" genes had duplicates\" ) print ( \"dropped\" , weird , \"weird sequences\" ) return genes_found","title":"utils"},{"location":"utils/#documentation-for-the-utils-modules","text":"","title":"Documentation for the utils modules"},{"location":"utils/#scprint.utils.sinkhorn","text":"","title":"sinkhorn"},{"location":"utils/#scprint.utils.sinkhorn.SinkhornDistance","text":"Bases: Module SinkhornDistance Initialize the SinkhornDistance class Parameters: eps ( float , default: 0.01 ) \u2013 Regularization parameter. Defaults to 1e-2. max_iter ( int , default: 100 ) \u2013 Maximum number of Sinkhorn iterations. Defaults to 100. reduction ( str , default: 'none' ) \u2013 Specifies the reduction to apply to the output. Defaults to \"none\". Source code in scprint/utils/sinkhorn.py 8 9 10 11 12 13 14 15 16 17 18 19 20 def __init__ ( self , eps : float = 1e-2 , max_iter : int = 100 , reduction : str = \"none\" ): \"\"\" SinkhornDistance Initialize the SinkhornDistance class Args: eps (float, optional): Regularization parameter. Defaults to 1e-2. max_iter (int, optional): Maximum number of Sinkhorn iterations. Defaults to 100. reduction (str, optional): Specifies the reduction to apply to the output. Defaults to \"none\". \"\"\" super ( SinkhornDistance , self ) . __init__ () self . eps = eps self . max_iter = max_iter self . reduction = reduction","title":"SinkhornDistance"},{"location":"utils/#scprint.utils.sinkhorn.SinkhornDistance.M","text":"Modified cost for logarithmic updates Source code in scprint/utils/sinkhorn.py 99 100 101 102 def M ( self , C , u , v ): \"Modified cost for logarithmic updates\" \"\"\"$M_{ij} = (-c_{ij} + u_i + v_j) / epsilon$\"\"\" return ( - C + u . unsqueeze ( - 1 ) + v . unsqueeze ( 1 )) / self . eps","title":"M"},{"location":"utils/#scprint.utils.sinkhorn.SinkhornDistance.ave","text":"Barycenter subroutine, used by kinetic acceleration through extrapolation. Source code in scprint/utils/sinkhorn.py 104 105 106 107 @staticmethod def ave ( u , u1 , tau ): \"Barycenter subroutine, used by kinetic acceleration through extrapolation.\" return tau * u + ( 1 - tau ) * u1","title":"ave"},{"location":"utils/#scprint.utils.sinkhorn.SinkhornDistance.forward","text":"forward Compute the Sinkhorn distance between two measures with cost matrix c Parameters: c ( Tensor ) \u2013 The cost matrix between the two measures. Returns: \u2013 torch.Tensor: The computed Sinkhorn distance. Source code in scprint/utils/sinkhorn.py 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 def forward ( self , c : torch . Tensor ): \"\"\" forward Compute the Sinkhorn distance between two measures with cost matrix c Args: c (torch.Tensor): The cost matrix between the two measures. Returns: torch.Tensor: The computed Sinkhorn distance. \"\"\" C = - c x_points = C . shape [ - 2 ] batch_size = C . shape [ 0 ] # both marginals are fixed with equal weights mu = ( torch . empty ( batch_size , x_points , dtype = C . dtype , requires_grad = False , device = C . device , ) . fill_ ( 1.0 / x_points ) . squeeze () ) nu = ( torch . empty ( batch_size , x_points , dtype = C . dtype , requires_grad = False , device = C . device , ) . fill_ ( 1.0 / x_points ) . squeeze () ) u = torch . zeros_like ( mu ) v = torch . zeros_like ( nu ) # Stopping criterion thresh = 1e-12 # Sinkhorn iterations for i in range ( self . max_iter ): if i % 2 == 0 : u1 = u # useful to check the update u = ( self . eps * ( torch . log ( mu ) - torch . logsumexp ( self . M ( C , u , v ), dim =- 1 )) + u ) err = ( u - u1 ) . abs () . sum ( - 1 ) . mean () else : v = ( self . eps * ( torch . log ( nu ) - torch . logsumexp ( self . M ( C , u , v ) . transpose ( - 2 , - 1 ), dim =- 1 ) ) + v ) v = v . detach () . requires_grad_ ( False ) v [ v > 9 * 1e8 ] = 0.0 v = v . detach () . requires_grad_ ( True ) if err . item () < thresh : break U , V = u , v # Transport plan pi = diag(a)*K*diag(b) pi = torch . exp ( self . M ( C , U , V )) # Sinkhorn distance return pi , C , U , V","title":"forward"},{"location":"utils/#scprint.utils.utils","text":"","title":"utils"},{"location":"utils/#scprint.utils.utils.category_str2int","text":"category_str2int converts a list of category strings to a list of category integers. Parameters: category_strs ( List [ str ] ) \u2013 A list of category strings to be converted. Returns: List [ int ] \u2013 List[int]: A list of integers corresponding to the input category strings. Source code in scprint/utils/utils.py 99 100 101 102 103 104 105 106 107 108 109 110 111 def category_str2int ( category_strs : List [ str ]) -> List [ int ]: \"\"\" category_str2int converts a list of category strings to a list of category integers. Args: category_strs (List[str]): A list of category strings to be converted. Returns: List[int]: A list of integers corresponding to the input category strings. \"\"\" set_category_strs = set ( category_strs ) name2id = { name : i for i , name in enumerate ( set_category_strs )} return [ name2id [ name ] for name in category_strs ]","title":"category_str2int"},{"location":"utils/#scprint.utils.utils.createFoldersFor","text":"will recursively create folders if needed until having all the folders required to save the file in this filepath Source code in scprint/utils/utils.py 88 89 90 91 92 93 94 95 96 def createFoldersFor ( filepath ): \"\"\" will recursively create folders if needed until having all the folders required to save the file in this filepath \"\"\" prevval = \"\" for val in os . path . expanduser ( filepath ) . split ( \"/\" )[: - 1 ]: prevval += val + \"/\" if not os . path . exists ( prevval ): os . mkdir ( prevval )","title":"createFoldersFor"},{"location":"utils/#scprint.utils.utils.fileToList","text":"loads an input file with a\\n b\\n.. into a list [a,b,..] Parameters: input_str ( str ) \u2013 The input string to be completed. Returns: str ( list ) \u2013 The completed string with 'complete' appended. Source code in scprint/utils/utils.py 46 47 48 49 50 51 52 53 54 55 56 57 def fileToList ( filename : str , strconv : callable = lambda x : x ) -> list : \"\"\" loads an input file with a\\\\n b\\\\n.. into a list [a,b,..] Args: input_str (str): The input string to be completed. Returns: str: The completed string with 'complete' appended. \"\"\" with open ( filename ) as f : return [ strconv ( val [: - 1 ]) for val in f . readlines ()]","title":"fileToList"},{"location":"utils/#scprint.utils.utils.get_free_gpu","text":"get_free_gpu finds the GPU with the most free memory using nvidia-smi. Returns: int \u2013 The index of the GPU with the most free memory. Source code in scprint/utils/utils.py 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 def get_free_gpu (): \"\"\" get_free_gpu finds the GPU with the most free memory using nvidia-smi. Returns: int: The index of the GPU with the most free memory. \"\"\" import subprocess import sys from io import StringIO import pandas as pd gpu_stats = subprocess . check_output ( [ \"nvidia-smi\" , \"--format=csv\" , \"--query-gpu=memory.used,memory.free\" , ] ) . decode ( \"utf-8\" ) gpu_df = pd . read_csv ( StringIO ( gpu_stats ), names = [ \"memory.used\" , \"memory.free\" ], skiprows = 1 ) print ( \"GPU usage: \\n {} \" . format ( gpu_df )) gpu_df [ \"memory.free\" ] = gpu_df [ \"memory.free\" ] . map ( lambda x : int ( x . rstrip ( \" [MiB]\" ))) idx = gpu_df [ \"memory.free\" ] . idxmax () print ( \"Find free GPU {} with {} free MiB\" . format ( idx , gpu_df . iloc [ idx ][ \"memory.free\" ]) ) return idx","title":"get_free_gpu"},{"location":"utils/#scprint.utils.utils.get_git_commit","text":"get_git_commit gets the current git commit hash. Returns: str \u2013 The current git commit Source code in scprint/utils/utils.py 196 197 198 199 200 201 202 203 def get_git_commit (): \"\"\" get_git_commit gets the current git commit hash. Returns: str: The current git commit \"\"\" return subprocess . check_output ([ \"git\" , \"rev-parse\" , \"HEAD\" ]) . decode ( \"utf-8\" ) . strip ()","title":"get_git_commit"},{"location":"utils/#scprint.utils.utils.inf_loop","text":"wrapper function for endless data loader. Source code in scprint/utils/utils.py 224 225 226 227 def inf_loop ( data_loader ): \"\"\"wrapper function for endless data loader.\"\"\" for loader in repeat ( data_loader ): yield from loader","title":"inf_loop"},{"location":"utils/#scprint.utils.utils.isnotebook","text":"check whether excuting in jupyter notebook. Source code in scprint/utils/utils.py 114 115 116 117 118 119 120 121 122 123 124 125 def isnotebook () -> bool : \"\"\"check whether excuting in jupyter notebook.\"\"\" try : shell = get_ipython () . __class__ . __name__ if shell == \"ZMQInteractiveShell\" : return True # Jupyter notebook or qtconsole elif shell == \"TerminalInteractiveShell\" : return True # Terminal running IPython else : return False # Other type (?) except NameError : return False # Probably standard Python interpreter","title":"isnotebook"},{"location":"utils/#scprint.utils.utils.listToFile","text":"listToFile loads a list with [a,b,..] into an input file a\\n b\\n.. Parameters: l ( list ) \u2013 The list of elements to be written to the file. filename ( str ) \u2013 The name of the file where the list will be written. strconv ( callable , default: lambda x: str ( x ) ) \u2013 A function to convert each element of the list to a string. Defaults to str. Returns: None \u2013 None Source code in scprint/utils/utils.py 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 def listToFile ( li : list , filename : str , strconv : callable = lambda x : str ( x )) -> None : \"\"\" listToFile loads a list with [a,b,..] into an input file a\\\\n b\\\\n.. Args: l (list): The list of elements to be written to the file. filename (str): The name of the file where the list will be written. strconv (callable, optional): A function to convert each element of the list to a string. Defaults to str. Returns: None \"\"\" with open ( filename , \"w\" ) as f : for item in li : f . write ( \" %s \\n \" % strconv ( item ))","title":"listToFile"},{"location":"utils/#scprint.utils.utils.load_genes","text":"load_genes loads the genes for a given organism. Parameters: organisms ( Union [ str , list ] , default: 'NCBITaxon:9606' ) \u2013 A string or list of strings representing the organism(s) to load genes for. Defaults to \"NCBITaxon:9606\". Returns: \u2013 pd.DataFrame: A DataFrame containing gene information for the specified organism(s). Source code in scprint/utils/utils.py 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 def load_genes ( organisms : Union [ str , list ] = \"NCBITaxon:9606\" ): # \"NCBITaxon:10090\", \"\"\" load_genes loads the genes for a given organism. Args: organisms (Union[str, list], optional): A string or list of strings representing the organism(s) to load genes for. Defaults to \"NCBITaxon:9606\". Returns: pd.DataFrame: A DataFrame containing gene information for the specified organism(s). \"\"\" organismdf = [] if type ( organisms ) is str : organisms = [ organisms ] for organism in organisms : genesdf = bt . Gene . filter ( organism_id = bt . Organism . filter ( ontology_id = organism ) . first () . id ) . df () genesdf = genesdf [ ~ genesdf [ \"public_source_id\" ] . isna ()] genesdf = genesdf . drop_duplicates ( subset = \"ensembl_gene_id\" ) genesdf = genesdf . set_index ( \"ensembl_gene_id\" ) . sort_index () # mitochondrial genes genesdf [ \"mt\" ] = genesdf . symbol . astype ( str ) . str . startswith ( \"MT-\" ) # ribosomal genes genesdf [ \"ribo\" ] = genesdf . symbol . astype ( str ) . str . startswith (( \"RPS\" , \"RPL\" )) # hemoglobin genes. genesdf [ \"hb\" ] = genesdf . symbol . astype ( str ) . str . contains (( \"^HB[^(P)]\" )) genesdf [ \"organism\" ] = organism organismdf . append ( genesdf ) organismdf = pd . concat ( organismdf ) organismdf . drop ( columns = [ \"source_id\" , \"stable_id\" , \"run_id\" , \"created_by_id\" , \"updated_at\" ], inplace = True , ) return organismdf","title":"load_genes"},{"location":"utils/#scprint.utils.utils.prepare_device","text":"setup GPU device if available. get gpu device indices which are used for DataParallel Source code in scprint/utils/utils.py 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 def prepare_device ( n_gpu_use ): \"\"\" setup GPU device if available. get gpu device indices which are used for DataParallel \"\"\" n_gpu = torch . cuda . device_count () if n_gpu_use > 0 and n_gpu == 0 : print ( \"Warning: There's no GPU available on this machine,\" \"training will be performed on CPU.\" ) n_gpu_use = 0 if n_gpu_use > n_gpu : print ( f \"Warning: The number of GPU's configured to use is { n_gpu_use } , but only { n_gpu } are \" \"available on this machine.\" ) n_gpu_use = n_gpu device = torch . device ( \"cuda:0\" if n_gpu_use > 0 else \"cpu\" ) list_ids = list ( range ( n_gpu_use )) return device , list_ids","title":"prepare_device"},{"location":"utils/#scprint.utils.utils.run_command","text":"run_command runs a command in the shell and prints the output. Parameters: command ( str ) \u2013 The command to be executed in the shell. Returns: int \u2013 The return code of the command executed. Source code in scprint/utils/utils.py 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 def run_command ( command : str , ** kwargs ): \"\"\" run_command runs a command in the shell and prints the output. Args: command (str): The command to be executed in the shell. Returns: int: The return code of the command executed. \"\"\" process = subprocess . Popen ( command , stdout = subprocess . PIPE , ** kwargs ) while True : if process . poll () is not None : break output = process . stdout . readline () if output : print ( output . strip ()) rc = process . poll () return rc","title":"run_command"},{"location":"utils/#scprint.utils.utils.set_seed","text":"set random seed. Source code in scprint/utils/utils.py 77 78 79 80 81 82 83 def set_seed ( seed : int = 42 ): \"\"\"set random seed.\"\"\" random . seed ( seed ) np . random . seed ( seed ) torch . manual_seed ( seed ) torch . backends . cudnn . deterministic = True torch . backends . cudnn . benchmark = False","title":"set_seed"},{"location":"utils/#scprint.utils.get_seq","text":"","title":"get_seq"},{"location":"utils/#scprint.utils.get_seq.load_fasta_species","text":"Downloads and caches FASTA files for a given species from the Ensembl FTP server. Parameters: species ( str , default: 'homo_sapiens' ) \u2013 The species name for which to download FASTA files. Defaults to \"homo_sapiens\". output_path ( str , default: '/tmp/data/fasta/' ) \u2013 The local directory path where the FASTA files will be saved. Defaults to \"/tmp/data/fasta/\". cache ( bool , default: True ) \u2013 If True, use cached files if they exist. If False, re-download the files. Defaults to True. Source code in scprint/utils/get_seq.py 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 def load_fasta_species ( species : str = \"homo_sapiens\" , output_path : str = \"/tmp/data/fasta/\" , cache : bool = True , ) -> None : \"\"\" Downloads and caches FASTA files for a given species from the Ensembl FTP server. Args: species (str, optional): The species name for which to download FASTA files. Defaults to \"homo_sapiens\". output_path (str, optional): The local directory path where the FASTA files will be saved. Defaults to \"/tmp/data/fasta/\". cache (bool, optional): If True, use cached files if they exist. If False, re-download the files. Defaults to True. \"\"\" ftp = ftplib . FTP ( \"ftp.ensembl.org\" ) ftp . login () ftp . cwd ( \"/pub/release-110/fasta/\" + species + \"/pep/\" ) file = list_files ( ftp , \".all.fa.gz\" )[ 0 ] local_file_path = output_path + file if not os . path . exists ( local_file_path ) or not cache : os . makedirs ( os . path . dirname ( local_file_path ), exist_ok = True ) with open ( local_file_path , \"wb\" ) as local_file : ftp . retrbinary ( \"RETR \" + file , local_file . write ) ftp . cwd ( \"/pub/release-110/fasta/\" + species + \"/ncrna/\" ) file = list_files ( ftp , \".ncrna.fa.gz\" )[ 0 ] local_file_path = output_path + file if not os . path . exists ( local_file_path ) or not cache : with open ( local_file_path , \"wb\" ) as local_file : ftp . retrbinary ( \"RETR \" + file , local_file . write ) ftp . quit ()","title":"load_fasta_species"},{"location":"utils/#scprint.utils.get_seq.seq","text":"Fetch nucleotide or amino acid sequence (FASTA) of a gene (and all its isoforms) or transcript by Ensembl, WormBase, or FlyBase ID. Parameters: ens_ids ( Union [ str , List [ str ]] ) \u2013 One or more Ensembl IDs (passed as string or list of strings). Also supports WormBase and FlyBase IDs. translate ( bool , default: False ) \u2013 Defines whether nucleotide or amino acid sequences are returned. Defaults to False (returns nucleotide sequences). Nucleotide sequences are fetched from the Ensembl REST API server. Amino acid sequences are fetched from the UniProt REST API server. isoforms ( bool , default: False ) \u2013 If True, returns the sequences of all known transcripts. Defaults to False. (Only for gene IDs.) parallel ( bool , default: True ) \u2013 If True, fetches sequences in parallel. Defaults to True. save ( bool , default: False ) \u2013 If True, saves output FASTA to current directory. Defaults to False. transcribe ( bool , default: None ) \u2013 Deprecated. Use 'translate' instead. seqtype ( str , default: None ) \u2013 Deprecated. Use 'translate' instead. verbose ( bool , default: True ) \u2013 If True, prints progress information. Defaults to True. Returns: List [ str ] \u2013 List[str]: A list containing the requested sequences, or a FASTA file if 'save' is True. Raises: ValueError \u2013 If an invalid Ensembl ID is provided. Source code in scprint/utils/get_seq.py 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 def seq ( ens_ids : Union [ str , List [ str ]], translate : bool = False , isoforms : bool = False , parallel : bool = True , save : bool = False , transcribe : Optional [ bool ] = None , seqtype : Optional [ str ] = None , verbose : bool = True , ) -> List [ str ]: \"\"\" Fetch nucleotide or amino acid sequence (FASTA) of a gene (and all its isoforms) or transcript by Ensembl, WormBase, or FlyBase ID. Args: ens_ids (Union[str, List[str]]): One or more Ensembl IDs (passed as string or list of strings). Also supports WormBase and FlyBase IDs. translate (bool, optional): Defines whether nucleotide or amino acid sequences are returned. Defaults to False (returns nucleotide sequences). Nucleotide sequences are fetched from the Ensembl REST API server. Amino acid sequences are fetched from the UniProt REST API server. isoforms (bool, optional): If True, returns the sequences of all known transcripts. Defaults to False. (Only for gene IDs.) parallel (bool, optional): If True, fetches sequences in parallel. Defaults to True. save (bool, optional): If True, saves output FASTA to current directory. Defaults to False. transcribe (bool, optional): Deprecated. Use 'translate' instead. seqtype (str, optional): Deprecated. Use 'translate' instead. verbose (bool, optional): If True, prints progress information. Defaults to True. Returns: List[str]: A list containing the requested sequences, or a FASTA file if 'save' is True. Raises: ValueError: If an invalid Ensembl ID is provided. \"\"\" # Handle deprecated arguments if seqtype : logging . error ( \"'seqtype' argument deprecated! Please use True/False argument 'translate' instead.\" ) return if transcribe : translate = transcribe ## Clean up arguments # Clean up Ensembl IDs # If single Ensembl ID passed as string, convert to list if type ( ens_ids ) is str : ens_ids = [ ens_ids ] # Remove Ensembl ID version if passed ens_ids_clean = [] temp = 0 for ensembl_ID in ens_ids : # But only for Ensembl ID (and not for flybase/wormbase IDs) if ensembl_ID . startswith ( \"ENS\" ): ens_ids_clean . append ( ensembl_ID . split ( \".\" )[ 0 ]) if \".\" in ensembl_ID and temp == 0 : if verbose : logging . info ( \"We noticed that you may have passed a version number with your Ensembl ID. \\n \" \"Please note that gget seq will return information linked to the latest Ensembl ID version.\" ) temp = + 1 else : ens_ids_clean . append ( ensembl_ID ) # Initiate empty 'fasta' fasta = [] ## Fetch nucleotide sequece if translate is False : # Define Ensembl REST API server server = ENSEMBL_REST_API # Define type of returned content from REST content_type = \"application/json\" # Initiate dictionary to save results for all IDs in master_dict = {} # Query REST APIs from https://rest.ensembl.org/ for ensembl_ID in ens_ids_clean : # Create dict to save query results results_dict = { ensembl_ID : {}} # If isoforms False, just fetch sequences of passed Ensembl ID if isoforms is False : # sequence/id/ query: Request sequence by stable identifier query = \"sequence/id/\" + ensembl_ID + \"?\" # Try if query valid try : # Submit query; this will throw RuntimeError if ID not found df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"id\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ({ \"seq\" : df_temp }) if verbose : logging . info ( f \"Requesting nucleotide sequence of { ensembl_ID } from Ensembl.\" ) except RuntimeError : logging . error ( f \"ID { ensembl_ID } not found. Please double-check spelling/arguments and try again.\" ) # If isoforms true, fetch sequences of isoforms instead if isoforms is True : # Get ID type (gene, transcript, ...) using gget info info_df = info ( ensembl_ID , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check if Ensembl ID was found if isinstance ( info_df , type ( None )): logging . warning ( f \"ID ' { ensembl_ID } ' not found. Please double-check spelling/arguments and try again.\" ) continue ens_ID_type = info_df . loc [ ensembl_ID ][ \"object_type\" ] # If the ID is a gene, get the IDs of all its transcripts if ens_ID_type == \"Gene\" : if verbose : logging . info ( f \"Requesting nucleotide sequences of all transcripts of { ensembl_ID } from Ensembl.\" ) for transcipt_id in info_df . loc [ ensembl_ID ][ \"all_transcripts\" ]: # Remove version number for Ensembl IDs (not for flybase/wormbase IDs) if transcipt_id . startswith ( \"ENS\" ): transcipt_id = transcipt_id . split ( \".\" )[ 0 ] # Try if query is valid try : # Define the REST query query = \"sequence/id/\" + transcipt_id + \"?\" # Submit query df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ( { f \" { transcipt_id } \" : df_temp } ) except RuntimeError : logging . error ( f \"ID { transcipt_id } not found. \" \"Please double-check spelling/arguments and try again.\" ) # If isoform true, but ID is not a gene; ignore the isoform parameter else : # Try if query is valid try : # Define the REST query query = \"sequence/id/\" + ensembl_ID + \"?\" # Submit query df_temp = rest_query ( server , query , content_type ) # Delete superfluous entries keys_to_delete = [ \"query\" , \"id\" , \"version\" , \"molecule\" ] for key in keys_to_delete : # Pop keys, None -> do not raise an error if key to delete not found df_temp . pop ( key , None ) # Add results to main dict results_dict [ ensembl_ID ] . update ({ \"seq\" : df_temp }) logging . info ( f \"Requesting nucleotide sequence of { ensembl_ID } from Ensembl.\" ) logging . warning ( \"The isoform option only applies to gene IDs.\" ) except RuntimeError : logging . error ( f \"ID { ensembl_ID } not found. \" \"Please double-check spelling/arguments and try again.\" ) # Add results to master dict master_dict . update ( results_dict ) # Build FASTA file for ens_ID in master_dict : for key in master_dict [ ens_ID ] . keys (): if key == \"seq\" : fasta . append ( \">\" + ens_ID + \" \" + master_dict [ ens_ID ][ key ][ \"desc\" ]) fasta . append ( master_dict [ ens_ID ][ key ][ \"seq\" ]) else : fasta . append ( \">\" + master_dict [ ens_ID ][ key ][ \"id\" ] + \" \" + master_dict [ ens_ID ][ key ][ \"desc\" ] ) fasta . append ( master_dict [ ens_ID ][ key ][ \"seq\" ]) ## Fetch amino acid sequences from UniProt if translate is True : if isoforms is False : # List to collect transcript IDs trans_ids = [] # Get ID type (gene, transcript, ...) using gget info info_df = info ( ens_ids_clean , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check that Ensembl ID was found missing = set ( ens_ids_clean ) - set ( info_df . index . values ) if len ( missing ) > 0 : logging . warning ( f \" { str ( missing ) } IDs not found. Please double-check spelling/arguments.\" ) ens_ID_type = info_df . loc [ ens_ids_clean [ 0 ]][ \"object_type\" ] # If the ID is a gene, use the ID of its canonical transcript if ens_ID_type == \"Gene\" : # Get ID of canonical transcript for ensembl_ID in info_df . index . values : can_trans = info_df . loc [ ensembl_ID ][ \"canonical_transcript\" ] if ensembl_ID . startswith ( \"ENS\" ): # Remove Ensembl ID version from transcript IDs and append to transcript IDs list temp_trans_id = can_trans . split ( \".\" )[ 0 ] trans_ids . append ( temp_trans_id ) elif ensembl_ID . startswith ( \"WB\" ): # Remove added \".\" at the end of transcript IDs temp_trans_id = \".\" . join ( can_trans . split ( \".\" )[: - 1 ]) # # For WormBase transcript IDs, also remove the version number for submission to UniProt API # temp_trans_id = \".\".join(temp_trans_id1.split(\".\")[:-1]) trans_ids . append ( temp_trans_id ) else : # Remove added \".\" at the end of other transcript IDs temp_trans_id = \".\" . join ( can_trans . split ( \".\" )[: - 1 ]) trans_ids . append ( temp_trans_id ) if verbose : logging . info ( f \"Requesting amino acid sequence of the canonical transcript { temp_trans_id } of gene { ensembl_ID } from UniProt.\" ) # If the ID is a transcript, append the ID directly elif ens_ID_type == \"Transcript\" : # # For WormBase transcript IDs, remove the version number for submission to UniProt API # if ensembl_ID.startswith(\"T\"): # trans_ids.append(\".\".join(ensembl_ID.split(\".\")[:-1])) # else: trans_ids = ens_ids_clean if verbose : logging . info ( f \"Requesting amino acid sequence of { trans_ids } from UniProt.\" ) else : logging . warning ( \"ensembl_IDs not recognized as either a gene or transcript ID. It will not be included in the UniProt query.\" ) # Fetch the amino acid sequences of the transcript Ensembl IDs df_uniprot = get_uniprot_seqs ( UNIPROT_REST_API , trans_ids ) # Add info_df.loc[ensembl_ID] to df_uniprot by joining on \"canonical_transcript\" / \"gene_name\" respectively import pdb pdb . set_trace () info_df . set_index ( \"canonical_transcript\" , inplace = True ) df_uniprot . loc [:, \"gene_id\" ] = info_df . loc [ df_uniprot [ \"query\" ], \"gene_name\" ] . values if isoforms is True : # List to collect transcript IDs trans_ids = [] for ensembl_ID in ens_ids_clean : # Get ID type (gene, transcript, ...) using gget info info_df = info ( ensembl_ID , verbose = False , pdb = False , ncbi = False , uniprot = False ) # Check that Ensembl ID was found if isinstance ( info_df , type ( None )): logging . warning ( f \"ID ' { ensembl_ID } ' not found. Please double-check spelling/arguments.\" ) continue ens_ID_type = info_df . loc [ ensembl_ID ][ \"object_type\" ] # If the ID is a gene, get the IDs of all isoforms if ens_ID_type == \"Gene\" : # Get the IDs of all transcripts from the gget info results for transcipt_id in info_df . loc [ ensembl_ID ][ \"all_transcripts\" ]: if ensembl_ID . startswith ( \"ENS\" ): # Append transcript ID (without Ensembl version number) to list of transcripts to fetch trans_ids . append ( transcipt_id . split ( \".\" )[ 0 ]) # elif ensembl_ID.startswith(\"WB\"): # # For WormBase transcript IDs, remove the version number for submission to UniProt API # temp_trans_id = \".\".join(transcipt_id.split(\".\")[:-1]) # trans_ids.append(temp_trans_id) else : # Note: No need to remove the added \".\" at the end of unversioned transcripts here, because \"all_transcripts\" are returned without it trans_ids . append ( transcipt_id ) if verbose : logging . info ( f \"Requesting amino acid sequences of all transcripts of gene { ensembl_ID } from UniProt.\" ) elif ens_ID_type == \"Transcript\" : # # For WormBase transcript IDs, remove the version number for submission to UniProt API # if ensembl_ID.startswith(\"T\"): # trans_ids.append(\".\".join(ensembl_ID.split(\".\")[:-1])) # else: trans_ids . append ( ensembl_ID ) if verbose : logging . info ( f \"Requesting amino acid sequence of { ensembl_ID } from UniProt.\" ) logging . warning ( \"The isoform option only applies to gene IDs.\" ) else : logging . warning ( f \" { ensembl_ID } not recognized as either a gene or transcript ID. It will not be included in the UniProt query.\" ) # Fetch amino acid sequences of all isoforms from the UniProt REST API df_uniprot = get_uniprot_seqs ( UNIPROT_REST_API , trans_ids ) # Check if any results were found if len ( df_uniprot ) < 1 : logging . error ( \"No UniProt amino acid sequences were found for these ID(s).\" ) else : # Build FASTA file from UniProt results for ( uniprot_id , query_ensembl_id , gene_name , organism , sequence_length , uniprot_seq , ) in zip ( df_uniprot [ \"uniprot_id\" ] . values , df_uniprot [ \"query\" ] . values , df_uniprot [ \"gene_name\" ] . values , df_uniprot [ \"gene_id\" ] . values , df_uniprot [ \"organism\" ] . values , df_uniprot [ \"sequence_length\" ] . values , df_uniprot [ \"sequence\" ] . values , ): fasta . append ( \">\" + str ( query_ensembl_id ) + \" uniprot_id: \" + str ( uniprot_id ) + \" ensembl_id: \" + str ( query_ensembl_id ) + \" gene_name: \" + str ( gene_name ) + \" organism: \" + str ( organism ) + \" sequence_length: \" + str ( sequence_length ) ) fasta . append ( str ( uniprot_seq )) # Save if save : file = open ( \"gget_seq_results.fa\" , \"w\" ) for element in fasta : file . write ( element + \" \\n \" ) file . close () # missed samples return ( set ( trans_ids ) - set ( df_uniprot [ \"query\" ] . values )) | set ( missing ) return fasta","title":"seq"},{"location":"utils/#scprint.utils.get_seq.subset_fasta","text":"subset_fasta: creates a new fasta file with only the sequence which names contain one of gene_names Parameters: gene_tosubset ( set ) \u2013 A set of gene names to subset from the original FASTA file. fasta_path ( str ) \u2013 The path to the original FASTA file. subfasta_path ( str , default: './data/fasta/subset.fa' ) \u2013 The path to save the subsetted FASTA file. Defaults to \"./data/fasta/subset.fa\". drop_unknown_seq ( bool , default: True ) \u2013 If True, drop sequences containing unknown amino acids (denoted by '*'). Defaults to True. Returns: set ( set ) \u2013 A set of gene names that were found and included in the subsetted FASTA file. Raises: ValueError \u2013 If a gene name does not start with \"ENS\". Source code in scprint/utils/get_seq.py 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 def subset_fasta ( gene_tosubset : set , fasta_path : str , subfasta_path : str = \"./data/fasta/subset.fa\" , drop_unknown_seq : bool = True , ) -> set : \"\"\" subset_fasta: creates a new fasta file with only the sequence which names contain one of gene_names Args: gene_tosubset (set): A set of gene names to subset from the original FASTA file. fasta_path (str): The path to the original FASTA file. subfasta_path (str, optional): The path to save the subsetted FASTA file. Defaults to \"./data/fasta/subset.fa\". drop_unknown_seq (bool, optional): If True, drop sequences containing unknown amino acids (denoted by '*'). Defaults to True. Returns: set: A set of gene names that were found and included in the subsetted FASTA file. Raises: ValueError: If a gene name does not start with \"ENS\". \"\"\" dup = set () weird = 0 genes_found = set () gene_tosubset = set ( gene_tosubset ) with open ( fasta_path , \"r\" ) as original_fasta , open ( subfasta_path , \"w\" ) as subset_fasta : for record in SeqIO . parse ( original_fasta , \"fasta\" ): gene_name = ( record . description . split ( \" gene:\" )[ 1 ] . split ( \" transcript\" )[ 0 ] . split ( \".\" )[ 0 ] ) if gene_name in gene_tosubset : if drop_unknown_seq : if \"*\" in record . seq : weird += 1 continue if not gene_name . startswith ( \"ENS\" ): raise ValueError ( \"issue\" , gene_name ) if gene_name in genes_found : dup . add ( gene_name ) continue record . description = \"\" record . id = gene_name SeqIO . write ( record , subset_fasta , \"fasta\" ) genes_found . add ( gene_name ) print ( len ( dup ), \" genes had duplicates\" ) print ( \"dropped\" , weird , \"weird sequences\" ) return genes_found","title":"subset_fasta"},{"location":"notebooks/cancer_usecase/","text":"(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.ClipboardCopyElement = factory()); }(this, function () { 'use strict'; function createNode(text) { const node = document.createElement('pre'); node.style.width = '1px'; node.style.height = '1px'; node.style.position = 'fixed'; node.style.top = '5px'; node.textContent = text; return node; } function copyNode(node) { if ('clipboard' in navigator) { // eslint-disable-next-line flowtype/no-flow-fix-me-comments // $FlowFixMe Clipboard is not defined in Flow yet. return navigator.clipboard.writeText(node.textContent); } const selection = getSelection(); if (selection == null) { return Promise.reject(new Error()); } selection.removeAllRanges(); const range = document.createRange(); range.selectNodeContents(node); selection.addRange(range); document.execCommand('copy'); selection.removeAllRanges(); return Promise.resolve(); } function copyText(text) { if ('clipboard' in navigator) { // eslint-disable-next-line flowtype/no-flow-fix-me-comments // $FlowFixMe Clipboard is not defined in Flow yet. return navigator.clipboard.writeText(text); } const body = document.body; if (!body) { return Promise.reject(new Error()); } const node = createNode(text); body.appendChild(node); copyNode(node); body.removeChild(node); return Promise.resolve(); } function copy(button) { const id = button.getAttribute('for'); const text = button.getAttribute('value'); function trigger() { button.dispatchEvent(new CustomEvent('clipboard-copy', { bubbles: true })); } if (text) { copyText(text).then(trigger); } else if (id) { const root = 'getRootNode' in Element.prototype ? button.getRootNode() : button.ownerDocument; if (!(root instanceof Document || 'ShadowRoot' in window && root instanceof ShadowRoot)) return; const node = root.getElementById(id); if (node) copyTarget(node).then(trigger); } } function copyTarget(content) { if (content instanceof HTMLInputElement || content instanceof HTMLTextAreaElement) { return copyText(content.value); } else if (content instanceof HTMLAnchorElement && content.hasAttribute('href')) { return copyText(content.href); } else { return copyNode(content); } } function clicked(event) { const button = event.currentTarget; if (button instanceof HTMLElement) { copy(button); } } function keydown(event) { if (event.key === ' ' || event.key === 'Enter') { const button = event.currentTarget; if (button instanceof HTMLElement) { event.preventDefault(); copy(button); } } } function focused(event) { event.currentTarget.addEventListener('keydown', keydown); } function blurred(event) { event.currentTarget.removeEventListener('keydown', keydown); } class ClipboardCopyElement extends HTMLElement { constructor() { super(); this.addEventListener('click', clicked); this.addEventListener('focus', focused); this.addEventListener('blur', blurred); } connectedCallback() { if (!this.hasAttribute('tabindex')) { this.setAttribute('tabindex', '0'); } if (!this.hasAttribute('role')) { this.setAttribute('role', 'button'); } } get value() { return this.getAttribute('value') || ''; } set value(text) { this.setAttribute('value', text); } } if (!window.customElements.get('clipboard-copy')) { window.ClipboardCopyElement = ClipboardCopyElement; window.customElements.define('clipboard-copy', ClipboardCopyElement); } return ClipboardCopyElement; })); document.addEventListener('clipboard-copy', function(event) { const notice = event.target.querySelector('.notice') notice.hidden = false setTimeout(function() { notice.hidden = true }, 1000) }) pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) } .highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) } .highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */ .highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */ .highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */ .highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */ .highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */ .highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */ .highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */ .highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */ .highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */ .highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */ .highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */ .highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */ .highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */ .highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */ .highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */ .highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */ .highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */ .highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */ .highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */ .highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */ .highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */ .highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */ .highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */ .highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */ .highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */ .highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */ .highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */ .highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */ .highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */ .highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */ .highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */ .highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */ .highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */ .highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */ .highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */ .highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */ .highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */ .highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */ .highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */ .highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */ .highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */ @charset \"UTF-8\";.jupyter-wrapper{--md-red-50: #ffebee;--md-red-100: #ffcdd2;--md-red-200: #ef9a9a;--md-red-300: #e57373;--md-red-400: #ef5350;--md-red-500: #f44336;--md-red-600: #e53935;--md-red-700: #d32f2f;--md-red-800: #c62828;--md-red-900: #b71c1c;--md-red-A100: #ff8a80;--md-red-A200: #ff5252;--md-red-A400: #ff1744;--md-red-A700: #d50000;--md-pink-50: #fce4ec;--md-pink-100: #f8bbd0;--md-pink-200: #f48fb1;--md-pink-300: #f06292;--md-pink-400: #ec407a;--md-pink-500: #e91e63;--md-pink-600: #d81b60;--md-pink-700: #c2185b;--md-pink-800: #ad1457;--md-pink-900: #880e4f;--md-pink-A100: #ff80ab;--md-pink-A200: #ff4081;--md-pink-A400: #f50057;--md-pink-A700: #c51162;--md-purple-50: #f3e5f5;--md-purple-100: #e1bee7;--md-purple-200: #ce93d8;--md-purple-300: #ba68c8;--md-purple-400: #ab47bc;--md-purple-500: #9c27b0;--md-purple-600: #8e24aa;--md-purple-700: #7b1fa2;--md-purple-800: #6a1b9a;--md-purple-900: #4a148c;--md-purple-A100: #ea80fc;--md-purple-A200: #e040fb;--md-purple-A400: #d500f9;--md-purple-A700: #aa00ff;--md-deep-purple-50: #ede7f6;--md-deep-purple-100: #d1c4e9;--md-deep-purple-200: #b39ddb;--md-deep-purple-300: #9575cd;--md-deep-purple-400: #7e57c2;--md-deep-purple-500: #673ab7;--md-deep-purple-600: #5e35b1;--md-deep-purple-700: #512da8;--md-deep-purple-800: #4527a0;--md-deep-purple-900: #311b92;--md-deep-purple-A100: #b388ff;--md-deep-purple-A200: #7c4dff;--md-deep-purple-A400: #651fff;--md-deep-purple-A700: #6200ea;--md-indigo-50: #e8eaf6;--md-indigo-100: #c5cae9;--md-indigo-200: #9fa8da;--md-indigo-300: #7986cb;--md-indigo-400: #5c6bc0;--md-indigo-500: #3f51b5;--md-indigo-600: #3949ab;--md-indigo-700: #303f9f;--md-indigo-800: #283593;--md-indigo-900: #1a237e;--md-indigo-A100: #8c9eff;--md-indigo-A200: #536dfe;--md-indigo-A400: #3d5afe;--md-indigo-A700: #304ffe;--md-blue-50: #e3f2fd;--md-blue-100: #bbdefb;--md-blue-200: #90caf9;--md-blue-300: #64b5f6;--md-blue-400: #42a5f5;--md-blue-500: #2196f3;--md-blue-600: #1e88e5;--md-blue-700: #1976d2;--md-blue-800: #1565c0;--md-blue-900: #0d47a1;--md-blue-A100: #82b1ff;--md-blue-A200: #448aff;--md-blue-A400: #2979ff;--md-blue-A700: #2962ff;--md-light-blue-50: #e1f5fe;--md-light-blue-100: #b3e5fc;--md-light-blue-200: #81d4fa;--md-light-blue-300: #4fc3f7;--md-light-blue-400: #29b6f6;--md-light-blue-500: #03a9f4;--md-light-blue-600: #039be5;--md-light-blue-700: #0288d1;--md-light-blue-800: #0277bd;--md-light-blue-900: #01579b;--md-light-blue-A100: #80d8ff;--md-light-blue-A200: #40c4ff;--md-light-blue-A400: #00b0ff;--md-light-blue-A700: #0091ea;--md-cyan-50: #e0f7fa;--md-cyan-100: #b2ebf2;--md-cyan-200: #80deea;--md-cyan-300: #4dd0e1;--md-cyan-400: #26c6da;--md-cyan-500: #00bcd4;--md-cyan-600: #00acc1;--md-cyan-700: #0097a7;--md-cyan-800: #00838f;--md-cyan-900: #006064;--md-cyan-A100: #84ffff;--md-cyan-A200: #18ffff;--md-cyan-A400: #00e5ff;--md-cyan-A700: #00b8d4;--md-teal-50: #e0f2f1;--md-teal-100: #b2dfdb;--md-teal-200: #80cbc4;--md-teal-300: #4db6ac;--md-teal-400: #26a69a;--md-teal-500: #009688;--md-teal-600: #00897b;--md-teal-700: #00796b;--md-teal-800: #00695c;--md-teal-900: #004d40;--md-teal-A100: #a7ffeb;--md-teal-A200: #64ffda;--md-teal-A400: #1de9b6;--md-teal-A700: #00bfa5;--md-green-50: #e8f5e9;--md-green-100: #c8e6c9;--md-green-200: #a5d6a7;--md-green-300: #81c784;--md-green-400: #66bb6a;--md-green-500: #4caf50;--md-green-600: #43a047;--md-green-700: #388e3c;--md-green-800: #2e7d32;--md-green-900: #1b5e20;--md-green-A100: #b9f6ca;--md-green-A200: #69f0ae;--md-green-A400: #00e676;--md-green-A700: #00c853;--md-light-green-50: #f1f8e9;--md-light-green-100: #dcedc8;--md-light-green-200: #c5e1a5;--md-light-green-300: #aed581;--md-light-green-400: #9ccc65;--md-light-green-500: #8bc34a;--md-light-green-600: #7cb342;--md-light-green-700: #689f38;--md-light-green-800: #558b2f;--md-light-green-900: #33691e;--md-light-green-A100: #ccff90;--md-light-green-A200: #b2ff59;--md-light-green-A400: #76ff03;--md-light-green-A700: #64dd17;--md-lime-50: #f9fbe7;--md-lime-100: #f0f4c3;--md-lime-200: #e6ee9c;--md-lime-300: #dce775;--md-lime-400: #d4e157;--md-lime-500: #cddc39;--md-lime-600: #c0ca33;--md-lime-700: #afb42b;--md-lime-800: #9e9d24;--md-lime-900: #827717;--md-lime-A100: #f4ff81;--md-lime-A200: #eeff41;--md-lime-A400: #c6ff00;--md-lime-A700: #aeea00;--md-yellow-50: #fffde7;--md-yellow-100: #fff9c4;--md-yellow-200: #fff59d;--md-yellow-300: #fff176;--md-yellow-400: #ffee58;--md-yellow-500: #ffeb3b;--md-yellow-600: #fdd835;--md-yellow-700: #fbc02d;--md-yellow-800: #f9a825;--md-yellow-900: #f57f17;--md-yellow-A100: #ffff8d;--md-yellow-A200: #ffff00;--md-yellow-A400: #ffea00;--md-yellow-A700: #ffd600;--md-amber-50: #fff8e1;--md-amber-100: #ffecb3;--md-amber-200: #ffe082;--md-amber-300: #ffd54f;--md-amber-400: #ffca28;--md-amber-500: #ffc107;--md-amber-600: #ffb300;--md-amber-700: #ffa000;--md-amber-800: #ff8f00;--md-amber-900: #ff6f00;--md-amber-A100: #ffe57f;--md-amber-A200: #ffd740;--md-amber-A400: #ffc400;--md-amber-A700: #ffab00;--md-orange-50: #fff3e0;--md-orange-100: #ffe0b2;--md-orange-200: #ffcc80;--md-orange-300: #ffb74d;--md-orange-400: #ffa726;--md-orange-500: #ff9800;--md-orange-600: #fb8c00;--md-orange-700: #f57c00;--md-orange-800: #ef6c00;--md-orange-900: #e65100;--md-orange-A100: #ffd180;--md-orange-A200: #ffab40;--md-orange-A400: #ff9100;--md-orange-A700: #ff6d00;--md-deep-orange-50: #fbe9e7;--md-deep-orange-100: #ffccbc;--md-deep-orange-200: #ffab91;--md-deep-orange-300: #ff8a65;--md-deep-orange-400: #ff7043;--md-deep-orange-500: #ff5722;--md-deep-orange-600: #f4511e;--md-deep-orange-700: #e64a19;--md-deep-orange-800: #d84315;--md-deep-orange-900: #bf360c;--md-deep-orange-A100: #ff9e80;--md-deep-orange-A200: #ff6e40;--md-deep-orange-A400: #ff3d00;--md-deep-orange-A700: #dd2c00;--md-brown-50: #efebe9;--md-brown-100: #d7ccc8;--md-brown-200: #bcaaa4;--md-brown-300: #a1887f;--md-brown-400: #8d6e63;--md-brown-500: #795548;--md-brown-600: #6d4c41;--md-brown-700: #5d4037;--md-brown-800: #4e342e;--md-brown-900: #3e2723;--md-grey-50: #fafafa;--md-grey-100: #f5f5f5;--md-grey-200: #eeeeee;--md-grey-300: #e0e0e0;--md-grey-400: #bdbdbd;--md-grey-500: #9e9e9e;--md-grey-600: #757575;--md-grey-700: #616161;--md-grey-800: #424242;--md-grey-900: #212121;--md-blue-grey-50: #eceff1;--md-blue-grey-100: #cfd8dc;--md-blue-grey-200: #b0bec5;--md-blue-grey-300: #90a4ae;--md-blue-grey-400: #78909c;--md-blue-grey-500: #607d8b;--md-blue-grey-600: #546e7a;--md-blue-grey-700: #455a64;--md-blue-grey-800: #37474f;--md-blue-grey-900: #263238}.jupyter-wrapper{--jp-shadow-base-lightness: 0;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-400);--jp-border-color1: var(--md-grey-400);--jp-border-color2: var(--md-grey-300);--jp-border-color3: var(--md-grey-200);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(0, 0, 0, 1);--jp-ui-font-color1: rgba(0, 0, 0, .87);--jp-ui-font-color2: rgba(0, 0, 0, .54);--jp-ui-font-color3: rgba(0, 0, 0, .38);--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color2: rgba(255, 255, 255, .7);--jp-ui-inverse-font-color3: rgba(255, 255, 255, .5);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(0, 0, 0, 1);--jp-content-font-color1: rgba(0, 0, 0, .87);--jp-content-font-color2: rgba(0, 0, 0, .54);--jp-content-font-color3: rgba(0, 0, 0, .38);--jp-content-link-color: var(--md-blue-700);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: white;--jp-layout-color1: white;--jp-layout-color2: var(--md-grey-200);--jp-layout-color3: var(--md-grey-400);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: #111111;--jp-inverse-layout-color1: var(--md-grey-900);--jp-inverse-layout-color2: var(--md-grey-800);--jp-inverse-layout-color3: var(--md-grey-700);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-900);--jp-brand-color1: var(--md-blue-700);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-900);--jp-accent-color1: var(--md-green-700);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-900);--jp-warn-color1: var(--md-orange-700);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-900);--jp-error-color1: var(--md-red-700);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-900);--jp-success-color1: var(--md-green-700);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-900);--jp-info-color1: var(--md-cyan-700);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--md-grey-100);--jp-cell-editor-border-color: var(--md-grey-300);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: .5;--jp-cell-prompt-not-active-font-color: var(--md-grey-700);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: var(--md-blue-50);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: #fdd;--jp-rendermime-table-row-background: var(--md-grey-100);--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);--jp-dialog-background: rgba(0, 0, 0, .25);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color1);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .24);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--md-grey-300);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color1);--jp-input-hover-background: var(--jp-layout-color1);--jp-input-background: var(--md-grey-100);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: #d9d9d9;--jp-editor-selected-focused-background: #d7d4f0;--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: #008000;--jp-mirror-editor-atom-color: #88f;--jp-mirror-editor-number-color: #080;--jp-mirror-editor-def-color: #00f;--jp-mirror-editor-variable-color: var(--md-grey-900);--jp-mirror-editor-variable-2-color: #05a;--jp-mirror-editor-variable-3-color: #085;--jp-mirror-editor-punctuation-color: #05a;--jp-mirror-editor-property-color: #05a;--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ba2121;--jp-mirror-editor-string-2-color: #708;--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: #008000;--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: #170;--jp-mirror-editor-attribute-color: #00c;--jp-mirror-editor-header-color: blue;--jp-mirror-editor-quote-color: #090;--jp-mirror-editor-link-color: #00c;--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ffad8e;--jp-collaborator-color2: #dac83d;--jp-collaborator-color3: #72dd76;--jp-collaborator-color4: #00e4d0;--jp-collaborator-color5: #45d4ff;--jp-collaborator-color6: #e2b1ff;--jp-collaborator-color7: #ff9de6;--jp-vega-background: white;--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .5;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(245, 200, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-700);--jp-console-icon-background-color: var(--md-blue-700);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-800);--jp-terminal-icon-color: var(--md-grey-200);--jp-text-editor-icon-color: var(--md-grey-700);--jp-inspector-icon-color: var(--md-grey-700);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-900)}[data-md-color-scheme=slate] .jupyter-wrapper{--jp-shadow-base-lightness: 32;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-700);--jp-border-color1: var(--md-grey-700);--jp-border-color2: var(--md-grey-800);--jp-border-color3: var(--md-grey-900);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(255, 255, 255, 1);--jp-ui-font-color1: rgba(255, 255, 255, .87);--jp-ui-font-color2: rgba(255, 255, 255, .54);--jp-ui-font-color3: rgba(255, 255, 255, .38);--jp-ui-inverse-font-color0: rgba(0, 0, 0, 1);--jp-ui-inverse-font-color1: rgba(0, 0, 0, .8);--jp-ui-inverse-font-color2: rgba(0, 0, 0, .5);--jp-ui-inverse-font-color3: rgba(0, 0, 0, .3);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(255, 255, 255, 1);--jp-content-font-color1: rgba(255, 255, 255, 1);--jp-content-font-color2: rgba(255, 255, 255, .7);--jp-content-font-color3: rgba(255, 255, 255, .5);--jp-content-link-color: var(--md-blue-300);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: #111111;--jp-layout-color1: var(--md-grey-900);--jp-layout-color2: var(--md-grey-800);--jp-layout-color3: var(--md-grey-700);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: white;--jp-inverse-layout-color1: white;--jp-inverse-layout-color2: var(--md-grey-200);--jp-inverse-layout-color3: var(--md-grey-400);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-700);--jp-brand-color1: var(--md-blue-500);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-700);--jp-accent-color1: var(--md-green-500);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-700);--jp-warn-color1: var(--md-orange-500);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-700);--jp-error-color1: var(--md-red-500);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-700);--jp-success-color1: var(--md-green-500);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-700);--jp-info-color1: var(--md-cyan-500);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--jp-layout-color1);--jp-cell-editor-border-color: var(--md-grey-700);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: 1;--jp-cell-prompt-not-active-font-color: var(--md-grey-300);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: rgba(33, 150, 243, .24);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: rgba(244, 67, 54, .28);--jp-rendermime-table-row-background: var(--md-grey-900);--jp-rendermime-table-row-hover-background: rgba(3, 169, 244, .2);--jp-dialog-background: rgba(0, 0, 0, .6);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color2);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .8);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--jp-layout-color0);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color0);--jp-input-hover-background: var(--jp-layout-color2);--jp-input-background: var(--md-grey-800);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: var(--jp-layout-color2);--jp-editor-selected-focused-background: rgba(33, 150, 243, .24);--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: var(--md-green-500);--jp-mirror-editor-atom-color: var(--md-blue-300);--jp-mirror-editor-number-color: var(--md-green-400);--jp-mirror-editor-def-color: var(--md-blue-600);--jp-mirror-editor-variable-color: var(--md-grey-300);--jp-mirror-editor-variable-2-color: var(--md-blue-400);--jp-mirror-editor-variable-3-color: var(--md-green-600);--jp-mirror-editor-punctuation-color: var(--md-blue-400);--jp-mirror-editor-property-color: var(--md-blue-400);--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ff7070;--jp-mirror-editor-string-2-color: var(--md-purple-300);--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: var(--md-green-600);--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: var(--md-green-700);--jp-mirror-editor-attribute-color: var(--md-blue-700);--jp-mirror-editor-header-color: var(--md-blue-500);--jp-mirror-editor-quote-color: var(--md-green-300);--jp-mirror-editor-link-color: var(--md-blue-700);--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ad4a00;--jp-collaborator-color2: #7b6a00;--jp-collaborator-color3: #007e00;--jp-collaborator-color4: #008772;--jp-collaborator-color5: #0079b9;--jp-collaborator-color6: #8b45c6;--jp-collaborator-color7: #be208b;--jp-vega-background: var(--md-grey-400);--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .6;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(255, 225, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-scrollbar-background-color: #3f4244;--jp-scrollbar-thumb-color: 88, 96, 97;--jp-scrollbar-endpad: 3px;--jp-scrollbar-thumb-margin: 3.5px;--jp-scrollbar-thumb-radius: 9px;--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-500);--jp-console-icon-background-color: var(--md-blue-500);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-200);--jp-terminal-icon-color: var(--md-grey-800);--jp-text-editor-icon-color: var(--md-grey-200);--jp-inspector-icon-color: var(--md-grey-200);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-700)}.jupyter-wrapper [data-jp-theme-scrollbars=true]{scrollbar-color:rgb(var(--jp-scrollbar-thumb-color)) var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar{scrollbar-color:rgba(var(--jp-scrollbar-thumb-color),.5) transparent}.jupyter-wrapper .jp-scrollbar-tiny{scrollbar-color:rgba(var(--jp-scrollbar-thumb-color),.5) transparent;scrollbar-width:thin}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-corner{background:var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-thumb{background:rgb(var(--jp-scrollbar-thumb-color));border:var(--jp-scrollbar-thumb-margin) solid transparent;background-clip:content-box;border-radius:var(--jp-scrollbar-thumb-radius)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-track:horizontal{border-left:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color);border-right:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-track:vertical{border-top:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color);border-bottom:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-corner,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-corner{background-color:transparent}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-thumb,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-thumb{background:rgba(var(--jp-scrollbar-thumb-color),.5);border:var(--jp-scrollbar-thumb-margin) solid transparent;background-clip:content-box;border-radius:var(--jp-scrollbar-thumb-radius)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-track:horizontal{border-left:var(--jp-scrollbar-endpad) solid transparent;border-right:var(--jp-scrollbar-endpad) solid transparent}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-track:vertical{border-top:var(--jp-scrollbar-endpad) solid transparent;border-bottom:var(--jp-scrollbar-endpad) solid transparent}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar,.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-corner{background-color:transparent;height:4px;width:4px}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-thumb{background:rgba(var(--jp-scrollbar-thumb-color),.5)}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-track:horizontal{border-left:0px solid transparent;border-right:0px solid transparent}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-track:vertical{border-top:0px solid transparent;border-bottom:0px solid transparent}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal]{min-height:16px;max-height:16px;min-width:45px;border-top:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical]{min-width:16px;max-width:16px;min-height:45px;border-left:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar-button{background-color:#f0f0f0;background-position:center center;min-height:15px;max-height:15px;min-width:15px;max-width:15px}.jupyter-wrapper .lm-ScrollBar-button:hover{background-color:#dadada}.jupyter-wrapper .lm-ScrollBar-button.lm-mod-active{background-color:#cdcdcd}.jupyter-wrapper .lm-ScrollBar-track{background:#f0f0f0}.jupyter-wrapper .lm-ScrollBar-thumb{background:#cdcdcd}.jupyter-wrapper .lm-ScrollBar-thumb:hover{background:#bababa}.jupyter-wrapper .lm-ScrollBar-thumb.lm-mod-active{background:#a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-thumb{height:100%;min-width:15px;border-left:1px solid #a0a0a0;border-right:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-thumb{width:100%;min-height:15px;border-top:1px solid #a0a0a0;border-bottom:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-button[data-action=decrement]{background-image:var(--jp-icon-caret-left);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-button[data-action=increment]{background-image:var(--jp-icon-caret-right);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-button[data-action=decrement]{background-image:var(--jp-icon-caret-up);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-button[data-action=increment]{background-image:var(--jp-icon-caret-down);background-size:17px}.jupyter-wrapper .p-Widget,.jupyter-wrapper .lm-Widget{box-sizing:border-box;position:relative;overflow:hidden;cursor:default}.jupyter-wrapper .p-Widget.p-mod-hidden,.jupyter-wrapper .lm-Widget.lm-mod-hidden{display:none!important}.jupyter-wrapper .lm-AccordionPanel[data-orientation=horizontal]>.lm-AccordionPanel-title{display:block;transform-origin:top left;transform:rotate(-90deg) translate(-100%)}.jupyter-wrapper .p-CommandPalette,.jupyter-wrapper .lm-CommandPalette{display:flex;flex-direction:column;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-CommandPalette-search,.jupyter-wrapper .lm-CommandPalette-search{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-content,.jupyter-wrapper .lm-CommandPalette-content{flex:1 1 auto;margin:0;padding:0;min-height:0;overflow:auto;list-style-type:none}.jupyter-wrapper .p-CommandPalette-header,.jupyter-wrapper .lm-CommandPalette-header{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .p-CommandPalette-item,.jupyter-wrapper .lm-CommandPalette-item{display:flex;flex-direction:row}.jupyter-wrapper .p-CommandPalette-itemIcon,.jupyter-wrapper .lm-CommandPalette-itemIcon{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-itemContent,.jupyter-wrapper .lm-CommandPalette-itemContent{flex:1 1 auto;overflow:hidden}.jupyter-wrapper .p-CommandPalette-itemShortcut,.jupyter-wrapper .lm-CommandPalette-itemShortcut{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-itemLabel,.jupyter-wrapper .lm-CommandPalette-itemLabel{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .lm-close-icon{border:1px solid transparent;background-color:transparent;position:absolute;z-index:1;right:3%;top:0;bottom:0;margin:auto;padding:7px 0;display:none;vertical-align:middle;outline:0;cursor:pointer}.jupyter-wrapper .lm-close-icon:after{content:\"X\";display:block;width:15px;height:15px;text-align:center;color:#000;font-weight:400;font-size:12px;cursor:pointer}.jupyter-wrapper .p-DockPanel,.jupyter-wrapper .lm-DockPanel,.jupyter-wrapper .p-DockPanel-widget,.jupyter-wrapper .lm-DockPanel-widget{z-index:0}.jupyter-wrapper .p-DockPanel-tabBar,.jupyter-wrapper .lm-DockPanel-tabBar{z-index:1}.jupyter-wrapper .p-DockPanel-handle,.jupyter-wrapper .lm-DockPanel-handle{z-index:2}.jupyter-wrapper .p-DockPanel-handle.p-mod-hidden,.jupyter-wrapper .lm-DockPanel-handle.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-DockPanel-handle:after,.jupyter-wrapper .lm-DockPanel-handle:after{position:absolute;top:0;left:0;width:100%;height:100%;content:\"\"}.jupyter-wrapper .p-DockPanel-handle[data-orientation=horizontal],.jupyter-wrapper .lm-DockPanel-handle[data-orientation=horizontal]{cursor:ew-resize}.jupyter-wrapper .p-DockPanel-handle[data-orientation=vertical],.jupyter-wrapper .lm-DockPanel-handle[data-orientation=vertical]{cursor:ns-resize}.jupyter-wrapper .p-DockPanel-handle[data-orientation=horizontal]:after,.jupyter-wrapper .lm-DockPanel-handle[data-orientation=horizontal]:after{left:50%;min-width:8px;transform:translate(-50%)}.jupyter-wrapper .p-DockPanel-handle[data-orientation=vertical]:after,.jupyter-wrapper .lm-DockPanel-handle[data-orientation=vertical]:after{top:50%;min-height:8px;transform:translateY(-50%)}.jupyter-wrapper .p-DockPanel-overlay,.jupyter-wrapper .lm-DockPanel-overlay{z-index:3;box-sizing:border-box;pointer-events:none}.jupyter-wrapper .p-DockPanel-overlay.p-mod-hidden,.jupyter-wrapper .lm-DockPanel-overlay.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-Menu,.jupyter-wrapper .lm-Menu{z-index:10000;position:absolute;white-space:nowrap;overflow-x:hidden;overflow-y:auto;outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-Menu-content,.jupyter-wrapper .lm-Menu-content{margin:0;padding:0;display:table;list-style-type:none}.jupyter-wrapper .p-Menu-item,.jupyter-wrapper .lm-Menu-item{display:table-row}.jupyter-wrapper .p-Menu-item.p-mod-hidden,.jupyter-wrapper .p-Menu-item.p-mod-collapsed,.jupyter-wrapper .lm-Menu-item.lm-mod-hidden,.jupyter-wrapper .lm-Menu-item.lm-mod-collapsed{display:none!important}.jupyter-wrapper .p-Menu-itemIcon,.jupyter-wrapper .p-Menu-itemSubmenuIcon,.jupyter-wrapper .lm-Menu-itemIcon,.jupyter-wrapper .lm-Menu-itemSubmenuIcon{display:table-cell;text-align:center}.jupyter-wrapper .p-Menu-itemLabel,.jupyter-wrapper .lm-Menu-itemLabel{display:table-cell;text-align:left}.jupyter-wrapper .p-Menu-itemShortcut,.jupyter-wrapper .lm-Menu-itemShortcut{display:table-cell;text-align:right}.jupyter-wrapper .p-MenuBar,.jupyter-wrapper .lm-MenuBar{outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-MenuBar-content,.jupyter-wrapper .lm-MenuBar-content{margin:0;padding:0;display:flex;flex-direction:row;list-style-type:none}.jupyter-wrapper .p--MenuBar-item,.jupyter-wrapper .lm-MenuBar-item{box-sizing:border-box}.jupyter-wrapper .p-MenuBar-itemIcon,.jupyter-wrapper .p-MenuBar-itemLabel,.jupyter-wrapper .lm-MenuBar-itemIcon,.jupyter-wrapper .lm-MenuBar-itemLabel{display:inline-block}.jupyter-wrapper .p-ScrollBar,.jupyter-wrapper .lm-ScrollBar{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-ScrollBar[data-orientation=horizontal],.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal]{flex-direction:row}.jupyter-wrapper .p-ScrollBar[data-orientation=vertical],.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical]{flex-direction:column}.jupyter-wrapper .p-ScrollBar-button,.jupyter-wrapper .lm-ScrollBar-button{box-sizing:border-box;flex:0 0 auto}.jupyter-wrapper .p-ScrollBar-track,.jupyter-wrapper .lm-ScrollBar-track{box-sizing:border-box;position:relative;overflow:hidden;flex:1 1 auto}.jupyter-wrapper .p-ScrollBar-thumb,.jupyter-wrapper .lm-ScrollBar-thumb{box-sizing:border-box;position:absolute}.jupyter-wrapper .p-SplitPanel-child,.jupyter-wrapper .lm-SplitPanel-child{z-index:0}.jupyter-wrapper .p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel-handle{z-index:1}.jupyter-wrapper .p-SplitPanel-handle.p-mod-hidden,.jupyter-wrapper .lm-SplitPanel-handle.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel-handle:after{position:absolute;top:0;left:0;width:100%;height:100%;content:\"\"}.jupyter-wrapper .p-SplitPanel[data-orientation=horizontal]>.p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel[data-orientation=horizontal]>.lm-SplitPanel-handle{cursor:ew-resize}.jupyter-wrapper .p-SplitPanel[data-orientation=vertical]>.p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel[data-orientation=vertical]>.lm-SplitPanel-handle{cursor:ns-resize}.jupyter-wrapper .p-SplitPanel[data-orientation=horizontal]>.p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel[data-orientation=horizontal]>.lm-SplitPanel-handle:after{left:50%;min-width:8px;transform:translate(-50%)}.jupyter-wrapper .p-SplitPanel[data-orientation=vertical]>.p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel[data-orientation=vertical]>.lm-SplitPanel-handle:after{top:50%;min-height:8px;transform:translateY(-50%)}.jupyter-wrapper .p-TabBar,.jupyter-wrapper .lm-TabBar{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-TabBar[data-orientation=horizontal],.jupyter-wrapper .lm-TabBar[data-orientation=horizontal]{flex-direction:row;align-items:flex-end}.jupyter-wrapper .p-TabBar[data-orientation=vertical],.jupyter-wrapper .lm-TabBar[data-orientation=vertical]{flex-direction:column;align-items:flex-end}.jupyter-wrapper .p-TabBar-content,.jupyter-wrapper .lm-TabBar-content{margin:0;padding:0;display:flex;flex:1 1 auto;list-style-type:none}.jupyter-wrapper .p-TabBar[data-orientation=horizontal]>.p-TabBar-content,.jupyter-wrapper .lm-TabBar[data-orientation=horizontal]>.lm-TabBar-content{flex-direction:row}.jupyter-wrapper .p-TabBar[data-orientation=vertical]>.p-TabBar-content,.jupyter-wrapper .lm-TabBar[data-orientation=vertical]>.lm-TabBar-content{flex-direction:column}.jupyter-wrapper .p-TabBar-tab,.jupyter-wrapper .lm-TabBar-tab{display:flex;flex-direction:row;box-sizing:border-box;overflow:hidden;touch-action:none}.jupyter-wrapper .p-TabBar-tabIcon,.jupyter-wrapper .p-TabBar-tabCloseIcon,.jupyter-wrapper .lm-TabBar-tabIcon,.jupyter-wrapper .lm-TabBar-tabCloseIcon{flex:0 0 auto}.jupyter-wrapper .p-TabBar-tabLabel,.jupyter-wrapper .lm-TabBar-tabLabel{flex:1 1 auto;overflow:hidden;white-space:nowrap}.jupyter-wrapper .lm-TabBar-tabInput{-webkit-user-select:all;user-select:all;width:100%;box-sizing:border-box}.jupyter-wrapper .p-TabBar-tab.p-mod-hidden,.jupyter-wrapper .lm-TabBar-tab.lm-mod-hidden,.jupyter-wrapper .lm-TabBar-addButton.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-TabBar.p-mod-dragging .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging .lm-TabBar-tab{position:relative}.jupyter-wrapper .p-TabBar.p-mod-dragging[data-orientation=horizontal] .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging[data-orientation=horizontal] .lm-TabBar-tab{left:0;transition:left .15s ease}.jupyter-wrapper .p-TabBar.p-mod-dragging[data-orientation=vertical] .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging[data-orientation=vertical] .lm-TabBar-tab{top:0;transition:top .15s ease}.jupyter-wrapper .p-TabBar.p-mod-dragging .p-TabBar-tab.p-mod-dragging,.jupyter-wrapper .lm-TabBar.lm-mod-dragging .lm-TabBar-tab.lm-mod-dragging{transition:none}.jupyter-wrapper .lm-TabBar-tabLabel .lm-TabBar-tabInput{-webkit-user-select:all;user-select:all;width:100%;box-sizing:border-box;background:inherit}.jupyter-wrapper .p-TabPanel-tabBar,.jupyter-wrapper .lm-TabPanel-tabBar{z-index:1}.jupyter-wrapper .p-TabPanel-stackedPanel,.jupyter-wrapper .lm-TabPanel-stackedPanel{z-index:0}.jupyter-wrapper html{-webkit-box-sizing:border-box;box-sizing:border-box}.jupyter-wrapper *,.jupyter-wrapper *:before,.jupyter-wrapper *:after{-webkit-box-sizing:inherit;box-sizing:inherit}.jupyter-wrapper body{font-size:14px;font-weight:400;letter-spacing:0;line-height:1.28581;text-transform:none;color:#182026;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,Icons16,sans-serif}.jupyter-wrapper p{margin-bottom:10px;margin-top:0}.jupyter-wrapper small{font-size:12px}.jupyter-wrapper strong{font-weight:600}.jupyter-wrapper ::-moz-selection{background:rgba(125,188,255,.6)}.jupyter-wrapper ::selection{background:rgba(125,188,255,.6)}.jupyter-wrapper .bp3-heading{color:#182026;font-weight:600;margin:0 0 10px;padding:0}.jupyter-wrapper .bp3-dark .bp3-heading{color:#f5f8fa}.jupyter-wrapper h1.bp3-heading,.jupyter-wrapper .bp3-running-text h1{font-size:36px;line-height:40px}.jupyter-wrapper h2.bp3-heading,.jupyter-wrapper .bp3-running-text h2{font-size:28px;line-height:32px}.jupyter-wrapper h3.bp3-heading,.jupyter-wrapper .bp3-running-text h3{font-size:22px;line-height:25px}.jupyter-wrapper h4.bp3-heading,.jupyter-wrapper .bp3-running-text h4{font-size:18px;line-height:21px}.jupyter-wrapper h5.bp3-heading,.jupyter-wrapper .bp3-running-text h5{font-size:16px;line-height:19px}.jupyter-wrapper h6.bp3-heading,.jupyter-wrapper .bp3-running-text h6{font-size:14px;line-height:16px}.jupyter-wrapper .bp3-ui-text{font-size:14px;font-weight:400;letter-spacing:0;line-height:1.28581;text-transform:none}.jupyter-wrapper .bp3-monospace-text{font-family:monospace;text-transform:none}.jupyter-wrapper .bp3-text-muted{color:#5c7080}.jupyter-wrapper .bp3-dark .bp3-text-muted{color:#a7b6c2}.jupyter-wrapper .bp3-text-disabled{color:#5c708099}.jupyter-wrapper .bp3-dark .bp3-text-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-text-overflow-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal}.jupyter-wrapper .bp3-running-text{font-size:14px;line-height:1.5}.jupyter-wrapper .bp3-running-text h1{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h1{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h2{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h2{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h3{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h3{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h4{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h4{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h5{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h5{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h6{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h6{color:#f5f8fa}.jupyter-wrapper .bp3-running-text hr{border:none;border-bottom:1px solid rgba(16,22,26,.15);margin:20px 0}.jupyter-wrapper .bp3-dark .bp3-running-text hr{border-color:#ffffff26}.jupyter-wrapper .bp3-running-text p{margin:0 0 10px;padding:0}.jupyter-wrapper .bp3-text-large{font-size:16px}.jupyter-wrapper .bp3-text-small{font-size:12px}.jupyter-wrapper a .bp3-icon,.jupyter-wrapper a .bp3-icon-standard,.jupyter-wrapper a .bp3-icon-large,.jupyter-wrapper a code,.jupyter-wrapper .bp3-dark a code{color:inherit}.jupyter-wrapper .bp3-dark a,.jupyter-wrapper .bp3-dark a:hover{color:#48aff0}.jupyter-wrapper .bp3-dark a .bp3-icon,.jupyter-wrapper .bp3-dark a .bp3-icon-standard,.jupyter-wrapper .bp3-dark a .bp3-icon-large,.jupyter-wrapper .bp3-dark a:hover .bp3-icon,.jupyter-wrapper .bp3-dark a:hover .bp3-icon-standard,.jupyter-wrapper .bp3-dark a:hover .bp3-icon-large{color:inherit}.jupyter-wrapper .bp3-running-text code,.jupyter-wrapper .bp3-code{font-family:monospace;text-transform:none;background:rgba(255,255,255,.7);border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33;color:#5c7080;font-size:smaller;padding:2px 5px}.jupyter-wrapper .bp3-dark .bp3-running-text code,.jupyter-wrapper .bp3-running-text .bp3-dark code,.jupyter-wrapper .bp3-dark .bp3-code{background:rgba(16,22,26,.3);-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66;color:#a7b6c2}.jupyter-wrapper .bp3-running-text a>code,.jupyter-wrapper a>.bp3-code{color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-running-text a>code,.jupyter-wrapper .bp3-running-text .bp3-dark a>code,.jupyter-wrapper .bp3-dark a>.bp3-code{color:inherit}.jupyter-wrapper .bp3-running-text pre,.jupyter-wrapper .bp3-code-block{font-family:monospace;text-transform:none;background:rgba(255,255,255,.7);border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26;color:#182026;display:block;font-size:13px;line-height:1.4;margin:10px 0;padding:13px 15px 12px;word-break:break-all;word-wrap:break-word}.jupyter-wrapper .bp3-dark .bp3-running-text pre,.jupyter-wrapper .bp3-running-text .bp3-dark pre,.jupyter-wrapper .bp3-dark .bp3-code-block{background:rgba(16,22,26,.3);-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-running-text pre>code,.jupyter-wrapper .bp3-code-block>code{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit;font-size:inherit;padding:0}.jupyter-wrapper .bp3-running-text kbd,.jupyter-wrapper .bp3-key{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#ffffff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;color:#5c7080;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-family:inherit;font-size:12px;height:24px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:24px;min-width:24px;padding:3px 6px;vertical-align:middle}.jupyter-wrapper .bp3-running-text kbd .bp3-icon,.jupyter-wrapper .bp3-key .bp3-icon,.jupyter-wrapper .bp3-running-text kbd .bp3-icon-standard,.jupyter-wrapper .bp3-key .bp3-icon-standard,.jupyter-wrapper .bp3-running-text kbd .bp3-icon-large,.jupyter-wrapper .bp3-key .bp3-icon-large{margin-right:5px}.jupyter-wrapper .bp3-dark .bp3-running-text kbd,.jupyter-wrapper .bp3-running-text .bp3-dark kbd,.jupyter-wrapper .bp3-dark .bp3-key{background:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66;color:#a7b6c2}.jupyter-wrapper .bp3-running-text blockquote,.jupyter-wrapper .bp3-blockquote{border-left:solid 4px rgba(167,182,194,.5);margin:0 0 10px;padding:0 20px}.jupyter-wrapper .bp3-dark .bp3-running-text blockquote,.jupyter-wrapper .bp3-running-text .bp3-dark blockquote,.jupyter-wrapper .bp3-dark .bp3-blockquote{border-color:#73869480}.jupyter-wrapper .bp3-running-text ul,.jupyter-wrapper .bp3-running-text ol,.jupyter-wrapper .bp3-list{margin:10px 0;padding-left:30px}.jupyter-wrapper .bp3-running-text ul li:not(:last-child),.jupyter-wrapper .bp3-running-text ol li:not(:last-child),.jupyter-wrapper .bp3-list li:not(:last-child){margin-bottom:5px}.jupyter-wrapper .bp3-running-text ul ol,.jupyter-wrapper .bp3-running-text ol ol,.jupyter-wrapper .bp3-list ol,.jupyter-wrapper .bp3-running-text ul ul,.jupyter-wrapper .bp3-running-text ol ul,.jupyter-wrapper .bp3-list ul{margin-top:5px}.jupyter-wrapper .bp3-list-unstyled{list-style:none;margin:0;padding:0}.jupyter-wrapper .bp3-list-unstyled li{padding:0}.jupyter-wrapper .bp3-rtl{text-align:right}.jupyter-wrapper .bp3-dark{color:#f5f8fa}.jupyter-wrapper :focus{outline:rgba(19,124,189,.6) auto 2px;outline-offset:2px;-moz-outline-radius:6px}.jupyter-wrapper .bp3-focus-disabled :focus{outline:none!important}.jupyter-wrapper .bp3-focus-disabled :focus~.bp3-control-indicator{outline:none!important}.jupyter-wrapper .bp3-alert{max-width:400px;padding:20px}.jupyter-wrapper .bp3-alert-body{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-alert-body .bp3-icon{font-size:40px;margin-right:20px;margin-top:0}.jupyter-wrapper .bp3-alert-contents{word-break:break-word}.jupyter-wrapper .bp3-alert-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;margin-top:10px}.jupyter-wrapper .bp3-alert-footer .bp3-button{margin-left:10px}.jupyter-wrapper .bp3-breadcrumbs{-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:default;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;height:30px;list-style:none;margin:0;padding:0}.jupyter-wrapper .bp3-breadcrumbs>li{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-breadcrumbs>li:after{background:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.71 7.29l-4-4a1.003 1.003 0 00-1.42 1.42L8.59 8 5.3 11.29c-.19.18-.3.43-.3.71a1.003 1.003 0 001.71.71l4-4c.18-.18.29-.43.29-.71 0-.28-.11-.53-.29-.71z' fill='%235C7080'/%3e%3c/svg%3e\");content:\"\";display:block;height:16px;margin:0 5px;width:16px}.jupyter-wrapper .bp3-breadcrumbs>li:last-of-type:after{display:none}.jupyter-wrapper .bp3-breadcrumb,.jupyter-wrapper .bp3-breadcrumb-current,.jupyter-wrapper .bp3-breadcrumbs-collapsed{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:16px}.jupyter-wrapper .bp3-breadcrumb,.jupyter-wrapper .bp3-breadcrumbs-collapsed{color:#5c7080}.jupyter-wrapper .bp3-breadcrumb:hover{text-decoration:none}.jupyter-wrapper .bp3-breadcrumb.bp3-disabled{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-breadcrumb .bp3-icon{margin-right:5px}.jupyter-wrapper .bp3-breadcrumb-current{color:inherit;font-weight:600}.jupyter-wrapper .bp3-breadcrumb-current .bp3-input{font-size:inherit;font-weight:inherit;vertical-align:baseline}.jupyter-wrapper .bp3-breadcrumbs-collapsed{background:#ced9e0;border:none;border-radius:3px;cursor:pointer;margin-right:2px;padding:1px 5px;vertical-align:text-bottom}.jupyter-wrapper .bp3-breadcrumbs-collapsed:before{background:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cg fill='%235C7080'%3e%3ccircle cx='2' cy='8.03' r='2'/%3e%3ccircle cx='14' cy='8.03' r='2'/%3e%3ccircle cx='8' cy='8.03' r='2'/%3e%3c/g%3e%3c/svg%3e\") center no-repeat;content:\"\";display:block;height:16px;width:16px}.jupyter-wrapper .bp3-breadcrumbs-collapsed:hover{background:#bfccd6;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-dark .bp3-breadcrumb,.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs>li:after{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-breadcrumb.bp3-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-breadcrumb-current{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed:hover{background:rgba(16,22,26,.6);color:#f5f8fa}.jupyter-wrapper .bp3-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;border-radius:3px;cursor:pointer;font-size:14px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:5px 10px;text-align:left;vertical-align:middle;min-height:30px;min-width:30px}.jupyter-wrapper .bp3-button>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-button>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-button:before,.jupyter-wrapper .bp3-button>*{margin-right:7px}.jupyter-wrapper .bp3-button:empty:before,.jupyter-wrapper .bp3-button>:last-child{margin-right:0}.jupyter-wrapper .bp3-button:empty{padding:0!important}.jupyter-wrapper .bp3-button:disabled,.jupyter-wrapper .bp3-button.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-button.bp3-align-right,.jupyter-wrapper .bp3-align-right .bp3-button{text-align:right}.jupyter-wrapper .bp3-button.bp3-align-left,.jupyter-wrapper .bp3-align-left .bp3-button{text-align:left}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]){background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active:hover,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-button.bp3-intent-primary{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-primary:hover{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-active{background-color:#0e5a8a;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-disabled{background-color:#137cbd80;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-success{background-color:#0f9960;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-success:hover{background-color:#0d8050;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-active{background-color:#0a6640;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-disabled{background-color:#0f996080;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-warning{background-color:#d9822b;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-warning:hover{background-color:#bf7326;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-active{background-color:#a66321;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-disabled{background-color:#d9822b80;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-danger{background-color:#db3737;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-danger:hover{background-color:#c23030;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-active{background-color:#a82a2a;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-disabled{background-color:#db373780;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-button-spinner .bp3-spinner-head{stroke:#fff}.jupyter-wrapper .bp3-button.bp3-large,.jupyter-wrapper .bp3-large .bp3-button{min-height:40px;min-width:40px;font-size:16px;padding:5px 15px}.jupyter-wrapper .bp3-button.bp3-large:before,.jupyter-wrapper .bp3-button.bp3-large>*,.jupyter-wrapper .bp3-large .bp3-button:before,.jupyter-wrapper .bp3-large .bp3-button>*{margin-right:10px}.jupyter-wrapper .bp3-button.bp3-large:empty:before,.jupyter-wrapper .bp3-button.bp3-large>:last-child,.jupyter-wrapper .bp3-large .bp3-button:empty:before,.jupyter-wrapper .bp3-large .bp3-button>:last-child{margin-right:0}.jupyter-wrapper .bp3-button.bp3-small,.jupyter-wrapper .bp3-small .bp3-button{min-height:24px;min-width:24px;padding:0 7px}.jupyter-wrapper .bp3-button.bp3-loading{position:relative}.jupyter-wrapper .bp3-button.bp3-loading[class*=bp3-icon-]:before{visibility:hidden}.jupyter-wrapper .bp3-button.bp3-loading .bp3-button-spinner{margin:0;position:absolute}.jupyter-wrapper .bp3-button.bp3-loading>:not(.bp3-button-spinner){visibility:hidden}.jupyter-wrapper .bp3-button[class*=bp3-icon-]:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#5c7080}.jupyter-wrapper .bp3-button .bp3-icon,.jupyter-wrapper .bp3-button .bp3-icon-standard,.jupyter-wrapper .bp3-button .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-button .bp3-icon.bp3-align-right,.jupyter-wrapper .bp3-button .bp3-icon-standard.bp3-align-right,.jupyter-wrapper .bp3-button .bp3-icon-large.bp3-align-right{margin-left:7px}.jupyter-wrapper .bp3-button .bp3-icon:first-child:last-child,.jupyter-wrapper .bp3-button .bp3-spinner+.bp3-icon:last-child{margin:0 -7px}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]){background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):hover,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):disabled,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-])[class*=bp3-icon-]:before{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon-large{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-],.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:active,.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-].bp3-active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:disabled,.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-].bp3-disabled{background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#ffffff4d}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-] .bp3-button-spinner .bp3-spinner-head{stroke:#8a9ba8}.jupyter-wrapper .bp3-button:disabled:before,.jupyter-wrapper .bp3-button:disabled .bp3-icon,.jupyter-wrapper .bp3-button:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-button:disabled .bp3-icon-large,.jupyter-wrapper .bp3-button.bp3-disabled:before,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon-standard,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon-large,.jupyter-wrapper .bp3-button[class*=bp3-intent-]:before,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon-standard,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon-large{color:inherit!important}.jupyter-wrapper .bp3-button.bp3-minimal{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-button.bp3-minimal:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-button.bp3-minimal:disabled:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-minimal:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined{background:none;-webkit-box-shadow:none;box-shadow:none;border:1px solid rgba(24,32,38,.2);-webkit-box-sizing:border-box;box-sizing:border-box}.jupyter-wrapper .bp3-button.bp3-outlined:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-outlined:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover{border-color:#5c70801a}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined{border-color:#fff6}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover{border-color:#fff3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary{border-color:#106ba399}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{border-color:#106ba333}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary{border-color:#48aff099}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{border-color:#48aff033}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success{border-color:#0d805099}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{border-color:#0d805033}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success{border-color:#3dcc9199}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{border-color:#3dcc9133}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning{border-color:#bf732699}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{border-color:#bf732633}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning{border-color:#ffb36699}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{border-color:#ffb36633}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger{border-color:#c2303099}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{border-color:#c2303033}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger{border-color:#ff737399}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{border-color:#ff737333}.jupyter-wrapper a.bp3-button{text-align:center;text-decoration:none;-webkit-transition:none;transition:none}.jupyter-wrapper a.bp3-button,.jupyter-wrapper a.bp3-button:hover,.jupyter-wrapper a.bp3-button:active{color:#182026}.jupyter-wrapper a.bp3-button.bp3-disabled{color:#5c708099}.jupyter-wrapper .bp3-button-text{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.jupyter-wrapper .bp3-button.bp3-align-left .bp3-button-text,.jupyter-wrapper .bp3-button.bp3-align-right .bp3-button-text,.jupyter-wrapper .bp3-button-group.bp3-align-left .bp3-button-text,.jupyter-wrapper .bp3-button-group.bp3-align-right .bp3-button-text{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.jupyter-wrapper .bp3-button-group .bp3-button{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;position:relative;z-index:4}.jupyter-wrapper .bp3-button-group .bp3-button:focus{z-index:5}.jupyter-wrapper .bp3-button-group .bp3-button:hover{z-index:6}.jupyter-wrapper .bp3-button-group .bp3-button:active,.jupyter-wrapper .bp3-button-group .bp3-button.bp3-active{z-index:7}.jupyter-wrapper .bp3-button-group .bp3-button:disabled,.jupyter-wrapper .bp3-button-group .bp3-button.bp3-disabled{z-index:3}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]{z-index:9}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:focus{z-index:10}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:hover{z-index:11}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:active,.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-].bp3-active{z-index:12}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:disabled,.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-].bp3-disabled{z-index:8}.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:first-child) .bp3-button,.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:hover,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button-group .bp3-popover-wrapper,.jupyter-wrapper .bp3-button-group .bp3-popover-target{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-button-group .bp3-button.bp3-fill,.jupyter-wrapper .bp3-button-group.bp3-fill .bp3-button:not(.bp3-fixed){-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group.bp3-vertical{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;vertical-align:top}.jupyter-wrapper .bp3-button-group.bp3-vertical.bp3-fill{height:100%;width:unset}.jupyter-wrapper .bp3-button-group.bp3-vertical .bp3-button{margin-right:0!important;width:100%}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:first-child .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:first-child{border-radius:3px 3px 0 0}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:last-child .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:last-child{border-radius:0 0 3px 3px}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:not(:last-child){margin-bottom:-1px}.jupyter-wrapper .bp3-button-group.bp3-align-left .bp3-button{text-align:left}.jupyter-wrapper .bp3-dark .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-dark .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:last-child){margin-right:1px}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-vertical>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-vertical>.bp3-button:not(:last-child){margin-bottom:1px}.jupyter-wrapper .bp3-callout{font-size:14px;line-height:1.5;background-color:#8a9ba826;border-radius:3px;padding:10px 12px 9px;position:relative;width:100%}.jupyter-wrapper .bp3-callout[class*=bp3-icon-]{padding-left:40px}.jupyter-wrapper .bp3-callout[class*=bp3-icon-]:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#5c7080;left:10px;position:absolute;top:10px}.jupyter-wrapper .bp3-callout.bp3-callout-icon{padding-left:40px}.jupyter-wrapper .bp3-callout.bp3-callout-icon>.bp3-icon:first-child{color:#5c7080;left:10px;position:absolute;top:10px}.jupyter-wrapper .bp3-callout .bp3-heading{line-height:20px;margin-bottom:5px;margin-top:0}.jupyter-wrapper .bp3-callout .bp3-heading:last-child{margin-bottom:0}.jupyter-wrapper .bp3-dark .bp3-callout{background-color:#8a9ba833}.jupyter-wrapper .bp3-dark .bp3-callout[class*=bp3-icon-]:before{color:#a7b6c2}.jupyter-wrapper .bp3-callout.bp3-intent-primary{background-color:#137cbd26}.jupyter-wrapper .bp3-callout.bp3-intent-primary[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-primary>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-primary .bp3-heading{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary{background-color:#137cbd40}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary .bp3-heading{color:#48aff0}.jupyter-wrapper .bp3-callout.bp3-intent-success{background-color:#0f996026}.jupyter-wrapper .bp3-callout.bp3-intent-success[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-success>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-success .bp3-heading{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success{background-color:#0f996040}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success .bp3-heading{color:#3dcc91}.jupyter-wrapper .bp3-callout.bp3-intent-warning{background-color:#d9822b26}.jupyter-wrapper .bp3-callout.bp3-intent-warning[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-warning>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-warning .bp3-heading{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning{background-color:#d9822b40}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning .bp3-heading{color:#ffb366}.jupyter-wrapper .bp3-callout.bp3-intent-danger{background-color:#db373726}.jupyter-wrapper .bp3-callout.bp3-intent-danger[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-danger>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-danger .bp3-heading{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger{background-color:#db373740}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger .bp3-heading{color:#ff7373}.jupyter-wrapper .bp3-running-text .bp3-callout{margin:20px 0}.jupyter-wrapper .bp3-card{background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.15),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a26,0 0 #10161a00,0 0 #10161a00;padding:20px;-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),box-shadow .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-card.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a66,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-0{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.15),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a26,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-0.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-0{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a66,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-1{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33}.jupyter-wrapper .bp3-elevation-1.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-1{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-elevation-2{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 1px 1px rgba(16,22,26,.2),0 2px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 1px 1px #10161a33,0 2px 6px #10161a33}.jupyter-wrapper .bp3-elevation-2.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-2{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.4),0 2px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a66,0 2px 6px #10161a66}.jupyter-wrapper .bp3-elevation-3{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33}.jupyter-wrapper .bp3-elevation-3.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-3{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-elevation-4{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33}.jupyter-wrapper .bp3-elevation-4.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-4{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66}.jupyter-wrapper .bp3-card.bp3-interactive:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;cursor:pointer}.jupyter-wrapper .bp3-card.bp3-interactive:hover.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card.bp3-interactive:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-card.bp3-interactive:active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;opacity:.9;-webkit-transition-duration:0;transition-duration:0}.jupyter-wrapper .bp3-card.bp3-interactive:active.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card.bp3-interactive:active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-collapse{height:0;overflow-y:hidden;-webkit-transition:height .2s cubic-bezier(.4,1,.75,.9);transition:height .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-collapse .bp3-collapse-body{-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-collapse .bp3-collapse-body[aria-hidden=true]{display:none}.jupyter-wrapper .bp3-context-menu .bp3-popover-target{display:block}.jupyter-wrapper .bp3-context-menu-popover-target{position:fixed}.jupyter-wrapper .bp3-dialog-container{opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;min-height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-enter>.bp3-dialog,.jupyter-wrapper .bp3-dialog-container.bp3-overlay-appear>.bp3-dialog{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-enter-active>.bp3-dialog,.jupyter-wrapper .bp3-dialog-container.bp3-overlay-appear-active>.bp3-dialog{opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-exit>.bp3-dialog{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-exit-active>.bp3-dialog{opacity:0;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-dialog{background:#ebf1f5;border-radius:6px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:30px 0;padding-bottom:20px;pointer-events:all;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;width:500px}.jupyter-wrapper .bp3-dialog:focus{outline:0}.jupyter-wrapper .bp3-dialog.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-dialog{background:#293742;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dialog-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#ffffff;border-radius:6px 6px 0 0;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;min-height:40px;padding-left:20px;padding-right:5px;z-index:30}.jupyter-wrapper .bp3-dialog-header .bp3-icon-large,.jupyter-wrapper .bp3-dialog-header .bp3-icon{color:#5c7080;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-right:10px}.jupyter-wrapper .bp3-dialog-header .bp3-heading{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:inherit;margin:0}.jupyter-wrapper .bp3-dialog-header .bp3-heading:last-child{margin-right:20px}.jupyter-wrapper .bp3-dark .bp3-dialog-header{background:#30404d;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.4);box-shadow:0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-dialog-header .bp3-icon-large,.jupyter-wrapper .bp3-dark .bp3-dialog-header .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dialog-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:18px;margin:20px}.jupyter-wrapper .bp3-dialog-footer{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin:0 20px}.jupyter-wrapper .bp3-dialog-footer-actions{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.jupyter-wrapper .bp3-dialog-footer-actions .bp3-button{margin-left:10px}.jupyter-wrapper .bp3-multistep-dialog-panels{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-multistep-dialog-left-panel{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-left-panel{background:#202b33}.jupyter-wrapper .bp3-multistep-dialog-right-panel{background-color:#f5f8fa;border-left:1px solid rgba(16,22,26,.15);border-radius:0 0 6px;-webkit-box-flex:3;-ms-flex:3;flex:3;min-width:0}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-right-panel{background-color:#293742;border-left:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-multistep-dialog-footer{background-color:#fff;border-radius:0 0 6px;border-top:1px solid rgba(16,22,26,.15);padding:10px}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-footer{background:#30404d;border-top:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dialog-step-container{background-color:#f5f8fa;border-bottom:1px solid rgba(16,22,26,.15)}.jupyter-wrapper .bp3-dark .bp3-dialog-step-container{background:#293742;border-bottom:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dialog-step-container.bp3-dialog-step-viewed{background-color:#fff}.jupyter-wrapper .bp3-dark .bp3-dialog-step-container.bp3-dialog-step-viewed{background:#30404d}.jupyter-wrapper .bp3-dialog-step{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#f5f8fa;border-radius:6px;cursor:not-allowed;display:-webkit-box;display:-ms-flexbox;display:flex;margin:4px;padding:6px 14px}.jupyter-wrapper .bp3-dark .bp3-dialog-step{background:#293742}.jupyter-wrapper .bp3-dialog-step-viewed .bp3-dialog-step{background-color:#fff;cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-dialog-step-viewed .bp3-dialog-step{background:#30404d}.jupyter-wrapper .bp3-dialog-step:hover{background-color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-dialog-step:hover{background:#293742}.jupyter-wrapper .bp3-dialog-step-icon{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#5c708099;border-radius:50%;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;height:25px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:25px}.jupyter-wrapper .bp3-dark .bp3-dialog-step-icon{background-color:#a7b6c299}.jupyter-wrapper .bp3-active.bp3-dialog-step-viewed .bp3-dialog-step-icon{background-color:#2b95d6}.jupyter-wrapper .bp3-dialog-step-viewed .bp3-dialog-step-icon{background-color:#8a9ba8}.jupyter-wrapper .bp3-dialog-step-title{color:#5c708099;-webkit-box-flex:1;-ms-flex:1;flex:1;padding-left:10px}.jupyter-wrapper .bp3-dark .bp3-dialog-step-title{color:#a7b6c299}.jupyter-wrapper .bp3-active.bp3-dialog-step-viewed .bp3-dialog-step-title{color:#2b95d6}.jupyter-wrapper .bp3-dialog-step-viewed:not(.bp3-active) .bp3-dialog-step-title{color:#182026}.jupyter-wrapper .bp3-dark .bp3-dialog-step-viewed:not(.bp3-active) .bp3-dialog-step-title{color:#f5f8fa}.jupyter-wrapper .bp3-drawer{background:#ffffff;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0;padding:0}.jupyter-wrapper .bp3-drawer:focus{outline:0}.jupyter-wrapper .bp3-drawer.bp3-position-top{height:50%;left:0;right:0;top:0}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-appear{-webkit-transform:translateY(-100%);transform:translateY(-100%)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-exit-active{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom{bottom:0;height:50%;left:0;right:0}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-appear{-webkit-transform:translateY(100%);transform:translateY(100%)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-exit-active{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-left{bottom:0;left:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-appear{-webkit-transform:translateX(-100%);transform:translate(-100%)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-exit-active{-webkit-transform:translateX(-100%);transform:translate(-100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-right{bottom:0;right:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-appear{-webkit-transform:translateX(100%);transform:translate(100%)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical){bottom:0;right:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-enter,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-appear{-webkit-transform:translateX(100%);transform:translate(100%)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical{bottom:0;height:50%;left:0;right:0}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-appear{-webkit-transform:translateY(100%);transform:translateY(100%)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-exit-active{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-drawer{background:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-drawer-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:0;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;min-height:40px;padding:5px 5px 5px 20px;position:relative}.jupyter-wrapper .bp3-drawer-header .bp3-icon-large,.jupyter-wrapper .bp3-drawer-header .bp3-icon{color:#5c7080;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-right:10px}.jupyter-wrapper .bp3-drawer-header .bp3-heading{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:inherit;margin:0}.jupyter-wrapper .bp3-drawer-header .bp3-heading:last-child{margin-right:20px}.jupyter-wrapper .bp3-dark .bp3-drawer-header{-webkit-box-shadow:0 1px 0 rgba(16,22,26,.4);box-shadow:0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-drawer-header .bp3-icon-large,.jupyter-wrapper .bp3-dark .bp3-drawer-header .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-drawer-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:18px;overflow:auto}.jupyter-wrapper .bp3-drawer-footer{-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;padding:10px 20px;position:relative}.jupyter-wrapper .bp3-dark .bp3-drawer-footer{-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.4);box-shadow:inset 0 1px #10161a66}.jupyter-wrapper .bp3-editable-text{cursor:text;display:inline-block;max-width:100%;position:relative;vertical-align:top;white-space:nowrap}.jupyter-wrapper .bp3-editable-text:before{bottom:-3px;left:-3px;position:absolute;right:-3px;top:-3px;border-radius:3px;content:\"\";-webkit-transition:background-color .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-editable-text:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-editable-text.bp3-editable-text-editing:before{background-color:#fff;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-disabled:before{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-primary .bp3-editable-text-content{color:#137cbd}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(19,124,189,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd66}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-success .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-success .bp3-editable-text-content{color:#0f9960}.jupyter-wrapper .bp3-editable-text.bp3-intent-success:hover:before{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px rgba(15,153,96,.4);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f996066}.jupyter-wrapper .bp3-editable-text.bp3-intent-success.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-warning .bp3-editable-text-content{color:#d9822b}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning:hover:before{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px rgba(217,130,43,.4);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b66}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-danger .bp3-editable-text-content{color:#db3737}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger:hover:before{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px rgba(219,55,55,.4);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db373766}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-dark .bp3-editable-text:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(255,255,255,.15);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #ffffff26}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-editable-text-editing:before{background-color:#10161a4d;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-disabled:before{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary .bp3-editable-text-content{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary:hover:before{-webkit-box-shadow:0 0 0 0 rgba(72,175,240,0),0 0 0 0 rgba(72,175,240,0),inset 0 0 0 1px rgba(72,175,240,.4);box-shadow:0 0 #48aff000,0 0 #48aff000,inset 0 0 0 1px #48aff066}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #48aff0,0 0 0 3px rgba(72,175,240,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #48aff0,0 0 0 3px #48aff04d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success .bp3-editable-text-content{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success:hover:before{-webkit-box-shadow:0 0 0 0 rgba(61,204,145,0),0 0 0 0 rgba(61,204,145,0),inset 0 0 0 1px rgba(61,204,145,.4);box-shadow:0 0 #3dcc9100,0 0 #3dcc9100,inset 0 0 0 1px #3dcc9166}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #3dcc91,0 0 0 3px rgba(61,204,145,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #3dcc91,0 0 0 3px #3dcc914d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning .bp3-editable-text-content{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning:hover:before{-webkit-box-shadow:0 0 0 0 rgba(255,179,102,0),0 0 0 0 rgba(255,179,102,0),inset 0 0 0 1px rgba(255,179,102,.4);box-shadow:0 0 #ffb36600,0 0 #ffb36600,inset 0 0 0 1px #ffb36666}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #ffb366,0 0 0 3px rgba(255,179,102,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #ffb366,0 0 0 3px #ffb3664d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger .bp3-editable-text-content{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger:hover:before{-webkit-box-shadow:0 0 0 0 rgba(255,115,115,0),0 0 0 0 rgba(255,115,115,0),inset 0 0 0 1px rgba(255,115,115,.4);box-shadow:0 0 #ff737300,0 0 #ff737300,inset 0 0 0 1px #ff737366}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #ff7373,0 0 0 3px rgba(255,115,115,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #ff7373,0 0 0 3px #ff73734d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text-content{color:inherit;display:inherit;font:inherit;letter-spacing:inherit;max-width:inherit;min-width:inherit;position:relative;resize:none;text-transform:inherit;vertical-align:top}.jupyter-wrapper .bp3-editable-text-input{background:none;border:none;-webkit-box-shadow:none;box-shadow:none;padding:0;white-space:pre-wrap;width:100%}.jupyter-wrapper .bp3-editable-text-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input:focus{outline:none}.jupyter-wrapper .bp3-editable-text-input::-ms-clear{display:none}.jupyter-wrapper .bp3-editable-text-content{overflow:hidden;padding-right:2px;text-overflow:ellipsis;white-space:pre}.jupyter-wrapper .bp3-editable-text-editing>.bp3-editable-text-content{left:0;position:absolute;visibility:hidden}.jupyter-wrapper .bp3-editable-text-placeholder>.bp3-editable-text-content{color:#5c708099}.jupyter-wrapper .bp3-dark .bp3-editable-text-placeholder>.bp3-editable-text-content{color:#a7b6c299}.jupyter-wrapper .bp3-editable-text.bp3-multiline{display:block}.jupyter-wrapper .bp3-editable-text.bp3-multiline .bp3-editable-text-content{overflow:auto;white-space:pre-wrap;word-wrap:break-word}.jupyter-wrapper .bp3-divider{border-bottom:1px solid rgba(16,22,26,.15);border-right:1px solid rgba(16,22,26,.15);margin:5px}.jupyter-wrapper .bp3-dark .bp3-divider{border-color:#10161a66}.jupyter-wrapper .bp3-control-group{-webkit-transform:translateZ(0);transform:translateZ(0);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.jupyter-wrapper .bp3-control-group>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-control-group>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-control-group .bp3-button,.jupyter-wrapper .bp3-control-group .bp3-html-select,.jupyter-wrapper .bp3-control-group .bp3-input,.jupyter-wrapper .bp3-control-group .bp3-select{position:relative}.jupyter-wrapper .bp3-control-group .bp3-input{border-radius:inherit;z-index:2}.jupyter-wrapper .bp3-control-group .bp3-input:focus{border-radius:3px;z-index:14}.jupyter-wrapper .bp3-control-group .bp3-input[class*=bp3-intent]{z-index:13}.jupyter-wrapper .bp3-control-group .bp3-input[class*=bp3-intent]:focus{z-index:15}.jupyter-wrapper .bp3-control-group .bp3-input[readonly],.jupyter-wrapper .bp3-control-group .bp3-input:disabled,.jupyter-wrapper .bp3-control-group .bp3-input.bp3-disabled{z-index:1}.jupyter-wrapper .bp3-control-group .bp3-input-group[class*=bp3-intent] .bp3-input{z-index:13}.jupyter-wrapper .bp3-control-group .bp3-input-group[class*=bp3-intent] .bp3-input:focus{z-index:15}.jupyter-wrapper .bp3-control-group .bp3-button,.jupyter-wrapper .bp3-control-group .bp3-html-select select,.jupyter-wrapper .bp3-control-group .bp3-select select{-webkit-transform:translateZ(0);transform:translateZ(0);border-radius:inherit;z-index:4}.jupyter-wrapper .bp3-control-group .bp3-button:focus,.jupyter-wrapper .bp3-control-group .bp3-html-select select:focus,.jupyter-wrapper .bp3-control-group .bp3-select select:focus{z-index:5}.jupyter-wrapper .bp3-control-group .bp3-button:hover,.jupyter-wrapper .bp3-control-group .bp3-html-select select:hover,.jupyter-wrapper .bp3-control-group .bp3-select select:hover{z-index:6}.jupyter-wrapper .bp3-control-group .bp3-button:active,.jupyter-wrapper .bp3-control-group .bp3-html-select select:active,.jupyter-wrapper .bp3-control-group .bp3-select select:active{z-index:7}.jupyter-wrapper .bp3-control-group .bp3-button[readonly],.jupyter-wrapper .bp3-control-group .bp3-button:disabled,.jupyter-wrapper .bp3-control-group .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[readonly],.jupyter-wrapper .bp3-control-group .bp3-html-select select:disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[readonly],.jupyter-wrapper .bp3-control-group .bp3-select select:disabled,.jupyter-wrapper .bp3-control-group .bp3-select select.bp3-disabled{z-index:3}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent],.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent],.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]{z-index:9}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:focus,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:focus,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:focus{z-index:10}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:hover,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:hover,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:hover{z-index:11}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:active,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:active,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:active{z-index:12}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent].bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent].bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent].bp3-disabled{z-index:8}.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-icon,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-button,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-input-action{z-index:16}.jupyter-wrapper .bp3-control-group .bp3-select:after,.jupyter-wrapper .bp3-control-group .bp3-html-select:after,.jupyter-wrapper .bp3-control-group .bp3-select>.bp3-icon,.jupyter-wrapper .bp3-control-group .bp3-html-select>.bp3-icon{z-index:17}.jupyter-wrapper .bp3-control-group .bp3-select:focus-within{z-index:5}.jupyter-wrapper .bp3-control-group:not(.bp3-vertical)>*:not(.bp3-divider){margin-right:-1px}.jupyter-wrapper .bp3-control-group:not(.bp3-vertical)>.bp3-divider:not(:first-child){margin-left:6px}.jupyter-wrapper .bp3-dark .bp3-control-group:not(.bp3-vertical)>*:not(.bp3-divider){margin-right:0}.jupyter-wrapper .bp3-dark .bp3-control-group:not(.bp3-vertical)>.bp3-button+.bp3-button{margin-left:1px}.jupyter-wrapper .bp3-control-group .bp3-popover-wrapper,.jupyter-wrapper .bp3-control-group .bp3-popover-target{border-radius:inherit}.jupyter-wrapper .bp3-control-group>:first-child{border-radius:3px 0 0 3px}.jupyter-wrapper .bp3-control-group>:last-child{border-radius:0 3px 3px 0;margin-right:0}.jupyter-wrapper .bp3-control-group>:only-child{border-radius:3px;margin-right:0}.jupyter-wrapper .bp3-control-group .bp3-input-group .bp3-button{border-radius:3px}.jupyter-wrapper .bp3-control-group .bp3-numeric-input:not(:first-child) .bp3-input-group{border-bottom-left-radius:0;border-top-left-radius:0}.jupyter-wrapper .bp3-control-group.bp3-fill{width:100%}.jupyter-wrapper .bp3-control-group>.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-control-group.bp3-fill>*:not(.bp3-fixed){-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-control-group.bp3-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-control-group.bp3-vertical>*{margin-top:-1px}.jupyter-wrapper .bp3-control-group.bp3-vertical>:first-child{border-radius:3px 3px 0 0;margin-top:0}.jupyter-wrapper .bp3-control-group.bp3-vertical>:last-child{border-radius:0 0 3px 3px}.jupyter-wrapper .bp3-control{cursor:pointer;display:block;margin-bottom:10px;position:relative;text-transform:none}.jupyter-wrapper .bp3-control input:checked~.bp3-control-indicator{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-control:hover input:checked~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-control input:not(:disabled):active:checked~.bp3-control-indicator{background:#0e5a8a;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control input:disabled:checked~.bp3-control-indicator{background:rgba(19,124,189,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-control input:checked~.bp3-control-indicator{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control:hover input:checked~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control input:not(:disabled):active:checked~.bp3-control-indicator{background-color:#0e5a8a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control input:disabled:checked~.bp3-control-indicator{background:rgba(14,90,138,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-control:not(.bp3-align-right){padding-left:26px}.jupyter-wrapper .bp3-control:not(.bp3-align-right) .bp3-control-indicator{margin-left:-26px}.jupyter-wrapper .bp3-control.bp3-align-right{padding-right:26px}.jupyter-wrapper .bp3-control.bp3-align-right .bp3-control-indicator{margin-right:-26px}.jupyter-wrapper .bp3-control.bp3-disabled{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-control.bp3-inline{display:inline-block;margin-right:20px}.jupyter-wrapper .bp3-control input{left:0;opacity:0;position:absolute;top:0;z-index:-1}.jupyter-wrapper .bp3-control .bp3-control-indicator{background-clip:padding-box;background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));border:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;cursor:pointer;display:inline-block;font-size:16px;height:1em;margin-right:10px;margin-top:-3px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;width:1em}.jupyter-wrapper .bp3-control .bp3-control-indicator:before{content:\"\";display:block;height:1em;width:1em}.jupyter-wrapper .bp3-control:hover .bp3-control-indicator{background-color:#ebf1f5}.jupyter-wrapper .bp3-control input:not(:disabled):active~.bp3-control-indicator{background:#d8e1e8;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control input:disabled~.bp3-control-indicator{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;cursor:not-allowed}.jupyter-wrapper .bp3-control input:focus~.bp3-control-indicator{outline:rgba(19,124,189,.6) auto 2px;outline-offset:2px;-moz-outline-radius:6px}.jupyter-wrapper .bp3-control.bp3-align-right .bp3-control-indicator{float:right;margin-left:10px;margin-top:1px}.jupyter-wrapper .bp3-control.bp3-large{font-size:16px}.jupyter-wrapper .bp3-control.bp3-large:not(.bp3-align-right){padding-left:30px}.jupyter-wrapper .bp3-control.bp3-large:not(.bp3-align-right) .bp3-control-indicator{margin-left:-30px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right{padding-right:30px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right .bp3-control-indicator{margin-right:-30px}.jupyter-wrapper .bp3-control.bp3-large .bp3-control-indicator{font-size:20px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right .bp3-control-indicator{margin-top:0}.jupyter-wrapper .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-control.bp3-checkbox:hover input:indeterminate~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-control.bp3-checkbox input:not(:disabled):active:indeterminate~.bp3-control-indicator{background:#0e5a8a;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{background:rgba(19,124,189,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox:hover input:indeterminate~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:not(:disabled):active:indeterminate~.bp3-control-indicator{background-color:#0e5a8a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{background:rgba(14,90,138,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-control.bp3-checkbox .bp3-control-indicator{border-radius:3px}.jupyter-wrapper .bp3-control.bp3-checkbox input:checked~.bp3-control-indicator:before{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='white'/%3e%3c/svg%3e\")}.jupyter-wrapper .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator:before{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 7H5c-.55 0-1 .45-1 1s.45 1 1 1h6c.55 0 1-.45 1-1s-.45-1-1-1z' fill='white'/%3e%3c/svg%3e\")}.jupyter-wrapper .bp3-control.bp3-radio .bp3-control-indicator{border-radius:50%}.jupyter-wrapper .bp3-control.bp3-radio input:checked~.bp3-control-indicator:before{background-image:radial-gradient(#ffffff,#ffffff 28%,transparent 32%)}.jupyter-wrapper .bp3-control.bp3-radio input:checked:disabled~.bp3-control-indicator:before{opacity:.5}.jupyter-wrapper .bp3-control.bp3-radio input:focus~.bp3-control-indicator{-moz-outline-radius:16px}.jupyter-wrapper .bp3-control.bp3-switch input~.bp3-control-indicator{background:rgba(167,182,194,.5)}.jupyter-wrapper .bp3-control.bp3-switch:hover input~.bp3-control-indicator{background:rgba(115,134,148,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:not(:disabled):active~.bp3-control-indicator{background:rgba(92,112,128,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:disabled~.bp3-control-indicator{background:rgba(206,217,224,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:disabled~.bp3-control-indicator:before{background:rgba(255,255,255,.8)}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator{background:#137cbd}.jupyter-wrapper .bp3-control.bp3-switch:hover input:checked~.bp3-control-indicator{background:#106ba3}.jupyter-wrapper .bp3-control.bp3-switch input:checked:not(:disabled):active~.bp3-control-indicator{background:#0e5a8a}.jupyter-wrapper .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator{background:rgba(19,124,189,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator:before{background:rgba(255,255,255,.8)}.jupyter-wrapper .bp3-control.bp3-switch:not(.bp3-align-right){padding-left:38px}.jupyter-wrapper .bp3-control.bp3-switch:not(.bp3-align-right) .bp3-control-indicator{margin-left:-38px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-align-right{padding-right:38px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-align-right .bp3-control-indicator{margin-right:-38px}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator{border:none;border-radius:1.75em;-webkit-box-shadow:none!important;box-shadow:none!important;min-width:1.75em;-webkit-transition:background-color .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9);width:auto}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator:before{background:#ffffff;border-radius:50%;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;height:calc(1em - 4px);left:0;margin:2px;position:absolute;-webkit-transition:left .1s cubic-bezier(.4,1,.75,.9);transition:left .1s cubic-bezier(.4,1,.75,.9);width:calc(1em - 4px)}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator:before{left:calc(100% - 1em)}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large:not(.bp3-align-right){padding-left:45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large:not(.bp3-align-right) .bp3-control-indicator{margin-left:-45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large.bp3-align-right{padding-right:45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large.bp3-align-right .bp3-control-indicator{margin-right:-45px}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input~.bp3-control-indicator{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch:hover input~.bp3-control-indicator{background:rgba(16,22,26,.7)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:not(:disabled):active~.bp3-control-indicator{background:rgba(16,22,26,.9)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:disabled~.bp3-control-indicator{background:rgba(57,75,89,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:disabled~.bp3-control-indicator:before{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked~.bp3-control-indicator{background:#137cbd}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch:hover input:checked~.bp3-control-indicator{background:#106ba3}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:not(:disabled):active~.bp3-control-indicator{background:#0e5a8a}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator{background:rgba(14,90,138,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator:before{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch .bp3-control-indicator:before{background:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked~.bp3-control-indicator:before{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-control.bp3-switch .bp3-switch-inner-text{font-size:.7em;text-align:center}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator-child:first-child{line-height:0;margin-left:.5em;margin-right:1.2em;visibility:hidden}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator-child:last-child{line-height:1em;margin-left:1.2em;margin-right:.5em;visibility:visible}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator .bp3-control-indicator-child:first-child{line-height:1em;visibility:visible}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator .bp3-control-indicator-child:last-child{line-height:0;visibility:hidden}.jupyter-wrapper .bp3-dark .bp3-control{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-control.bp3-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-control .bp3-control-indicator{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control:hover .bp3-control-indicator{background-color:#30404d}.jupyter-wrapper .bp3-dark .bp3-control input:not(:disabled):active~.bp3-control-indicator{background:#202b33;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control input:disabled~.bp3-control-indicator{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:checked~.bp3-control-indicator,.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{color:#a7b6c299}.jupyter-wrapper .bp3-file-input{cursor:pointer;display:inline-block;height:30px;position:relative}.jupyter-wrapper .bp3-file-input input{margin:0;min-width:200px;opacity:0}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active:hover,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input:after,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-file-input.bp3-file-input-has-selection .bp3-file-upload-input{color:#182026}.jupyter-wrapper .bp3-dark .bp3-file-input.bp3-file-input-has-selection .bp3-file-upload-input{color:#f5f8fa}.jupyter-wrapper .bp3-file-input.bp3-fill{width:100%}.jupyter-wrapper .bp3-file-input.bp3-large,.jupyter-wrapper .bp3-large .bp3-file-input{height:40px}.jupyter-wrapper .bp3-file-input .bp3-file-upload-input-custom-text:after{content:attr(bp3-button-text)}.jupyter-wrapper .bp3-file-upload-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff;border:none;border-radius:3px;-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33;color:#182026;font-size:14px;font-weight:400;height:30px;line-height:30px;outline:none;padding:0 80px 0 10px;-webkit-transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;color:#5c708099;left:0;position:absolute;right:0;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-file-upload-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input:focus,.jupyter-wrapper .bp3-file-upload-input.bp3-active{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-file-upload-input[type=search],.jupyter-wrapper .bp3-file-upload-input.bp3-round{border-radius:30px;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:10px}.jupyter-wrapper .bp3-file-upload-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-file-upload-input:disabled,.jupyter-wrapper .bp3-file-upload-input.bp3-disabled{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-file-upload-input:after{background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;min-height:24px;min-width:24px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;border-radius:3px;content:\"Browse\";line-height:24px;margin:3px;position:absolute;right:0;text-align:center;top:0;width:70px}.jupyter-wrapper .bp3-file-upload-input:after:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-file-upload-input:after .bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-file-upload-input:after:disabled,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-file-upload-input:after:disabled .bp3-active,.jupyter-wrapper .bp3-file-upload-input:after:disabled .bp3-active:hover,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled.bp3-active,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-file-upload-input:hover:after{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-file-upload-input:active:after{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-large .bp3-file-upload-input{font-size:16px;height:40px;line-height:40px;padding-right:95px}.jupyter-wrapper .bp3-large .bp3-file-upload-input[type=search],.jupyter-wrapper .bp3-large .bp3-file-upload-input.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-large .bp3-file-upload-input:after{min-height:30px;min-width:30px;line-height:30px;margin:5px;width:85px}.jupyter-wrapper .bp3-dark .bp3-file-upload-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:disabled,.jupyter-wrapper .bp3-dark .bp3-file-upload-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:hover,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:disabled,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:disabled .bp3-active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:hover:after{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:active:after{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-file-upload-input:after{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 0 15px}.jupyter-wrapper .bp3-form-group label.bp3-label{margin-bottom:5px}.jupyter-wrapper .bp3-form-group .bp3-control{margin-top:7px}.jupyter-wrapper .bp3-form-group .bp3-form-helper-text{color:#5c7080;font-size:12px;margin-top:5px}.jupyter-wrapper .bp3-form-group.bp3-intent-primary .bp3-form-helper-text{color:#106ba3}.jupyter-wrapper .bp3-form-group.bp3-intent-success .bp3-form-helper-text{color:#0d8050}.jupyter-wrapper .bp3-form-group.bp3-intent-warning .bp3-form-helper-text{color:#bf7326}.jupyter-wrapper .bp3-form-group.bp3-intent-danger .bp3-form-helper-text{color:#c23030}.jupyter-wrapper .bp3-form-group.bp3-inline{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.jupyter-wrapper .bp3-form-group.bp3-inline.bp3-large label.bp3-label{line-height:40px;margin:0 10px 0 0}.jupyter-wrapper .bp3-form-group.bp3-inline label.bp3-label{line-height:30px;margin:0 10px 0 0}.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-label,.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-text-muted,.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-form-helper-text{color:#5c708099!important}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-primary .bp3-form-helper-text{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-success .bp3-form-helper-text{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-warning .bp3-form-helper-text{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-danger .bp3-form-helper-text{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-form-group .bp3-form-helper-text{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-label,.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-text-muted,.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-form-helper-text{color:#a7b6c299!important}.jupyter-wrapper .bp3-input-group{display:block;position:relative}.jupyter-wrapper .bp3-input-group .bp3-input{position:relative;width:100%}.jupyter-wrapper .bp3-input-group .bp3-input:not(:first-child){padding-left:30px}.jupyter-wrapper .bp3-input-group .bp3-input:not(:last-child){padding-right:30px}.jupyter-wrapper .bp3-input-group .bp3-input-action,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-input-group>.bp3-button,.jupyter-wrapper .bp3-input-group>.bp3-icon{position:absolute;top:0}.jupyter-wrapper .bp3-input-group .bp3-input-action:first-child,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container:first-child,.jupyter-wrapper .bp3-input-group>.bp3-button:first-child,.jupyter-wrapper .bp3-input-group>.bp3-icon:first-child{left:0}.jupyter-wrapper .bp3-input-group .bp3-input-action:last-child,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container:last-child,.jupyter-wrapper .bp3-input-group>.bp3-button:last-child,.jupyter-wrapper .bp3-input-group>.bp3-icon:last-child{right:0}.jupyter-wrapper .bp3-input-group .bp3-button{min-height:24px;min-width:24px;margin:3px;padding:0 7px}.jupyter-wrapper .bp3-input-group .bp3-button:empty{padding:0}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-input-group>.bp3-icon{z-index:1}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group>.bp3-icon{color:#5c7080}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon:empty,.jupyter-wrapper .bp3-input-group>.bp3-icon:empty{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group>.bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input-action>.bp3-spinner{margin:7px}.jupyter-wrapper .bp3-input-group .bp3-tag{margin:5px}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus),.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus){color:#5c7080}.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus),.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus){color:#a7b6c2}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-large,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled{color:#5c708099!important}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon-large,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon-large{color:#5c708099!important}.jupyter-wrapper .bp3-input-group.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-input-group.bp3-disabled .bp3-icon{color:#5c708099}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-button{min-height:30px;min-width:30px;margin:5px}.jupyter-wrapper .bp3-input-group.bp3-large>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-large>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input-action>.bp3-spinner{margin:12px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input{font-size:16px;height:40px;line-height:40px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input[type=search],.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input:not(:first-child){padding-left:40px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input:not(:last-child){padding-right:40px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-button,.jupyter-wrapper .bp3-input-group.bp3-small .bp3-tag{min-height:20px;min-width:20px;margin:2px}.jupyter-wrapper .bp3-input-group.bp3-small>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-small>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input-action>.bp3-spinner{margin:4px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input{font-size:12px;height:24px;line-height:24px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input[type=search],.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input.bp3-round{padding:0 12px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input:not(:first-child){padding-left:24px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input:not(:last-child){padding-right:24px}.jupyter-wrapper .bp3-input-group.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:100%}.jupyter-wrapper .bp3-input-group.bp3-round .bp3-button,.jupyter-wrapper .bp3-input-group.bp3-round .bp3-input,.jupyter-wrapper .bp3-input-group.bp3-round .bp3-tag{border-radius:30px}.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-disabled .bp3-icon{color:#a7b6c299}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-primary>.bp3-icon{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-primary>.bp3-icon{color:#48aff0}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-success>.bp3-icon{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-success>.bp3-icon{color:#3dcc91}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-warning>.bp3-icon{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-warning>.bp3-icon{color:#ffb366}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-danger>.bp3-icon{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-danger>.bp3-icon{color:#ff7373}.jupyter-wrapper .bp3-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff;border:none;border-radius:3px;-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33;color:#182026;font-size:14px;font-weight:400;height:30px;line-height:30px;outline:none;padding:0 10px;-webkit-transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);vertical-align:middle}.jupyter-wrapper .bp3-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input:focus,.jupyter-wrapper .bp3-input.bp3-active{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input[type=search],.jupyter-wrapper .bp3-input.bp3-round{border-radius:30px;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:10px}.jupyter-wrapper .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-input:disabled,.jupyter-wrapper .bp3-input.bp3-disabled{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-input.bp3-large{font-size:16px;height:40px;line-height:40px}.jupyter-wrapper .bp3-input.bp3-large[type=search],.jupyter-wrapper .bp3-input.bp3-large.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-input.bp3-small{font-size:12px;height:24px;line-height:24px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-input.bp3-small[type=search],.jupyter-wrapper .bp3-input.bp3-small.bp3-round{padding:0 12px}.jupyter-wrapper .bp3-input.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:100%}.jupyter-wrapper .bp3-dark .bp3-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-input.bp3-intent-primary{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-primary:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-primary[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-input.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-input.bp3-intent-primary.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-success{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-success:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-success[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-input.bp3-intent-success:disabled,.jupyter-wrapper .bp3-input.bp3-intent-success.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #0f996000,0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #0f9960,0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-warning{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-warning:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-warning[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-input.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-input.bp3-intent-warning.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #d9822b00,0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #d9822b,0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-danger{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-danger:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-danger[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-input.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-input.bp3-intent-danger.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #db373700,0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #db3737,0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input::-ms-clear{display:none}.jupyter-wrapper textarea.bp3-input{max-width:100%;padding:10px}.jupyter-wrapper textarea.bp3-input,.jupyter-wrapper textarea.bp3-input.bp3-large,.jupyter-wrapper textarea.bp3-input.bp3-small{height:auto;line-height:inherit}.jupyter-wrapper textarea.bp3-input.bp3-small{padding:8px}.jupyter-wrapper .bp3-dark textarea.bp3-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark textarea.bp3-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark textarea.bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark textarea.bp3-input:disabled,.jupyter-wrapper .bp3-dark textarea.bp3-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper label.bp3-label{display:block;margin-bottom:15px;margin-top:0}.jupyter-wrapper label.bp3-label .bp3-html-select,.jupyter-wrapper label.bp3-label .bp3-input,.jupyter-wrapper label.bp3-label .bp3-select,.jupyter-wrapper label.bp3-label .bp3-slider,.jupyter-wrapper label.bp3-label .bp3-popover-wrapper{display:block;margin-top:5px;text-transform:none}.jupyter-wrapper label.bp3-label .bp3-button-group{margin-top:5px}.jupyter-wrapper label.bp3-label .bp3-select select,.jupyter-wrapper label.bp3-label .bp3-html-select select{font-weight:400;vertical-align:top;width:100%}.jupyter-wrapper label.bp3-label.bp3-disabled,.jupyter-wrapper label.bp3-label.bp3-disabled .bp3-text-muted{color:#5c708099}.jupyter-wrapper label.bp3-label.bp3-inline{line-height:30px}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-html-select,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input-group,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-select,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-popover-wrapper{display:inline-block;margin:0 0 0 5px;vertical-align:top}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-button-group{margin:0 0 0 5px}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input-group .bp3-input{margin-left:0}.jupyter-wrapper label.bp3-label.bp3-inline.bp3-large{line-height:40px}.jupyter-wrapper label.bp3-label:not(.bp3-inline) .bp3-popover-target{display:block}.jupyter-wrapper .bp3-dark label.bp3-label{color:#f5f8fa}.jupyter-wrapper .bp3-dark label.bp3-label.bp3-disabled,.jupyter-wrapper .bp3-dark label.bp3-label.bp3-disabled .bp3-text-muted{color:#a7b6c299}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button{-webkit-box-flex:1;-ms-flex:1 1 14px;flex:1 1 14px;min-height:0;padding:0;width:30px}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button:first-child{border-radius:0 3px 0 0}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button:last-child{border-radius:0 0 3px}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical:first-child>.bp3-button:first-child{border-radius:3px 0 0}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical:first-child>.bp3-button:last-child{border-radius:0 0 0 3px}.jupyter-wrapper .bp3-numeric-input.bp3-large .bp3-button-group.bp3-vertical>.bp3-button{width:40px}.jupyter-wrapper form{display:block}.jupyter-wrapper .bp3-html-select select,.jupyter-wrapper .bp3-select select{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;cursor:pointer;font-size:14px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:left;vertical-align:middle;background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;-moz-appearance:none;-webkit-appearance:none;border-radius:3px;height:30px;padding:0 25px 0 10px;width:100%}.jupyter-wrapper .bp3-html-select select>*,.jupyter-wrapper .bp3-select select>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-html-select select>.bp3-fill,.jupyter-wrapper .bp3-select select>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-html-select select:before,.jupyter-wrapper .bp3-select select:before,.jupyter-wrapper .bp3-html-select select>*,.jupyter-wrapper .bp3-select select>*{margin-right:7px}.jupyter-wrapper .bp3-html-select select:empty:before,.jupyter-wrapper .bp3-select select:empty:before,.jupyter-wrapper .bp3-html-select select>:last-child,.jupyter-wrapper .bp3-select select>:last-child{margin-right:0}.jupyter-wrapper .bp3-html-select select:hover,.jupyter-wrapper .bp3-select select:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-html-select select:active,.jupyter-wrapper .bp3-select select:active,.jupyter-wrapper .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-select select.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-html-select select:disabled,.jupyter-wrapper .bp3-select select:disabled,.jupyter-wrapper .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-select select.bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-html-select select:disabled.bp3-active,.jupyter-wrapper .bp3-select select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select select:disabled.bp3-active:hover,.jupyter-wrapper .bp3-select select:disabled.bp3-active:hover,.jupyter-wrapper .bp3-html-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select select.bp3-disabled.bp3-active:hover,.jupyter-wrapper .bp3-select select.bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-html-select.bp3-minimal select,.jupyter-wrapper .bp3-select.bp3-minimal select{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal select:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-html-select.bp3-large select,.jupyter-wrapper .bp3-select.bp3-large select{font-size:16px;height:40px;padding-right:35px}.jupyter-wrapper .bp3-dark .bp3-html-select select,.jupyter-wrapper .bp3-dark .bp3-select select{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select select:hover,.jupyter-wrapper .bp3-dark .bp3-select select:hover,.jupyter-wrapper .bp3-dark .bp3-html-select select:active,.jupyter-wrapper .bp3-dark .bp3-select select:active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select select:hover,.jupyter-wrapper .bp3-dark .bp3-select select:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-html-select select:active,.jupyter-wrapper .bp3-dark .bp3-select select:active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-html-select select:disabled,.jupyter-wrapper .bp3-dark .bp3-select select:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-html-select select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-html-select select .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-dark .bp3-select select .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-html-select select:disabled,.jupyter-wrapper .bp3-select select:disabled{background-color:#ced9e080;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-select .bp3-icon,.jupyter-wrapper .bp3-select:after{color:#5c7080;pointer-events:none;position:absolute;right:7px;top:7px}.jupyter-wrapper .bp3-html-select .bp3-disabled.bp3-icon,.jupyter-wrapper .bp3-select .bp3-disabled.bp3-icon,.jupyter-wrapper .bp3-disabled.bp3-select:after{color:#5c708099}.jupyter-wrapper .bp3-html-select,.jupyter-wrapper .bp3-select{display:inline-block;letter-spacing:normal;position:relative;vertical-align:middle}.jupyter-wrapper .bp3-html-select select::-ms-expand,.jupyter-wrapper .bp3-select select::-ms-expand{display:none}.jupyter-wrapper .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-select .bp3-icon{color:#5c7080}.jupyter-wrapper .bp3-html-select .bp3-icon:hover,.jupyter-wrapper .bp3-select .bp3-icon:hover{color:#182026}.jupyter-wrapper .bp3-dark .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-select .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-html-select .bp3-icon:hover,.jupyter-wrapper .bp3-dark .bp3-select .bp3-icon:hover{color:#f5f8fa}.jupyter-wrapper .bp3-html-select.bp3-large:after,.jupyter-wrapper .bp3-html-select.bp3-large .bp3-icon,.jupyter-wrapper .bp3-select.bp3-large:after,.jupyter-wrapper .bp3-select.bp3-large .bp3-icon{right:12px;top:12px}.jupyter-wrapper .bp3-html-select.bp3-fill,.jupyter-wrapper .bp3-html-select.bp3-fill select,.jupyter-wrapper .bp3-select.bp3-fill,.jupyter-wrapper .bp3-select.bp3-fill select{width:100%}.jupyter-wrapper .bp3-dark .bp3-html-select option,.jupyter-wrapper .bp3-dark .bp3-select option{background-color:#30404d;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select option:disabled,.jupyter-wrapper .bp3-dark .bp3-select option:disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-html-select:after,.jupyter-wrapper .bp3-dark .bp3-select:after{color:#a7b6c2}.jupyter-wrapper .bp3-select:after{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;content:\"\ue6c6\"}.jupyter-wrapper .bp3-running-text table,.jupyter-wrapper table.bp3-html-table{border-spacing:0;font-size:14px}.jupyter-wrapper .bp3-running-text table th,.jupyter-wrapper table.bp3-html-table th,.jupyter-wrapper .bp3-running-text table td,.jupyter-wrapper table.bp3-html-table td{padding:11px;text-align:left;vertical-align:top}.jupyter-wrapper .bp3-running-text table th,.jupyter-wrapper table.bp3-html-table th{color:#182026;font-weight:600}.jupyter-wrapper .bp3-running-text table td,.jupyter-wrapper table.bp3-html-table td{color:#182026}.jupyter-wrapper .bp3-running-text table tbody tr:first-child th,.jupyter-wrapper table.bp3-html-table tbody tr:first-child th,.jupyter-wrapper .bp3-running-text table tbody tr:first-child td,.jupyter-wrapper table.bp3-html-table tbody tr:first-child td,.jupyter-wrapper .bp3-running-text table tfoot tr:first-child th,.jupyter-wrapper table.bp3-html-table tfoot tr:first-child th,.jupyter-wrapper .bp3-running-text table tfoot tr:first-child td,.jupyter-wrapper table.bp3-html-table tfoot tr:first-child td{-webkit-box-shadow:inset 0 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26}.jupyter-wrapper .bp3-dark .bp3-running-text table th,.jupyter-wrapper .bp3-running-text .bp3-dark table th,.jupyter-wrapper .bp3-dark table.bp3-html-table th,.jupyter-wrapper .bp3-dark .bp3-running-text table td,.jupyter-wrapper .bp3-running-text .bp3-dark table td,.jupyter-wrapper .bp3-dark table.bp3-html-table td{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-running-text table tbody tr:first-child th,.jupyter-wrapper .bp3-running-text .bp3-dark table tbody tr:first-child th,.jupyter-wrapper .bp3-dark table.bp3-html-table tbody tr:first-child th,.jupyter-wrapper .bp3-dark .bp3-running-text table tbody tr:first-child td,.jupyter-wrapper .bp3-running-text .bp3-dark table tbody tr:first-child td,.jupyter-wrapper .bp3-dark table.bp3-html-table tbody tr:first-child td,.jupyter-wrapper .bp3-dark .bp3-running-text table tfoot tr:first-child th,.jupyter-wrapper .bp3-running-text .bp3-dark table tfoot tr:first-child th,.jupyter-wrapper .bp3-dark table.bp3-html-table tfoot tr:first-child th,.jupyter-wrapper .bp3-dark .bp3-running-text table tfoot tr:first-child td,.jupyter-wrapper .bp3-running-text .bp3-dark table tfoot tr:first-child td,.jupyter-wrapper .bp3-dark table.bp3-html-table tfoot tr:first-child td{-webkit-box-shadow:inset 0 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 0 1px #ffffff26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-condensed th,.jupyter-wrapper table.bp3-html-table.bp3-html-table-condensed td,.jupyter-wrapper table.bp3-html-table.bp3-small th,.jupyter-wrapper table.bp3-html-table.bp3-small td{padding-bottom:6px;padding-top:6px}.jupyter-wrapper table.bp3-html-table.bp3-html-table-striped tbody tr:nth-child(odd) td{background:rgba(191,204,214,.15)}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered th:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 0 #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tbody tr td,.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tfoot tr td{-webkit-box-shadow:inset 0 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tbody tr td:not(:first-child),.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tfoot tr td:not(:first-child){-webkit-box-shadow:inset 1px 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 1px #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 0 #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-interactive tbody tr:hover td{background-color:#bfccd64d;cursor:pointer}.jupyter-wrapper table.bp3-html-table.bp3-interactive tbody tr:active td{background-color:#bfccd666}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-striped tbody tr:nth-child(odd) td{background:rgba(92,112,128,.15)}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered th:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 0 #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tbody tr td,.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tfoot tr td{-webkit-box-shadow:inset 0 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 0 1px #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tbody tr td:not(:first-child),.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tfoot tr td:not(:first-child){-webkit-box-shadow:inset 1px 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 1px #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td{-webkit-box-shadow:inset 1px 0 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 0 #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td:first-child{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-interactive tbody tr:hover td{background-color:#5c70804d;cursor:pointer}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-interactive tbody tr:active td{background-color:#5c708066}.jupyter-wrapper .bp3-key-combo{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.jupyter-wrapper .bp3-key-combo>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-key-combo>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-key-combo:before,.jupyter-wrapper .bp3-key-combo>*{margin-right:5px}.jupyter-wrapper .bp3-key-combo:empty:before,.jupyter-wrapper .bp3-key-combo>:last-child{margin-right:0}.jupyter-wrapper .bp3-hotkey-dialog{padding-bottom:0;top:40px}.jupyter-wrapper .bp3-hotkey-dialog .bp3-dialog-body{margin:0;padding:0}.jupyter-wrapper .bp3-hotkey-dialog .bp3-hotkey-label{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.jupyter-wrapper .bp3-hotkey-column{margin:auto;max-height:80vh;overflow-y:auto;padding:30px}.jupyter-wrapper .bp3-hotkey-column .bp3-heading{margin-bottom:20px}.jupyter-wrapper .bp3-hotkey-column .bp3-heading:not(:first-child){margin-top:40px}.jupyter-wrapper .bp3-hotkey{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin-left:0;margin-right:0}.jupyter-wrapper .bp3-hotkey:not(:last-child){margin-bottom:10px}.jupyter-wrapper .bp3-icon{display:inline-block;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;vertical-align:text-bottom}.jupyter-wrapper .bp3-icon:not(:empty):before{content:\"\"!important;content:unset!important}.jupyter-wrapper .bp3-icon>svg{display:block}.jupyter-wrapper .bp3-icon>svg:not([fill]){fill:currentColor}.jupyter-wrapper .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-icon-large.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-icon-large.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-icon-large.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-icon-large.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-danger{color:#ff7373}.jupyter-wrapper span.bp3-icon-standard{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block}.jupyter-wrapper span.bp3-icon-large{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block}.jupyter-wrapper span.bp3-icon:empty{font-family:Icons20;font-size:inherit;font-style:normal;font-weight:400;line-height:1}.jupyter-wrapper span.bp3-icon:empty:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.jupyter-wrapper .bp3-icon-add:before{content:\"\ue63e\"}.jupyter-wrapper .bp3-icon-add-column-left:before{content:\"\ue6f9\"}.jupyter-wrapper .bp3-icon-add-column-right:before{content:\"\ue6fa\"}.jupyter-wrapper .bp3-icon-add-row-bottom:before{content:\"\ue6f8\"}.jupyter-wrapper .bp3-icon-add-row-top:before{content:\"\ue6f7\"}.jupyter-wrapper .bp3-icon-add-to-artifact:before{content:\"\ue67c\"}.jupyter-wrapper .bp3-icon-add-to-folder:before{content:\"\ue6d2\"}.jupyter-wrapper .bp3-icon-airplane:before{content:\"\ue74b\"}.jupyter-wrapper .bp3-icon-align-center:before{content:\"\ue603\"}.jupyter-wrapper .bp3-icon-align-justify:before{content:\"\ue605\"}.jupyter-wrapper .bp3-icon-align-left:before{content:\"\ue602\"}.jupyter-wrapper .bp3-icon-align-right:before{content:\"\ue604\"}.jupyter-wrapper .bp3-icon-alignment-bottom:before{content:\"\ue727\"}.jupyter-wrapper .bp3-icon-alignment-horizontal-center:before{content:\"\ue726\"}.jupyter-wrapper .bp3-icon-alignment-left:before{content:\"\ue722\"}.jupyter-wrapper .bp3-icon-alignment-right:before{content:\"\ue724\"}.jupyter-wrapper .bp3-icon-alignment-top:before{content:\"\ue725\"}.jupyter-wrapper .bp3-icon-alignment-vertical-center:before{content:\"\ue723\"}.jupyter-wrapper .bp3-icon-annotation:before{content:\"\ue6f0\"}.jupyter-wrapper .bp3-icon-application:before{content:\"\ue735\"}.jupyter-wrapper .bp3-icon-applications:before{content:\"\ue621\"}.jupyter-wrapper .bp3-icon-archive:before{content:\"\ue907\"}.jupyter-wrapper .bp3-icon-arrow-bottom-left:before{content:\"\u2199\"}.jupyter-wrapper .bp3-icon-arrow-bottom-right:before{content:\"\u2198\"}.jupyter-wrapper .bp3-icon-arrow-down:before{content:\"\u2193\"}.jupyter-wrapper .bp3-icon-arrow-left:before{content:\"\u2190\"}.jupyter-wrapper .bp3-icon-arrow-right:before{content:\"\u2192\"}.jupyter-wrapper .bp3-icon-arrow-top-left:before{content:\"\u2196\"}.jupyter-wrapper .bp3-icon-arrow-top-right:before{content:\"\u2197\"}.jupyter-wrapper .bp3-icon-arrow-up:before{content:\"\u2191\"}.jupyter-wrapper .bp3-icon-arrows-horizontal:before{content:\"\u2194\"}.jupyter-wrapper .bp3-icon-arrows-vertical:before{content:\"\u2195\"}.jupyter-wrapper .bp3-icon-asterisk:before{content:\"*\"}.jupyter-wrapper .bp3-icon-automatic-updates:before{content:\"\ue65f\"}.jupyter-wrapper .bp3-icon-badge:before{content:\"\ue6e3\"}.jupyter-wrapper .bp3-icon-ban-circle:before{content:\"\ue69d\"}.jupyter-wrapper .bp3-icon-bank-account:before{content:\"\ue76f\"}.jupyter-wrapper .bp3-icon-barcode:before{content:\"\ue676\"}.jupyter-wrapper .bp3-icon-blank:before{content:\"\ue900\"}.jupyter-wrapper .bp3-icon-blocked-person:before{content:\"\ue768\"}.jupyter-wrapper .bp3-icon-bold:before{content:\"\ue606\"}.jupyter-wrapper .bp3-icon-book:before{content:\"\ue6b8\"}.jupyter-wrapper .bp3-icon-bookmark:before{content:\"\ue61a\"}.jupyter-wrapper .bp3-icon-box:before{content:\"\ue6bf\"}.jupyter-wrapper .bp3-icon-briefcase:before{content:\"\ue674\"}.jupyter-wrapper .bp3-icon-bring-data:before{content:\"\ue90a\"}.jupyter-wrapper .bp3-icon-build:before{content:\"\ue72d\"}.jupyter-wrapper .bp3-icon-calculator:before{content:\"\ue70b\"}.jupyter-wrapper .bp3-icon-calendar:before{content:\"\ue62b\"}.jupyter-wrapper .bp3-icon-camera:before{content:\"\ue69e\"}.jupyter-wrapper .bp3-icon-caret-down:before{content:\"\u2304\"}.jupyter-wrapper .bp3-icon-caret-left:before{content:\"\u2329\"}.jupyter-wrapper .bp3-icon-caret-right:before{content:\"\u232a\"}.jupyter-wrapper .bp3-icon-caret-up:before{content:\"\u2303\"}.jupyter-wrapper .bp3-icon-cell-tower:before{content:\"\ue770\"}.jupyter-wrapper .bp3-icon-MKDOCS_changes:before{content:\"\ue623\"}.jupyter-wrapper .bp3-icon-chart:before{content:\"\ue67e\"}.jupyter-wrapper .bp3-icon-chat:before{content:\"\ue689\"}.jupyter-wrapper .bp3-icon-chevron-backward:before{content:\"\ue6df\"}.jupyter-wrapper .bp3-icon-chevron-down:before{content:\"\ue697\"}.jupyter-wrapper .bp3-icon-chevron-forward:before{content:\"\ue6e0\"}.jupyter-wrapper .bp3-icon-chevron-left:before{content:\"\ue694\"}.jupyter-wrapper .bp3-icon-chevron-right:before{content:\"\ue695\"}.jupyter-wrapper .bp3-icon-chevron-up:before{content:\"\ue696\"}.jupyter-wrapper .bp3-icon-circle:before{content:\"\ue66a\"}.jupyter-wrapper .bp3-icon-circle-arrow-down:before{content:\"\ue68e\"}.jupyter-wrapper .bp3-icon-circle-arrow-left:before{content:\"\ue68c\"}.jupyter-wrapper .bp3-icon-circle-arrow-right:before{content:\"\ue68b\"}.jupyter-wrapper .bp3-icon-circle-arrow-up:before{content:\"\ue68d\"}.jupyter-wrapper .bp3-icon-citation:before{content:\"\ue61b\"}.jupyter-wrapper .bp3-icon-clean:before{content:\"\ue7c5\"}.jupyter-wrapper .bp3-icon-clipboard:before{content:\"\ue61d\"}.jupyter-wrapper .bp3-icon-cloud:before{content:\"\u2601\"}.jupyter-wrapper .bp3-icon-cloud-download:before{content:\"\ue690\"}.jupyter-wrapper .bp3-icon-cloud-upload:before{content:\"\ue691\"}.jupyter-wrapper .bp3-icon-code:before{content:\"\ue661\"}.jupyter-wrapper .bp3-icon-code-block:before{content:\"\ue6c5\"}.jupyter-wrapper .bp3-icon-cog:before{content:\"\ue645\"}.jupyter-wrapper .bp3-icon-collapse-all:before{content:\"\ue763\"}.jupyter-wrapper .bp3-icon-column-layout:before{content:\"\ue6da\"}.jupyter-wrapper .bp3-icon-comment:before{content:\"\ue68a\"}.jupyter-wrapper .bp3-icon-comparison:before{content:\"\ue637\"}.jupyter-wrapper .bp3-icon-compass:before{content:\"\ue79c\"}.jupyter-wrapper .bp3-icon-compressed:before{content:\"\ue6c0\"}.jupyter-wrapper .bp3-icon-confirm:before{content:\"\ue639\"}.jupyter-wrapper .bp3-icon-console:before{content:\"\ue79b\"}.jupyter-wrapper .bp3-icon-contrast:before{content:\"\ue6cb\"}.jupyter-wrapper .bp3-icon-control:before{content:\"\ue67f\"}.jupyter-wrapper .bp3-icon-credit-card:before{content:\"\ue649\"}.jupyter-wrapper .bp3-icon-cross:before{content:\"\u2717\"}.jupyter-wrapper .bp3-icon-crown:before{content:\"\ue7b4\"}.jupyter-wrapper .bp3-icon-cube:before{content:\"\ue7c8\"}.jupyter-wrapper .bp3-icon-cube-add:before{content:\"\ue7c9\"}.jupyter-wrapper .bp3-icon-cube-remove:before{content:\"\ue7d0\"}.jupyter-wrapper .bp3-icon-curved-range-chart:before{content:\"\ue71b\"}.jupyter-wrapper .bp3-icon-cut:before{content:\"\ue6ef\"}.jupyter-wrapper .bp3-icon-dashboard:before{content:\"\ue751\"}.jupyter-wrapper .bp3-icon-data-lineage:before{content:\"\ue908\"}.jupyter-wrapper .bp3-icon-database:before{content:\"\ue683\"}.jupyter-wrapper .bp3-icon-delete:before{content:\"\ue644\"}.jupyter-wrapper .bp3-icon-delta:before{content:\"\u0394\"}.jupyter-wrapper .bp3-icon-derive-column:before{content:\"\ue739\"}.jupyter-wrapper .bp3-icon-desktop:before{content:\"\ue6af\"}.jupyter-wrapper .bp3-icon-diagnosis:before{content:\"\ue90d\"}.jupyter-wrapper .bp3-icon-diagram-tree:before{content:\"\ue7b3\"}.jupyter-wrapper .bp3-icon-direction-left:before{content:\"\ue681\"}.jupyter-wrapper .bp3-icon-direction-right:before{content:\"\ue682\"}.jupyter-wrapper .bp3-icon-disable:before{content:\"\ue600\"}.jupyter-wrapper .bp3-icon-document:before{content:\"\ue630\"}.jupyter-wrapper .bp3-icon-document-open:before{content:\"\ue71e\"}.jupyter-wrapper .bp3-icon-document-share:before{content:\"\ue71f\"}.jupyter-wrapper .bp3-icon-dollar:before{content:\"$\"}.jupyter-wrapper .bp3-icon-dot:before{content:\"\u2022\"}.jupyter-wrapper .bp3-icon-double-caret-horizontal:before{content:\"\ue6c7\"}.jupyter-wrapper .bp3-icon-double-caret-vertical:before{content:\"\ue6c6\"}.jupyter-wrapper .bp3-icon-double-chevron-down:before{content:\"\ue703\"}.jupyter-wrapper .bp3-icon-double-chevron-left:before{content:\"\ue6ff\"}.jupyter-wrapper .bp3-icon-double-chevron-right:before{content:\"\ue701\"}.jupyter-wrapper .bp3-icon-double-chevron-up:before{content:\"\ue702\"}.jupyter-wrapper .bp3-icon-doughnut-chart:before{content:\"\ue6ce\"}.jupyter-wrapper .bp3-icon-download:before{content:\"\ue62f\"}.jupyter-wrapper .bp3-icon-drag-handle-horizontal:before{content:\"\ue716\"}.jupyter-wrapper .bp3-icon-drag-handle-vertical:before{content:\"\ue715\"}.jupyter-wrapper .bp3-icon-draw:before{content:\"\ue66b\"}.jupyter-wrapper .bp3-icon-drive-time:before{content:\"\ue615\"}.jupyter-wrapper .bp3-icon-duplicate:before{content:\"\ue69c\"}.jupyter-wrapper .bp3-icon-edit:before{content:\"\u270e\"}.jupyter-wrapper .bp3-icon-eject:before{content:\"\u23cf\"}.jupyter-wrapper .bp3-icon-endorsed:before{content:\"\ue75f\"}.jupyter-wrapper .bp3-icon-envelope:before{content:\"\u2709\"}.jupyter-wrapper .bp3-icon-equals:before{content:\"\ue7d9\"}.jupyter-wrapper .bp3-icon-eraser:before{content:\"\ue773\"}.jupyter-wrapper .bp3-icon-error:before{content:\"\ue648\"}.jupyter-wrapper .bp3-icon-euro:before{content:\"\u20ac\"}.jupyter-wrapper .bp3-icon-MKDOCS_exchange:before{content:\"\ue636\"}.jupyter-wrapper .bp3-icon-exclude-row:before{content:\"\ue6ea\"}.jupyter-wrapper .bp3-icon-expand-all:before{content:\"\ue764\"}.jupyter-wrapper .bp3-icon-export:before{content:\"\ue633\"}.jupyter-wrapper .bp3-icon-eye-off:before{content:\"\ue6cc\"}.jupyter-wrapper .bp3-icon-eye-on:before{content:\"\ue75a\"}.jupyter-wrapper .bp3-icon-eye-open:before{content:\"\ue66f\"}.jupyter-wrapper .bp3-icon-fast-backward:before{content:\"\ue6a8\"}.jupyter-wrapper .bp3-icon-fast-forward:before{content:\"\ue6ac\"}.jupyter-wrapper .bp3-icon-feed:before{content:\"\ue656\"}.jupyter-wrapper .bp3-icon-feed-subscribed:before{content:\"\ue78f\"}.jupyter-wrapper .bp3-icon-film:before{content:\"\ue6a1\"}.jupyter-wrapper .bp3-icon-filter:before{content:\"\ue638\"}.jupyter-wrapper .bp3-icon-filter-keep:before{content:\"\ue78c\"}.jupyter-wrapper .bp3-icon-filter-list:before{content:\"\ue6ee\"}.jupyter-wrapper .bp3-icon-filter-open:before{content:\"\ue7d7\"}.jupyter-wrapper .bp3-icon-filter-remove:before{content:\"\ue78d\"}.jupyter-wrapper .bp3-icon-flag:before{content:\"\u2691\"}.jupyter-wrapper .bp3-icon-flame:before{content:\"\ue7a9\"}.jupyter-wrapper .bp3-icon-flash:before{content:\"\ue6b3\"}.jupyter-wrapper .bp3-icon-floppy-disk:before{content:\"\ue6b7\"}.jupyter-wrapper .bp3-icon-flow-branch:before{content:\"\ue7c1\"}.jupyter-wrapper .bp3-icon-flow-end:before{content:\"\ue7c4\"}.jupyter-wrapper .bp3-icon-flow-linear:before{content:\"\ue7c0\"}.jupyter-wrapper .bp3-icon-flow-review:before{content:\"\ue7c2\"}.jupyter-wrapper .bp3-icon-flow-review-branch:before{content:\"\ue7c3\"}.jupyter-wrapper .bp3-icon-flows:before{content:\"\ue659\"}.jupyter-wrapper .bp3-icon-folder-close:before{content:\"\ue652\"}.jupyter-wrapper .bp3-icon-folder-new:before{content:\"\ue7b0\"}.jupyter-wrapper .bp3-icon-folder-open:before{content:\"\ue651\"}.jupyter-wrapper .bp3-icon-folder-shared:before{content:\"\ue653\"}.jupyter-wrapper .bp3-icon-folder-shared-open:before{content:\"\ue670\"}.jupyter-wrapper .bp3-icon-follower:before{content:\"\ue760\"}.jupyter-wrapper .bp3-icon-following:before{content:\"\ue761\"}.jupyter-wrapper .bp3-icon-font:before{content:\"\ue6b4\"}.jupyter-wrapper .bp3-icon-fork:before{content:\"\ue63a\"}.jupyter-wrapper .bp3-icon-form:before{content:\"\ue795\"}.jupyter-wrapper .bp3-icon-full-circle:before{content:\"\ue685\"}.jupyter-wrapper .bp3-icon-full-stacked-chart:before{content:\"\ue75e\"}.jupyter-wrapper .bp3-icon-fullscreen:before{content:\"\ue699\"}.jupyter-wrapper .bp3-icon-function:before{content:\"\ue6e5\"}.jupyter-wrapper .bp3-icon-gantt-chart:before{content:\"\ue6f4\"}.jupyter-wrapper .bp3-icon-geolocation:before{content:\"\ue640\"}.jupyter-wrapper .bp3-icon-geosearch:before{content:\"\ue613\"}.jupyter-wrapper .bp3-icon-git-branch:before{content:\"\ue72a\"}.jupyter-wrapper .bp3-icon-git-commit:before{content:\"\ue72b\"}.jupyter-wrapper .bp3-icon-git-merge:before{content:\"\ue729\"}.jupyter-wrapper .bp3-icon-git-new-branch:before{content:\"\ue749\"}.jupyter-wrapper .bp3-icon-git-pull:before{content:\"\ue728\"}.jupyter-wrapper .bp3-icon-git-push:before{content:\"\ue72c\"}.jupyter-wrapper .bp3-icon-git-repo:before{content:\"\ue748\"}.jupyter-wrapper .bp3-icon-glass:before{content:\"\ue6b1\"}.jupyter-wrapper .bp3-icon-globe:before{content:\"\ue666\"}.jupyter-wrapper .bp3-icon-globe-network:before{content:\"\ue7b5\"}.jupyter-wrapper .bp3-icon-graph:before{content:\"\ue673\"}.jupyter-wrapper .bp3-icon-graph-remove:before{content:\"\ue609\"}.jupyter-wrapper .bp3-icon-greater-than:before{content:\"\ue7e1\"}.jupyter-wrapper .bp3-icon-greater-than-or-equal-to:before{content:\"\ue7e2\"}.jupyter-wrapper .bp3-icon-grid:before{content:\"\ue6d0\"}.jupyter-wrapper .bp3-icon-grid-view:before{content:\"\ue6e4\"}.jupyter-wrapper .bp3-icon-group-objects:before{content:\"\ue60a\"}.jupyter-wrapper .bp3-icon-grouped-bar-chart:before{content:\"\ue75d\"}.jupyter-wrapper .bp3-icon-hand:before{content:\"\ue6de\"}.jupyter-wrapper .bp3-icon-hand-down:before{content:\"\ue6bb\"}.jupyter-wrapper .bp3-icon-hand-left:before{content:\"\ue6bc\"}.jupyter-wrapper .bp3-icon-hand-right:before{content:\"\ue6b9\"}.jupyter-wrapper .bp3-icon-hand-up:before{content:\"\ue6ba\"}.jupyter-wrapper .bp3-icon-header:before{content:\"\ue6b5\"}.jupyter-wrapper .bp3-icon-header-one:before{content:\"\ue793\"}.jupyter-wrapper .bp3-icon-header-two:before{content:\"\ue794\"}.jupyter-wrapper .bp3-icon-headset:before{content:\"\ue6dc\"}.jupyter-wrapper .bp3-icon-heart:before{content:\"\u2665\"}.jupyter-wrapper .bp3-icon-heart-broken:before{content:\"\ue7a2\"}.jupyter-wrapper .bp3-icon-heat-grid:before{content:\"\ue6f3\"}.jupyter-wrapper .bp3-icon-heatmap:before{content:\"\ue614\"}.jupyter-wrapper .bp3-icon-help:before{content:\"?\"}.jupyter-wrapper .bp3-icon-helper-management:before{content:\"\ue66d\"}.jupyter-wrapper .bp3-icon-highlight:before{content:\"\ue6ed\"}.jupyter-wrapper .bp3-icon-history:before{content:\"\ue64a\"}.jupyter-wrapper .bp3-icon-home:before{content:\"\u2302\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart:before{content:\"\ue70c\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart-asc:before{content:\"\ue75c\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart-desc:before{content:\"\ue71d\"}.jupyter-wrapper .bp3-icon-horizontal-distribution:before{content:\"\ue720\"}.jupyter-wrapper .bp3-icon-id-number:before{content:\"\ue771\"}.jupyter-wrapper .bp3-icon-image-rotate-left:before{content:\"\ue73a\"}.jupyter-wrapper .bp3-icon-image-rotate-right:before{content:\"\ue73b\"}.jupyter-wrapper .bp3-icon-import:before{content:\"\ue632\"}.jupyter-wrapper .bp3-icon-inbox:before{content:\"\ue629\"}.jupyter-wrapper .bp3-icon-inbox-filtered:before{content:\"\ue7d1\"}.jupyter-wrapper .bp3-icon-inbox-geo:before{content:\"\ue7d2\"}.jupyter-wrapper .bp3-icon-inbox-search:before{content:\"\ue7d3\"}.jupyter-wrapper .bp3-icon-inbox-update:before{content:\"\ue7d4\"}.jupyter-wrapper .bp3-icon-info-sign:before{content:\"\u2139\"}.jupyter-wrapper .bp3-icon-inheritance:before{content:\"\ue7d5\"}.jupyter-wrapper .bp3-icon-inner-join:before{content:\"\ue7a3\"}.jupyter-wrapper .bp3-icon-insert:before{content:\"\ue66c\"}.jupyter-wrapper .bp3-icon-intersection:before{content:\"\ue765\"}.jupyter-wrapper .bp3-icon-ip-address:before{content:\"\ue772\"}.jupyter-wrapper .bp3-icon-issue:before{content:\"\ue774\"}.jupyter-wrapper .bp3-icon-issue-closed:before{content:\"\ue776\"}.jupyter-wrapper .bp3-icon-issue-new:before{content:\"\ue775\"}.jupyter-wrapper .bp3-icon-italic:before{content:\"\ue607\"}.jupyter-wrapper .bp3-icon-join-table:before{content:\"\ue738\"}.jupyter-wrapper .bp3-icon-key:before{content:\"\ue78e\"}.jupyter-wrapper .bp3-icon-key-backspace:before{content:\"\ue707\"}.jupyter-wrapper .bp3-icon-key-command:before{content:\"\ue705\"}.jupyter-wrapper .bp3-icon-key-control:before{content:\"\ue704\"}.jupyter-wrapper .bp3-icon-key-delete:before{content:\"\ue708\"}.jupyter-wrapper .bp3-icon-key-enter:before{content:\"\ue70a\"}.jupyter-wrapper .bp3-icon-key-escape:before{content:\"\ue709\"}.jupyter-wrapper .bp3-icon-key-option:before{content:\"\ue742\"}.jupyter-wrapper .bp3-icon-key-shift:before{content:\"\ue706\"}.jupyter-wrapper .bp3-icon-key-tab:before{content:\"\ue757\"}.jupyter-wrapper .bp3-icon-known-vehicle:before{content:\"\ue73c\"}.jupyter-wrapper .bp3-icon-lab-test:before{content:\"\ue90e\"}.jupyter-wrapper .bp3-icon-label:before{content:\"\ue665\"}.jupyter-wrapper .bp3-icon-layer:before{content:\"\ue6cf\"}.jupyter-wrapper .bp3-icon-layers:before{content:\"\ue618\"}.jupyter-wrapper .bp3-icon-layout:before{content:\"\ue60c\"}.jupyter-wrapper .bp3-icon-layout-auto:before{content:\"\ue60d\"}.jupyter-wrapper .bp3-icon-layout-balloon:before{content:\"\ue6d3\"}.jupyter-wrapper .bp3-icon-layout-circle:before{content:\"\ue60e\"}.jupyter-wrapper .bp3-icon-layout-grid:before{content:\"\ue610\"}.jupyter-wrapper .bp3-icon-layout-group-by:before{content:\"\ue611\"}.jupyter-wrapper .bp3-icon-layout-hierarchy:before{content:\"\ue60f\"}.jupyter-wrapper .bp3-icon-layout-linear:before{content:\"\ue6c3\"}.jupyter-wrapper .bp3-icon-layout-skew-grid:before{content:\"\ue612\"}.jupyter-wrapper .bp3-icon-layout-sorted-clusters:before{content:\"\ue6d4\"}.jupyter-wrapper .bp3-icon-learning:before{content:\"\ue904\"}.jupyter-wrapper .bp3-icon-left-join:before{content:\"\ue7a4\"}.jupyter-wrapper .bp3-icon-less-than:before{content:\"\ue7e3\"}.jupyter-wrapper .bp3-icon-less-than-or-equal-to:before{content:\"\ue7e4\"}.jupyter-wrapper .bp3-icon-lifesaver:before{content:\"\ue7c7\"}.jupyter-wrapper .bp3-icon-lightbulb:before{content:\"\ue6b0\"}.jupyter-wrapper .bp3-icon-link:before{content:\"\ue62d\"}.jupyter-wrapper .bp3-icon-list:before{content:\"\u2630\"}.jupyter-wrapper .bp3-icon-list-columns:before{content:\"\ue7b9\"}.jupyter-wrapper .bp3-icon-list-detail-view:before{content:\"\ue743\"}.jupyter-wrapper .bp3-icon-locate:before{content:\"\ue619\"}.jupyter-wrapper .bp3-icon-lock:before{content:\"\ue625\"}.jupyter-wrapper .bp3-icon-log-in:before{content:\"\ue69a\"}.jupyter-wrapper .bp3-icon-log-out:before{content:\"\ue64c\"}.jupyter-wrapper .bp3-icon-manual:before{content:\"\ue6f6\"}.jupyter-wrapper .bp3-icon-manually-entered-data:before{content:\"\ue74a\"}.jupyter-wrapper .bp3-icon-map:before{content:\"\ue662\"}.jupyter-wrapper .bp3-icon-map-create:before{content:\"\ue741\"}.jupyter-wrapper .bp3-icon-map-marker:before{content:\"\ue67d\"}.jupyter-wrapper .bp3-icon-maximize:before{content:\"\ue635\"}.jupyter-wrapper .bp3-icon-media:before{content:\"\ue62c\"}.jupyter-wrapper .bp3-icon-menu:before{content:\"\ue762\"}.jupyter-wrapper .bp3-icon-menu-closed:before{content:\"\ue655\"}.jupyter-wrapper .bp3-icon-menu-open:before{content:\"\ue654\"}.jupyter-wrapper .bp3-icon-merge-columns:before{content:\"\ue74f\"}.jupyter-wrapper .bp3-icon-merge-links:before{content:\"\ue60b\"}.jupyter-wrapper .bp3-icon-minimize:before{content:\"\ue634\"}.jupyter-wrapper .bp3-icon-minus:before{content:\"\u2212\"}.jupyter-wrapper .bp3-icon-mobile-phone:before{content:\"\ue717\"}.jupyter-wrapper .bp3-icon-mobile-video:before{content:\"\ue69f\"}.jupyter-wrapper .bp3-icon-moon:before{content:\"\ue754\"}.jupyter-wrapper .bp3-icon-more:before{content:\"\ue62a\"}.jupyter-wrapper .bp3-icon-mountain:before{content:\"\ue7b1\"}.jupyter-wrapper .bp3-icon-move:before{content:\"\ue693\"}.jupyter-wrapper .bp3-icon-mugshot:before{content:\"\ue6db\"}.jupyter-wrapper .bp3-icon-multi-select:before{content:\"\ue680\"}.jupyter-wrapper .bp3-icon-music:before{content:\"\ue6a6\"}.jupyter-wrapper .bp3-icon-new-drawing:before{content:\"\ue905\"}.jupyter-wrapper .bp3-icon-new-grid-item:before{content:\"\ue747\"}.jupyter-wrapper .bp3-icon-new-layer:before{content:\"\ue902\"}.jupyter-wrapper .bp3-icon-new-layers:before{content:\"\ue903\"}.jupyter-wrapper .bp3-icon-new-link:before{content:\"\ue65c\"}.jupyter-wrapper .bp3-icon-new-object:before{content:\"\ue65d\"}.jupyter-wrapper .bp3-icon-new-person:before{content:\"\ue6e9\"}.jupyter-wrapper .bp3-icon-new-prescription:before{content:\"\ue78b\"}.jupyter-wrapper .bp3-icon-new-text-box:before{content:\"\ue65b\"}.jupyter-wrapper .bp3-icon-ninja:before{content:\"\ue675\"}.jupyter-wrapper .bp3-icon-not-equal-to:before{content:\"\ue7e0\"}.jupyter-wrapper .bp3-icon-notifications:before{content:\"\ue624\"}.jupyter-wrapper .bp3-icon-notifications-updated:before{content:\"\ue7b8\"}.jupyter-wrapper .bp3-icon-numbered-list:before{content:\"\ue746\"}.jupyter-wrapper .bp3-icon-numerical:before{content:\"\ue756\"}.jupyter-wrapper .bp3-icon-office:before{content:\"\ue69b\"}.jupyter-wrapper .bp3-icon-offline:before{content:\"\ue67a\"}.jupyter-wrapper .bp3-icon-oil-field:before{content:\"\ue73f\"}.jupyter-wrapper .bp3-icon-one-column:before{content:\"\ue658\"}.jupyter-wrapper .bp3-icon-outdated:before{content:\"\ue7a8\"}.jupyter-wrapper .bp3-icon-page-layout:before{content:\"\ue660\"}.jupyter-wrapper .bp3-icon-panel-stats:before{content:\"\ue777\"}.jupyter-wrapper .bp3-icon-panel-table:before{content:\"\ue778\"}.jupyter-wrapper .bp3-icon-paperclip:before{content:\"\ue664\"}.jupyter-wrapper .bp3-icon-paragraph:before{content:\"\ue76c\"}.jupyter-wrapper .bp3-icon-path:before{content:\"\ue753\"}.jupyter-wrapper .bp3-icon-path-search:before{content:\"\ue65e\"}.jupyter-wrapper .bp3-icon-pause:before{content:\"\ue6a9\"}.jupyter-wrapper .bp3-icon-people:before{content:\"\ue63d\"}.jupyter-wrapper .bp3-icon-percentage:before{content:\"\ue76a\"}.jupyter-wrapper .bp3-icon-person:before{content:\"\ue63c\"}.jupyter-wrapper .bp3-icon-phone:before{content:\"\u260e\"}.jupyter-wrapper .bp3-icon-pie-chart:before{content:\"\ue684\"}.jupyter-wrapper .bp3-icon-pin:before{content:\"\ue646\"}.jupyter-wrapper .bp3-icon-pivot:before{content:\"\ue6f1\"}.jupyter-wrapper .bp3-icon-pivot-table:before{content:\"\ue6eb\"}.jupyter-wrapper .bp3-icon-play:before{content:\"\ue6ab\"}.jupyter-wrapper .bp3-icon-plus:before{content:\"+\"}.jupyter-wrapper .bp3-icon-polygon-filter:before{content:\"\ue6d1\"}.jupyter-wrapper .bp3-icon-power:before{content:\"\ue6d9\"}.jupyter-wrapper .bp3-icon-predictive-analysis:before{content:\"\ue617\"}.jupyter-wrapper .bp3-icon-prescription:before{content:\"\ue78a\"}.jupyter-wrapper .bp3-icon-presentation:before{content:\"\ue687\"}.jupyter-wrapper .bp3-icon-print:before{content:\"\u2399\"}.jupyter-wrapper .bp3-icon-projects:before{content:\"\ue622\"}.jupyter-wrapper .bp3-icon-properties:before{content:\"\ue631\"}.jupyter-wrapper .bp3-icon-property:before{content:\"\ue65a\"}.jupyter-wrapper .bp3-icon-publish-function:before{content:\"\ue752\"}.jupyter-wrapper .bp3-icon-pulse:before{content:\"\ue6e8\"}.jupyter-wrapper .bp3-icon-random:before{content:\"\ue698\"}.jupyter-wrapper .bp3-icon-record:before{content:\"\ue6ae\"}.jupyter-wrapper .bp3-icon-redo:before{content:\"\ue6c4\"}.jupyter-wrapper .bp3-icon-refresh:before{content:\"\ue643\"}.jupyter-wrapper .bp3-icon-regression-chart:before{content:\"\ue758\"}.jupyter-wrapper .bp3-icon-remove:before{content:\"\ue63f\"}.jupyter-wrapper .bp3-icon-remove-column:before{content:\"\ue755\"}.jupyter-wrapper .bp3-icon-remove-column-left:before{content:\"\ue6fd\"}.jupyter-wrapper .bp3-icon-remove-column-right:before{content:\"\ue6fe\"}.jupyter-wrapper .bp3-icon-remove-row-bottom:before{content:\"\ue6fc\"}.jupyter-wrapper .bp3-icon-remove-row-top:before{content:\"\ue6fb\"}.jupyter-wrapper .bp3-icon-repeat:before{content:\"\ue692\"}.jupyter-wrapper .bp3-icon-reset:before{content:\"\ue7d6\"}.jupyter-wrapper .bp3-icon-resolve:before{content:\"\ue672\"}.jupyter-wrapper .bp3-icon-rig:before{content:\"\ue740\"}.jupyter-wrapper .bp3-icon-right-join:before{content:\"\ue7a5\"}.jupyter-wrapper .bp3-icon-ring:before{content:\"\ue6f2\"}.jupyter-wrapper .bp3-icon-rotate-document:before{content:\"\ue6e1\"}.jupyter-wrapper .bp3-icon-rotate-page:before{content:\"\ue6e2\"}.jupyter-wrapper .bp3-icon-satellite:before{content:\"\ue76b\"}.jupyter-wrapper .bp3-icon-saved:before{content:\"\ue6b6\"}.jupyter-wrapper .bp3-icon-scatter-plot:before{content:\"\ue73e\"}.jupyter-wrapper .bp3-icon-search:before{content:\"\ue64b\"}.jupyter-wrapper .bp3-icon-search-around:before{content:\"\ue608\"}.jupyter-wrapper .bp3-icon-search-template:before{content:\"\ue628\"}.jupyter-wrapper .bp3-icon-search-text:before{content:\"\ue663\"}.jupyter-wrapper .bp3-icon-segmented-control:before{content:\"\ue6ec\"}.jupyter-wrapper .bp3-icon-select:before{content:\"\ue616\"}.jupyter-wrapper .bp3-icon-selection:before{content:\"\u29bf\"}.jupyter-wrapper .bp3-icon-send-to:before{content:\"\ue66e\"}.jupyter-wrapper .bp3-icon-send-to-graph:before{content:\"\ue736\"}.jupyter-wrapper .bp3-icon-send-to-map:before{content:\"\ue737\"}.jupyter-wrapper .bp3-icon-series-add:before{content:\"\ue796\"}.jupyter-wrapper .bp3-icon-series-configuration:before{content:\"\ue79a\"}.jupyter-wrapper .bp3-icon-series-derived:before{content:\"\ue799\"}.jupyter-wrapper .bp3-icon-series-filtered:before{content:\"\ue798\"}.jupyter-wrapper .bp3-icon-series-search:before{content:\"\ue797\"}.jupyter-wrapper .bp3-icon-settings:before{content:\"\ue6a2\"}.jupyter-wrapper .bp3-icon-share:before{content:\"\ue62e\"}.jupyter-wrapper .bp3-icon-shield:before{content:\"\ue7b2\"}.jupyter-wrapper .bp3-icon-shop:before{content:\"\ue6c2\"}.jupyter-wrapper .bp3-icon-shopping-cart:before{content:\"\ue6c1\"}.jupyter-wrapper .bp3-icon-signal-search:before{content:\"\ue909\"}.jupyter-wrapper .bp3-icon-sim-card:before{content:\"\ue718\"}.jupyter-wrapper .bp3-icon-slash:before{content:\"\ue769\"}.jupyter-wrapper .bp3-icon-small-cross:before{content:\"\ue6d7\"}.jupyter-wrapper .bp3-icon-small-minus:before{content:\"\ue70e\"}.jupyter-wrapper .bp3-icon-small-plus:before{content:\"\ue70d\"}.jupyter-wrapper .bp3-icon-small-tick:before{content:\"\ue6d8\"}.jupyter-wrapper .bp3-icon-snowflake:before{content:\"\ue7b6\"}.jupyter-wrapper .bp3-icon-social-media:before{content:\"\ue671\"}.jupyter-wrapper .bp3-icon-sort:before{content:\"\ue64f\"}.jupyter-wrapper .bp3-icon-sort-alphabetical:before{content:\"\ue64d\"}.jupyter-wrapper .bp3-icon-sort-alphabetical-desc:before{content:\"\ue6c8\"}.jupyter-wrapper .bp3-icon-sort-asc:before{content:\"\ue6d5\"}.jupyter-wrapper .bp3-icon-sort-desc:before{content:\"\ue6d6\"}.jupyter-wrapper .bp3-icon-sort-numerical:before{content:\"\ue64e\"}.jupyter-wrapper .bp3-icon-sort-numerical-desc:before{content:\"\ue6c9\"}.jupyter-wrapper .bp3-icon-split-columns:before{content:\"\ue750\"}.jupyter-wrapper .bp3-icon-square:before{content:\"\ue686\"}.jupyter-wrapper .bp3-icon-stacked-chart:before{content:\"\ue6e7\"}.jupyter-wrapper .bp3-icon-star:before{content:\"\u2605\"}.jupyter-wrapper .bp3-icon-star-empty:before{content:\"\u2606\"}.jupyter-wrapper .bp3-icon-step-backward:before{content:\"\ue6a7\"}.jupyter-wrapper .bp3-icon-step-chart:before{content:\"\ue70f\"}.jupyter-wrapper .bp3-icon-step-forward:before{content:\"\ue6ad\"}.jupyter-wrapper .bp3-icon-stop:before{content:\"\ue6aa\"}.jupyter-wrapper .bp3-icon-stopwatch:before{content:\"\ue901\"}.jupyter-wrapper .bp3-icon-strikethrough:before{content:\"\ue7a6\"}.jupyter-wrapper .bp3-icon-style:before{content:\"\ue601\"}.jupyter-wrapper .bp3-icon-swap-horizontal:before{content:\"\ue745\"}.jupyter-wrapper .bp3-icon-swap-vertical:before{content:\"\ue744\"}.jupyter-wrapper .bp3-icon-symbol-circle:before{content:\"\ue72e\"}.jupyter-wrapper .bp3-icon-symbol-cross:before{content:\"\ue731\"}.jupyter-wrapper .bp3-icon-symbol-diamond:before{content:\"\ue730\"}.jupyter-wrapper .bp3-icon-symbol-square:before{content:\"\ue72f\"}.jupyter-wrapper .bp3-icon-symbol-triangle-down:before{content:\"\ue733\"}.jupyter-wrapper .bp3-icon-symbol-triangle-up:before{content:\"\ue732\"}.jupyter-wrapper .bp3-icon-tag:before{content:\"\ue61c\"}.jupyter-wrapper .bp3-icon-take-action:before{content:\"\ue6ca\"}.jupyter-wrapper .bp3-icon-taxi:before{content:\"\ue79e\"}.jupyter-wrapper .bp3-icon-text-highlight:before{content:\"\ue6dd\"}.jupyter-wrapper .bp3-icon-th:before{content:\"\ue667\"}.jupyter-wrapper .bp3-icon-th-derived:before{content:\"\ue669\"}.jupyter-wrapper .bp3-icon-th-disconnect:before{content:\"\ue7d8\"}.jupyter-wrapper .bp3-icon-th-filtered:before{content:\"\ue7c6\"}.jupyter-wrapper .bp3-icon-th-list:before{content:\"\ue668\"}.jupyter-wrapper .bp3-icon-thumbs-down:before{content:\"\ue6be\"}.jupyter-wrapper .bp3-icon-thumbs-up:before{content:\"\ue6bd\"}.jupyter-wrapper .bp3-icon-tick:before{content:\"\u2713\"}.jupyter-wrapper .bp3-icon-tick-circle:before{content:\"\ue779\"}.jupyter-wrapper .bp3-icon-time:before{content:\"\u23f2\"}.jupyter-wrapper .bp3-icon-timeline-area-chart:before{content:\"\ue6cd\"}.jupyter-wrapper .bp3-icon-timeline-bar-chart:before{content:\"\ue620\"}.jupyter-wrapper .bp3-icon-timeline-events:before{content:\"\ue61e\"}.jupyter-wrapper .bp3-icon-timeline-line-chart:before{content:\"\ue61f\"}.jupyter-wrapper .bp3-icon-tint:before{content:\"\ue6b2\"}.jupyter-wrapper .bp3-icon-torch:before{content:\"\ue677\"}.jupyter-wrapper .bp3-icon-tractor:before{content:\"\ue90c\"}.jupyter-wrapper .bp3-icon-train:before{content:\"\ue79f\"}.jupyter-wrapper .bp3-icon-translate:before{content:\"\ue759\"}.jupyter-wrapper .bp3-icon-trash:before{content:\"\ue63b\"}.jupyter-wrapper .bp3-icon-tree:before{content:\"\ue7b7\"}.jupyter-wrapper .bp3-icon-trending-down:before{content:\"\ue71a\"}.jupyter-wrapper .bp3-icon-trending-up:before{content:\"\ue719\"}.jupyter-wrapper .bp3-icon-truck:before{content:\"\ue90b\"}.jupyter-wrapper .bp3-icon-two-columns:before{content:\"\ue657\"}.jupyter-wrapper .bp3-icon-unarchive:before{content:\"\ue906\"}.jupyter-wrapper .bp3-icon-underline:before{content:\"\u2381\"}.jupyter-wrapper .bp3-icon-undo:before{content:\"\u238c\"}.jupyter-wrapper .bp3-icon-ungroup-objects:before{content:\"\ue688\"}.jupyter-wrapper .bp3-icon-unknown-vehicle:before{content:\"\ue73d\"}.jupyter-wrapper .bp3-icon-unlock:before{content:\"\ue626\"}.jupyter-wrapper .bp3-icon-unpin:before{content:\"\ue650\"}.jupyter-wrapper .bp3-icon-unresolve:before{content:\"\ue679\"}.jupyter-wrapper .bp3-icon-updated:before{content:\"\ue7a7\"}.jupyter-wrapper .bp3-icon-upload:before{content:\"\ue68f\"}.jupyter-wrapper .bp3-icon-user:before{content:\"\ue627\"}.jupyter-wrapper .bp3-icon-variable:before{content:\"\ue6f5\"}.jupyter-wrapper .bp3-icon-vertical-bar-chart-asc:before{content:\"\ue75b\"}.jupyter-wrapper .bp3-icon-vertical-bar-chart-desc:before{content:\"\ue71c\"}.jupyter-wrapper .bp3-icon-vertical-distribution:before{content:\"\ue721\"}.jupyter-wrapper .bp3-icon-video:before{content:\"\ue6a0\"}.jupyter-wrapper .bp3-icon-volume-down:before{content:\"\ue6a4\"}.jupyter-wrapper .bp3-icon-volume-off:before{content:\"\ue6a3\"}.jupyter-wrapper .bp3-icon-volume-up:before{content:\"\ue6a5\"}.jupyter-wrapper .bp3-icon-walk:before{content:\"\ue79d\"}.jupyter-wrapper .bp3-icon-warning-sign:before{content:\"\ue647\"}.jupyter-wrapper .bp3-icon-waterfall-chart:before{content:\"\ue6e6\"}.jupyter-wrapper .bp3-icon-widget:before{content:\"\ue678\"}.jupyter-wrapper .bp3-icon-widget-button:before{content:\"\ue790\"}.jupyter-wrapper .bp3-icon-widget-footer:before{content:\"\ue792\"}.jupyter-wrapper .bp3-icon-widget-header:before{content:\"\ue791\"}.jupyter-wrapper .bp3-icon-wrench:before{content:\"\ue734\"}.jupyter-wrapper .bp3-icon-zoom-in:before{content:\"\ue641\"}.jupyter-wrapper .bp3-icon-zoom-out:before{content:\"\ue642\"}.jupyter-wrapper .bp3-icon-zoom-to-fit:before{content:\"\ue67b\"}.jupyter-wrapper .bp3-submenu>.bp3-popover-wrapper{display:block}.jupyter-wrapper .bp3-submenu .bp3-popover-target{display:block}.jupyter-wrapper .bp3-submenu.bp3-popover{-webkit-box-shadow:none;box-shadow:none;padding:0 5px}.jupyter-wrapper .bp3-submenu.bp3-popover>.bp3-popover-content{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33}.jupyter-wrapper .bp3-dark .bp3-submenu.bp3-popover,.jupyter-wrapper .bp3-submenu.bp3-popover.bp3-dark{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-submenu.bp3-popover>.bp3-popover-content,.jupyter-wrapper .bp3-submenu.bp3-popover.bp3-dark>.bp3-popover-content{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-menu{background:#ffffff;border-radius:3px;color:#182026;list-style:none;margin:0;min-width:180px;padding:5px;text-align:left}.jupyter-wrapper .bp3-menu-divider{border-top:1px solid rgba(16,22,26,.15);display:block;margin:5px}.jupyter-wrapper .bp3-dark .bp3-menu-divider{border-top-color:#ffffff26}.jupyter-wrapper .bp3-menu-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;border-radius:2px;color:inherit;line-height:20px;padding:5px 7px;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-menu-item>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-menu-item>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item>*{margin-right:7px}.jupyter-wrapper .bp3-menu-item:empty:before,.jupyter-wrapper .bp3-menu-item>:last-child{margin-right:0}.jupyter-wrapper .bp3-menu-item>.bp3-fill{word-break:break-word}.jupyter-wrapper .bp3-menu-item:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item{background-color:#a7b6c24d;cursor:pointer;text-decoration:none}.jupyter-wrapper .bp3-menu-item.bp3-disabled{background-color:inherit;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-menu-item{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-menu-item{background-color:#8a9ba826;color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled{background-color:inherit;color:#a7b6c299}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary .bp3-menu-item-label{color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active{background-color:#137cbd}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active{background-color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success .bp3-menu-item-label{color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active{background-color:#0f9960}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active{background-color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning .bp3-menu-item-label{color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active{background-color:#d9822b}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active{background-color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger .bp3-menu-item-label{color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active{background-color:#db3737}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active{background-color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-right:7px}.jupyter-wrapper .bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item>.bp3-icon{color:#5c7080;margin-top:2px}.jupyter-wrapper .bp3-menu-item .bp3-menu-item-label{color:#5c7080}.jupyter-wrapper .bp3-menu-item:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-active,.jupyter-wrapper .bp3-menu-item:active{background-color:#7386944d}.jupyter-wrapper .bp3-menu-item.bp3-disabled{background-color:inherit!important;color:#5c708099!important;cursor:not-allowed!important;outline:none!important}.jupyter-wrapper .bp3-menu-item.bp3-disabled:before,.jupyter-wrapper .bp3-menu-item.bp3-disabled>.bp3-icon,.jupyter-wrapper .bp3-menu-item.bp3-disabled .bp3-menu-item-label{color:#5c708099!important}.jupyter-wrapper .bp3-large .bp3-menu-item{font-size:16px;line-height:22px;padding:9px 7px}.jupyter-wrapper .bp3-large .bp3-menu-item .bp3-icon{margin-top:3px}.jupyter-wrapper .bp3-large .bp3-menu-item:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-right:10px;margin-top:1px}.jupyter-wrapper button.bp3-menu-item{background:none;border:none;text-align:left;width:100%}.jupyter-wrapper .bp3-menu-header{border-top:1px solid rgba(16,22,26,.15);display:block;margin:5px;cursor:default;padding-left:2px}.jupyter-wrapper .bp3-dark .bp3-menu-header{border-top-color:#ffffff26}.jupyter-wrapper .bp3-menu-header:first-of-type{border-top:none}.jupyter-wrapper .bp3-menu-header>h6{color:#182026;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;line-height:17px;margin:0;padding:10px 7px 0 1px}.jupyter-wrapper .bp3-menu-header:first-of-type>h6{padding-top:0}.jupyter-wrapper .bp3-large .bp3-menu-header>h6{font-size:18px;padding-bottom:5px;padding-top:15px}.jupyter-wrapper .bp3-large .bp3-menu-header:first-of-type>h6{padding-top:0}.jupyter-wrapper .bp3-dark .bp3-menu{background:#30404d;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary .bp3-menu-item-label{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active{background-color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active{background-color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success .bp3-menu-item-label{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active{background-color:#0f9960}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active{background-color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning .bp3-menu-item-label{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active{background-color:#d9822b}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active{background-color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger .bp3-menu-item-label{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active{background-color:#db3737}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active{background-color:#c23030}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item>.bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-menu-item .bp3-menu-item-label{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item:active{background-color:#8a9ba84d}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled{color:#a7b6c299!important}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled .bp3-menu-item-label{color:#a7b6c299!important}.jupyter-wrapper .bp3-dark .bp3-menu-divider,.jupyter-wrapper .bp3-dark .bp3-menu-header{border-color:#ffffff26}.jupyter-wrapper .bp3-dark .bp3-menu-header>h6{color:#f5f8fa}.jupyter-wrapper .bp3-label .bp3-menu{margin-top:5px}.jupyter-wrapper .bp3-navbar{background-color:#fff;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;height:50px;padding:0 15px;position:relative;width:100%;z-index:10}.jupyter-wrapper .bp3-navbar.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-navbar{background-color:#394b59}.jupyter-wrapper .bp3-navbar.bp3-dark{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-navbar{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-navbar.bp3-fixed-top{left:0;position:fixed;right:0;top:0}.jupyter-wrapper .bp3-navbar-heading{font-size:16px;margin-right:15px}.jupyter-wrapper .bp3-navbar-group{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:50px}.jupyter-wrapper .bp3-navbar-group.bp3-align-left{float:left}.jupyter-wrapper .bp3-navbar-group.bp3-align-right{float:right}.jupyter-wrapper .bp3-navbar-divider{border-left:1px solid rgba(16,22,26,.15);height:20px;margin:0 10px}.jupyter-wrapper .bp3-dark .bp3-navbar-divider{border-left-color:#ffffff26}.jupyter-wrapper .bp3-non-ideal-state{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%}.jupyter-wrapper .bp3-non-ideal-state>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-non-ideal-state>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-non-ideal-state:before,.jupyter-wrapper .bp3-non-ideal-state>*{margin-bottom:20px}.jupyter-wrapper .bp3-non-ideal-state:empty:before,.jupyter-wrapper .bp3-non-ideal-state>:last-child{margin-bottom:0}.jupyter-wrapper .bp3-non-ideal-state>*{max-width:400px}.jupyter-wrapper .bp3-non-ideal-state-visual{color:#5c708099;font-size:60px}.jupyter-wrapper .bp3-dark .bp3-non-ideal-state-visual{color:#a7b6c299}.jupyter-wrapper .bp3-overflow-list{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;min-width:0}.jupyter-wrapper .bp3-overflow-list-spacer{-ms-flex-negative:1;flex-shrink:1;width:1px}.jupyter-wrapper body.bp3-overlay-open{overflow:hidden}.jupyter-wrapper .bp3-overlay{bottom:0;left:0;position:static;right:0;top:0;z-index:20}.jupyter-wrapper .bp3-overlay:not(.bp3-overlay-open){pointer-events:none}.jupyter-wrapper .bp3-overlay.bp3-overlay-container{overflow:hidden;position:fixed}.jupyter-wrapper .bp3-overlay.bp3-overlay-container.bp3-overlay-inline{position:absolute}.jupyter-wrapper .bp3-overlay.bp3-overlay-scroll-container{overflow:auto;position:fixed}.jupyter-wrapper .bp3-overlay.bp3-overlay-scroll-container.bp3-overlay-inline{position:absolute}.jupyter-wrapper .bp3-overlay.bp3-overlay-inline{display:inline;overflow:visible}.jupyter-wrapper .bp3-overlay-content{position:fixed;z-index:20}.jupyter-wrapper .bp3-overlay-inline .bp3-overlay-content,.jupyter-wrapper .bp3-overlay-scroll-container .bp3-overlay-content{position:absolute}.jupyter-wrapper .bp3-overlay-backdrop{bottom:0;left:0;position:fixed;right:0;top:0;opacity:1;background-color:#10161ab3;overflow:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:20}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-enter,.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-appear{opacity:0}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-enter-active,.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-appear-active{opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-exit{opacity:1}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-exit-active{opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-overlay-backdrop:focus{outline:none}.jupyter-wrapper .bp3-overlay-inline .bp3-overlay-backdrop{position:absolute}.jupyter-wrapper .bp3-panel-stack{overflow:hidden;position:relative}.jupyter-wrapper .bp3-panel-stack-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-shadow:0 1px rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;height:30px;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack-header{-webkit-box-shadow:0 1px rgba(255,255,255,.15);box-shadow:0 1px #ffffff26}.jupyter-wrapper .bp3-panel-stack-header>span{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1}.jupyter-wrapper .bp3-panel-stack-header .bp3-heading{margin:0 5px}.jupyter-wrapper .bp3-button.bp3-panel-stack-header-back{margin-left:5px;padding-left:0;white-space:nowrap}.jupyter-wrapper .bp3-button.bp3-panel-stack-header-back .bp3-icon{margin:0 2px}.jupyter-wrapper .bp3-panel-stack-view{bottom:0;left:0;position:absolute;right:0;top:0;background-color:#fff;border-right:1px solid rgba(16,22,26,.15);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:-1px;overflow-y:auto;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack-view{background-color:#30404d}.jupyter-wrapper .bp3-panel-stack-view:nth-last-child(n+4){display:none}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-enter,.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-appear{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-enter-active,.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-exit-active{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-enter,.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-appear{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-enter-active,.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2{overflow:hidden;position:relative}.jupyter-wrapper .bp3-panel-stack2-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-shadow:0 1px rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;height:30px;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack2-header{-webkit-box-shadow:0 1px rgba(255,255,255,.15);box-shadow:0 1px #ffffff26}.jupyter-wrapper .bp3-panel-stack2-header>span{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1}.jupyter-wrapper .bp3-panel-stack2-header .bp3-heading{margin:0 5px}.jupyter-wrapper .bp3-button.bp3-panel-stack2-header-back{margin-left:5px;padding-left:0;white-space:nowrap}.jupyter-wrapper .bp3-button.bp3-panel-stack2-header-back .bp3-icon{margin:0 2px}.jupyter-wrapper .bp3-panel-stack2-view{bottom:0;left:0;position:absolute;right:0;top:0;background-color:#fff;border-right:1px solid rgba(16,22,26,.15);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:-1px;overflow-y:auto;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack2-view{background-color:#30404d}.jupyter-wrapper .bp3-panel-stack2-view:nth-last-child(n+4){display:none}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-enter,.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-appear{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-enter-active,.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-exit-active{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-enter,.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-appear{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-enter-active,.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-popover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;-webkit-transform:scale(1);transform:scale(1);border-radius:3px;display:inline-block;z-index:20}.jupyter-wrapper .bp3-popover .bp3-popover-arrow{height:30px;position:absolute;width:30px}.jupyter-wrapper .bp3-popover .bp3-popover-arrow:before{height:20px;margin:5px;width:20px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover{margin-bottom:17px;margin-top:-17px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow{bottom:-11px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover{margin-left:17px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow{left:-11px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(0);transform:rotate(0)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover{margin-top:17px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow{top:-11px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover{margin-left:-17px;margin-right:17px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow{right:-11px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.jupyter-wrapper .bp3-tether-element-attached-middle>.bp3-popover>.bp3-popover-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.jupyter-wrapper .bp3-tether-element-attached-center>.bp3-popover>.bp3-popover-arrow{right:50%;-webkit-transform:translateX(50%);transform:translate(50%)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow{top:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow{right:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow{left:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow{bottom:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:top left;transform-origin:top left}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:top center;transform-origin:top center}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:top right;transform-origin:top right}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:center left;transform-origin:center left}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:center center;transform-origin:center center}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:center right;transform-origin:center right}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:bottom left;transform-origin:bottom left}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:bottom center;transform-origin:bottom center}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:bottom right;transform-origin:bottom right}.jupyter-wrapper .bp3-popover .bp3-popover-content{background:#ffffff;color:inherit}.jupyter-wrapper .bp3-popover .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.2);box-shadow:1px 1px 6px #10161a33}.jupyter-wrapper .bp3-popover .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.1}.jupyter-wrapper .bp3-popover .bp3-popover-arrow-fill{fill:#fff}.jupyter-wrapper .bp3-popover-enter>.bp3-popover,.jupyter-wrapper .bp3-popover-appear>.bp3-popover{-webkit-transform:scale(.3);transform:scale(.3)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-popover,.jupyter-wrapper .bp3-popover-appear-active>.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-popover-exit>.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-popover{-webkit-transform:scale(.3);transform:scale(.3);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-popover .bp3-popover-content{border-radius:3px;position:relative}.jupyter-wrapper .bp3-popover.bp3-popover-content-sizing .bp3-popover-content{max-width:350px;padding:20px}.jupyter-wrapper .bp3-popover-target+.bp3-overlay .bp3-popover.bp3-popover-content-sizing{width:350px}.jupyter-wrapper .bp3-popover.bp3-minimal{margin:0!important}.jupyter-wrapper .bp3-popover.bp3-minimal .bp3-popover-arrow{display:none}.jupyter-wrapper .bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-enter>.bp3-popover.bp3-minimal.bp3-popover,.jupyter-wrapper .bp3-popover-appear>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-popover.bp3-minimal.bp3-popover,.jupyter-wrapper .bp3-popover-appear-active>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover-exit>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-popover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-content,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-content{background:#30404d;color:inherit}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow:before,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.4);box-shadow:1px 1px 6px #10161a66}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow-border,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.2}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow-fill,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow-fill{fill:#30404d}.jupyter-wrapper .bp3-popover-arrow:before{border-radius:2px;content:\"\";display:block;position:absolute;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.jupyter-wrapper .bp3-tether-pinned .bp3-popover-arrow{display:none}.jupyter-wrapper .bp3-popover-backdrop{background:rgba(255,255,255,0)}.jupyter-wrapper .bp3-transition-container{opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;z-index:20}.jupyter-wrapper .bp3-transition-container.bp3-popover-enter,.jupyter-wrapper .bp3-transition-container.bp3-popover-appear{opacity:0}.jupyter-wrapper .bp3-transition-container.bp3-popover-enter-active,.jupyter-wrapper .bp3-transition-container.bp3-popover-appear-active{opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-transition-container.bp3-popover-exit{opacity:1}.jupyter-wrapper .bp3-transition-container.bp3-popover-exit-active{opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-transition-container:focus{outline:none}.jupyter-wrapper .bp3-transition-container.bp3-popover-leave .bp3-popover-content{pointer-events:none}.jupyter-wrapper .bp3-transition-container[data-x-out-of-boundaries]{display:none}.jupyter-wrapper span.bp3-popover-target{display:inline-block}.jupyter-wrapper .bp3-popover-wrapper.bp3-fill{width:100%}.jupyter-wrapper .bp3-portal{left:0;position:absolute;right:0;top:0}@-webkit-keyframes linear-progress-bar-stripes{0%{background-position:0 0}to{background-position:30px 0}}@keyframes linear-progress-bar-stripes{0%{background-position:0 0}to{background-position:30px 0}}.jupyter-wrapper .bp3-progress-bar{background:rgba(92,112,128,.2);border-radius:40px;display:block;height:8px;overflow:hidden;position:relative;width:100%}.jupyter-wrapper .bp3-progress-bar .bp3-progress-meter{background:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%);background-color:#5c7080cc;background-size:30px 30px;border-radius:40px;height:100%;position:absolute;-webkit-transition:width .2s cubic-bezier(.4,1,.75,.9);transition:width .2s cubic-bezier(.4,1,.75,.9);width:100%}.jupyter-wrapper .bp3-progress-bar:not(.bp3-no-animation):not(.bp3-no-stripes) .bp3-progress-meter{animation:linear-progress-bar-stripes .3s linear infinite reverse}.jupyter-wrapper .bp3-progress-bar.bp3-no-stripes .bp3-progress-meter{background-image:none}.jupyter-wrapper .bp3-dark .bp3-progress-bar{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-dark .bp3-progress-bar .bp3-progress-meter{background-color:#8a9ba8}.jupyter-wrapper .bp3-progress-bar.bp3-intent-primary .bp3-progress-meter{background-color:#137cbd}.jupyter-wrapper .bp3-progress-bar.bp3-intent-success .bp3-progress-meter{background-color:#0f9960}.jupyter-wrapper .bp3-progress-bar.bp3-intent-warning .bp3-progress-meter{background-color:#d9822b}.jupyter-wrapper .bp3-progress-bar.bp3-intent-danger .bp3-progress-meter{background-color:#db3737}@-webkit-keyframes skeleton-glow{0%{background:rgba(206,217,224,.2);border-color:#ced9e033}to{background:rgba(92,112,128,.2);border-color:#5c708033}}@keyframes skeleton-glow{0%{background:rgba(206,217,224,.2);border-color:#ced9e033}to{background:rgba(92,112,128,.2);border-color:#5c708033}}.jupyter-wrapper .bp3-skeleton{-webkit-animation:1s linear infinite alternate skeleton-glow;animation:1s linear infinite alternate skeleton-glow;background:rgba(206,217,224,.2);background-clip:padding-box!important;border-color:#ced9e033!important;border-radius:2px;-webkit-box-shadow:none!important;box-shadow:none!important;color:transparent!important;cursor:default;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-skeleton:before,.jupyter-wrapper .bp3-skeleton:after,.jupyter-wrapper .bp3-skeleton *{visibility:hidden!important}.jupyter-wrapper .bp3-slider{height:40px;min-width:150px;width:100%;cursor:default;outline:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-slider:hover{cursor:pointer}.jupyter-wrapper .bp3-slider:active{cursor:-webkit-grabbing;cursor:grabbing}.jupyter-wrapper .bp3-slider.bp3-disabled{cursor:not-allowed;opacity:.5}.jupyter-wrapper .bp3-slider.bp3-slider-unlabeled{height:16px}.jupyter-wrapper .bp3-slider-track,.jupyter-wrapper .bp3-slider-progress{height:6px;left:0;right:0;top:5px;position:absolute}.jupyter-wrapper .bp3-slider-track{border-radius:3px;overflow:hidden}.jupyter-wrapper .bp3-slider-progress{background:rgba(92,112,128,.2)}.jupyter-wrapper .bp3-dark .bp3-slider-progress{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-slider-progress.bp3-intent-primary{background-color:#137cbd}.jupyter-wrapper .bp3-slider-progress.bp3-intent-success{background-color:#0f9960}.jupyter-wrapper .bp3-slider-progress.bp3-intent-warning{background-color:#d9822b}.jupyter-wrapper .bp3-slider-progress.bp3-intent-danger{background-color:#db3737}.jupyter-wrapper .bp3-slider-handle{background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;cursor:pointer;height:16px;left:0;position:absolute;top:0;width:16px}.jupyter-wrapper .bp3-slider-handle:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-slider-handle:active,.jupyter-wrapper .bp3-slider-handle.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-slider-handle:disabled,.jupyter-wrapper .bp3-slider-handle.bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-slider-handle:disabled.bp3-active,.jupyter-wrapper .bp3-slider-handle:disabled.bp3-active:hover,.jupyter-wrapper .bp3-slider-handle.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-slider-handle.bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-slider-handle:focus{z-index:1}.jupyter-wrapper .bp3-slider-handle:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;cursor:-webkit-grab;cursor:grab;z-index:2}.jupyter-wrapper .bp3-slider-handle.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),inset 0 1px 1px rgba(16,22,26,.1);box-shadow:0 0 0 1px #10161a33,inset 0 1px 1px #10161a1a;cursor:-webkit-grabbing;cursor:grabbing}.jupyter-wrapper .bp3-disabled .bp3-slider-handle{background:#bfccd6;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.jupyter-wrapper .bp3-dark .bp3-slider-handle{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover,.jupyter-wrapper .bp3-dark .bp3-slider-handle:active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-slider-handle:active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-slider-handle:disabled,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-slider-handle:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-slider-handle .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-slider-handle,.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover{background-color:#394b59}.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{background-color:#293742}.jupyter-wrapper .bp3-dark .bp3-disabled .bp3-slider-handle{background:#5c7080;border-color:#5c7080;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-slider-handle .bp3-slider-label{background:#394b59;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;color:#f5f8fa;margin-left:8px}.jupyter-wrapper .bp3-dark .bp3-slider-handle .bp3-slider-label{background:#e1e8ed;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66;color:#394b59}.jupyter-wrapper .bp3-disabled .bp3-slider-handle .bp3-slider-label{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-slider-handle.bp3-start,.jupyter-wrapper .bp3-slider-handle.bp3-end{width:8px}.jupyter-wrapper .bp3-slider-handle.bp3-start{border-bottom-right-radius:0;border-top-right-radius:0}.jupyter-wrapper .bp3-slider-handle.bp3-end{border-bottom-left-radius:0;border-top-left-radius:0;margin-left:8px}.jupyter-wrapper .bp3-slider-handle.bp3-end .bp3-slider-label{margin-left:0}.jupyter-wrapper .bp3-slider-label{-webkit-transform:translate(-50%,20px);transform:translate(-50%,20px);display:inline-block;font-size:12px;line-height:1;padding:2px 5px;position:absolute;vertical-align:top}.jupyter-wrapper .bp3-slider.bp3-vertical{height:150px;min-width:40px;width:40px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-track,.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-progress{bottom:0;height:auto;left:5px;top:0;width:6px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-progress{top:auto}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-label{-webkit-transform:translate(20px,50%);transform:translate(20px,50%)}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle{top:auto}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle .bp3-slider-label{margin-left:0;margin-top:-8px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-end,.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start{height:8px;margin-left:0;width:16px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start{border-bottom-right-radius:3px;border-top-left-radius:0}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start .bp3-slider-label{-webkit-transform:translate(20px);transform:translate(20px)}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-end{border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:3px;margin-bottom:8px}@-webkit-keyframes pt-spinner-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes pt-spinner-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.jupyter-wrapper .bp3-spinner{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:visible;vertical-align:middle}.jupyter-wrapper .bp3-spinner svg{display:block}.jupyter-wrapper .bp3-spinner path{fill-opacity:0}.jupyter-wrapper .bp3-spinner .bp3-spinner-head{stroke:#5c7080cc;stroke-linecap:round;-webkit-transform-origin:center;transform-origin:center;-webkit-transition:stroke-dashoffset .2s cubic-bezier(.4,1,.75,.9);transition:stroke-dashoffset .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-spinner .bp3-spinner-track{stroke:#5c708033}.jupyter-wrapper .bp3-spinner-animation{-webkit-animation:pt-spinner-animation .5s linear infinite;animation:pt-spinner-animation .5s linear infinite}.jupyter-wrapper .bp3-no-spin>.bp3-spinner-animation{-webkit-animation:none;animation:none}.jupyter-wrapper .bp3-dark .bp3-spinner .bp3-spinner-head{stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-spinner .bp3-spinner-track{stroke:#10161a80}.jupyter-wrapper .bp3-spinner.bp3-intent-primary .bp3-spinner-head{stroke:#137cbd}.jupyter-wrapper .bp3-spinner.bp3-intent-success .bp3-spinner-head{stroke:#0f9960}.jupyter-wrapper .bp3-spinner.bp3-intent-warning .bp3-spinner-head{stroke:#d9822b}.jupyter-wrapper .bp3-spinner.bp3-intent-danger .bp3-spinner-head{stroke:#db3737}.jupyter-wrapper .bp3-tabs.bp3-vertical{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab{border-radius:3px;padding:0 10px;width:100%}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab[aria-selected=true]{background-color:#137cbd33;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab-indicator-wrapper .bp3-tab-indicator{background-color:#137cbd33;border-radius:3px;bottom:0;height:auto;left:0;right:0;top:0}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-panel{margin-top:0;padding-left:20px}.jupyter-wrapper .bp3-tab-list{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;border:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;list-style:none;margin:0;padding:0;position:relative}.jupyter-wrapper .bp3-tab-list>*:not(:last-child){margin-right:20px}.jupyter-wrapper .bp3-tab{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;color:#182026;cursor:pointer;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;font-size:14px;line-height:30px;max-width:100%;position:relative;vertical-align:top}.jupyter-wrapper .bp3-tab a{color:inherit;display:block;text-decoration:none}.jupyter-wrapper .bp3-tab-indicator-wrapper~.bp3-tab{background-color:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}.jupyter-wrapper .bp3-tab[aria-disabled=true]{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tab[aria-selected=true]{border-radius:0;-webkit-box-shadow:inset 0 -3px 0 #106ba3;box-shadow:inset 0 -3px #106ba3}.jupyter-wrapper .bp3-tab[aria-selected=true],.jupyter-wrapper .bp3-tab:not([aria-disabled=true]):hover{color:#106ba3}.jupyter-wrapper .bp3-tab:focus{-moz-outline-radius:0}.jupyter-wrapper .bp3-large>.bp3-tab{font-size:16px;line-height:40px}.jupyter-wrapper .bp3-tab-panel{margin-top:20px}.jupyter-wrapper .bp3-tab-panel[aria-hidden=true]{display:none}.jupyter-wrapper .bp3-tab-indicator-wrapper{left:0;pointer-events:none;position:absolute;top:0;-webkit-transform:translateX(0),translateY(0);transform:translate(0),translateY(0);-webkit-transition:height,width,-webkit-transform;transition:height,width,-webkit-transform;transition:height,transform,width;transition:height,transform,width,-webkit-transform;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tab-indicator-wrapper .bp3-tab-indicator{background-color:#106ba3;bottom:0;height:3px;left:0;position:absolute;right:0}.jupyter-wrapper .bp3-tab-indicator-wrapper.bp3-no-animation{-webkit-transition:none;transition:none}.jupyter-wrapper .bp3-dark .bp3-tab{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tab[aria-disabled=true]{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tab[aria-selected=true]{-webkit-box-shadow:inset 0 -3px 0 #48aff0;box-shadow:inset 0 -3px #48aff0}.jupyter-wrapper .bp3-dark .bp3-tab[aria-selected=true],.jupyter-wrapper .bp3-dark .bp3-tab:not([aria-disabled=true]):hover{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-tab-indicator{background-color:#48aff0}.jupyter-wrapper .bp3-flex-expander{-webkit-box-flex:1;-ms-flex:1 1;flex:1 1}.jupyter-wrapper .bp3-tag{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#5c7080;border:none;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;color:#f5f8fa;font-size:12px;line-height:16px;max-width:100%;min-height:20px;min-width:20px;padding:2px 6px;position:relative}.jupyter-wrapper .bp3-tag.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-interactive:hover{background-color:#5c7080d9}.jupyter-wrapper .bp3-tag.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-interactive:active{background-color:#5c7080b3}.jupyter-wrapper .bp3-tag>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag:before,.jupyter-wrapper .bp3-tag>*{margin-right:4px}.jupyter-wrapper .bp3-tag:empty:before,.jupyter-wrapper .bp3-tag>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag:focus{outline:rgba(19,124,189,.6) auto 2px;outline-offset:0;-moz-outline-radius:6px}.jupyter-wrapper .bp3-tag.bp3-round{border-radius:30px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-dark .bp3-tag{background-color:#bfccd6;color:#182026}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive:hover{background-color:#bfccd6d9}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive:active{background-color:#bfccd6b3}.jupyter-wrapper .bp3-dark .bp3-tag>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tag .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tag .bp3-icon-large{fill:currentColor}.jupyter-wrapper .bp3-tag>.bp3-icon,.jupyter-wrapper .bp3-tag .bp3-icon-standard,.jupyter-wrapper .bp3-tag .bp3-icon-large{fill:#fff}.jupyter-wrapper .bp3-tag.bp3-large,.jupyter-wrapper .bp3-large .bp3-tag{font-size:14px;line-height:20px;min-height:30px;min-width:30px;padding:5px 10px}.jupyter-wrapper .bp3-tag.bp3-large:before,.jupyter-wrapper .bp3-tag.bp3-large>*,.jupyter-wrapper .bp3-large .bp3-tag:before,.jupyter-wrapper .bp3-large .bp3-tag>*{margin-right:7px}.jupyter-wrapper .bp3-tag.bp3-large:empty:before,.jupyter-wrapper .bp3-tag.bp3-large>:last-child,.jupyter-wrapper .bp3-large .bp3-tag:empty:before,.jupyter-wrapper .bp3-large .bp3-tag>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag.bp3-large.bp3-round,.jupyter-wrapper .bp3-large .bp3-tag.bp3-round{padding-left:12px;padding-right:12px}.jupyter-wrapper .bp3-tag.bp3-intent-primary{background:#137cbd;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbdd9}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive:active{background-color:#137cbdb3}.jupyter-wrapper .bp3-tag.bp3-intent-success{background:#0f9960;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive:hover{background-color:#0f9960d9}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive:active{background-color:#0f9960b3}.jupyter-wrapper .bp3-tag.bp3-intent-warning{background:#d9822b;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822bd9}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive:active{background-color:#d9822bb3}.jupyter-wrapper .bp3-tag.bp3-intent-danger{background:#db3737;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive:hover{background-color:#db3737d9}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive:active{background-color:#db3737b3}.jupyter-wrapper .bp3-tag.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-tag.bp3-minimal>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal .bp3-icon-large{fill:#5c7080}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]){background-color:#8a9ba833;color:#182026}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:hover{background-color:#5c70804d}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:active{background-color:#5c708066}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]){color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:hover{background-color:#bfccd64d}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:active{background-color:#bfccd666}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-])>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]) .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]) .bp3-icon-large{fill:#a7b6c2}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary{background-color:#137cbd26;color:#106ba3}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbd40}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:active{background-color:#137cbd59}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary .bp3-icon-large{fill:#137cbd}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary{background-color:#137cbd40;color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbd59}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:active{background-color:#137cbd73}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success{background-color:#0f996026;color:#0d8050}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:hover{background-color:#0f996040}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:active{background-color:#0f996059}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success .bp3-icon-large{fill:#0f9960}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success{background-color:#0f996040;color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:hover{background-color:#0f996059}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:active{background-color:#0f996073}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning{background-color:#d9822b26;color:#bf7326}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822b40}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:active{background-color:#d9822b59}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning .bp3-icon-large{fill:#d9822b}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning{background-color:#d9822b40;color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822b59}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:active{background-color:#d9822b73}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger{background-color:#db373726;color:#c23030}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:hover{background-color:#db373740}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:active{background-color:#db373759}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger .bp3-icon-large{fill:#db3737}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger{background-color:#db373740;color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:hover{background-color:#db373759}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:active{background-color:#db373773}.jupyter-wrapper .bp3-tag-remove{background:none;border:none;color:inherit;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:-2px;margin-right:-6px!important;margin-top:-2px;opacity:.5;padding:2px 2px 2px 0}.jupyter-wrapper .bp3-tag-remove:hover{background:none;opacity:.8;text-decoration:none}.jupyter-wrapper .bp3-tag-remove:active{opacity:1}.jupyter-wrapper .bp3-tag-remove:empty:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;content:\"\ue6d7\"}.jupyter-wrapper .bp3-large .bp3-tag-remove{margin-right:-10px!important;padding:0 5px 0 0}.jupyter-wrapper .bp3-large .bp3-tag-remove:empty:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1}.jupyter-wrapper .bp3-tag-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;cursor:text;height:auto;line-height:inherit;min-height:30px;padding-left:5px;padding-right:0}.jupyter-wrapper .bp3-tag-input>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag-input>.bp3-tag-input-values{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-icon{color:#5c7080;margin-left:2px;margin-right:7px;margin-top:7px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-item-align:stretch;align-self:stretch;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:7px;margin-top:5px;min-width:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:before,.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{margin-right:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:empty:before,.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:first-child .bp3-input-ghost:first-child{padding-left:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{margin-bottom:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag{overflow-wrap:break-word}.jupyter-wrapper .bp3-tag-input .bp3-tag.bp3-active{outline:rgba(19,124,189,.6) auto 2px;outline-offset:0;-moz-outline-radius:6px}.jupyter-wrapper .bp3-tag-input .bp3-input-ghost{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:20px;width:80px}.jupyter-wrapper .bp3-tag-input .bp3-input-ghost:disabled,.jupyter-wrapper .bp3-tag-input .bp3-input-ghost.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-tag-input .bp3-button,.jupyter-wrapper .bp3-tag-input .bp3-spinner{margin:3px 3px 3px 0}.jupyter-wrapper .bp3-tag-input .bp3-button{min-height:24px;min-width:24px;padding:0 7px}.jupyter-wrapper .bp3-tag-input.bp3-large{height:auto;min-height:40px}.jupyter-wrapper .bp3-tag-input.bp3-large:before,.jupyter-wrapper .bp3-tag-input.bp3-large>*{margin-right:10px}.jupyter-wrapper .bp3-tag-input.bp3-large:empty:before,.jupyter-wrapper .bp3-tag-input.bp3-large>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-tag-input-icon{margin-left:5px;margin-top:10px}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-input-ghost{line-height:30px}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-button{min-height:30px;min-width:30px;padding:5px 10px;margin:5px 5px 5px 0}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-spinner{margin:8px 8px 8px 0}.jupyter-wrapper .bp3-tag-input.bp3-active{background-color:#fff;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-primary{-webkit-box-shadow:0 0 0 1px #106ba3,0 0 0 3px rgba(16,107,163,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #106ba3,0 0 0 3px #106ba34d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-success{-webkit-box-shadow:0 0 0 1px #0d8050,0 0 0 3px rgba(13,128,80,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0d8050,0 0 0 3px #0d80504d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-warning{-webkit-box-shadow:0 0 0 1px #bf7326,0 0 0 3px rgba(191,115,38,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #bf7326,0 0 0 3px #bf73264d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-danger{-webkit-box-shadow:0 0 0 1px #c23030,0 0 0 3px rgba(194,48,48,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #c23030,0 0 0 3px #c230304d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-tag-input-icon,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-tag-input-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-webkit-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-moz-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost:-ms-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-ms-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active{background-color:#10161a4d;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-primary,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-primary{-webkit-box-shadow:0 0 0 1px #106ba3,0 0 0 3px rgba(16,107,163,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #106ba3,0 0 0 3px #106ba34d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-success,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-success{-webkit-box-shadow:0 0 0 1px #0d8050,0 0 0 3px rgba(13,128,80,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #0d8050,0 0 0 3px #0d80504d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-warning,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-warning{-webkit-box-shadow:0 0 0 1px #bf7326,0 0 0 3px rgba(191,115,38,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #bf7326,0 0 0 3px #bf73264d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-danger,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-danger{-webkit-box-shadow:0 0 0 1px #c23030,0 0 0 3px rgba(194,48,48,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #c23030,0 0 0 3px #c230304d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-input-ghost{background:none;border:none;-webkit-box-shadow:none;box-shadow:none;padding:0}.jupyter-wrapper .bp3-input-ghost::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost:focus{outline:none!important}.jupyter-wrapper .bp3-toast{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;margin:20px 0 0;max-width:500px;min-width:300px;pointer-events:all;position:relative!important}.jupyter-wrapper .bp3-toast.bp3-toast-enter,.jupyter-wrapper .bp3-toast.bp3-toast-appear{-webkit-transform:translateY(-40px);transform:translateY(-40px)}.jupyter-wrapper .bp3-toast.bp3-toast-enter-active,.jupyter-wrapper .bp3-toast.bp3-toast-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-toast.bp3-toast-enter~.bp3-toast,.jupyter-wrapper .bp3-toast.bp3-toast-appear~.bp3-toast{-webkit-transform:translateY(-40px);transform:translateY(-40px)}.jupyter-wrapper .bp3-toast.bp3-toast-enter-active~.bp3-toast,.jupyter-wrapper .bp3-toast.bp3-toast-appear-active~.bp3-toast{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-toast.bp3-toast-exit{opacity:1;-webkit-filter:blur(0);filter:blur(0)}.jupyter-wrapper .bp3-toast.bp3-toast-exit-active{opacity:0;-webkit-filter:blur(10px);filter:blur(10px);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:opacity,filter;transition-property:opacity,filter,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-toast.bp3-toast-exit~.bp3-toast{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-toast.bp3-toast-exit-active~.bp3-toast{-webkit-transform:translateY(-40px);transform:translateY(-40px);-webkit-transition-delay:50ms;transition-delay:50ms;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-toast .bp3-button-group{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;padding:5px 5px 5px 0}.jupyter-wrapper .bp3-toast>.bp3-icon{color:#5c7080;margin:12px 0 12px 12px}.jupyter-wrapper .bp3-toast.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-toast{background-color:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-toast.bp3-dark>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-toast>.bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] a{color:#ffffffb3}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] a:hover{color:#fff}.jupyter-wrapper .bp3-toast[class*=bp3-intent-]>.bp3-icon{color:#fff}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:before,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button .bp3-icon,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:active{color:#ffffffb3!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:focus{outline-color:#ffffff80}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:hover{background-color:#ffffff26!important;color:#fff!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:active{background-color:#ffffff4d!important;color:#fff!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:after{background:rgba(255,255,255,.3)!important}.jupyter-wrapper .bp3-toast.bp3-intent-primary{background-color:#137cbd;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-success{background-color:#0f9960;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-warning{background-color:#d9822b;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-danger{background-color:#db3737;color:#fff}.jupyter-wrapper .bp3-toast-message{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:11px;word-break:break-word}.jupyter-wrapper .bp3-toast-container{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;left:0;overflow:hidden;padding:0 20px 20px;pointer-events:none;right:0;z-index:40}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-in-portal{position:fixed}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-inline{position:absolute}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-top{top:0}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-bottom{bottom:0;-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;top:auto}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-left{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-right{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-enter:not(.bp3-toast-enter-active),.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-enter:not(.bp3-toast-enter-active)~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-appear:not(.bp3-toast-appear-active),.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-appear:not(.bp3-toast-appear-active)~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-exit-active~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-leave-active~.bp3-toast{-webkit-transform:translateY(60px);transform:translateY(60px)}.jupyter-wrapper .bp3-tooltip{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow{height:22px;position:absolute;width:22px}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow:before{height:14px;margin:4px;width:14px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip{margin-bottom:11px;margin-top:-11px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow{bottom:-8px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip{margin-left:11px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow{left:-8px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(0);transform:rotate(0)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip{margin-top:11px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow{top:-8px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip{margin-left:-11px;margin-right:11px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow{right:-8px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.jupyter-wrapper .bp3-tether-element-attached-middle>.bp3-tooltip>.bp3-popover-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.jupyter-wrapper .bp3-tether-element-attached-center>.bp3-tooltip>.bp3-popover-arrow{right:50%;-webkit-transform:translateX(50%);transform:translate(50%)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow{top:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow{right:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow{left:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow{bottom:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:top left;transform-origin:top left}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:top center;transform-origin:top center}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:top right;transform-origin:top right}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:center left;transform-origin:center left}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:center center;transform-origin:center center}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:center right;transform-origin:center right}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:bottom left;transform-origin:bottom left}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:bottom center;transform-origin:bottom center}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:bottom right;transform-origin:bottom right}.jupyter-wrapper .bp3-tooltip .bp3-popover-content{background:#394b59;color:#f5f8fa}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.2);box-shadow:1px 1px 6px #10161a33}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.1}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow-fill{fill:#394b59}.jupyter-wrapper .bp3-popover-enter>.bp3-tooltip,.jupyter-wrapper .bp3-popover-appear>.bp3-tooltip{-webkit-transform:scale(.8);transform:scale(.8)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-tooltip,.jupyter-wrapper .bp3-popover-appear-active>.bp3-tooltip{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover-exit>.bp3-tooltip{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-tooltip{-webkit-transform:scale(.8);transform:scale(.8);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tooltip .bp3-popover-content{padding:10px 12px}.jupyter-wrapper .bp3-tooltip.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-tooltip{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-content,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-content{background:#e1e8ed;color:#394b59}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow:before,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.4);box-shadow:1px 1px 6px #10161a66}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow-border,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.2}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow-fill,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow-fill{fill:#e1e8ed}.jupyter-wrapper .bp3-tooltip.bp3-intent-primary .bp3-popover-content{background:#137cbd;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-primary .bp3-popover-arrow-fill{fill:#137cbd}.jupyter-wrapper .bp3-tooltip.bp3-intent-success .bp3-popover-content{background:#0f9960;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-success .bp3-popover-arrow-fill{fill:#0f9960}.jupyter-wrapper .bp3-tooltip.bp3-intent-warning .bp3-popover-content{background:#d9822b;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-warning .bp3-popover-arrow-fill{fill:#d9822b}.jupyter-wrapper .bp3-tooltip.bp3-intent-danger .bp3-popover-content{background:#db3737;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-danger .bp3-popover-arrow-fill{fill:#db3737}.jupyter-wrapper .bp3-tooltip-indicator{border-bottom:dotted 1px;cursor:help}.jupyter-wrapper .bp3-tree .bp3-icon,.jupyter-wrapper .bp3-tree .bp3-icon-standard,.jupyter-wrapper .bp3-tree .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-primary{color:#137cbd}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-success{color:#0f9960}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-warning{color:#d9822b}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-danger{color:#db3737}.jupyter-wrapper .bp3-tree-node-list{list-style:none;margin:0;padding-left:0}.jupyter-wrapper .bp3-tree-root{background-color:transparent;cursor:default;padding-left:0;position:relative}.jupyter-wrapper .bp3-tree-node-content-0{padding-left:0}.jupyter-wrapper .bp3-tree-node-content-1{padding-left:23px}.jupyter-wrapper .bp3-tree-node-content-2{padding-left:46px}.jupyter-wrapper .bp3-tree-node-content-3{padding-left:69px}.jupyter-wrapper .bp3-tree-node-content-4{padding-left:92px}.jupyter-wrapper .bp3-tree-node-content-5{padding-left:115px}.jupyter-wrapper .bp3-tree-node-content-6{padding-left:138px}.jupyter-wrapper .bp3-tree-node-content-7{padding-left:161px}.jupyter-wrapper .bp3-tree-node-content-8{padding-left:184px}.jupyter-wrapper .bp3-tree-node-content-9{padding-left:207px}.jupyter-wrapper .bp3-tree-node-content-10{padding-left:230px}.jupyter-wrapper .bp3-tree-node-content-11{padding-left:253px}.jupyter-wrapper .bp3-tree-node-content-12{padding-left:276px}.jupyter-wrapper .bp3-tree-node-content-13{padding-left:299px}.jupyter-wrapper .bp3-tree-node-content-14{padding-left:322px}.jupyter-wrapper .bp3-tree-node-content-15{padding-left:345px}.jupyter-wrapper .bp3-tree-node-content-16{padding-left:368px}.jupyter-wrapper .bp3-tree-node-content-17{padding-left:391px}.jupyter-wrapper .bp3-tree-node-content-18{padding-left:414px}.jupyter-wrapper .bp3-tree-node-content-19{padding-left:437px}.jupyter-wrapper .bp3-tree-node-content-20{padding-left:460px}.jupyter-wrapper .bp3-tree-node-content{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:30px;padding-right:5px;width:100%}.jupyter-wrapper .bp3-tree-node-content:hover{background-color:#bfccd666}.jupyter-wrapper .bp3-tree-node-caret,.jupyter-wrapper .bp3-tree-node-caret-none{min-width:30px}.jupyter-wrapper .bp3-tree-node-caret{color:#5c7080;cursor:pointer;padding:7px;-webkit-transform:rotate(0deg);transform:rotate(0);-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tree-node-caret:hover{color:#182026}.jupyter-wrapper .bp3-dark .bp3-tree-node-caret{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tree-node-caret:hover{color:#f5f8fa}.jupyter-wrapper .bp3-tree-node-caret.bp3-tree-node-caret-open{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tree-node-caret.bp3-icon-standard:before{content:\"\ue695\"}.jupyter-wrapper .bp3-tree-node-icon{margin-right:7px;position:relative}.jupyter-wrapper .bp3-tree-node-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-tree-node-label span{display:inline}.jupyter-wrapper .bp3-tree-node-secondary-label{padding:0 5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-tree-node-secondary-label .bp3-popover-wrapper,.jupyter-wrapper .bp3-tree-node-secondary-label .bp3-popover-target{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-content{background-color:inherit;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-caret,.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-icon{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content{background-color:#137cbd}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon-standard,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon-large{color:#fff}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-tree-node-caret:before{color:#ffffffb3}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-tree-node-caret:hover:before{color:#fff}.jupyter-wrapper .bp3-dark .bp3-tree-node-content:hover{background-color:#5c70804d}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-primary{color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-success{color:#0f9960}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-warning{color:#d9822b}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-danger{color:#db3737}.jupyter-wrapper .bp3-dark .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content{background-color:#137cbd}.jupyter-wrapper .bp3-omnibar{-webkit-filter:blur(0);filter:blur(0);opacity:1;background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;left:calc(50% - 250px);top:20vh;width:500px;z-index:21}.jupyter-wrapper .bp3-omnibar.bp3-overlay-enter,.jupyter-wrapper .bp3-omnibar.bp3-overlay-appear{-webkit-filter:blur(20px);filter:blur(20px);opacity:.2}.jupyter-wrapper .bp3-omnibar.bp3-overlay-enter-active,.jupyter-wrapper .bp3-omnibar.bp3-overlay-appear-active{-webkit-filter:blur(0);filter:blur(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:filter,opacity;transition-property:filter,opacity,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-omnibar.bp3-overlay-exit{-webkit-filter:blur(0);filter:blur(0);opacity:1}.jupyter-wrapper .bp3-omnibar.bp3-overlay-exit-active{-webkit-filter:blur(20px);filter:blur(20px);opacity:.2;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:filter,opacity;transition-property:filter,opacity,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-omnibar .bp3-input{background-color:transparent;border-radius:0}.jupyter-wrapper .bp3-omnibar .bp3-input,.jupyter-wrapper .bp3-omnibar .bp3-input:focus{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-omnibar .bp3-menu{background-color:transparent;border-radius:0;-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26;max-height:calc(60vh - 40px);overflow:auto}.jupyter-wrapper .bp3-omnibar .bp3-menu:empty{display:none}.jupyter-wrapper .bp3-dark .bp3-omnibar,.jupyter-wrapper .bp3-omnibar.bp3-dark{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66}.jupyter-wrapper .bp3-omnibar-overlay .bp3-overlay-backdrop{background-color:#10161a33}.jupyter-wrapper .bp3-multi-select{min-width:150px}.jupyter-wrapper .bp3-multi-select-popover .bp3-menu{max-height:300px;max-width:400px;overflow:auto}.jupyter-wrapper .bp3-select-popover .bp3-popover-content{padding:5px}.jupyter-wrapper .bp3-select-popover .bp3-input-group{margin-bottom:0}.jupyter-wrapper .bp3-select-popover .bp3-menu{max-height:300px;max-width:400px;overflow:auto;padding:0}.jupyter-wrapper .bp3-select-popover .bp3-menu:not(:first-child){padding-top:5px}.jupyter-wrapper :root{--jp-icon-add-above: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5MikiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik00Ljc1IDQuOTMwNjZINi42MjVWNi44MDU2NkM2LjYyNSA3LjAxMTkxIDYuNzkzNzUgNy4xODA2NiA3IDcuMTgwNjZDNy4yMDYyNSA3LjE4MDY2IDcuMzc1IDcuMDExOTEgNy4zNzUgNi44MDU2NlY0LjkzMDY2SDkuMjVDOS40NTYyNSA0LjkzMDY2IDkuNjI1IDQuNzYxOTEgOS42MjUgNC41NTU2NkM5LjYyNSA0LjM0OTQxIDkuNDU2MjUgNC4xODA2NiA5LjI1IDQuMTgwNjZINy4zNzVWMi4zMDU2NkM3LjM3NSAyLjA5OTQxIDcuMjA2MjUgMS45MzA2NiA3IDEuOTMwNjZDNi43OTM3NSAxLjkzMDY2IDYuNjI1IDIuMDk5NDEgNi42MjUgMi4zMDU2NlY0LjE4MDY2SDQuNzVDNC41NDM3NSA0LjE4MDY2IDQuMzc1IDQuMzQ5NDEgNC4zNzUgNC41NTU2NkM0LjM3NSA0Ljc2MTkxIDQuNTQzNzUgNC45MzA2NiA0Ljc1IDQuOTMwNjZaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC43Ii8+CjwvZz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTExLjUgOS41VjExLjVMMi41IDExLjVWOS41TDExLjUgOS41Wk0xMiA4QzEyLjU1MjMgOCAxMyA4LjQ0NzcyIDEzIDlWMTJDMTMgMTIuNTUyMyAxMi41NTIzIDEzIDEyIDEzTDIgMTNDMS40NDc3MiAxMyAxIDEyLjU1MjMgMSAxMlY5QzEgOC40NDc3MiAxLjQ0NzcxIDggMiA4TDEyIDhaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5MiI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KC0xIDAgMCAxIDEwIDEuNTU1NjYpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==);--jp-icon-add-below: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5OCkiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik05LjI1IDEwLjA2OTNMNy4zNzUgMTAuMDY5M0w3LjM3NSA4LjE5NDM0QzcuMzc1IDcuOTg4MDkgNy4yMDYyNSA3LjgxOTM0IDcgNy44MTkzNEM2Ljc5Mzc1IDcuODE5MzQgNi42MjUgNy45ODgwOSA2LjYyNSA4LjE5NDM0TDYuNjI1IDEwLjA2OTNMNC43NSAxMC4wNjkzQzQuNTQzNzUgMTAuMDY5MyA0LjM3NSAxMC4yMzgxIDQuMzc1IDEwLjQ0NDNDNC4zNzUgMTAuNjUwNiA0LjU0Mzc1IDEwLjgxOTMgNC43NSAxMC44MTkzTDYuNjI1IDEwLjgxOTNMNi42MjUgMTIuNjk0M0M2LjYyNSAxMi45MDA2IDYuNzkzNzUgMTMuMDY5MyA3IDEzLjA2OTNDNy4yMDYyNSAxMy4wNjkzIDcuMzc1IDEyLjkwMDYgNy4zNzUgMTIuNjk0M0w3LjM3NSAxMC44MTkzTDkuMjUgMTAuODE5M0M5LjQ1NjI1IDEwLjgxOTMgOS42MjUgMTAuNjUwNiA5LjYyNSAxMC40NDQzQzkuNjI1IDEwLjIzODEgOS40NTYyNSAxMC4wNjkzIDkuMjUgMTAuMDY5M1oiIGZpbGw9IiM2MTYxNjEiIHN0cm9rZT0iIzYxNjE2MSIgc3Ryb2tlLXdpZHRoPSIwLjciLz4KPC9nPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMi41IDUuNUwyLjUgMy41TDExLjUgMy41TDExLjUgNS41TDIuNSA1LjVaTTIgN0MxLjQ0NzcyIDcgMSA2LjU1MjI4IDEgNkwxIDNDMSAyLjQ0NzcyIDEuNDQ3NzIgMiAyIDJMMTIgMkMxMi41NTIzIDIgMTMgMi40NDc3MiAxMyAzTDEzIDZDMTMgNi41NTIyOSAxMi41NTIzIDcgMTIgN0wyIDdaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5OCI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KDEgMS43NDg0NmUtMDcgMS43NDg0NmUtMDcgLTEgNCAxMy40NDQzKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=);--jp-icon-add: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDEzaC02djZoLTJ2LTZINXYtMmg2VjVoMnY2aDZ2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-bell: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiB2ZXJzaW9uPSIxLjEiPgogICA8cGF0aCBjbGFzcz0ianAtaWNvbjIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzMzMzMzIgogICAgICBkPSJtOCAwLjI5Yy0xLjQgMC0yLjcgMC43My0zLjYgMS44LTEuMiAxLjUtMS40IDMuNC0xLjUgNS4yLTAuMTggMi4yLTAuNDQgNC0yLjMgNS4zbDAuMjggMS4zaDVjMC4wMjYgMC42NiAwLjMyIDEuMSAwLjcxIDEuNSAwLjg0IDAuNjEgMiAwLjYxIDIuOCAwIDAuNTItMC40IDAuNi0xIDAuNzEtMS41aDVsMC4yOC0xLjNjLTEuOS0wLjk3LTIuMi0zLjMtMi4zLTUuMy0wLjEzLTEuOC0wLjI2LTMuNy0xLjUtNS4yLTAuODUtMS0yLjItMS44LTMuNi0xLjh6bTAgMS40YzAuODggMCAxLjkgMC41NSAyLjUgMS4zIDAuODggMS4xIDEuMSAyLjcgMS4yIDQuNCAwLjEzIDEuNyAwLjIzIDMuNiAxLjMgNS4yaC0xMGMxLjEtMS42IDEuMi0zLjQgMS4zLTUuMiAwLjEzLTEuNyAwLjMtMy4zIDEuMi00LjQgMC41OS0wLjcyIDEuNi0xLjMgMi41LTEuM3ptLTAuNzQgMTJoMS41Yy0wLjAwMTUgMC4yOCAwLjAxNSAwLjc5LTAuNzQgMC43OS0wLjczIDAuMDAxNi0wLjcyLTAuNTMtMC43NC0wLjc5eiIgLz4KPC9zdmc+Cg==);--jp-icon-bug-dot: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiPgogICAgICAgIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTcuMTkgOEgyMFYxMEgxNy45MUMxNy45NiAxMC4zMyAxOCAxMC42NiAxOCAxMVYxMkgyMFYxNEgxOC41SDE4VjE0LjAyNzVDMTUuNzUgMTQuMjc2MiAxNCAxNi4xODM3IDE0IDE4LjVDMTQgMTkuMjA4IDE0LjE2MzUgMTkuODc3OSAxNC40NTQ5IDIwLjQ3MzlDMTMuNzA2MyAyMC44MTE3IDEyLjg3NTcgMjEgMTIgMjFDOS43OCAyMSA3Ljg1IDE5Ljc5IDYuODEgMThINFYxNkg2LjA5QzYuMDQgMTUuNjcgNiAxNS4zNCA2IDE1VjE0SDRWMTJINlYxMUM2IDEwLjY2IDYuMDQgMTAuMzMgNi4wOSAxMEg0VjhINi44MUM3LjI2IDcuMjIgNy44OCA2LjU1IDguNjIgNi4wNEw3IDQuNDFMOC40MSAzTDEwLjU5IDUuMTdDMTEuMDQgNS4wNiAxMS41MSA1IDEyIDVDMTIuNDkgNSAxMi45NiA1LjA2IDEzLjQyIDUuMTdMMTUuNTkgM0wxNyA0LjQxTDE1LjM3IDYuMDRDMTYuMTIgNi41NSAxNi43NCA3LjIyIDE3LjE5IDhaTTEwIDE2SDE0VjE0SDEwVjE2Wk0xMCAxMkgxNFYxMEgxMFYxMloiIGZpbGw9IiM2MTYxNjEiLz4KICAgICAgICA8cGF0aCBkPSJNMjIgMTguNUMyMiAyMC40MzMgMjAuNDMzIDIyIDE4LjUgMjJDMTYuNTY3IDIyIDE1IDIwLjQzMyAxNSAxOC41QzE1IDE2LjU2NyAxNi41NjcgMTUgMTguNSAxNUMyMC40MzMgMTUgMjIgMTYuNTY3IDIyIDE4LjVaIiBmaWxsPSIjNjE2MTYxIi8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-bug: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yMCA4aC0yLjgxYy0uNDUtLjc4LTEuMDctMS40NS0xLjgyLTEuOTZMMTcgNC40MSAxNS41OSAzbC0yLjE3IDIuMTdDMTIuOTYgNS4wNiAxMi40OSA1IDEyIDVjLS40OSAwLS45Ni4wNi0xLjQxLjE3TDguNDEgMyA3IDQuNDFsMS42MiAxLjYzQzcuODggNi41NSA3LjI2IDcuMjIgNi44MSA4SDR2MmgyLjA5Yy0uMDUuMzMtLjA5LjY2LS4wOSAxdjFINHYyaDJ2MWMwIC4zNC4wNC42Ny4wOSAxSDR2MmgyLjgxYzEuMDQgMS43OSAyLjk3IDMgNS4xOSAzczQuMTUtMS4yMSA1LjE5LTNIMjB2LTJoLTIuMDljLjA1LS4zMy4wOS0uNjYuMDktMXYtMWgydi0yaC0ydi0xYzAtLjM0LS4wNC0uNjctLjA5LTFIMjBWOHptLTYgOGgtNHYtMmg0djJ6bTAtNGgtNHYtMmg0djJ6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-build: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE0LjkgMTcuNDVDMTYuMjUgMTcuNDUgMTcuMzUgMTYuMzUgMTcuMzUgMTVDMTcuMzUgMTMuNjUgMTYuMjUgMTIuNTUgMTQuOSAxMi41NUMxMy41NCAxMi41NSAxMi40NSAxMy42NSAxMi40NSAxNUMxMi40NSAxNi4zNSAxMy41NCAxNy40NSAxNC45IDE3LjQ1Wk0yMC4xIDE1LjY4TDIxLjU4IDE2Ljg0QzIxLjcxIDE2Ljk1IDIxLjc1IDE3LjEzIDIxLjY2IDE3LjI5TDIwLjI2IDE5LjcxQzIwLjE3IDE5Ljg2IDIwIDE5LjkyIDE5LjgzIDE5Ljg2TDE4LjA5IDE5LjE2QzE3LjczIDE5LjQ0IDE3LjMzIDE5LjY3IDE2LjkxIDE5Ljg1TDE2LjY0IDIxLjdDMTYuNjIgMjEuODcgMTYuNDcgMjIgMTYuMyAyMkgxMy41QzEzLjMyIDIyIDEzLjE4IDIxLjg3IDEzLjE1IDIxLjdMMTIuODkgMTkuODVDMTIuNDYgMTkuNjcgMTIuMDcgMTkuNDQgMTEuNzEgMTkuMTZMOS45NjAwMiAxOS44NkM5LjgxMDAyIDE5LjkyIDkuNjIwMDIgMTkuODYgOS41NDAwMiAxOS43MUw4LjE0MDAyIDE3LjI5QzguMDUwMDIgMTcuMTMgOC4wOTAwMiAxNi45NSA4LjIyMDAyIDE2Ljg0TDkuNzAwMDIgMTUuNjhMOS42NTAwMSAxNUw5LjcwMDAyIDE0LjMxTDguMjIwMDIgMTMuMTZDOC4wOTAwMiAxMy4wNSA4LjA1MDAyIDEyLjg2IDguMTQwMDIgMTIuNzFMOS41NDAwMiAxMC4yOUM5LjYyMDAyIDEwLjEzIDkuODEwMDIgMTAuMDcgOS45NjAwMiAxMC4xM0wxMS43MSAxMC44NEMxMi4wNyAxMC41NiAxMi40NiAxMC4zMiAxMi44OSAxMC4xNUwxMy4xNSA4LjI4OTk4QzEzLjE4IDguMTI5OTggMTMuMzIgNy45OTk5OCAxMy41IDcuOTk5OThIMTYuM0MxNi40NyA3Ljk5OTk4IDE2LjYyIDguMTI5OTggMTYuNjQgOC4yODk5OEwxNi45MSAxMC4xNUMxNy4zMyAxMC4zMiAxNy43MyAxMC41NiAxOC4wOSAxMC44NEwxOS44MyAxMC4xM0MyMCAxMC4wNyAyMC4xNyAxMC4xMyAyMC4yNiAxMC4yOUwyMS42NiAxMi43MUMyMS43NSAxMi44NiAyMS43MSAxMy4wNSAyMS41OCAxMy4xNkwyMC4xIDE0LjMxTDIwLjE1IDE1TDIwLjEgMTUuNjhaIi8+CiAgICA8cGF0aCBkPSJNNy4zMjk2NiA3LjQ0NDU0QzguMDgzMSA3LjAwOTU0IDguMzM5MzIgNi4wNTMzMiA3LjkwNDMyIDUuMjk5ODhDNy40NjkzMiA0LjU0NjQzIDYuNTA4MSA0LjI4MTU2IDUuNzU0NjYgNC43MTY1NkM1LjM5MTc2IDQuOTI2MDggNS4xMjY5NSA1LjI3MTE4IDUuMDE4NDkgNS42NzU5NEM0LjkxMDA0IDYuMDgwNzEgNC45NjY4MiA2LjUxMTk4IDUuMTc2MzQgNi44NzQ4OEM1LjYxMTM0IDcuNjI4MzIgNi41NzYyMiA3Ljg3OTU0IDcuMzI5NjYgNy40NDQ1NFpNOS42NTcxOCA0Ljc5NTkzTDEwLjg2NzIgNC45NTE3OUMxMC45NjI4IDQuOTc3NDEgMTEuMDQwMiA1LjA3MTMzIDExLjAzODIgNS4xODc5M0wxMS4wMzg4IDYuOTg4OTNDMTEuMDQ1NSA3LjEwMDU0IDEwLjk2MTYgNy4xOTUxOCAxMC44NTUgNy4yMTA1NEw5LjY2MDAxIDcuMzgwODNMOS4yMzkxNSA4LjEzMTg4TDkuNjY5NjEgOS4yNTc0NUM5LjcwNzI5IDkuMzYyNzEgOS42NjkzNCA5LjQ3Njk5IDkuNTc0MDggOS41MzE5OUw4LjAxNTIzIDEwLjQzMkM3LjkxMTMxIDEwLjQ5MiA3Ljc5MzM3IDEwLjQ2NzcgNy43MjEwNSAxMC4zODI0TDYuOTg3NDggOS40MzE4OEw2LjEwOTMxIDkuNDMwODNMNS4zNDcwNCAxMC4zOTA1QzUuMjg5MDkgMTAuNDcwMiA1LjE3MzgzIDEwLjQ5MDUgNS4wNzE4NyAxMC40MzM5TDMuNTEyNDUgOS41MzI5M0MzLjQxMDQ5IDkuNDc2MzMgMy4zNzY0NyA5LjM1NzQxIDMuNDEwNzUgOS4yNTY3OUwzLjg2MzQ3IDguMTQwOTNMMy42MTc0OSA3Ljc3NDg4TDMuNDIzNDcgNy4zNzg4M0wyLjIzMDc1IDcuMjEyOTdDMi4xMjY0NyA3LjE5MjM1IDIuMDQwNDkgNy4xMDM0MiAyLjA0MjQ1IDYuOTg2ODJMMi4wNDE4NyA1LjE4NTgyQzIuMDQzODMgNS4wNjkyMiAyLjExOTA5IDQuOTc5NTggMi4yMTcwNCA0Ljk2OTIyTDMuNDIwNjUgNC43OTM5M0wzLjg2NzQ5IDQuMDI3ODhMMy40MTEwNSAyLjkxNzMxQzMuMzczMzcgMi44MTIwNCAzLjQxMTMxIDIuNjk3NzYgMy41MTUyMyAyLjYzNzc2TDUuMDc0MDggMS43Mzc3NkM1LjE2OTM0IDEuNjgyNzYgNS4yODcyOSAxLjcwNzA0IDUuMzU5NjEgMS43OTIzMUw2LjExOTE1IDIuNzI3ODhMNi45ODAwMSAyLjczODkzTDcuNzI0OTYgMS43ODkyMkM3Ljc5MTU2IDEuNzA0NTggNy45MTU0OCAxLjY3OTIyIDguMDA4NzkgMS43NDA4Mkw5LjU2ODIxIDIuNjQxODJDOS42NzAxNyAyLjY5ODQyIDkuNzEyODUgMi44MTIzNCA5LjY4NzIzIDIuOTA3OTdMOS4yMTcxOCA0LjAzMzgzTDkuNDYzMTYgNC4zOTk4OEw5LjY1NzE4IDQuNzk1OTNaIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-caret-down-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iOS45LDEzLjYgMy42LDcuNCA0LjQsNi42IDkuOSwxMi4yIDE1LjQsNi43IDE2LjEsNy40ICIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-caret-down-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNS45TDksOS43bDMuOC0zLjhsMS4yLDEuMmwtNC45LDVsLTQuOS01TDUuMiw1Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-caret-down: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNy41TDksMTEuMmwzLjgtMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-caret-left: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik0xMC44LDEyLjhMNy4xLDlsMy44LTMuOGwwLDcuNkgxMC44eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-caret-right: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik03LjIsNS4yTDEwLjksOWwtMy44LDMuOFY1LjJINy4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-caret-up-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iMTUuNCwxMy4zIDkuOSw3LjcgNC40LDEzLjIgMy42LDEyLjUgOS45LDYuMyAxNi4xLDEyLjYgIi8+Cgk8L2c+Cjwvc3ZnPgo=);--jp-icon-caret-up: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik01LjIsMTAuNUw5LDYuOGwzLjgsMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-case-sensitive: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgogIDxnIGNsYXNzPSJqcC1pY29uLWFjY2VudDIiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTcuNiw4aDAuOWwzLjUsOGgtMS4xTDEwLDE0SDZsLTAuOSwySDRMNy42LDh6IE04LDkuMUw2LjQsMTNoMy4yTDgsOS4xeiIvPgogICAgPHBhdGggZD0iTTE2LjYsOS44Yy0wLjIsMC4xLTAuNCwwLjEtMC43LDAuMWMtMC4yLDAtMC40LTAuMS0wLjYtMC4yYy0wLjEtMC4xLTAuMi0wLjQtMC4yLTAuNyBjLTAuMywwLjMtMC42LDAuNS0wLjksMC43Yy0wLjMsMC4xLTAuNywwLjItMS4xLDAuMmMtMC4zLDAtMC41LDAtMC43LTAuMWMtMC4yLTAuMS0wLjQtMC4yLTAuNi0wLjNjLTAuMi0wLjEtMC4zLTAuMy0wLjQtMC41IGMtMC4xLTAuMi0wLjEtMC40LTAuMS0wLjdjMC0wLjMsMC4xLTAuNiwwLjItMC44YzAuMS0wLjIsMC4zLTAuNCwwLjQtMC41QzEyLDcsMTIuMiw2LjksMTIuNSw2LjhjMC4yLTAuMSwwLjUtMC4xLDAuNy0wLjIgYzAuMy0wLjEsMC41LTAuMSwwLjctMC4xYzAuMiwwLDAuNC0wLjEsMC42LTAuMWMwLjIsMCwwLjMtMC4xLDAuNC0wLjJjMC4xLTAuMSwwLjItMC4yLDAuMi0wLjRjMC0xLTEuMS0xLTEuMy0xIGMtMC40LDAtMS40LDAtMS40LDEuMmgtMC45YzAtMC40LDAuMS0wLjcsMC4yLTFjMC4xLTAuMiwwLjMtMC40LDAuNS0wLjZjMC4yLTAuMiwwLjUtMC4zLDAuOC0wLjNDMTMuMyw0LDEzLjYsNCwxMy45LDQgYzAuMywwLDAuNSwwLDAuOCwwLjFjMC4zLDAsMC41LDAuMSwwLjcsMC4yYzAuMiwwLjEsMC40LDAuMywwLjUsMC41QzE2LDUsMTYsNS4yLDE2LDUuNnYyLjljMCwwLjIsMCwwLjQsMCwwLjUgYzAsMC4xLDAuMSwwLjIsMC4zLDAuMmMwLjEsMCwwLjIsMCwwLjMsMFY5Ljh6IE0xNS4yLDYuOWMtMS4yLDAuNi0zLjEsMC4yLTMuMSwxLjRjMCwxLjQsMy4xLDEsMy4xLTAuNVY2Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-check: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-circle-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDJDNi40NyAyIDIgNi40NyAyIDEyczQuNDcgMTAgMTAgMTAgMTAtNC40NyAxMC0xMFMxNy41MyAyIDEyIDJ6bTAgMThjLTQuNDEgMC04LTMuNTktOC04czMuNTktOCA4LTggOCAzLjU5IDggOC0zLjU5IDgtOCA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-circle: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iOSIgY3k9IjkiIHI9IjgiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-clear: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8bWFzayBpZD0iZG9udXRIb2xlIj4KICAgIDxyZWN0IHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0id2hpdGUiIC8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSI4IiBmaWxsPSJibGFjayIvPgogIDwvbWFzaz4KCiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxyZWN0IGhlaWdodD0iMTgiIHdpZHRoPSIyIiB4PSIxMSIgeT0iMyIgdHJhbnNmb3JtPSJyb3RhdGUoMzE1LCAxMiwgMTIpIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIgbWFzaz0idXJsKCNkb251dEhvbGUpIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-close: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1ub25lIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIGpwLWljb24zLWhvdmVyIiBmaWxsPSJub25lIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjExIi8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIGpwLWljb24tYWNjZW50Mi1ob3ZlciIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPgogIDwvZz4KCiAgPGcgY2xhc3M9ImpwLWljb24tbm9uZSBqcC1pY29uLWJ1c3kiIGZpbGw9Im5vbmUiPgogICAgPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iNyIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-code: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTExLjQgMTguNkw2LjggMTRMMTEuNCA5LjRMMTAgOEw0IDE0TDEwIDIwTDExLjQgMTguNlpNMTYuNiAxOC42TDIxLjIgMTRMMTYuNiA5LjRMMTggOEwyNCAxNEwxOCAyMEwxNi42IDE4LjZWMTguNloiLz4KCTwvZz4KPC9zdmc+Cg==);--jp-icon-console: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwMCAyMDAiPgogIDxnIGNsYXNzPSJqcC1jb25zb2xlLWljb24tYmFja2dyb3VuZC1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMjg4RDEiPgogICAgPHBhdGggZD0iTTIwIDE5LjhoMTYwdjE1OS45SDIweiIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtY29uc29sZS1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIj4KICAgIDxwYXRoIGQ9Ik0xMDUgMTI3LjNoNDB2MTIuOGgtNDB6TTUxLjEgNzdMNzQgOTkuOWwtMjMuMyAyMy4zIDEwLjUgMTAuNSAyMy4zLTIzLjNMOTUgOTkuOSA4NC41IDg5LjQgNjEuNiA2Ni41eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-copy: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTExLjksMUgzLjJDMi40LDEsMS43LDEuNywxLjcsMi41djEwLjJoMS41VjIuNWg4LjdWMXogTTE0LjEsMy45aC04Yy0wLjgsMC0xLjUsMC43LTEuNSwxLjV2MTAuMmMwLDAuOCwwLjcsMS41LDEuNSwxLjVoOCBjMC44LDAsMS41LTAuNywxLjUtMS41VjUuNEMxNS41LDQuNiwxNC45LDMuOSwxNC4xLDMuOXogTTE0LjEsMTUuNWgtOFY1LjRoOFYxNS41eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-copyright: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCI+CiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0xMS44OCw5LjE0YzEuMjgsMC4wNiwxLjYxLDEuMTUsMS42MywxLjY2aDEuNzljLTAuMDgtMS45OC0xLjQ5LTMuMTktMy40NS0zLjE5QzkuNjQsNy42MSw4LDksOCwxMi4xNCBjMCwxLjk0LDAuOTMsNC4yNCwzLjg0LDQuMjRjMi4yMiwwLDMuNDEtMS42NSwzLjQ0LTIuOTVoLTEuNzljLTAuMDMsMC41OS0wLjQ1LDEuMzgtMS42MywxLjQ0QzEwLjU1LDE0LjgzLDEwLDEzLjgxLDEwLDEyLjE0IEMxMCw5LjI1LDExLjI4LDkuMTYsMTEuODgsOS4xNHogTTEyLDJDNi40OCwyLDIsNi40OCwyLDEyczQuNDgsMTAsMTAsMTBzMTAtNC40OCwxMC0xMFMxNy41MiwyLDEyLDJ6IE0xMiwyMGMtNC40MSwwLTgtMy41OS04LTggczMuNTktOCw4LThzOCwzLjU5LDgsOFMxNi40MSwyMCwxMiwyMHoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-cut: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkuNjQgNy42NGMuMjMtLjUuMzYtMS4wNS4zNi0xLjY0IDAtMi4yMS0xLjc5LTQtNC00UzIgMy43OSAyIDZzMS43OSA0IDQgNGMuNTkgMCAxLjE0LS4xMyAxLjY0LS4zNkwxMCAxMmwtMi4zNiAyLjM2QzcuMTQgMTQuMTMgNi41OSAxNCA2IDE0Yy0yLjIxIDAtNCAxLjc5LTQgNHMxLjc5IDQgNCA0IDQtMS43OSA0LTRjMC0uNTktLjEzLTEuMTQtLjM2LTEuNjRMMTIgMTRsNyA3aDN2LTFMOS42NCA3LjY0ek02IDhjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTAgMTJjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTYtNy41Yy0uMjggMC0uNS0uMjItLjUtLjVzLjIyLS41LjUtLjUuNS4yMi41LjUtLjIyLjUtLjUuNXpNMTkgM2wtNiA2IDIgMiA3LTdWM3oiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-delete: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCI+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjI2MjYyIiBkPSJNNiAxOWMwIDEuMS45IDIgMiAyaDhjMS4xIDAgMi0uOSAyLTJWN0g2djEyek0xOSA0aC0zLjVsLTEtMWgtNWwtMSAxSDV2MmgxNFY0eiIgLz4KPC9zdmc+Cg==);--jp-icon-download: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDloLTRWM0g5djZINWw3IDcgNy03ek01IDE4djJoMTR2LTJINXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-duplicate: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIuNzk5OTggMC44NzVIOC44OTU4MkM5LjIwMDYxIDAuODc1IDkuNDQ5OTggMS4xMzkxNCA5LjQ0OTk4IDEuNDYxOThDOS40NDk5OCAxLjc4NDgyIDkuMjAwNjEgMi4wNDg5NiA4Ljg5NTgyIDIuMDQ4OTZIMy4zNTQxNUMzLjA0OTM2IDIuMDQ4OTYgMi43OTk5OCAyLjMxMzEgMi43OTk5OCAyLjYzNTk0VjkuNjc5NjlDMi43OTk5OCAxMC4wMDI1IDIuNTUwNjEgMTAuMjY2NyAyLjI0NTgyIDEwLjI2NjdDMS45NDEwMyAxMC4yNjY3IDEuNjkxNjUgMTAuMDAyNSAxLjY5MTY1IDkuNjc5NjlWMi4wNDg5NkMxLjY5MTY1IDEuNDAzMjggMi4xOTA0IDAuODc1IDIuNzk5OTggMC44NzVaTTUuMzY2NjUgMTEuOVY0LjU1SDExLjA4MzNWMTEuOUg1LjM2NjY1Wk00LjE0MTY1IDQuMTQxNjdDNC4xNDE2NSAzLjY5MDYzIDQuNTA3MjggMy4zMjUgNC45NTgzMiAzLjMyNUgxMS40OTE3QzExLjk0MjcgMy4zMjUgMTIuMzA4MyAzLjY5MDYzIDEyLjMwODMgNC4xNDE2N1YxMi4zMDgzQzEyLjMwODMgMTIuNzU5NCAxMS45NDI3IDEzLjEyNSAxMS40OTE3IDEzLjEyNUg0Ljk1ODMyQzQuNTA3MjggMTMuMTI1IDQuMTQxNjUgMTIuNzU5NCA0LjE0MTY1IDEyLjMwODNWNC4xNDE2N1oiIGZpbGw9IiM2MTYxNjEiLz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNOS40MzU3NCA4LjI2NTA3SDguMzY0MzFWOS4zMzY1QzguMzY0MzEgOS40NTQzNSA4LjI2Nzg4IDkuNTUwNzggOC4xNTAwMiA5LjU1MDc4QzguMDMyMTcgOS41NTA3OCA3LjkzNTc0IDkuNDU0MzUgNy45MzU3NCA5LjMzNjVWOC4yNjUwN0g2Ljg2NDMxQzYuNzQ2NDUgOC4yNjUwNyA2LjY1MDAyIDguMTY4NjQgNi42NTAwMiA4LjA1MDc4QzYuNjUwMDIgNy45MzI5MiA2Ljc0NjQ1IDcuODM2NSA2Ljg2NDMxIDcuODM2NUg3LjkzNTc0VjYuNzY1MDdDNy45MzU3NCA2LjY0NzIxIDguMDMyMTcgNi41NTA3OCA4LjE1MDAyIDYuNTUwNzhDOC4yNjc4OCA2LjU1MDc4IDguMzY0MzEgNi42NDcyMSA4LjM2NDMxIDYuNzY1MDdWNy44MzY1SDkuNDM1NzRDOS41NTM2IDcuODM2NSA5LjY1MDAyIDcuOTMyOTIgOS42NTAwMiA4LjA1MDc4QzkuNjUwMDIgOC4xNjg2NCA5LjU1MzYgOC4yNjUwNyA5LjQzNTc0IDguMjY1MDdaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC41Ii8+Cjwvc3ZnPgo=);--jp-icon-edit: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMgMTcuMjVWMjFoMy43NUwxNy44MSA5Ljk0bC0zLjc1LTMuNzVMMyAxNy4yNXpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-ellipses: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iNSIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxOSIgY3k9IjEyIiByPSIyIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-extension: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwLjUgMTFIMTlWN2MwLTEuMS0uOS0yLTItMmgtNFYzLjVDMTMgMi4xMiAxMS44OCAxIDEwLjUgMVM4IDIuMTIgOCAzLjVWNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAydjMuOEgzLjVjMS40OSAwIDIuNyAxLjIxIDIuNyAyLjdzLTEuMjEgMi43LTIuNyAyLjdIMlYyMGMwIDEuMS45IDIgMiAyaDMuOHYtMS41YzAtMS40OSAxLjIxLTIuNyAyLjctMi43IDEuNDkgMCAyLjcgMS4yMSAyLjcgMi43VjIySDE3YzEuMSAwIDItLjkgMi0ydi00aDEuNWMxLjM4IDAgMi41LTEuMTIgMi41LTIuNVMyMS44OCAxMSAyMC41IDExeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-fast-forward: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTQgMThsOC41LTZMNCA2djEyem05LTEydjEybDguNS02TDEzIDZ6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-file-upload: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkgMTZoNnYtNmg0bC03LTctNyA3aDR6bS00IDJoMTR2Mkg1eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-file: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuMyA4LjJsLTUuNS01LjVjLS4zLS4zLS43LS41LTEuMi0uNUgzLjljLS44LjEtMS42LjktMS42IDEuOHYxNC4xYzAgLjkuNyAxLjYgMS42IDEuNmgxNC4yYy45IDAgMS42LS43IDEuNi0xLjZWOS40Yy4xLS41LS4xLS45LS40LTEuMnptLTUuOC0zLjNsMy40IDMuNmgtMy40VjQuOXptMy45IDEyLjdINC43Yy0uMSAwLS4yIDAtLjItLjJWNC43YzAtLjIuMS0uMy4yLS4zaDcuMnY0LjRzMCAuOC4zIDEuMWMuMy4zIDEuMS4zIDEuMS4zaDQuM3Y3LjJzLS4xLjItLjIuMnoiLz4KPC9zdmc+Cg==);--jp-icon-filter-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEwIDE4aDR2LTJoLTR2MnpNMyA2djJoMThWNkgzem0zIDdoMTJ2LTJINnYyeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-folder-favorite: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggY2xhc3M9ImpwLWljb24zIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxNjE2MSIgZD0iTTIwIDZoLThsLTItMkg0Yy0xLjEgMC0yIC45LTIgMnYxMmMwIDEuMS45IDIgMiAyaDE2YzEuMSAwIDItLjkgMi0yVjhjMC0xLjEtLjktMi0yLTJ6bS0yLjA2IDExTDE1IDE1LjI4IDEyLjA2IDE3bC43OC0zLjMzLTIuNTktMi4yNCAzLjQxLS4yOUwxNSA4bDEuMzQgMy4xNCAzLjQxLjI5LTIuNTkgMi4yNC43OCAzLjMzeiIvPgo8L3N2Zz4K);--jp-icon-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY4YzAtMS4xLS45LTItMi0yaC04bC0yLTJ6Ii8+Cjwvc3ZnPgo=);--jp-icon-home: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xMCAyMHYtNmg0djZoNXYtOGgzTDEyIDMgMiAxMmgzdjh6Ii8+Cjwvc3ZnPgo=);--jp-icon-html5: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uMCBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMDAiIGQ9Ik0xMDguNCAwaDIzdjIyLjhoMjEuMlYwaDIzdjY5aC0yM1Y0NmgtMjF2MjNoLTIzLjJNMjA2IDIzaC0yMC4zVjBoNjMuN3YyM0gyMjl2NDZoLTIzbTUzLjUtNjloMjQuMWwxNC44IDI0LjNMMzEzLjIgMGgyNC4xdjY5aC0yM1YzNC44bC0xNi4xIDI0LjgtMTYuMS0yNC44VjY5aC0yMi42bTg5LjItNjloMjN2NDYuMmgzMi42VjY5aC01NS42Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2U0NGQyNiIgZD0iTTEwNy42IDQ3MWwtMzMtMzcwLjRoMzYyLjhsLTMzIDM3MC4yTDI1NS43IDUxMiIvPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNmMTY1MjkiIGQ9Ik0yNTYgNDgwLjVWMTMxaDE0OC4zTDM3NiA0NDciLz4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNlYmViZWIiIGQ9Ik0xNDIgMTc2LjNoMTE0djQ1LjRoLTY0LjJsNC4yIDQ2LjVoNjB2NDUuM0gxNTQuNG0yIDIyLjhIMjAybDMuMiAzNi4zIDUwLjggMTMuNnY0Ny40bC05My4yLTI2Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIiBkPSJNMzY5LjYgMTc2LjNIMjU1Ljh2NDUuNGgxMDkuNm0tNC4xIDQ2LjVIMjU1Ljh2NDUuNGg1NmwtNS4zIDU5LTUwLjcgMTMuNnY0Ny4ybDkzLTI1LjgiLz4KPC9zdmc+Cg==);--jp-icon-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1icmFuZDQganAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNGRkYiIGQ9Ik0yLjIgMi4yaDE3LjV2MTcuNUgyLjJ6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzNGNTFCNSIgZD0iTTIuMiAyLjJ2MTcuNWgxNy41bC4xLTE3LjVIMi4yem0xMi4xIDIuMmMxLjIgMCAyLjIgMSAyLjIgMi4ycy0xIDIuMi0yLjIgMi4yLTIuMi0xLTIuMi0yLjIgMS0yLjIgMi4yLTIuMnpNNC40IDE3LjZsMy4zLTguOCAzLjMgNi42IDIuMi0zLjIgNC40IDUuNEg0LjR6Ii8+Cjwvc3ZnPgo=);--jp-icon-inspector: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaW5zcGVjdG9yLWljb24tY29sb3IganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yem0tNSAxNEg0di00aDExdjR6bTAtNUg0VjloMTF2NHptNSA1aC00VjloNHY5eiIvPgo8L3N2Zz4K);--jp-icon-json: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtanNvbi1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0Y5QTgyNSI+CiAgICA8cGF0aCBkPSJNMjAuMiAxMS44Yy0xLjYgMC0xLjcuNS0xLjcgMSAwIC40LjEuOS4xIDEuMy4xLjUuMS45LjEgMS4zIDAgMS43LTEuNCAyLjMtMy41IDIuM2gtLjl2LTEuOWguNWMxLjEgMCAxLjQgMCAxLjQtLjggMC0uMyAwLS42LS4xLTEgMC0uNC0uMS0uOC0uMS0xLjIgMC0xLjMgMC0xLjggMS4zLTItMS4zLS4yLTEuMy0uNy0xLjMtMiAwLS40LjEtLjguMS0xLjIuMS0uNC4xLS43LjEtMSAwLS44LS40LS43LTEuNC0uOGgtLjVWNC4xaC45YzIuMiAwIDMuNS43IDMuNSAyLjMgMCAuNC0uMS45LS4xIDEuMy0uMS41LS4xLjktLjEgMS4zIDAgLjUuMiAxIDEuNyAxdjEuOHpNMS44IDEwLjFjMS42IDAgMS43LS41IDEuNy0xIDAtLjQtLjEtLjktLjEtMS4zLS4xLS41LS4xLS45LS4xLTEuMyAwLTEuNiAxLjQtMi4zIDMuNS0yLjNoLjl2MS45aC0uNWMtMSAwLTEuNCAwLTEuNC44IDAgLjMgMCAuNi4xIDEgMCAuMi4xLjYuMSAxIDAgMS4zIDAgMS44LTEuMyAyQzYgMTEuMiA2IDExLjcgNiAxM2MwIC40LS4xLjgtLjEgMS4yLS4xLjMtLjEuNy0uMSAxIDAgLjguMy44IDEuNC44aC41djEuOWgtLjljLTIuMSAwLTMuNS0uNi0zLjUtMi4zIDAtLjQuMS0uOS4xLTEuMy4xLS41LjEtLjkuMS0xLjMgMC0uNS0uMi0xLTEuNy0xdi0xLjl6Ii8+CiAgICA8Y2lyY2xlIGN4PSIxMSIgY3k9IjEzLjgiIHI9IjIuMSIvPgogICAgPGNpcmNsZSBjeD0iMTEiIGN5PSI4LjIiIHI9IjIuMSIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-julia: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDMyNSAzMDAiPgogIDxnIGNsYXNzPSJqcC1icmFuZDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjY2IzYzMzIj4KICAgIDxwYXRoIGQ9Ik0gMTUwLjg5ODQzOCAyMjUgQyAxNTAuODk4NDM4IDI2Ni40MjE4NzUgMTE3LjMyMDMxMiAzMDAgNzUuODk4NDM4IDMwMCBDIDM0LjQ3NjU2MiAzMDAgMC44OTg0MzggMjY2LjQyMTg3NSAwLjg5ODQzOCAyMjUgQyAwLjg5ODQzOCAxODMuNTc4MTI1IDM0LjQ3NjU2MiAxNTAgNzUuODk4NDM4IDE1MCBDIDExNy4zMjAzMTIgMTUwIDE1MC44OTg0MzggMTgzLjU3ODEyNSAxNTAuODk4NDM4IDIyNSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzM4OTgyNiI+CiAgICA8cGF0aCBkPSJNIDIzNy41IDc1IEMgMjM3LjUgMTE2LjQyMTg3NSAyMDMuOTIxODc1IDE1MCAxNjIuNSAxNTAgQyAxMjEuMDc4MTI1IDE1MCA4Ny41IDExNi40MjE4NzUgODcuNSA3NSBDIDg3LjUgMzMuNTc4MTI1IDEyMS4wNzgxMjUgMCAxNjIuNSAwIEMgMjAzLjkyMTg3NSAwIDIzNy41IDMzLjU3ODEyNSAyMzcuNSA3NSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzk1NThiMiI+CiAgICA8cGF0aCBkPSJNIDMyNC4xMDE1NjIgMjI1IEMgMzI0LjEwMTU2MiAyNjYuNDIxODc1IDI5MC41MjM0MzggMzAwIDI0OS4xMDE1NjIgMzAwIEMgMjA3LjY3OTY4OCAzMDAgMTc0LjEwMTU2MiAyNjYuNDIxODc1IDE3NC4xMDE1NjIgMjI1IEMgMTc0LjEwMTU2MiAxODMuNTc4MTI1IDIwNy42Nzk2ODggMTUwIDI0OS4xMDE1NjIgMTUwIEMgMjkwLjUyMzQzOCAxNTAgMzI0LjEwMTU2MiAxODMuNTc4MTI1IDMyNC4xMDE1NjIgMjI1Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-jupyter-favicon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUyIiBoZWlnaHQ9IjE2NSIgdmlld0JveD0iMCAwIDE1MiAxNjUiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgPGcgY2xhc3M9ImpwLWp1cHl0ZXItaWNvbi1jb2xvciIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA3ODk0NywgMTEwLjU4MjkyNykiIGQ9Ik03NS45NDIyODQyLDI5LjU4MDQ1NjEgQzQzLjMwMjM5NDcsMjkuNTgwNDU2MSAxNC43OTY3ODMyLDE3LjY1MzQ2MzQgMCwwIEM1LjUxMDgzMjExLDE1Ljg0MDY4MjkgMTUuNzgxNTM4OSwyOS41NjY3NzMyIDI5LjM5MDQ5NDcsMzkuMjc4NDE3MSBDNDIuOTk5Nyw0OC45ODk4NTM3IDU5LjI3MzcsNTQuMjA2NzgwNSA3NS45NjA1Nzg5LDU0LjIwNjc4MDUgQzkyLjY0NzQ1NzksNTQuMjA2NzgwNSAxMDguOTIxNDU4LDQ4Ljk4OTg1MzcgMTIyLjUzMDY2MywzOS4yNzg0MTcxIEMxMzYuMTM5NDUzLDI5LjU2Njc3MzIgMTQ2LjQxMDI4NCwxNS44NDA2ODI5IDE1MS45MjExNTgsMCBDMTM3LjA4Nzg2OCwxNy42NTM0NjM0IDEwOC41ODI1ODksMjkuNTgwNDU2MSA3NS45NDIyODQyLDI5LjU4MDQ1NjEgTDc1Ljk0MjI4NDIsMjkuNTgwNDU2MSBaIiAvPgogICAgPHBhdGggdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMzczNjgsIDAuNzA0ODc4KSIgZD0iTTc1Ljk3ODQ1NzksMjQuNjI2NDA3MyBDMTA4LjYxODc2MywyNC42MjY0MDczIDEzNy4xMjQ0NTgsMzYuNTUzNDQxNSAxNTEuOTIxMTU4LDU0LjIwNjc4MDUgQzE0Ni40MTAyODQsMzguMzY2MjIyIDEzNi4xMzk0NTMsMjQuNjQwMTMxNyAxMjIuNTMwNjYzLDE0LjkyODQ4NzggQzEwOC45MjE0NTgsNS4yMTY4NDM5IDkyLjY0NzQ1NzksMCA3NS45NjA1Nzg5LDAgQzU5LjI3MzcsMCA0Mi45OTk3LDUuMjE2ODQzOSAyOS4zOTA0OTQ3LDE0LjkyODQ4NzggQzE1Ljc4MTUzODksMjQuNjQwMTMxNyA1LjUxMDgzMjExLDM4LjM2NjIyMiAwLDU0LjIwNjc4MDUgQzE0LjgzMzA4MTYsMzYuNTg5OTI5MyA0My4zMzg1Njg0LDI0LjYyNjQwNzMgNzUuOTc4NDU3OSwyNC42MjY0MDczIEw3NS45Nzg0NTc5LDI0LjYyNjQwNzMgWiIgLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-jupyter: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzkiIGhlaWdodD0iNTEiIHZpZXdCb3g9IjAgMCAzOSA1MSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTYzOCAtMjI4MSkiPgogICAgIDxnIGNsYXNzPSJqcC1qdXB5dGVyLWljb24tY29sb3IiIGZpbGw9IiNGMzc3MjYiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5Ljc0IDIzMTEuOTgpIiBkPSJNIDE4LjI2NDYgNy4xMzQxMUMgMTAuNDE0NSA3LjEzNDExIDMuNTU4NzIgNC4yNTc2IDAgMEMgMS4zMjUzOSAzLjgyMDQgMy43OTU1NiA3LjEzMDgxIDcuMDY4NiA5LjQ3MzAzQyAxMC4zNDE3IDExLjgxNTIgMTQuMjU1NyAxMy4wNzM0IDE4LjI2OSAxMy4wNzM0QyAyMi4yODIzIDEzLjA3MzQgMjYuMTk2MyAxMS44MTUyIDI5LjQ2OTQgOS40NzMwM0MgMzIuNzQyNCA3LjEzMDgxIDM1LjIxMjYgMy44MjA0IDM2LjUzOCAwQyAzMi45NzA1IDQuMjU3NiAyNi4xMTQ4IDcuMTM0MTEgMTguMjY0NiA3LjEzNDExWiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5LjczIDIyODUuNDgpIiBkPSJNIDE4LjI3MzMgNS45MzkzMUMgMjYuMTIzNSA1LjkzOTMxIDMyLjk3OTMgOC44MTU4MyAzNi41MzggMTMuMDczNEMgMzUuMjEyNiA5LjI1MzAzIDMyLjc0MjQgNS45NDI2MiAyOS40Njk0IDMuNjAwNEMgMjYuMTk2MyAxLjI1ODE4IDIyLjI4MjMgMCAxOC4yNjkgMEMgMTQuMjU1NyAwIDEwLjM0MTcgMS4yNTgxOCA3LjA2ODYgMy42MDA0QyAzLjc5NTU2IDUuOTQyNjIgMS4zMjUzOSA5LjI1MzAzIDAgMTMuMDczNEMgMy41Njc0NSA4LjgyNDYzIDEwLjQyMzIgNS45MzkzMSAxOC4yNzMzIDUuOTM5MzFaIi8+CiAgICA8L2c+CiAgICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjY5LjMgMjI4MS4zMSkiIGQ9Ik0gNS44OTM1MyAyLjg0NEMgNS45MTg4OSAzLjQzMTY1IDUuNzcwODUgNC4wMTM2NyA1LjQ2ODE1IDQuNTE2NDVDIDUuMTY1NDUgNS4wMTkyMiA0LjcyMTY4IDUuNDIwMTUgNC4xOTI5OSA1LjY2ODUxQyAzLjY2NDMgNS45MTY4OCAzLjA3NDQ0IDYuMDAxNTEgMi40OTgwNSA1LjkxMTcxQyAxLjkyMTY2IDUuODIxOSAxLjM4NDYzIDUuNTYxNyAwLjk1NDg5OCA1LjE2NDAxQyAwLjUyNTE3IDQuNzY2MzMgMC4yMjIwNTYgNC4yNDkwMyAwLjA4MzkwMzcgMy42Nzc1N0MgLTAuMDU0MjQ4MyAzLjEwNjExIC0wLjAyMTIzIDIuNTA2MTcgMC4xNzg3ODEgMS45NTM2NEMgMC4zNzg3OTMgMS40MDExIDAuNzM2ODA5IDAuOTIwODE3IDEuMjA3NTQgMC41NzM1MzhDIDEuNjc4MjYgMC4yMjYyNTkgMi4yNDA1NSAwLjAyNzU5MTkgMi44MjMyNiAwLjAwMjY3MjI5QyAzLjYwMzg5IC0wLjAzMDcxMTUgNC4zNjU3MyAwLjI0OTc4OSA0Ljk0MTQyIDAuNzgyNTUxQyA1LjUxNzExIDEuMzE1MzEgNS44NTk1NiAyLjA1Njc2IDUuODkzNTMgMi44NDRaIi8+CiAgICAgIDxwYXRoIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2MzkuOCAyMzIzLjgxKSIgZD0iTSA3LjQyNzg5IDMuNTgzMzhDIDcuNDYwMDggNC4zMjQzIDcuMjczNTUgNS4wNTgxOSA2Ljg5MTkzIDUuNjkyMTNDIDYuNTEwMzEgNi4zMjYwNyA1Ljk1MDc1IDYuODMxNTYgNS4yODQxMSA3LjE0NDZDIDQuNjE3NDcgNy40NTc2MyAzLjg3MzcxIDcuNTY0MTQgMy4xNDcwMiA3LjQ1MDYzQyAyLjQyMDMyIDcuMzM3MTIgMS43NDMzNiA3LjAwODcgMS4yMDE4NCA2LjUwNjk1QyAwLjY2MDMyOCA2LjAwNTIgMC4yNzg2MSA1LjM1MjY4IDAuMTA1MDE3IDQuNjMyMDJDIC0wLjA2ODU3NTcgMy45MTEzNSAtMC4wMjYyMzYxIDMuMTU0OTQgMC4yMjY2NzUgMi40NTg1NkMgMC40Nzk1ODcgMS43NjIxNyAwLjkzMTY5NyAxLjE1NzEzIDEuNTI1NzYgMC43MjAwMzNDIDIuMTE5ODMgMC4yODI5MzUgMi44MjkxNCAwLjAzMzQzOTUgMy41NjM4OSAwLjAwMzEzMzQ0QyA0LjU0NjY3IC0wLjAzNzQwMzMgNS41MDUyOSAwLjMxNjcwNiA2LjIyOTYxIDAuOTg3ODM1QyA2Ljk1MzkzIDEuNjU4OTYgNy4zODQ4NCAyLjU5MjM1IDcuNDI3ODkgMy41ODMzOEwgNy40Mjc4OSAzLjU4MzM4WiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM4LjM2IDIyODYuMDYpIiBkPSJNIDIuMjc0NzEgNC4zOTYyOUMgMS44NDM2MyA0LjQxNTA4IDEuNDE2NzEgNC4zMDQ0NSAxLjA0Nzk5IDQuMDc4NDNDIDAuNjc5MjY4IDMuODUyNCAwLjM4NTMyOCAzLjUyMTE0IDAuMjAzMzcxIDMuMTI2NTZDIDAuMDIxNDEzNiAyLjczMTk4IC0wLjA0MDM3OTggMi4yOTE4MyAwLjAyNTgxMTYgMS44NjE4MUMgMC4wOTIwMDMxIDEuNDMxOCAwLjI4MzIwNCAxLjAzMTI2IDAuNTc1MjEzIDAuNzEwODgzQyAwLjg2NzIyMiAwLjM5MDUxIDEuMjQ2OTEgMC4xNjQ3MDggMS42NjYyMiAwLjA2MjA1OTJDIDIuMDg1NTMgLTAuMDQwNTg5NyAyLjUyNTYxIC0wLjAxNTQ3MTQgMi45MzA3NiAwLjEzNDIzNUMgMy4zMzU5MSAwLjI4Mzk0MSAzLjY4NzkyIDAuNTUxNTA1IDMuOTQyMjIgMC45MDMwNkMgNC4xOTY1MiAxLjI1NDYyIDQuMzQxNjkgMS42NzQzNiA0LjM1OTM1IDIuMTA5MTZDIDQuMzgyOTkgMi42OTEwNyA0LjE3Njc4IDMuMjU4NjkgMy43ODU5NyAzLjY4NzQ2QyAzLjM5NTE2IDQuMTE2MjQgMi44NTE2NiA0LjM3MTE2IDIuMjc0NzEgNC4zOTYyOUwgMi4yNzQ3MSA0LjM5NjI5WiIvPgogICAgPC9nPgogIDwvZz4+Cjwvc3ZnPgo=);--jp-icon-jupyterlab-wordmark: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIHZpZXdCb3g9IjAgMCAxODYwLjggNDc1Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0RTRFNEUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ4MC4xMzY0MDEsIDY0LjI3MTQ5MykiPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDU4Ljg3NTU2NikiPgogICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA4NzYwMywgMC4xNDAyOTQpIj4KICAgICAgICA8cGF0aCBkPSJNLTQyNi45LDE2OS44YzAsNDguNy0zLjcsNjQuNy0xMy42LDc2LjRjLTEwLjgsMTAtMjUsMTUuNS0zOS43LDE1LjVsMy43LDI5IGMyMi44LDAuMyw0NC44LTcuOSw2MS45LTIzLjFjMTcuOC0xOC41LDI0LTQ0LjEsMjQtODMuM1YwSC00Mjd2MTcwLjFMLTQyNi45LDE2OS44TC00MjYuOSwxNjkuOHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTU1LjA0NTI5NiwgNTYuODM3MTA0KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuNTYyNDUzLCAxLjc5OTg0MikiPgogICAgICAgIDxwYXRoIGQ9Ik0tMzEyLDE0OGMwLDIxLDAsMzkuNSwxLjcsNTUuNGgtMzEuOGwtMi4xLTMzLjNoLTAuOGMtNi43LDExLjYtMTYuNCwyMS4zLTI4LDI3LjkgYy0xMS42LDYuNi0yNC44LDEwLTM4LjIsOS44Yy0zMS40LDAtNjktMTcuNy02OS04OVYwaDM2LjR2MTEyLjdjMCwzOC43LDExLjYsNjQuNyw0NC42LDY0LjdjMTAuMy0wLjIsMjAuNC0zLjUsMjguOS05LjQgYzguNS01LjksMTUuMS0xNC4zLDE4LjktMjMuOWMyLjItNi4xLDMuMy0xMi41LDMuMy0xOC45VjAuMmgzNi40VjE0OEgtMzEyTC0zMTIsMTQ4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTAuMDEzMzIyLCA1My40Nzk2MzgpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS43MDY0NTgsIDAuMjMxNDI1KSI+CiAgICAgICAgPHBhdGggZD0iTS00NzguNiw3MS40YzAtMjYtMC44LTQ3LTEuNy02Ni43aDMyLjdsMS43LDM0LjhoMC44YzcuMS0xMi41LDE3LjUtMjIuOCwzMC4xLTI5LjcgYzEyLjUtNywyNi43LTEwLjMsNDEtOS44YzQ4LjMsMCw4NC43LDQxLjcsODQuNywxMDMuM2MwLDczLjEtNDMuNywxMDkuMi05MSwxMDkuMmMtMTIuMSwwLjUtMjQuMi0yLjItMzUtNy44IGMtMTAuOC01LjYtMTkuOS0xMy45LTI2LjYtMjQuMmgtMC44VjI5MWgtMzZ2LTIyMEwtNDc4LjYsNzEuNEwtNDc4LjYsNzEuNHogTS00NDIuNiwxMjUuNmMwLjEsNS4xLDAuNiwxMC4xLDEuNywxNS4xIGMzLDEyLjMsOS45LDIzLjMsMTkuOCwzMS4xYzkuOSw3LjgsMjIuMSwxMi4xLDM0LjcsMTIuMWMzOC41LDAsNjAuNy0zMS45LDYwLjctNzguNWMwLTQwLjctMjEuMS03NS42LTU5LjUtNzUuNiBjLTEyLjksMC40LTI1LjMsNS4xLTM1LjMsMTMuNGMtOS45LDguMy0xNi45LDE5LjctMTkuNiwzMi40Yy0xLjUsNC45LTIuMywxMC0yLjUsMTUuMVYxMjUuNkwtNDQyLjYsMTI1LjZMLTQ0Mi42LDEyNS42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2MDYuNzQwNzI2LCA1Ni44MzcxMDQpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC43NTEyMjYsIDEuOTg5Mjk5KSI+CiAgICAgICAgPHBhdGggZD0iTS00NDAuOCwwbDQzLjcsMTIwLjFjNC41LDEzLjQsOS41LDI5LjQsMTIuOCw0MS43aDAuOGMzLjctMTIuMiw3LjktMjcuNywxMi44LTQyLjQgbDM5LjctMTE5LjJoMzguNUwtMzQ2LjksMTQ1Yy0yNiw2OS43LTQzLjcsMTA1LjQtNjguNiwxMjcuMmMtMTIuNSwxMS43LTI3LjksMjAtNDQuNiwyMy45bC05LjEtMzEuMSBjMTEuNy0zLjksMjIuNS0xMC4xLDMxLjgtMTguMWMxMy4yLTExLjEsMjMuNy0yNS4yLDMwLjYtNDEuMmMxLjUtMi44LDIuNS01LjcsMi45LTguOGMtMC4zLTMuMy0xLjItNi42LTIuNS05LjdMLTQ4MC4yLDAuMSBoMzkuN0wtNDQwLjgsMEwtNDQwLjgsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODIyLjc0ODEwNCwgMC4wMDAwMDApIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS40NjQwNTAsIDAuMzc4OTE0KSI+CiAgICAgICAgPHBhdGggZD0iTS00MTMuNywwdjU4LjNoNTJ2MjguMmgtNTJWMTk2YzAsMjUsNywzOS41LDI3LjMsMzkuNWM3LjEsMC4xLDE0LjItMC43LDIxLjEtMi41IGwxLjcsMjcuN2MtMTAuMywzLjctMjEuMyw1LjQtMzIuMiw1Yy03LjMsMC40LTE0LjYtMC43LTIxLjMtMy40Yy02LjgtMi43LTEyLjktNi44LTE3LjktMTIuMWMtMTAuMy0xMC45LTE0LjEtMjktMTQuMS01Mi45IFY4Ni41aC0zMVY1OC4zaDMxVjkuNkwtNDEzLjcsMEwtNDEzLjcsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTc0LjQzMzI4NiwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAuOTkwMDM0LCAwLjYxMDMzOSkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDQ1LjgsMTEzYzAuOCw1MCwzMi4yLDcwLjYsNjguNiw3MC42YzE5LDAuNiwzNy45LTMsNTUuMy0xMC41bDYuMiwyNi40IGMtMjAuOSw4LjktNDMuNSwxMy4xLTY2LjIsMTIuNmMtNjEuNSwwLTk4LjMtNDEuMi05OC4zLTEwMi41Qy00ODAuMiw0OC4yLTQ0NC43LDAtMzg2LjUsMGM2NS4yLDAsODIuNyw1OC4zLDgyLjcsOTUuNyBjLTAuMSw1LjgtMC41LDExLjUtMS4yLDE3LjJoLTE0MC42SC00NDUuOEwtNDQ1LjgsMTEzeiBNLTMzOS4yLDg2LjZjMC40LTIzLjUtOS41LTYwLjEtNTAuNC02MC4xIGMtMzYuOCwwLTUyLjgsMzQuNC01NS43LDYwLjFILTMzOS4yTC0zMzkuMiw4Ni42TC0zMzkuMiw4Ni42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjAxLjk2MTA1OCwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuMTc5NjQwLCAwLjcwNTA2OCkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDc4LjYsNjhjMC0yMy45LTAuNC00NC41LTEuNy02My40aDMxLjhsMS4yLDM5LjloMS43YzkuMS0yNy4zLDMxLTQ0LjUsNTUuMy00NC41IGMzLjUtMC4xLDcsMC40LDEwLjMsMS4ydjM0LjhjLTQuMS0wLjktOC4yLTEuMy0xMi40LTEuMmMtMjUuNiwwLTQzLjcsMTkuNy00OC43LDQ3LjRjLTEsNS43LTEuNiwxMS41LTEuNywxNy4ydjEwOC4zaC0zNlY2OCBMLTQ3OC42LDY4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi13YXJuMCIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCBkPSJNMTM1Mi4zLDMyNi4yaDM3VjI4aC0zN1YzMjYuMnogTTE2MDQuOCwzMjYuMmMtMi41LTEzLjktMy40LTMxLjEtMy40LTQ4Ljd2LTc2IGMwLTQwLjctMTUuMS04My4xLTc3LjMtODMuMWMtMjUuNiwwLTUwLDcuMS02Ni44LDE4LjFsOC40LDI0LjRjMTQuMy05LjIsMzQtMTUuMSw1My0xNS4xYzQxLjYsMCw0Ni4yLDMwLjIsNDYuMiw0N3Y0LjIgYy03OC42LTAuNC0xMjIuMywyNi41LTEyMi4zLDc1LjZjMCwyOS40LDIxLDU4LjQsNjIuMiw1OC40YzI5LDAsNTAuOS0xNC4zLDYyLjItMzAuMmgxLjNsMi45LDI1LjZIMTYwNC44eiBNMTU2NS43LDI1Ny43IGMwLDMuOC0wLjgsOC0yLjEsMTEuOGMtNS45LDE3LjItMjIuNywzNC00OS4yLDM0Yy0xOC45LDAtMzQuOS0xMS4zLTM0LjktMzUuM2MwLTM5LjUsNDUuOC00Ni42LDg2LjItNDUuOFYyNTcuN3ogTTE2OTguNSwzMjYuMiBsMS43LTMzLjZoMS4zYzE1LjEsMjYuOSwzOC43LDM4LjIsNjguMSwzOC4yYzQ1LjQsMCw5MS4yLTM2LjEsOTEuMi0xMDguOGMwLjQtNjEuNy0zNS4zLTEwMy43LTg1LjctMTAzLjcgYy0zMi44LDAtNTYuMywxNC43LTY5LjMsMzcuNGgtMC44VjI4aC0zNi42djI0NS43YzAsMTguMS0wLjgsMzguNi0xLjcsNTIuNUgxNjk4LjV6IE0xNzA0LjgsMjA4LjJjMC01LjksMS4zLTEwLjksMi4xLTE1LjEgYzcuNi0yOC4xLDMxLjEtNDUuNCw1Ni4zLTQ1LjRjMzkuNSwwLDYwLjUsMzQuOSw2MC41LDc1LjZjMCw0Ni42LTIzLjEsNzguMS02MS44LDc4LjFjLTI2LjksMC00OC4zLTE3LjYtNTUuNS00My4zIGMtMC44LTQuMi0xLjctOC44LTEuNy0xMy40VjIwOC4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgZmlsbD0iIzYxNjE2MSIgZD0iTTE1IDlIOXY2aDZWOXptLTIgNGgtMnYtMmgydjJ6bTgtMlY5aC0yVjdjMC0xLjEtLjktMi0yLTJoLTJWM2gtMnYyaC0yVjNIOXYySDdjLTEuMSAwLTIgLjktMiAydjJIM3YyaDJ2MkgzdjJoMnYyYzAgMS4xLjkgMiAyIDJoMnYyaDJ2LTJoMnYyaDJ2LTJoMmMxLjEgMCAyLS45IDItMnYtMmgydi0yaC0ydi0yaDJ6bS00IDZIN1Y3aDEwdjEweiIvPgo8L3N2Zz4K);--jp-icon-keyboard: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMTdjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY3YzAtMS4xLS45LTItMi0yem0tOSAzaDJ2MmgtMlY4em0wIDNoMnYyaC0ydi0yek04IDhoMnYySDhWOHptMCAzaDJ2Mkg4di0yem0tMSAySDV2LTJoMnYyem0wLTNINVY4aDJ2MnptOSA3SDh2LTJoOHYyem0wLTRoLTJ2LTJoMnYyem0wLTNoLTJWOGgydjJ6bTMgM2gtMnYtMmgydjJ6bTAtM2gtMlY4aDJ2MnoiLz4KPC9zdmc+Cg==);--jp-icon-launch: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzIgMzIiIHdpZHRoPSIzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yNiwyOEg2YTIuMDAyNywyLjAwMjcsMCwwLDEtMi0yVjZBMi4wMDI3LDIuMDAyNywwLDAsMSw2LDRIMTZWNkg2VjI2SDI2VjE2aDJWMjZBMi4wMDI3LDIuMDAyNywwLDAsMSwyNiwyOFoiLz4KICAgIDxwb2x5Z29uIHBvaW50cz0iMjAgMiAyMCA0IDI2LjU4NiA0IDE4IDEyLjU4NiAxOS40MTQgMTQgMjggNS40MTQgMjggMTIgMzAgMTIgMzAgMiAyMCAyIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-launcher: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkgMTlINVY1aDdWM0g1YTIgMiAwIDAwLTIgMnYxNGEyIDIgMCAwMDIgMmgxNGMxLjEgMCAyLS45IDItMnYtN2gtMnY3ek0xNCAzdjJoMy41OWwtOS44MyA5LjgzIDEuNDEgMS40MUwxOSA2LjQxVjEwaDJWM2gtN3oiLz4KPC9zdmc+Cg==);--jp-icon-line-form: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGZpbGw9IndoaXRlIiBkPSJNNS44OCA0LjEyTDEzLjc2IDEybC03Ljg4IDcuODhMOCAyMmwxMC0xMEw4IDJ6Ii8+Cjwvc3ZnPgo=);--jp-icon-link: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMuOSAxMmMwLTEuNzEgMS4zOS0zLjEgMy4xLTMuMWg0VjdIN2MtMi43NiAwLTUgMi4yNC01IDVzMi4yNCA1IDUgNWg0di0xLjlIN2MtMS43MSAwLTMuMS0xLjM5LTMuMS0zLjF6TTggMTNoOHYtMkg4djJ6bTktNmgtNHYxLjloNGMxLjcxIDAgMy4xIDEuMzkgMy4xIDMuMXMtMS4zOSAzLjEtMy4xIDMuMWgtNFYxN2g0YzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xOSA1djE0SDVWNWgxNG0xLjEtMkgzLjljLS41IDAtLjkuNC0uOS45djE2LjJjMCAuNC40LjkuOS45aDE2LjJjLjQgMCAuOS0uNS45LS45VjMuOWMwLS41LS41LS45LS45LS45ek0xMSA3aDZ2MmgtNlY3em0wIDRoNnYyaC02di0yem0wIDRoNnYyaC02ek03IDdoMnYySDd6bTAgNGgydjJIN3ptMCA0aDJ2Mkg3eiIvPgo8L3N2Zz4=);--jp-icon-listings-info: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MC45NzggNTAuOTc4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MC45NzggNTAuOTc4OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+Cgk8Zz4KCQk8cGF0aCBzdHlsZT0iZmlsbDojMDEwMDAyOyIgZD0iTTQzLjUyLDcuNDU4QzM4LjcxMSwyLjY0OCwzMi4zMDcsMCwyNS40ODksMEMxOC42NywwLDEyLjI2NiwyLjY0OCw3LjQ1OCw3LjQ1OAoJCQljLTkuOTQzLDkuOTQxLTkuOTQzLDI2LjExOSwwLDM2LjA2MmM0LjgwOSw0LjgwOSwxMS4yMTIsNy40NTYsMTguMDMxLDcuNDU4YzAsMCwwLjAwMSwwLDAuMDAyLDAKCQkJYzYuODE2LDAsMTMuMjIxLTIuNjQ4LDE4LjAyOS03LjQ1OGM0LjgwOS00LjgwOSw3LjQ1Ny0xMS4yMTIsNy40NTctMTguMDNDNTAuOTc3LDE4LjY3LDQ4LjMyOCwxMi4yNjYsNDMuNTIsNy40NTh6CgkJCSBNNDIuMTA2LDQyLjEwNWMtNC40MzIsNC40MzEtMTAuMzMyLDYuODcyLTE2LjYxNSw2Ljg3MmgtMC4wMDJjLTYuMjg1LTAuMDAxLTEyLjE4Ny0yLjQ0MS0xNi42MTctNi44NzIKCQkJYy05LjE2Mi05LjE2My05LjE2Mi0yNC4wNzEsMC0zMy4yMzNDMTMuMzAzLDQuNDQsMTkuMjA0LDIsMjUuNDg5LDJjNi4yODQsMCwxMi4xODYsMi40NCwxNi42MTcsNi44NzIKCQkJYzQuNDMxLDQuNDMxLDYuODcxLDEwLjMzMiw2Ljg3MSwxNi42MTdDNDguOTc3LDMxLjc3Miw0Ni41MzYsMzcuNjc1LDQyLjEwNiw0Mi4xMDV6Ii8+CgkJPHBhdGggc3R5bGU9ImZpbGw6IzAxMDAwMjsiIGQ9Ik0yMy41NzgsMzIuMjE4Yy0wLjAyMy0xLjczNCwwLjE0My0zLjA1OSwwLjQ5Ni0zLjk3MmMwLjM1My0wLjkxMywxLjExLTEuOTk3LDIuMjcyLTMuMjUzCgkJCWMwLjQ2OC0wLjUzNiwwLjkyMy0xLjA2MiwxLjM2Ny0xLjU3NWMwLjYyNi0wLjc1MywxLjEwNC0xLjQ3OCwxLjQzNi0yLjE3NWMwLjMzMS0wLjcwNywwLjQ5NS0xLjU0MSwwLjQ5NS0yLjUKCQkJYzAtMS4wOTYtMC4yNi0yLjA4OC0wLjc3OS0yLjk3OWMtMC41NjUtMC44NzktMS41MDEtMS4zMzYtMi44MDYtMS4zNjljLTEuODAyLDAuMDU3LTIuOTg1LDAuNjY3LTMuNTUsMS44MzIKCQkJYy0wLjMwMSwwLjUzNS0wLjUwMywxLjE0MS0wLjYwNywxLjgxNGMtMC4xMzksMC43MDctMC4yMDcsMS40MzItMC4yMDcsMi4xNzRoLTIuOTM3Yy0wLjA5MS0yLjIwOCwwLjQwNy00LjExNCwxLjQ5My01LjcxOQoJCQljMS4wNjItMS42NCwyLjg1NS0yLjQ4MSw1LjM3OC0yLjUyN2MyLjE2LDAuMDIzLDMuODc0LDAuNjA4LDUuMTQxLDEuNzU4YzEuMjc4LDEuMTYsMS45MjksMi43NjQsMS45NSw0LjgxMQoJCQljMCwxLjE0Mi0wLjEzNywyLjExMS0wLjQxLDIuOTExYy0wLjMwOSwwLjg0NS0wLjczMSwxLjU5My0xLjI2OCwyLjI0M2MtMC40OTIsMC42NS0xLjA2OCwxLjMxOC0xLjczLDIuMDAyCgkJCWMtMC42NSwwLjY5Ny0xLjMxMywxLjQ3OS0xLjk4NywyLjM0NmMtMC4yMzksMC4zNzctMC40MjksMC43NzctMC41NjUsMS4xOTljLTAuMTYsMC45NTktMC4yMTcsMS45NTEtMC4xNzEsMi45NzkKCQkJQzI2LjU4OSwzMi4yMTgsMjMuNTc4LDMyLjIxOCwyMy41NzgsMzIuMjE4eiBNMjMuNTc4LDM4LjIydi0zLjQ4NGgzLjA3NnYzLjQ4NEgyMy41Nzh6Ii8+Cgk8L2c+Cjwvc3ZnPgo=);--jp-icon-markdown: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjN0IxRkEyIiBkPSJNNSAxNC45aDEybC02LjEgNnptOS40LTYuOGMwLTEuMy0uMS0yLjktLjEtNC41LS40IDEuNC0uOSAyLjktMS4zIDQuM2wtMS4zIDQuM2gtMkw4LjUgNy45Yy0uNC0xLjMtLjctMi45LTEtNC4zLS4xIDEuNi0uMSAzLjItLjIgNC42TDcgMTIuNEg0LjhsLjctMTFoMy4zTDEwIDVjLjQgMS4yLjcgMi43IDEgMy45LjMtMS4yLjctMi42IDEtMy45bDEuMi0zLjdoMy4zbC42IDExaC0yLjRsLS4zLTQuMnoiLz4KPC9zdmc+Cg==);--jp-icon-move-down: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMTIuNDcxIDcuNTI4OTlDMTIuNzYzMiA3LjIzNjg0IDEyLjc2MzIgNi43NjMxNiAxMi40NzEgNi40NzEwMVY2LjQ3MTAxQzEyLjE3OSA2LjE3OTA1IDExLjcwNTcgNi4xNzg4NCAxMS40MTM1IDYuNDcwNTRMNy43NSAxMC4xMjc1VjEuNzVDNy43NSAxLjMzNTc5IDcuNDE0MjEgMSA3IDFWMUM2LjU4NTc5IDEgNi4yNSAxLjMzNTc5IDYuMjUgMS43NVYxMC4xMjc1TDIuNTk3MjYgNi40NjgyMkMyLjMwMzM4IDYuMTczODEgMS44MjY0MSA2LjE3MzU5IDEuNTMyMjYgNi40Njc3NFY2LjQ2Nzc0QzEuMjM4MyA2Ljc2MTcgMS4yMzgzIDcuMjM4MyAxLjUzMjI2IDcuNTMyMjZMNi4yOTI4OSAxMi4yOTI5QzYuNjgzNDIgMTIuNjgzNCA3LjMxNjU4IDEyLjY4MzQgNy43MDcxMSAxMi4yOTI5TDEyLjQ3MSA3LjUyODk5WiIgZmlsbD0iIzYxNjE2MSIvPgo8L3N2Zz4K);--jp-icon-move-up: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMS41Mjg5OSA2LjQ3MTAxQzEuMjM2ODQgNi43NjMxNiAxLjIzNjg0IDcuMjM2ODQgMS41Mjg5OSA3LjUyODk5VjcuNTI4OTlDMS44MjA5NSA3LjgyMDk1IDIuMjk0MjYgNy44MjExNiAyLjU4NjQ5IDcuNTI5NDZMNi4yNSAzLjg3MjVWMTIuMjVDNi4yNSAxMi42NjQyIDYuNTg1NzkgMTMgNyAxM1YxM0M3LjQxNDIxIDEzIDcuNzUgMTIuNjY0MiA3Ljc1IDEyLjI1VjMuODcyNUwxMS40MDI3IDcuNTMxNzhDMTEuNjk2NiA3LjgyNjE5IDEyLjE3MzYgNy44MjY0MSAxMi40Njc3IDcuNTMyMjZWNy41MzIyNkMxMi43NjE3IDcuMjM4MyAxMi43NjE3IDYuNzYxNyAxMi40Njc3IDYuNDY3NzRMNy43MDcxMSAxLjcwNzExQzcuMzE2NTggMS4zMTY1OCA2LjY4MzQyIDEuMzE2NTggNi4yOTI4OSAxLjcwNzExTDEuNTI4OTkgNi40NzEwMVoiIGZpbGw9IiM2MTYxNjEiLz4KPC9zdmc+Cg==);--jp-icon-new-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwIDZoLThsLTItMkg0Yy0xLjExIDAtMS45OS44OS0xLjk5IDJMMiAxOGMwIDEuMTEuODkgMiAyIDJoMTZjMS4xMSAwIDItLjg5IDItMlY4YzAtMS4xMS0uODktMi0yLTJ6bS0xIDhoLTN2M2gtMnYtM2gtM3YtMmgzVjloMnYzaDN2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-not-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI1IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMTkgMTcuMTg0NCAyLjk2OTY4IDE0LjMwMzIgMS44NjA5NCAxMS40NDA5WiIvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24yIiBzdHJva2U9IiMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4zMTU5MiA5LjMyMDMxKSIgZD0iTTcuMzY4NDIgMEwwIDcuMzY0NzkiLz4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMzE1OTIgMTYuNjgzNikgc2NhbGUoMSAtMSkiIGQ9Ik03LjM2ODQyIDBMMCA3LjM2NDc5Ii8+Cjwvc3ZnPgo=);--jp-icon-notebook: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtbm90ZWJvb2staWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNFRjZDMDAiPgogICAgPHBhdGggZD0iTTE4LjcgMy4zdjE1LjRIMy4zVjMuM2gxNS40bTEuNS0xLjVIMS44djE4LjNoMTguM2wuMS0xOC4zeiIvPgogICAgPHBhdGggZD0iTTE2LjUgMTYuNWwtNS40LTQuMy01LjYgNC4zdi0xMWgxMXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-numbering: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTQgMTlINlYxOS41SDVWMjAuNUg2VjIxSDRWMjJIN1YxOEg0VjE5Wk01IDEwSDZWNkg0VjdINVYxMFpNNCAxM0g1LjhMNCAxNS4xVjE2SDdWMTVINS4yTDcgMTIuOVYxMkg0VjEzWk05IDdWOUgyM1Y3SDlaTTkgMjFIMjNWMTlIOVYyMVpNOSAxNUgyM1YxM0g5VjE1WiIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-offline-bolt: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDIuMDJjLTUuNTEgMC05Ljk4IDQuNDctOS45OCA5Ljk4czQuNDcgOS45OCA5Ljk4IDkuOTggOS45OC00LjQ3IDkuOTgtOS45OFMxNy41MSAyLjAyIDEyIDIuMDJ6TTExLjQ4IDIwdi02LjI2SDhMMTMgNHY2LjI2aDMuMzVMMTEuNDggMjB6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-palette: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE4IDEzVjIwSDRWNkg5LjAyQzkuMDcgNS4yOSA5LjI0IDQuNjIgOS41IDRINEMyLjkgNCAyIDQuOSAyIDZWMjBDMiAyMS4xIDIuOSAyMiA0IDIySDE4QzE5LjEgMjIgMjAgMjEuMSAyMCAyMFYxNUwxOCAxM1pNMTkuMyA4Ljg5QzE5Ljc0IDguMTkgMjAgNy4zOCAyMCA2LjVDMjAgNC4wMSAxNy45OSAyIDE1LjUgMkMxMy4wMSAyIDExIDQuMDEgMTEgNi41QzExIDguOTkgMTMuMDEgMTEgMTUuNDkgMTFDMTYuMzcgMTEgMTcuMTkgMTAuNzQgMTcuODggMTAuM0wyMSAxMy40MkwyMi40MiAxMkwxOS4zIDguODlaTTE1LjUgOUMxNC4xMiA5IDEzIDcuODggMTMgNi41QzEzIDUuMTIgMTQuMTIgNCAxNS41IDRDMTYuODggNCAxOCA1LjEyIDE4IDYuNUMxOCA3Ljg4IDE2Ljg4IDkgMTUuNSA5WiIvPgogICAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDZIOS4wMTg5NEM5LjAwNjM5IDYuMTY1MDIgOSA2LjMzMTc2IDkgNi41QzkgOC44MTU3NyAxMC4yMTEgMTAuODQ4NyAxMi4wMzQzIDEySDlWMTRIMTZWMTIuOTgxMUMxNi41NzAzIDEyLjkzNzcgMTcuMTIgMTIuODIwNyAxNy42Mzk2IDEyLjYzOTZMMTggMTNWMjBINFY2Wk04IDhINlYxMEg4VjhaTTYgMTJIOFYxNEg2VjEyWk04IDE2SDZWMThIOFYxNlpNOSAxNkgxNlYxOEg5VjE2WiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-paste: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE5IDJoLTQuMThDMTQuNC44NCAxMy4zIDAgMTIgMGMtMS4zIDAtMi40Ljg0LTIuODIgMkg1Yy0xLjEgMC0yIC45LTIgMnYxNmMwIDEuMS45IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6bS03IDBjLjU1IDAgMSAuNDUgMSAxcy0uNDUgMS0xIDEtMS0uNDUtMS0xIC40NS0xIDEtMXptNyAxOEg1VjRoMnYzaDEwVjRoMnYxNnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);--jp-icon-pdf: url(data:image/svg+xml;base64,PHN2ZwogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMiAyMiIgd2lkdGg9IjE2Ij4KICAgIDxwYXRoIHRyYW5zZm9ybT0icm90YXRlKDQ1KSIgY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0ZGMkEyQSIKICAgICAgIGQ9Im0gMjIuMzQ0MzY5LC0zLjAxNjM2NDIgaCA1LjYzODYwNCB2IDEuNTc5MjQzMyBoIC0zLjU0OTIyNyB2IDEuNTA4NjkyOTkgaCAzLjMzNzU3NiBWIDEuNjUwODE1NCBoIC0zLjMzNzU3NiB2IDMuNDM1MjYxMyBoIC0yLjA4OTM3NyB6IG0gLTcuMTM2NDQ0LDEuNTc5MjQzMyB2IDQuOTQzOTU0MyBoIDAuNzQ4OTIgcSAxLjI4MDc2MSwwIDEuOTUzNzAzLC0wLjYzNDk1MzUgMC42NzgzNjksLTAuNjM0OTUzNSAwLjY3ODM2OSwtMS44NDUxNjQxIDAsLTEuMjA0NzgzNTUgLTAuNjcyOTQyLC0xLjgzNDMxMDExIC0wLjY3Mjk0MiwtMC42Mjk1MjY1OSAtMS45NTkxMywtMC42Mjk1MjY1OSB6IG0gLTIuMDg5Mzc3LC0xLjU3OTI0MzMgaCAyLjIwMzM0MyBxIDEuODQ1MTY0LDAgMi43NDYwMzksMC4yNjU5MjA3IDAuOTA2MzAxLDAuMjYwNDkzNyAxLjU1MjEwOCwwLjg5MDAyMDMgMC41Njk4MywwLjU0ODEyMjMgMC44NDY2MDUsMS4yNjQ0ODAwNiAwLjI3Njc3NCwwLjcxNjM1NzgxIDAuMjc2Nzc0LDEuNjIyNjU4OTQgMCwwLjkxNzE1NTEgLTAuMjc2Nzc0LDEuNjM4OTM5OSAtMC4yNzY3NzUsMC43MTYzNTc4IC0wLjg0NjYwNSwxLjI2NDQ4IC0wLjY1MTIzNCwwLjYyOTUyNjYgLTEuNTYyOTYyLDAuODk1NDQ3MyAtMC45MTE3MjgsMC4yNjA0OTM3IC0yLjczNTE4NSwwLjI2MDQ5MzcgaCAtMi4yMDMzNDMgeiBtIC04LjE0NTg1NjUsMCBoIDMuNDY3ODIzIHEgMS41NDY2ODE2LDAgMi4zNzE1Nzg1LDAuNjg5MjIzIDAuODMwMzI0LDAuNjgzNzk2MSAwLjgzMDMyNCwxLjk1MzcwMzE0IDAsMS4yNzUzMzM5NyAtMC44MzAzMjQsMS45NjQ1NTcwNiBRIDkuOTg3MTk2MSwyLjI3NDkxNSA4LjQ0MDUxNDUsMi4yNzQ5MTUgSCA3LjA2MjA2ODQgViA1LjA4NjA3NjcgSCA0Ljk3MjY5MTUgWiBtIDIuMDg5Mzc2OSwxLjUxNDExOTkgdiAyLjI2MzAzOTQzIGggMS4xNTU5NDEgcSAwLjYwNzgxODgsMCAwLjkzODg2MjksLTAuMjkzMDU1NDcgMC4zMzEwNDQxLC0wLjI5ODQ4MjQxIDAuMzMxMDQ0MSwtMC44NDExNzc3MiAwLC0wLjU0MjY5NTMxIC0wLjMzMTA0NDEsLTAuODM1NzUwNzQgLTAuMzMxMDQ0MSwtMC4yOTMwNTU1IC0wLjkzODg2MjksLTAuMjkzMDU1NSB6IgovPgo8L3N2Zz4K);--jp-icon-python: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iLTEwIC0xMCAxMzEuMTYxMzYxNjk0MzM1OTQgMTMyLjM4ODk5OTkzODk2NDg0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzA2OTk4IiBkPSJNIDU0LjkxODc4NSw5LjE5Mjc0MjFlLTQgQyA1MC4zMzUxMzIsMC4wMjIyMTcyNyA0NS45NTc4NDYsMC40MTMxMzY5NyA0Mi4xMDYyODUsMS4wOTQ2NjkzIDMwLjc2MDA2OSwzLjA5OTE3MzEgMjguNzAwMDM2LDcuMjk0NzcxNCAyOC43MDAwMzUsMTUuMDMyMTY5IHYgMTAuMjE4NzUgaCAyNi44MTI1IHYgMy40MDYyNSBoIC0yNi44MTI1IC0xMC4wNjI1IGMgLTcuNzkyNDU5LDAgLTE0LjYxNTc1ODgsNC42ODM3MTcgLTE2Ljc0OTk5OTgsMTMuNTkzNzUgLTIuNDYxODE5OTgsMTAuMjEyOTY2IC0yLjU3MTAxNTA4LDE2LjU4NjAyMyAwLDI3LjI1IDEuOTA1OTI4Myw3LjkzNzg1MiA2LjQ1NzU0MzIsMTMuNTkzNzQ4IDE0LjI0OTk5OTgsMTMuNTkzNzUgaCA5LjIxODc1IHYgLTEyLjI1IGMgMCwtOC44NDk5MDIgNy42NTcxNDQsLTE2LjY1NjI0OCAxNi43NSwtMTYuNjU2MjUgaCAyNi43ODEyNSBjIDcuNDU0OTUxLDAgMTMuNDA2MjUzLC02LjEzODE2NCAxMy40MDYyNSwtMTMuNjI1IHYgLTI1LjUzMTI1IGMgMCwtNy4yNjYzMzg2IC02LjEyOTk4LC0xMi43MjQ3NzcxIC0xMy40MDYyNSwtMTMuOTM3NDk5NyBDIDY0LjI4MTU0OCwwLjMyNzk0Mzk3IDU5LjUwMjQzOCwtMC4wMjAzNzkwMyA1NC45MTg3ODUsOS4xOTI3NDIxZS00IFogbSAtMTQuNSw4LjIxODc1MDEyNTc5IGMgMi43Njk1NDcsMCA1LjAzMTI1LDIuMjk4NjQ1NiA1LjAzMTI1LDUuMTI0OTk5NiAtMmUtNiwyLjgxNjMzNiAtMi4yNjE3MDMsNS4wOTM3NSAtNS4wMzEyNSw1LjA5Mzc1IC0yLjc3OTQ3NiwtMWUtNiAtNS4wMzEyNSwtMi4yNzc0MTUgLTUuMDMxMjUsLTUuMDkzNzUgLTEwZS03LC0yLjgyNjM1MyAyLjI1MTc3NCwtNS4xMjQ5OTk2IDUuMDMxMjUsLTUuMTI0OTk5NiB6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2ZmZDQzYiIgZD0ibSA4NS42Mzc1MzUsMjguNjU3MTY5IHYgMTEuOTA2MjUgYyAwLDkuMjMwNzU1IC03LjgyNTg5NSwxNi45OTk5OTkgLTE2Ljc1LDE3IGggLTI2Ljc4MTI1IGMgLTcuMzM1ODMzLDAgLTEzLjQwNjI0OSw2LjI3ODQ4MyAtMTMuNDA2MjUsMTMuNjI1IHYgMjUuNTMxMjQ3IGMgMCw3LjI2NjM0NCA2LjMxODU4OCwxMS41NDAzMjQgMTMuNDA2MjUsMTMuNjI1MDA0IDguNDg3MzMxLDIuNDk1NjEgMTYuNjI2MjM3LDIuOTQ2NjMgMjYuNzgxMjUsMCA2Ljc1MDE1NSwtMS45NTQzOSAxMy40MDYyNTMsLTUuODg3NjEgMTMuNDA2MjUsLTEzLjYyNTAwNCBWIDg2LjUwMDkxOSBoIC0yNi43ODEyNSB2IC0zLjQwNjI1IGggMjYuNzgxMjUgMTMuNDA2MjU0IGMgNy43OTI0NjEsMCAxMC42OTYyNTEsLTUuNDM1NDA4IDEzLjQwNjI0MSwtMTMuNTkzNzUgMi43OTkzMywtOC4zOTg4ODYgMi42ODAyMiwtMTYuNDc1Nzc2IDAsLTI3LjI1IC0xLjkyNTc4LC03Ljc1NzQ0MSAtNS42MDM4NywtMTMuNTkzNzUgLTEzLjQwNjI0MSwtMTMuNTkzNzUgeiBtIC0xNS4wNjI1LDY0LjY1NjI1IGMgMi43Nzk0NzgsM2UtNiA1LjAzMTI1LDIuMjc3NDE3IDUuMDMxMjUsNS4wOTM3NDcgLTJlLTYsMi44MjYzNTQgLTIuMjUxNzc1LDUuMTI1MDA0IC01LjAzMTI1LDUuMTI1MDA0IC0yLjc2OTU1LDAgLTUuMDMxMjUsLTIuMjk4NjUgLTUuMDMxMjUsLTUuMTI1MDA0IDJlLTYsLTIuODE2MzMgMi4yNjE2OTcsLTUuMDkzNzQ3IDUuMDMxMjUsLTUuMDkzNzQ3IHoiLz4KPC9zdmc+Cg==);--jp-icon-r-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjE5NkYzIiBkPSJNNC40IDIuNWMxLjItLjEgMi45LS4zIDQuOS0uMyAyLjUgMCA0LjEuNCA1LjIgMS4zIDEgLjcgMS41IDEuOSAxLjUgMy41IDAgMi0xLjQgMy41LTIuOSA0LjEgMS4yLjQgMS43IDEuNiAyLjIgMyAuNiAxLjkgMSAzLjkgMS4zIDQuNmgtMy44Yy0uMy0uNC0uOC0xLjctMS4yLTMuN3MtMS4yLTIuNi0yLjYtMi42aC0uOXY2LjRINC40VjIuNXptMy43IDYuOWgxLjRjMS45IDAgMi45LS45IDIuOS0yLjNzLTEtMi4zLTIuOC0yLjNjLS43IDAtMS4zIDAtMS42LjJ2NC41aC4xdi0uMXoiLz4KPC9zdmc+Cg==);--jp-icon-react: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMTUwIDE1MCA1NDEuOSAyOTUuMyI+CiAgPGcgY2xhc3M9ImpwLWljb24tYnJhbmQyIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxREFGQiI+CiAgICA8cGF0aCBkPSJNNjY2LjMgMjk2LjVjMC0zMi41LTQwLjctNjMuMy0xMDMuMS04Mi40IDE0LjQtNjMuNiA4LTExNC4yLTIwLjItMTMwLjQtNi41LTMuOC0xNC4xLTUuNi0yMi40LTUuNnYyMi4zYzQuNiAwIDguMy45IDExLjQgMi42IDEzLjYgNy44IDE5LjUgMzcuNSAxNC45IDc1LjctMS4xIDkuNC0yLjkgMTkuMy01LjEgMjkuNC0xOS42LTQuOC00MS04LjUtNjMuNS0xMC45LTEzLjUtMTguNS0yNy41LTM1LjMtNDEuNi01MCAzMi42LTMwLjMgNjMuMi00Ni45IDg0LTQ2LjlWNzhjLTI3LjUgMC02My41IDE5LjYtOTkuOSA1My42LTM2LjQtMzMuOC03Mi40LTUzLjItOTkuOS01My4ydjIyLjNjMjAuNyAwIDUxLjQgMTYuNSA4NCA0Ni42LTE0IDE0LjctMjggMzEuNC00MS4zIDQ5LjktMjIuNiAyLjQtNDQgNi4xLTYzLjYgMTEtMi4zLTEwLTQtMTkuNy01LjItMjktNC43LTM4LjIgMS4xLTY3LjkgMTQuNi03NS44IDMtMS44IDYuOS0yLjYgMTEuNS0yLjZWNzguNWMtOC40IDAtMTYgMS44LTIyLjYgNS42LTI4LjEgMTYuMi0zNC40IDY2LjctMTkuOSAxMzAuMS02Mi4yIDE5LjItMTAyLjcgNDkuOS0xMDIuNyA4Mi4zIDAgMzIuNSA0MC43IDYzLjMgMTAzLjEgODIuNC0xNC40IDYzLjYtOCAxMTQuMiAyMC4yIDEzMC40IDYuNSAzLjggMTQuMSA1LjYgMjIuNSA1LjYgMjcuNSAwIDYzLjUtMTkuNiA5OS45LTUzLjYgMzYuNCAzMy44IDcyLjQgNTMuMiA5OS45IDUzLjIgOC40IDAgMTYtMS44IDIyLjYtNS42IDI4LjEtMTYuMiAzNC40LTY2LjcgMTkuOS0xMzAuMSA2Mi0xOS4xIDEwMi41LTQ5LjkgMTAyLjUtODIuM3ptLTEzMC4yLTY2LjdjLTMuNyAxMi45LTguMyAyNi4yLTEzLjUgMzkuNS00LjEtOC04LjQtMTYtMTMuMS0yNC00LjYtOC05LjUtMTUuOC0xNC40LTIzLjQgMTQuMiAyLjEgMjcuOSA0LjcgNDEgNy45em0tNDUuOCAxMDYuNWMtNy44IDEzLjUtMTUuOCAyNi4zLTI0LjEgMzguMi0xNC45IDEuMy0zMCAyLTQ1LjIgMi0xNS4xIDAtMzAuMi0uNy00NS0xLjktOC4zLTExLjktMTYuNC0yNC42LTI0LjItMzgtNy42LTEzLjEtMTQuNS0yNi40LTIwLjgtMzkuOCA2LjItMTMuNCAxMy4yLTI2LjggMjAuNy0zOS45IDcuOC0xMy41IDE1LjgtMjYuMyAyNC4xLTM4LjIgMTQuOS0xLjMgMzAtMiA0NS4yLTIgMTUuMSAwIDMwLjIuNyA0NSAxLjkgOC4zIDExLjkgMTYuNCAyNC42IDI0LjIgMzggNy42IDEzLjEgMTQuNSAyNi40IDIwLjggMzkuOC02LjMgMTMuNC0xMy4yIDI2LjgtMjAuNyAzOS45em0zMi4zLTEzYzUuNCAxMy40IDEwIDI2LjggMTMuOCAzOS44LTEzLjEgMy4yLTI2LjkgNS45LTQxLjIgOCA0LjktNy43IDkuOC0xNS42IDE0LjQtMjMuNyA0LjYtOCA4LjktMTYuMSAxMy0yNC4xek00MjEuMiA0MzBjLTkuMy05LjYtMTguNi0yMC4zLTI3LjgtMzIgOSAuNCAxOC4yLjcgMjcuNS43IDkuNCAwIDE4LjctLjIgMjcuOC0uNy05IDExLjctMTguMyAyMi40LTI3LjUgMzJ6bS03NC40LTU4LjljLTE0LjItMi4xLTI3LjktNC43LTQxLTcuOSAzLjctMTIuOSA4LjMtMjYuMiAxMy41LTM5LjUgNC4xIDggOC40IDE2IDEzLjEgMjQgNC43IDggOS41IDE1LjggMTQuNCAyMy40ek00MjAuNyAxNjNjOS4zIDkuNiAxOC42IDIwLjMgMjcuOCAzMi05LS40LTE4LjItLjctMjcuNS0uNy05LjQgMC0xOC43LjItMjcuOC43IDktMTEuNyAxOC4zLTIyLjQgMjcuNS0zMnptLTc0IDU4LjljLTQuOSA3LjctOS44IDE1LjYtMTQuNCAyMy43LTQuNiA4LTguOSAxNi0xMyAyNC01LjQtMTMuNC0xMC0yNi44LTEzLjgtMzkuOCAxMy4xLTMuMSAyNi45LTUuOCA0MS4yLTcuOXptLTkwLjUgMTI1LjJjLTM1LjQtMTUuMS01OC4zLTM0LjktNTguMy01MC42IDAtMTUuNyAyMi45LTM1LjYgNTguMy01MC42IDguNi0zLjcgMTgtNyAyNy43LTEwLjEgNS43IDE5LjYgMTMuMiA0MCAyMi41IDYwLjktOS4yIDIwLjgtMTYuNiA0MS4xLTIyLjIgNjAuNi05LjktMy4xLTE5LjMtNi41LTI4LTEwLjJ6TTMxMCA0OTBjLTEzLjYtNy44LTE5LjUtMzcuNS0xNC45LTc1LjcgMS4xLTkuNCAyLjktMTkuMyA1LjEtMjkuNCAxOS42IDQuOCA0MSA4LjUgNjMuNSAxMC45IDEzLjUgMTguNSAyNy41IDM1LjMgNDEuNiA1MC0zMi42IDMwLjMtNjMuMiA0Ni45LTg0IDQ2LjktNC41LS4xLTguMy0xLTExLjMtMi43em0yMzcuMi03Ni4yYzQuNyAzOC4yLTEuMSA2Ny45LTE0LjYgNzUuOC0zIDEuOC02LjkgMi42LTExLjUgMi42LTIwLjcgMC01MS40LTE2LjUtODQtNDYuNiAxNC0xNC43IDI4LTMxLjQgNDEuMy00OS45IDIyLjYtMi40IDQ0LTYuMSA2My42LTExIDIuMyAxMC4xIDQuMSAxOS44IDUuMiAyOS4xem0zOC41LTY2LjdjLTguNiAzLjctMTggNy0yNy43IDEwLjEtNS43LTE5LjYtMTMuMi00MC0yMi41LTYwLjkgOS4yLTIwLjggMTYuNi00MS4xIDIyLjItNjAuNiA5LjkgMy4xIDE5LjMgNi41IDI4LjEgMTAuMiAzNS40IDE1LjEgNTguMyAzNC45IDU4LjMgNTAuNi0uMSAxNS43LTIzIDM1LjYtNTguNCA1MC42ek0zMjAuOCA3OC40eiIvPgogICAgPGNpcmNsZSBjeD0iNDIwLjkiIGN5PSIyOTYuNSIgcj0iNDUuNyIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-redo: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTE4LjQgMTAuNkMxNi41NSA4Ljk5IDE0LjE1IDggMTEuNSA4Yy00LjY1IDAtOC41OCAzLjAzLTkuOTYgNy4yMkwzLjkgMTZjMS4wNS0zLjE5IDQuMDUtNS41IDcuNi01LjUgMS45NSAwIDMuNzMuNzIgNS4xMiAxLjg4TDEzIDE2aDlWN2wtMy42IDMuNnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-refresh: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTkgMTMuNWMtMi40OSAwLTQuNS0yLjAxLTQuNS00LjVTNi41MSA0LjUgOSA0LjVjMS4yNCAwIDIuMzYuNTIgMy4xNyAxLjMzTDEwIDhoNVYzbC0xLjc2IDEuNzZDMTIuMTUgMy42OCAxMC42NiAzIDkgMyA1LjY5IDMgMy4wMSA1LjY5IDMuMDEgOVM1LjY5IDE1IDkgMTVjMi45NyAwIDUuNDMtMi4xNiA1LjktNWgtMS41MmMtLjQ2IDItMi4yNCAzLjUtNC4zOCAzLjV6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-regex: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi1hY2NlbnQyIiBmaWxsPSIjRkZGIj4KICAgIDxjaXJjbGUgY2xhc3M9InN0MiIgY3g9IjUuNSIgY3k9IjE0LjUiIHI9IjEuNSIvPgogICAgPHJlY3QgeD0iMTIiIHk9IjQiIGNsYXNzPSJzdDIiIHdpZHRoPSIxIiBoZWlnaHQ9IjgiLz4KICAgIDxyZWN0IHg9IjguNSIgeT0iNy41IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjg2NiAtMC41IDAuNSAwLjg2NiAtMi4zMjU1IDcuMzIxOSkiIGNsYXNzPSJzdDIiIHdpZHRoPSI4IiBoZWlnaHQ9IjEiLz4KICAgIDxyZWN0IHg9IjEyIiB5PSI0IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjUgLTAuODY2IDAuODY2IDAuNSAtMC42Nzc5IDE0LjgyNTIpIiBjbGFzcz0ic3QyIiB3aWR0aD0iMSIgaGVpZ2h0PSI4Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-run: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTggNXYxNGwxMS03eiIvPgogICAgPC9nPgo8L3N2Zz4K);--jp-icon-running: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMjU2IDhDMTE5IDggOCAxMTkgOCAyNTZzMTExIDI0OCAyNDggMjQ4IDI0OC0xMTEgMjQ4LTI0OFMzOTMgOCAyNTYgOHptOTYgMzI4YzAgOC44LTcuMiAxNi0xNiAxNkgxNzZjLTguOCAwLTE2LTcuMi0xNi0xNlYxNzZjMC04LjggNy4yLTE2IDE2LTE2aDE2MGM4LjggMCAxNiA3LjIgMTYgMTZ2MTYweiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-save: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE3IDNINWMtMS4xMSAwLTIgLjktMiAydjE0YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjdsLTQtNHptLTUgMTZjLTEuNjYgMC0zLTEuMzQtMy0zczEuMzQtMyAzLTMgMyAxLjM0IDMgMy0xLjM0IDMtMyAzem0zLTEwSDVWNWgxMHY0eiIvPgogICAgPC9nPgo8L3N2Zz4K);--jp-icon-search: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjEsMTAuOWgtMC43bC0wLjItMC4yYzAuOC0wLjksMS4zLTIuMiwxLjMtMy41YzAtMy0yLjQtNS40LTUuNC01LjRTMS44LDQuMiwxLjgsNy4xczIuNCw1LjQsNS40LDUuNCBjMS4zLDAsMi41LTAuNSwzLjUtMS4zbDAuMiwwLjJ2MC43bDQuMSw0LjFsMS4yLTEuMkwxMi4xLDEwLjl6IE03LjEsMTAuOWMtMi4xLDAtMy43LTEuNy0zLjctMy43czEuNy0zLjcsMy43LTMuN3MzLjcsMS43LDMuNywzLjcgUzkuMiwxMC45LDcuMSwxMC45eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-settings: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuNDMgMTIuOThjLjA0LS4zMi4wNy0uNjQuMDctLjk4cy0uMDMtLjY2LS4wNy0uOThsMi4xMS0xLjY1Yy4xOS0uMTUuMjQtLjQyLjEyLS42NGwtMi0zLjQ2Yy0uMTItLjIyLS4zOS0uMy0uNjEtLjIybC0yLjQ5IDFjLS41Mi0uNC0xLjA4LS43My0xLjY5LS45OGwtLjM4LTIuNjVBLjQ4OC40ODggMCAwMDE0IDJoLTRjLS4yNSAwLS40Ni4xOC0uNDkuNDJsLS4zOCAyLjY1Yy0uNjEuMjUtMS4xNy41OS0xLjY5Ljk4bC0yLjQ5LTFjLS4yMy0uMDktLjQ5IDAtLjYxLjIybC0yIDMuNDZjLS4xMy4yMi0uMDcuNDkuMTIuNjRsMi4xMSAxLjY1Yy0uMDQuMzItLjA3LjY1LS4wNy45OHMuMDMuNjYuMDcuOThsLTIuMTEgMS42NWMtLjE5LjE1LS4yNC40Mi0uMTIuNjRsMiAzLjQ2Yy4xMi4yMi4zOS4zLjYxLjIybDIuNDktMWMuNTIuNCAxLjA4LjczIDEuNjkuOThsLjM4IDIuNjVjLjAzLjI0LjI0LjQyLjQ5LjQyaDRjLjI1IDAgLjQ2LS4xOC40OS0uNDJsLjM4LTIuNjVjLjYxLS4yNSAxLjE3LS41OSAxLjY5LS45OGwyLjQ5IDFjLjIzLjA5LjQ5IDAgLjYxLS4yMmwyLTMuNDZjLjEyLS4yMi4wNy0uNDktLjEyLS42NGwtMi4xMS0xLjY1ek0xMiAxNS41Yy0xLjkzIDAtMy41LTEuNTctMy41LTMuNXMxLjU3LTMuNSAzLjUtMy41IDMuNSAxLjU3IDMuNSAzLjUtMS41NyAzLjUtMy41IDMuNXoiLz4KPC9zdmc+Cg==);--jp-icon-share: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTSAxOCAyIEMgMTYuMzU0OTkgMiAxNSAzLjM1NDk5MDQgMTUgNSBDIDE1IDUuMTkwOTUyOSAxNS4wMjE3OTEgNS4zNzcxMjI0IDE1LjA1NjY0MSA1LjU1ODU5MzggTCA3LjkyMTg3NSA5LjcyMDcwMzEgQyA3LjM5ODUzOTkgOS4yNzc4NTM5IDYuNzMyMDc3MSA5IDYgOSBDIDQuMzU0OTkwNCA5IDMgMTAuMzU0OTkgMyAxMiBDIDMgMTMuNjQ1MDEgNC4zNTQ5OTA0IDE1IDYgMTUgQyA2LjczMjA3NzEgMTUgNy4zOTg1Mzk5IDE0LjcyMjE0NiA3LjkyMTg3NSAxNC4yNzkyOTcgTCAxNS4wNTY2NDEgMTguNDM5NDUzIEMgMTUuMDIxNTU1IDE4LjYyMTUxNCAxNSAxOC44MDgzODYgMTUgMTkgQyAxNSAyMC42NDUwMSAxNi4zNTQ5OSAyMiAxOCAyMiBDIDE5LjY0NTAxIDIyIDIxIDIwLjY0NTAxIDIxIDE5IEMgMjEgMTcuMzU0OTkgMTkuNjQ1MDEgMTYgMTggMTYgQyAxNy4yNjc0OCAxNiAxNi42MDE1OTMgMTYuMjc5MzI4IDE2LjA3ODEyNSAxNi43MjI2NTYgTCA4Ljk0MzM1OTQgMTIuNTU4NTk0IEMgOC45NzgyMDk1IDEyLjM3NzEyMiA5IDEyLjE5MDk1MyA5IDEyIEMgOSAxMS44MDkwNDcgOC45NzgyMDk1IDExLjYyMjg3OCA4Ljk0MzM1OTQgMTEuNDQxNDA2IEwgMTYuMDc4MTI1IDcuMjc5Mjk2OSBDIDE2LjYwMTQ2IDcuNzIyMTQ2MSAxNy4yNjc5MjMgOCAxOCA4IEMgMTkuNjQ1MDEgOCAyMSA2LjY0NTAwOTYgMjEgNSBDIDIxIDMuMzU0OTkwNCAxOS42NDUwMSAyIDE4IDIgeiBNIDE4IDQgQyAxOC41NjQxMjkgNCAxOSA0LjQzNTg3MDYgMTkgNSBDIDE5IDUuNTY0MTI5NCAxOC41NjQxMjkgNiAxOCA2IEMgMTcuNDM1ODcxIDYgMTcgNS41NjQxMjk0IDE3IDUgQyAxNyA0LjQzNTg3MDYgMTcuNDM1ODcxIDQgMTggNCB6IE0gNiAxMSBDIDYuNTY0MTI5NCAxMSA3IDExLjQzNTg3MSA3IDEyIEMgNyAxMi41NjQxMjkgNi41NjQxMjk0IDEzIDYgMTMgQyA1LjQzNTg3MDYgMTMgNSAxMi41NjQxMjkgNSAxMiBDIDUgMTEuNDM1ODcxIDUuNDM1ODcwNiAxMSA2IDExIHogTSAxOCAxOCBDIDE4LjU2NDEyOSAxOCAxOSAxOC40MzU4NzEgMTkgMTkgQyAxOSAxOS41NjQxMjkgMTguNTY0MTI5IDIwIDE4IDIwIEMgMTcuNDM1ODcxIDIwIDE3IDE5LjU2NDEyOSAxNyAxOSBDIDE3IDE4LjQzNTg3MSAxNy40MzU4NzEgMTggMTggMTggeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-spreadsheet: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNENBRjUwIiBkPSJNMi4yIDIuMnYxNy42aDE3LjZWMi4ySDIuMnptMTUuNCA3LjdoLTUuNVY0LjRoNS41djUuNXpNOS45IDQuNHY1LjVINC40VjQuNGg1LjV6bS01LjUgNy43aDUuNXY1LjVINC40di01LjV6bTcuNyA1LjV2LTUuNWg1LjV2NS41aC01LjV6Ii8+Cjwvc3ZnPgo=);--jp-icon-stop: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik02IDZoMTJ2MTJINnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);--jp-icon-tab: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIxIDNIM2MtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxOGMxLjEgMCAyLS45IDItMlY1YzAtMS4xLS45LTItMi0yem0wIDE2SDNWNWgxMHY0aDh2MTB6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-table-rows: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMSw4SDNWNGgxOFY4eiBNMjEsMTBIM3Y0aDE4VjEweiBNMjEsMTZIM3Y0aDE4VjE2eiIvPgogICAgPC9nPgo8L3N2Zz4=);--jp-icon-tag: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCA0MyAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTI4LjgzMzIgMTIuMzM0TDMyLjk5OTggMTYuNTAwN0wzNy4xNjY1IDEyLjMzNEgyOC44MzMyWiIvPgoJCTxwYXRoIGQ9Ik0xNi4yMDk1IDIxLjYxMDRDMTUuNjg3MyAyMi4xMjk5IDE0Ljg0NDMgMjIuMTI5OSAxNC4zMjQ4IDIxLjYxMDRMNi45ODI5IDE0LjcyNDVDNi41NzI0IDE0LjMzOTQgNi4wODMxMyAxMy42MDk4IDYuMDQ3ODYgMTMuMDQ4MkM1Ljk1MzQ3IDExLjUyODggNi4wMjAwMiA4LjYxOTQ0IDYuMDY2MjEgNy4wNzY5NUM2LjA4MjgxIDYuNTE0NzcgNi41NTU0OCA2LjA0MzQ3IDcuMTE4MDQgNi4wMzA1NUM5LjA4ODYzIDUuOTg0NzMgMTMuMjYzOCA1LjkzNTc5IDEzLjY1MTggNi4zMjQyNUwyMS43MzY5IDEzLjYzOUMyMi4yNTYgMTQuMTU4NSAyMS43ODUxIDE1LjQ3MjQgMjEuMjYyIDE1Ljk5NDZMMTYuMjA5NSAyMS42MTA0Wk05Ljc3NTg1IDguMjY1QzkuMzM1NTEgNy44MjU2NiA4LjYyMzUxIDcuODI1NjYgOC4xODI4IDguMjY1QzcuNzQzNDYgOC43MDU3MSA3Ljc0MzQ2IDkuNDE3MzMgOC4xODI4IDkuODU2NjdDOC42MjM4MiAxMC4yOTY0IDkuMzM1ODIgMTAuMjk2NCA5Ljc3NTg1IDkuODU2NjdDMTAuMjE1NiA5LjQxNzMzIDEwLjIxNTYgOC43MDUzMyA5Ljc3NTg1IDguMjY1WiIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-terminal: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiA+CiAgICA8cmVjdCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1iYWNrZ3JvdW5kLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyIDIpIiBmaWxsPSIjMzMzMzMzIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUtaW52ZXJzZSIgZD0iTTUuMDU2NjQgOC43NjE3MkM1LjA1NjY0IDguNTk3NjYgNS4wMzEyNSA4LjQ1MzEyIDQuOTgwNDcgOC4zMjgxMkM0LjkzMzU5IDguMTk5MjIgNC44NTU0NyA4LjA4MjAzIDQuNzQ2MDkgNy45NzY1NkM0LjY0MDYyIDcuODcxMDkgNC41IDcuNzc1MzkgNC4zMjQyMiA3LjY4OTQ1QzQuMTUyMzQgNy41OTk2MSAzLjk0MzM2IDcuNTExNzIgMy42OTcyNyA3LjQyNTc4QzMuMzAyNzMgNy4yODUxNiAyLjk0MzM2IDcuMTM2NzIgMi42MTkxNCA2Ljk4MDQ3QzIuMjk0OTIgNi44MjQyMiAyLjAxNzU4IDYuNjQyNTggMS43ODcxMSA2LjQzNTU1QzEuNTYwNTUgNi4yMjg1MiAxLjM4NDc3IDUuOTg4MjggMS4yNTk3NyA1LjcxNDg0QzEuMTM0NzcgNS40Mzc1IDEuMDcyMjcgNS4xMDkzOCAxLjA3MjI3IDQuNzMwNDdDMS4wNzIyNyA0LjM5ODQ0IDEuMTI4OTEgNC4wOTU3IDEuMjQyMTkgMy44MjIyN0MxLjM1NTQ3IDMuNTQ0OTIgMS41MTU2MiAzLjMwNDY5IDEuNzIyNjYgMy4xMDE1NkMxLjkyOTY5IDIuODk4NDQgMi4xNzk2OSAyLjczNDM3IDIuNDcyNjYgMi42MDkzOEMyLjc2NTYyIDIuNDg0MzggMy4wOTE4IDIuNDA0MyAzLjQ1MTE3IDIuMzY5MTRWMS4xMDkzOEg0LjM4ODY3VjIuMzgwODZDNC43NDAyMyAyLjQyNzczIDUuMDU2NjQgMi41MjM0NCA1LjMzNzg5IDIuNjY3OTdDNS42MTkxNCAyLjgxMjUgNS44NTc0MiAzLjAwMTk1IDYuMDUyNzMgMy4yMzYzM0M2LjI1MTk1IDMuNDY2OCA2LjQwNDMgMy43NDAyMyA2LjUwOTc3IDQuMDU2NjRDNi42MTkxNCA0LjM2OTE0IDYuNjczODMgNC43MjA3IDYuNjczODMgNS4xMTEzM0g1LjA0NDkyQzUuMDQ0OTIgNC42Mzg2NyA0LjkzNzUgNC4yODEyNSA0LjcyMjY2IDQuMDM5MDZDNC41MDc4MSAzLjc5Mjk3IDQuMjE2OCAzLjY2OTkyIDMuODQ5NjEgMy42Njk5MkMzLjY1MDM5IDMuNjY5OTIgMy40NzY1NiAzLjY5NzI3IDMuMzI4MTIgMy43NTE5NUMzLjE4MzU5IDMuODAyNzMgMy4wNjQ0NSAzLjg3Njk1IDIuOTcwNyAzLjk3NDYxQzIuODc2OTUgNC4wNjgzNiAyLjgwNjY0IDQuMTc5NjkgMi43NTk3NyA0LjMwODU5QzIuNzE2OCA0LjQzNzUgMi42OTUzMSA0LjU3ODEyIDIuNjk1MzEgNC43MzA0N0MyLjY5NTMxIDQuODgyODEgMi43MTY4IDUuMDE5NTMgMi43NTk3NyA1LjE0MDYyQzIuODA2NjQgNS4yNTc4MSAyLjg4MjgxIDUuMzY3MTkgMi45ODgyOCA1LjQ2ODc1QzMuMDk3NjYgNS41NzAzMSAzLjI0MDIzIDUuNjY3OTcgMy40MTYwMiA1Ljc2MTcyQzMuNTkxOCA1Ljg1MTU2IDMuODEwNTUgNS45NDMzNiA0LjA3MjI3IDYuMDM3MTFDNC40NjY4IDYuMTg1NTUgNC44MjQyMiA2LjMzOTg0IDUuMTQ0NTMgNi41QzUuNDY0ODQgNi42NTYyNSA1LjczODI4IDYuODM5ODQgNS45NjQ4NCA3LjA1MDc4QzYuMTk1MzEgNy4yNTc4MSA2LjM3MTA5IDcuNSA2LjQ5MjE5IDcuNzc3MzRDNi42MTcxOSA4LjA1MDc4IDYuNjc5NjkgOC4zNzUgNi42Nzk2OSA4Ljc1QzYuNjc5NjkgOS4wOTM3NSA2LjYyMzA1IDkuNDA0MyA2LjUwOTc3IDkuNjgxNjRDNi4zOTY0OCA5Ljk1NTA4IDYuMjM0MzggMTAuMTkxNCA2LjAyMzQ0IDEwLjM5MDZDNS44MTI1IDEwLjU4OTggNS41NTg1OSAxMC43NSA1LjI2MTcyIDEwLjg3MTFDNC45NjQ4NCAxMC45ODgzIDQuNjMyODEgMTEuMDY0NSA0LjI2NTYyIDExLjA5OTZWMTIuMjQ4SDMuMzMzOThWMTEuMDk5NkMzLjAwMTk1IDExLjA2ODQgMi42Nzk2OSAxMC45OTYxIDIuMzY3MTkgMTAuODgyOEMyLjA1NDY5IDEwLjc2NTYgMS43NzczNCAxMC41OTc3IDEuNTM1MTYgMTAuMzc4OUMxLjI5Njg4IDEwLjE2MDIgMS4xMDU0NyA5Ljg4NDc3IDAuOTYwOTM4IDkuNTUyNzNDMC44MTY0MDYgOS4yMTY4IDAuNzQ0MTQxIDguODE0NDUgMC43NDQxNDEgOC4zNDU3SDIuMzc4OTFDMi4zNzg5MSA4LjYyNjk1IDIuNDE5OTIgOC44NjMyOCAyLjUwMTk1IDkuMDU0NjlDMi41ODM5OCA5LjI0MjE5IDIuNjg5NDUgOS4zOTI1OCAyLjgxODM2IDkuNTA1ODZDMi45NTExNyA5LjYxNTIzIDMuMTAxNTYgOS42OTMzNiAzLjI2OTUzIDkuNzQwMjNDMy40Mzc1IDkuNzg3MTEgMy42MDkzOCA5LjgxMDU1IDMuNzg1MTYgOS44MTA1NUM0LjIwMzEyIDkuODEwNTUgNC41MTk1MyA5LjcxMjg5IDQuNzM0MzggOS41MTc1OEM0Ljk0OTIyIDkuMzIyMjcgNS4wNTY2NCA5LjA3MDMxIDUuMDU2NjQgOC43NjE3MlpNMTMuNDE4IDEyLjI3MTVIOC4wNzQyMlYxMUgxMy40MThWMTIuMjcxNVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMuOTUyNjQgNikiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=);--jp-icon-text-editor: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtdGV4dC1lZGl0b3ItaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xNSAxNUgzdjJoMTJ2LTJ6bTAtOEgzdjJoMTJWN3pNMyAxM2gxOHYtMkgzdjJ6bTAgOGgxOHYtMkgzdjJ6TTMgM3YyaDE4VjNIM3oiLz4KPC9zdmc+Cg==);--jp-icon-toc: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik03LDVIMjFWN0g3VjVNNywxM1YxMUgyMVYxM0g3TTQsNC41QTEuNSwxLjUgMCAwLDEgNS41LDZBMS41LDEuNSAwIDAsMSA0LDcuNUExLjUsMS41IDAgMCwxIDIuNSw2QTEuNSwxLjUgMCAwLDEgNCw0LjVNNCwxMC41QTEuNSwxLjUgMCAwLDEgNS41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMy41QTEuNSwxLjUgMCAwLDEgMi41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMC41TTcsMTlWMTdIMjFWMTlIN000LDE2LjVBMS41LDEuNSAwIDAsMSA1LjUsMThBMS41LDEuNSAwIDAsMSA0LDE5LjVBMS41LDEuNSAwIDAsMSAyLjUsMThBMS41LDEuNSAwIDAsMSA0LDE2LjVaIiAvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-tree-view: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMiAxMVYzaC03djNIOVYzSDJ2OGg3VjhoMnYxMGg0djNoN3YtOGgtN3YzaC0yVjhoMnYzeiIvPgogICAgPC9nPgo8L3N2Zz4=);--jp-icon-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMiAxNy4xODQ0IDIuOTY5NjggMTQuMzAzMiAxLjg2MDk0IDExLjQ0MDlaIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiMzMzMzMzMiIHN0cm9rZT0iIzMzMzMzMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOCA5Ljg2NzE5KSIgZD0iTTIuODYwMTUgNC44NjUzNUwwLjcyNjU0OSAyLjk5OTU5TDAgMy42MzA0NUwyLjg2MDE1IDYuMTMxNTdMOCAwLjYzMDg3Mkw3LjI3ODU3IDBMMi44NjAxNSA0Ljg2NTM1WiIvPgo8L3N2Zz4K);--jp-icon-undo: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjUgOGMtMi42NSAwLTUuMDUuOTktNi45IDIuNkwyIDd2OWg5bC0zLjYyLTMuNjJjMS4zOS0xLjE2IDMuMTYtMS44OCA1LjEyLTEuODggMy41NCAwIDYuNTUgMi4zMSA3LjYgNS41bDIuMzctLjc4QzIxLjA4IDExLjAzIDE3LjE1IDggMTIuNSA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-user: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE2IDdhNCA0IDAgMTEtOCAwIDQgNCAwIDAxOCAwek0xMiAxNGE3IDcgMCAwMC03IDdoMTRhNyA3IDAgMDAtNy03eiIvPgogIDwvZz4KPC9zdmc+);--jp-icon-users: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDM2IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogPGcgY2xhc3M9ImpwLWljb24zIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjczMjcgMCAwIDEuNzMyNyAtMy42MjgyIC4wOTk1NzcpIiBmaWxsPSIjNjE2MTYxIj4KICA8cGF0aCB0cmFuc2Zvcm09Im1hdHJpeCgxLjUsMCwwLDEuNSwwLC02KSIgZD0ibTEyLjE4NiA3LjUwOThjLTEuMDUzNSAwLTEuOTc1NyAwLjU2NjUtMi40Nzg1IDEuNDEwMiAwLjc1MDYxIDAuMzEyNzcgMS4zOTc0IDAuODI2NDggMS44NzMgMS40NzI3aDMuNDg2M2MwLTEuNTkyLTEuMjg4OS0yLjg4MjgtMi44ODA5LTIuODgyOHoiLz4KICA8cGF0aCBkPSJtMjAuNDY1IDIuMzg5NWEyLjE4ODUgMi4xODg1IDAgMCAxLTIuMTg4NCAyLjE4ODUgMi4xODg1IDIuMTg4NSAwIDAgMS0yLjE4ODUtMi4xODg1IDIuMTg4NSAyLjE4ODUgMCAwIDEgMi4xODg1LTIuMTg4NSAyLjE4ODUgMi4xODg1IDAgMCAxIDIuMTg4NCAyLjE4ODV6Ii8+CiAgPHBhdGggdHJhbnNmb3JtPSJtYXRyaXgoMS41LDAsMCwxLjUsMCwtNikiIGQ9Im0zLjU4OTggOC40MjE5Yy0xLjExMjYgMC0yLjAxMzcgMC45MDExMS0yLjAxMzcgMi4wMTM3aDIuODE0NWMwLjI2Nzk3LTAuMzczMDkgMC41OTA3LTAuNzA0MzUgMC45NTg5OC0wLjk3ODUyLTAuMzQ0MzMtMC42MTY4OC0xLjAwMzEtMS4wMzUyLTEuNzU5OC0xLjAzNTJ6Ii8+CiAgPHBhdGggZD0ibTYuOTE1NCA0LjYyM2ExLjUyOTQgMS41Mjk0IDAgMCAxLTEuNTI5NCAxLjUyOTQgMS41Mjk0IDEuNTI5NCAwIDAgMS0xLjUyOTQtMS41Mjk0IDEuNTI5NCAxLjUyOTQgMCAwIDEgMS41Mjk0LTEuNTI5NCAxLjUyOTQgMS41Mjk0IDAgMCAxIDEuNTI5NCAxLjUyOTR6Ii8+CiAgPHBhdGggZD0ibTYuMTM1IDEzLjUzNWMwLTMuMjM5MiAyLjYyNTktNS44NjUgNS44NjUtNS44NjUgMy4yMzkyIDAgNS44NjUgMi42MjU5IDUuODY1IDUuODY1eiIvPgogIDxjaXJjbGUgY3g9IjEyIiBjeT0iMy43Njg1IiByPSIyLjk2ODUiLz4KIDwvZz4KPC9zdmc+Cg==);--jp-icon-vega: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbjEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjEyMTIxIj4KICAgIDxwYXRoIGQ9Ik0xMC42IDUuNGwyLjItMy4ySDIuMnY3LjNsNC02LjZ6Ii8+CiAgICA8cGF0aCBkPSJNMTUuOCAyLjJsLTQuNCA2LjZMNyA2LjNsLTQuOCA4djUuNWgxNy42VjIuMmgtNHptLTcgMTUuNEg1LjV2LTQuNGgzLjN2NC40em00LjQgMEg5LjhWOS44aDMuNHY3Ljh6bTQuNCAwaC0zLjRWNi41aDMuNHYxMS4xeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-yaml: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1jb250cmFzdDIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjRDgxQjYwIj4KICAgIDxwYXRoIGQ9Ik03LjIgMTguNnYtNS40TDMgNS42aDMuM2wxLjQgMy4xYy4zLjkuNiAxLjYgMSAyLjUuMy0uOC42LTEuNiAxLTIuNWwxLjQtMy4xaDMuNGwtNC40IDcuNnY1LjVsLTIuOS0uMXoiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxNi41IiByPSIyLjEiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxMSIgcj0iMi4xIi8+CiAgPC9nPgo8L3N2Zz4K)}.jupyter-wrapper .jp-AddAboveIcon{background-image:var(--jp-icon-add-above)}.jupyter-wrapper .jp-AddBelowIcon{background-image:var(--jp-icon-add-below)}.jupyter-wrapper .jp-AddIcon{background-image:var(--jp-icon-add)}.jupyter-wrapper .jp-BellIcon{background-image:var(--jp-icon-bell)}.jupyter-wrapper .jp-BugDotIcon{background-image:var(--jp-icon-bug-dot)}.jupyter-wrapper .jp-BugIcon{background-image:var(--jp-icon-bug)}.jupyter-wrapper .jp-BuildIcon{background-image:var(--jp-icon-build)}.jupyter-wrapper .jp-CaretDownEmptyIcon{background-image:var(--jp-icon-caret-down-empty)}.jupyter-wrapper .jp-CaretDownEmptyThinIcon{background-image:var(--jp-icon-caret-down-empty-thin)}.jupyter-wrapper .jp-CaretDownIcon{background-image:var(--jp-icon-caret-down)}.jupyter-wrapper .jp-CaretLeftIcon{background-image:var(--jp-icon-caret-left)}.jupyter-wrapper .jp-CaretRightIcon{background-image:var(--jp-icon-caret-right)}.jupyter-wrapper .jp-CaretUpEmptyThinIcon{background-image:var(--jp-icon-caret-up-empty-thin)}.jupyter-wrapper .jp-CaretUpIcon{background-image:var(--jp-icon-caret-up)}.jupyter-wrapper .jp-CaseSensitiveIcon{background-image:var(--jp-icon-case-sensitive)}.jupyter-wrapper .jp-CheckIcon{background-image:var(--jp-icon-check)}.jupyter-wrapper .jp-CircleEmptyIcon{background-image:var(--jp-icon-circle-empty)}.jupyter-wrapper .jp-CircleIcon{background-image:var(--jp-icon-circle)}.jupyter-wrapper .jp-ClearIcon{background-image:var(--jp-icon-clear)}.jupyter-wrapper .jp-CloseIcon{background-image:var(--jp-icon-close)}.jupyter-wrapper .jp-CodeIcon{background-image:var(--jp-icon-code)}.jupyter-wrapper .jp-ConsoleIcon{background-image:var(--jp-icon-console)}.jupyter-wrapper .jp-CopyIcon{background-image:var(--jp-icon-copy)}.jupyter-wrapper .jp-CopyrightIcon{background-image:var(--jp-icon-copyright)}.jupyter-wrapper .jp-CutIcon{background-image:var(--jp-icon-cut)}.jupyter-wrapper .jp-DeleteIcon{background-image:var(--jp-icon-delete)}.jupyter-wrapper .jp-DownloadIcon{background-image:var(--jp-icon-download)}.jupyter-wrapper .jp-DuplicateIcon{background-image:var(--jp-icon-duplicate)}.jupyter-wrapper .jp-EditIcon{background-image:var(--jp-icon-edit)}.jupyter-wrapper .jp-EllipsesIcon{background-image:var(--jp-icon-ellipses)}.jupyter-wrapper .jp-ExtensionIcon{background-image:var(--jp-icon-extension)}.jupyter-wrapper .jp-FastForwardIcon{background-image:var(--jp-icon-fast-forward)}.jupyter-wrapper .jp-FileIcon{background-image:var(--jp-icon-file)}.jupyter-wrapper .jp-FileUploadIcon{background-image:var(--jp-icon-file-upload)}.jupyter-wrapper .jp-FilterListIcon{background-image:var(--jp-icon-filter-list)}.jupyter-wrapper .jp-FolderFavoriteIcon{background-image:var(--jp-icon-folder-favorite)}.jupyter-wrapper .jp-FolderIcon{background-image:var(--jp-icon-folder)}.jupyter-wrapper .jp-HomeIcon{background-image:var(--jp-icon-home)}.jupyter-wrapper .jp-Html5Icon{background-image:var(--jp-icon-html5)}.jupyter-wrapper .jp-ImageIcon{background-image:var(--jp-icon-image)}.jupyter-wrapper .jp-InspectorIcon{background-image:var(--jp-icon-inspector)}.jupyter-wrapper .jp-JsonIcon{background-image:var(--jp-icon-json)}.jupyter-wrapper .jp-JuliaIcon{background-image:var(--jp-icon-julia)}.jupyter-wrapper .jp-JupyterFaviconIcon{background-image:var(--jp-icon-jupyter-favicon)}.jupyter-wrapper .jp-JupyterIcon{background-image:var(--jp-icon-jupyter)}.jupyter-wrapper .jp-JupyterlabWordmarkIcon{background-image:var(--jp-icon-jupyterlab-wordmark)}.jupyter-wrapper .jp-KernelIcon{background-image:var(--jp-icon-kernel)}.jupyter-wrapper .jp-KeyboardIcon{background-image:var(--jp-icon-keyboard)}.jupyter-wrapper .jp-LaunchIcon{background-image:var(--jp-icon-launch)}.jupyter-wrapper .jp-LauncherIcon{background-image:var(--jp-icon-launcher)}.jupyter-wrapper .jp-LineFormIcon{background-image:var(--jp-icon-line-form)}.jupyter-wrapper .jp-LinkIcon{background-image:var(--jp-icon-link)}.jupyter-wrapper .jp-ListIcon{background-image:var(--jp-icon-list)}.jupyter-wrapper .jp-ListingsInfoIcon{background-image:var(--jp-icon-listings-info)}.jupyter-wrapper .jp-MarkdownIcon{background-image:var(--jp-icon-markdown)}.jupyter-wrapper .jp-MoveDownIcon{background-image:var(--jp-icon-move-down)}.jupyter-wrapper .jp-MoveUpIcon{background-image:var(--jp-icon-move-up)}.jupyter-wrapper .jp-NewFolderIcon{background-image:var(--jp-icon-new-folder)}.jupyter-wrapper .jp-NotTrustedIcon{background-image:var(--jp-icon-not-trusted)}.jupyter-wrapper .jp-NotebookIcon{background-image:var(--jp-icon-notebook)}.jupyter-wrapper .jp-NumberingIcon{background-image:var(--jp-icon-numbering)}.jupyter-wrapper .jp-OfflineBoltIcon{background-image:var(--jp-icon-offline-bolt)}.jupyter-wrapper .jp-PaletteIcon{background-image:var(--jp-icon-palette)}.jupyter-wrapper .jp-PasteIcon{background-image:var(--jp-icon-paste)}.jupyter-wrapper .jp-PdfIcon{background-image:var(--jp-icon-pdf)}.jupyter-wrapper .jp-PythonIcon{background-image:var(--jp-icon-python)}.jupyter-wrapper .jp-RKernelIcon{background-image:var(--jp-icon-r-kernel)}.jupyter-wrapper .jp-ReactIcon{background-image:var(--jp-icon-react)}.jupyter-wrapper .jp-RedoIcon{background-image:var(--jp-icon-redo)}.jupyter-wrapper .jp-RefreshIcon{background-image:var(--jp-icon-refresh)}.jupyter-wrapper .jp-RegexIcon{background-image:var(--jp-icon-regex)}.jupyter-wrapper .jp-RunIcon{background-image:var(--jp-icon-run)}.jupyter-wrapper .jp-RunningIcon{background-image:var(--jp-icon-running)}.jupyter-wrapper .jp-SaveIcon{background-image:var(--jp-icon-save)}.jupyter-wrapper .jp-SearchIcon{background-image:var(--jp-icon-search)}.jupyter-wrapper .jp-SettingsIcon{background-image:var(--jp-icon-settings)}.jupyter-wrapper .jp-ShareIcon{background-image:var(--jp-icon-share)}.jupyter-wrapper .jp-SpreadsheetIcon{background-image:var(--jp-icon-spreadsheet)}.jupyter-wrapper .jp-StopIcon{background-image:var(--jp-icon-stop)}.jupyter-wrapper .jp-TabIcon{background-image:var(--jp-icon-tab)}.jupyter-wrapper .jp-TableRowsIcon{background-image:var(--jp-icon-table-rows)}.jupyter-wrapper .jp-TagIcon{background-image:var(--jp-icon-tag)}.jupyter-wrapper .jp-TerminalIcon{background-image:var(--jp-icon-terminal)}.jupyter-wrapper .jp-TextEditorIcon{background-image:var(--jp-icon-text-editor)}.jupyter-wrapper .jp-TocIcon{background-image:var(--jp-icon-toc)}.jupyter-wrapper .jp-TreeViewIcon{background-image:var(--jp-icon-tree-view)}.jupyter-wrapper .jp-TrustedIcon{background-image:var(--jp-icon-trusted)}.jupyter-wrapper .jp-UndoIcon{background-image:var(--jp-icon-undo)}.jupyter-wrapper .jp-UserIcon{background-image:var(--jp-icon-user)}.jupyter-wrapper .jp-UsersIcon{background-image:var(--jp-icon-users)}.jupyter-wrapper .jp-VegaIcon{background-image:var(--jp-icon-vega)}.jupyter-wrapper .jp-YamlIcon{background-image:var(--jp-icon-yaml)}.jupyter-wrapper .jp-Icon,.jupyter-wrapper .jp-MaterialIcon{background-position:center;background-repeat:no-repeat;background-size:16px;min-width:16px;min-height:16px}.jupyter-wrapper .jp-Icon-cover{background-position:center;background-repeat:no-repeat;background-size:cover}.jupyter-wrapper .jp-Icon-16{background-size:16px;min-width:16px;min-height:16px}.jupyter-wrapper .jp-Icon-18{background-size:18px;min-width:18px;min-height:18px}.jupyter-wrapper .jp-Icon-20{background-size:20px;min-width:20px;min-height:20px}.jupyter-wrapper .lm-TabBar .lm-TabBar-addButton{align-items:center;display:flex;padding:4px 4px 5px;margin-right:1px;background-color:var(--jp-layout-color2)}.jupyter-wrapper .lm-TabBar .lm-TabBar-addButton:hover{background-color:var(--jp-layout-color1)}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab{width:var(--jp-private-horizontal-tab-width)}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-content{flex:unset}.jupyter-wrapper .lm-DockPanel-tabBar[data-orientation=horizontal]{flex:1 1 auto}.jupyter-wrapper .jp-icon0[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon1[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon2[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon3[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon4[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon0[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon1[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon2[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon3[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon4[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-accent0[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-accent1[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-accent2[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-accent3[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-accent4[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-accent0[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-accent1[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-accent2[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-accent3[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-accent4[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-none[fill]{fill:none}.jupyter-wrapper .jp-icon-none[stroke]{stroke:none}.jupyter-wrapper .jp-icon-brand0[fill]{fill:var(--jp-brand-color0)}.jupyter-wrapper .jp-icon-brand1[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper .jp-icon-brand2[fill]{fill:var(--jp-brand-color2)}.jupyter-wrapper .jp-icon-brand3[fill]{fill:var(--jp-brand-color3)}.jupyter-wrapper .jp-icon-brand4[fill]{fill:var(--jp-brand-color4)}.jupyter-wrapper .jp-icon-brand0[stroke]{stroke:var(--jp-brand-color0)}.jupyter-wrapper .jp-icon-brand1[stroke]{stroke:var(--jp-brand-color1)}.jupyter-wrapper .jp-icon-brand2[stroke]{stroke:var(--jp-brand-color2)}.jupyter-wrapper .jp-icon-brand3[stroke]{stroke:var(--jp-brand-color3)}.jupyter-wrapper .jp-icon-brand4[stroke]{stroke:var(--jp-brand-color4)}.jupyter-wrapper .jp-icon-warn0[fill]{fill:var(--jp-warn-color0)}.jupyter-wrapper .jp-icon-warn1[fill]{fill:var(--jp-warn-color1)}.jupyter-wrapper .jp-icon-warn2[fill]{fill:var(--jp-warn-color2)}.jupyter-wrapper .jp-icon-warn3[fill]{fill:var(--jp-warn-color3)}.jupyter-wrapper .jp-icon-warn0[stroke]{stroke:var(--jp-warn-color0)}.jupyter-wrapper .jp-icon-warn1[stroke]{stroke:var(--jp-warn-color1)}.jupyter-wrapper .jp-icon-warn2[stroke]{stroke:var(--jp-warn-color2)}.jupyter-wrapper .jp-icon-warn3[stroke]{stroke:var(--jp-warn-color3)}.jupyter-wrapper .jp-icon-contrast0[fill]{fill:var(--jp-icon-contrast-color0)}.jupyter-wrapper .jp-icon-contrast1[fill]{fill:var(--jp-icon-contrast-color1)}.jupyter-wrapper .jp-icon-contrast2[fill]{fill:var(--jp-icon-contrast-color2)}.jupyter-wrapper .jp-icon-contrast3[fill]{fill:var(--jp-icon-contrast-color3)}.jupyter-wrapper .jp-icon-contrast0[stroke]{stroke:var(--jp-icon-contrast-color0)}.jupyter-wrapper .jp-icon-contrast1[stroke]{stroke:var(--jp-icon-contrast-color1)}.jupyter-wrapper .jp-icon-contrast2[stroke]{stroke:var(--jp-icon-contrast-color2)}.jupyter-wrapper .jp-icon-contrast3[stroke]{stroke:var(--jp-icon-contrast-color3)}.jupyter-wrapper .jp-jupyter-icon-color[fill]{fill:var(--jp-jupyter-icon-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-notebook-icon-color[fill]{fill:var(--jp-notebook-icon-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-json-icon-color[fill]{fill:var(--jp-json-icon-color, var(--jp-warn-color1))}.jupyter-wrapper .jp-console-icon-color[fill]{fill:var(--jp-console-icon-color, white)}.jupyter-wrapper .jp-console-icon-background-color[fill]{fill:var(--jp-console-icon-background-color, var(--jp-brand-color1))}.jupyter-wrapper .jp-terminal-icon-color[fill]{fill:var(--jp-terminal-icon-color, var(--jp-layout-color2))}.jupyter-wrapper .jp-terminal-icon-background-color[fill]{fill:var(--jp-terminal-icon-background-color, var(--jp-inverse-layout2))}.jupyter-wrapper .jp-text-editor-icon-color[fill]{fill:var(--jp-text-editor-icon-color, var(--jp-inverse-layout3))}.jupyter-wrapper .jp-inspector-icon-color[fill]{fill:var(--jp-inspector-icon-color, var(--jp-inverse-layout3))}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected .jp-icon-selectable-inverse[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-selectable-inverse[fill],.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-hover :hover .jp-icon-selectable[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-hover :hover .jp-icon-selectable-inverse[fill]{fill:#fff}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon3[fill]{fill:none}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty.jp-mod-active>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:#fff}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon3[fill]{fill:none}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper #jp-main-statusbar .jp-mod-selected .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper #jp-main-statusbar .jp-mod-selected .jp-icon-selectable-inverse[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper :root{--jp-warn-color0: var(--md-orange-700)}.jupyter-wrapper .jp-DragIcon{margin-right:4px}.jupyter-wrapper .jp-icon-alt .jp-icon0[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon1[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon2[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon3[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon4[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon0[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon1[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon2[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon3[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon4[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent0[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent1[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent2[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent3[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent4[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent0[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent1[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent2[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent3[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent4[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hoverShow:not(:hover) .jp-icon-hoverShow-content{display:none!important}.jupyter-wrapper .jp-icon-hover :hover .jp-icon0-hover[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon1-hover[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon2-hover[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon3-hover[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon4-hover[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon0-hover[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon1-hover[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon2-hover[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon3-hover[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon4-hover[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent0-hover[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent1-hover[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent2-hover[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent3-hover[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent4-hover[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent0-hover[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent1-hover[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent2-hover[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent3-hover[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent4-hover[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-none-hover[fill]{fill:none}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-none-hover[stroke]{stroke:none}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-switch{display:flex;align-items:center;padding-left:4px;padding-right:4px;font-size:var(--jp-ui-font-size1);background-color:transparent;color:var(--jp-ui-font-color1);border:none;height:20px}.jupyter-wrapper .jp-switch:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-switch-label{margin-right:5px}.jupyter-wrapper .jp-switch-track{cursor:pointer;background-color:var(--jp-switch-color, var(--jp-border-color1));-webkit-transition:.4s;transition:.4s;border-radius:34px;height:16px;width:35px;position:relative}.jupyter-wrapper .jp-switch-track:before{content:\"\";position:absolute;height:10px;width:10px;margin:3px;left:0;background-color:var(--jp-ui-inverse-font-color1);-webkit-transition:.4s;transition:.4s;border-radius:50%}.jupyter-wrapper .jp-switch[aria-checked=true] .jp-switch-track{background-color:var(--jp-switch-true-position-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-switch[aria-checked=true] .jp-switch-track:before{left:19px}.jupyter-wrapper html{box-sizing:unset}.jupyter-wrapper *,.jupyter-wrapper *:before,.jupyter-wrapper *:after{box-sizing:unset}.jupyter-wrapper body{color:unset;font-family:var(--jp-ui-font-family)}.jupyter-wrapper :focus{outline:unset;outline-offset:unset;-moz-outline-radius:unset}.jupyter-wrapper .jp-Button{border-radius:var(--jp-border-radius);padding:0 12px;font-size:var(--jp-ui-font-size1)}.jupyter-wrapper button.jp-Button.bp3-button.bp3-minimal:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-Button.minimal{color:unset!important}.jupyter-wrapper .jp-Button.jp-ToolbarButtonComponent{text-transform:none}.jupyter-wrapper .jp-InputGroup input{box-sizing:border-box;border-radius:0;background-color:transparent;color:var(--jp-ui-font-color0);box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color)}.jupyter-wrapper .jp-InputGroup input:focus{box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-active-box-shadow-color),inset 0 0 0 3px var(--jp-input-active-box-shadow-color)}.jupyter-wrapper .jp-InputGroup input::placeholder,.jupyter-wrapper input::placeholder{color:var(--jp-ui-font-color3)}.jupyter-wrapper .jp-BPIcon{display:inline-block;vertical-align:middle;margin:auto}.jupyter-wrapper .bp3-icon.jp-BPIcon>svg:not([fill]){fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-InputGroupAction{padding:6px}.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select{background-color:initial;border:none;border-radius:0;box-shadow:none;color:var(--jp-ui-font-color0);display:block;font-size:var(--jp-ui-font-size1);height:24px;line-height:14px;padding:0 25px 0 10px;text-align:left;-moz-appearance:none;-webkit-appearance:none}.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select:hover,.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select>option{background-color:var(--jp-layout-color2);color:var(--jp-ui-font-color0)}.jupyter-wrapper select{box-sizing:border-box}.jupyter-wrapper .jp-Collapse{display:flex;flex-direction:column;align-items:stretch;border-top:1px solid var(--jp-border-color2);border-bottom:1px solid var(--jp-border-color2)}.jupyter-wrapper .jp-Collapse-header{padding:1px 12px;color:var(--jp-ui-font-color1);background-color:var(--jp-layout-color1);font-size:var(--jp-ui-font-size2)}.jupyter-wrapper .jp-Collapse-header:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-Collapse-contents{padding:0 12px;background-color:var(--jp-layout-color1);color:var(--jp-ui-font-color1);overflow:auto}.jupyter-wrapper :root{--jp-private-commandpalette-search-height: 28px}.jupyter-wrapper .lm-CommandPalette{padding-bottom:0;color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .jp-ModalCommandPalette{position:absolute;z-index:10000;top:38px;left:30%;margin:0;padding:4px;width:40%;box-shadow:var(--jp-elevation-z4);border-radius:4px;background:var(--jp-layout-color0)}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette{max-height:40vh}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-close-icon:after{display:none}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-header{display:none}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item{margin-left:4px;margin-right:4px}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item.lm-mod-disabled{display:none}.jupyter-wrapper .lm-CommandPalette-search{padding:4px;background-color:var(--jp-layout-color1);z-index:2}.jupyter-wrapper .lm-CommandPalette-wrapper{overflow:overlay;padding:0 9px;background-color:var(--jp-input-active-background);height:30px;box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color)}.jupyter-wrapper .lm-CommandPalette.lm-mod-focused .lm-CommandPalette-wrapper{box-shadow:inset 0 0 0 1px var(--jp-input-active-box-shadow-color),inset 0 0 0 3px var(--jp-input-active-box-shadow-color)}.jupyter-wrapper .jp-SearchIconGroup{color:#fff;background-color:var(--jp-brand-color1);position:absolute;top:4px;right:4px;padding:5px 5px 1px}.jupyter-wrapper .jp-SearchIconGroup svg{height:20px;width:20px}.jupyter-wrapper .jp-SearchIconGroup .jp-icon3[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .lm-CommandPalette-input{background:transparent;width:calc(100% - 18px);float:left;border:none;outline:none;font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);line-height:var(--jp-private-commandpalette-search-height)}.jupyter-wrapper .lm-CommandPalette-input::-webkit-input-placeholder,.jupyter-wrapper .lm-CommandPalette-input::-moz-placeholder,.jupyter-wrapper .lm-CommandPalette-input:-ms-input-placeholder{color:var(--jp-ui-font-color2);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .lm-CommandPalette-header:first-child{margin-top:0}.jupyter-wrapper .lm-CommandPalette-header{border-bottom:solid var(--jp-border-width) var(--jp-border-color2);color:var(--jp-ui-font-color1);cursor:pointer;display:flex;font-size:var(--jp-ui-font-size0);font-weight:600;letter-spacing:1px;margin-top:8px;padding:8px 0 8px 12px;text-transform:uppercase}.jupyter-wrapper .lm-CommandPalette-header.lm-mod-active{background:var(--jp-layout-color2)}.jupyter-wrapper .lm-CommandPalette-header>mark{background-color:transparent;font-weight:700;color:var(--jp-ui-font-color1)}.jupyter-wrapper .lm-CommandPalette-item{padding:4px 12px 4px 4px;color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);font-weight:400;display:flex}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled{color:var(--jp-ui-font-color2)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active{color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active .jp-icon-selectable[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active .lm-CommandPalette-itemLabel>mark{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active:hover:not(.lm-mod-disabled){color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .lm-CommandPalette-item:hover:not(.lm-mod-active):not(.lm-mod-disabled){background:var(--jp-layout-color2)}.jupyter-wrapper .lm-CommandPalette-itemContent{overflow:hidden}.jupyter-wrapper .lm-CommandPalette-itemLabel>mark{color:var(--jp-ui-font-color0);background-color:transparent;font-weight:700}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled mark{color:var(--jp-ui-font-color2)}.jupyter-wrapper .lm-CommandPalette-item .lm-CommandPalette-itemIcon{margin:0 4px 0 0;position:relative;width:16px;top:2px;flex:0 0 auto}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled .lm-CommandPalette-itemIcon{opacity:.6}.jupyter-wrapper .lm-CommandPalette-item .lm-CommandPalette-itemShortcut{flex:0 0 auto}.jupyter-wrapper .lm-CommandPalette-itemCaption{display:none}.jupyter-wrapper .lm-CommandPalette-content{background-color:var(--jp-layout-color1)}.jupyter-wrapper .lm-CommandPalette-content:empty:after{content:\"No results\";margin:20px auto auto;width:100px;display:block;font-size:var(--jp-ui-font-size2);font-family:var(--jp-ui-font-family);font-weight:lighter}.jupyter-wrapper .lm-CommandPalette-emptyMessage{text-align:center;margin-top:24px;line-height:1.32;padding:0 8px;color:var(--jp-content-font-color3)}.jupyter-wrapper .jp-Dialog{position:absolute;z-index:10000;display:flex;flex-direction:column;align-items:center;justify-content:center;top:0;left:0;margin:0;padding:0;width:100%;height:100%;background:var(--jp-dialog-background)}.jupyter-wrapper .jp-Dialog-content{display:flex;flex-direction:column;margin-left:auto;margin-right:auto;background:var(--jp-layout-color1);padding:24px 24px 12px;min-width:300px;min-height:150px;max-width:1000px;max-height:500px;box-sizing:border-box;box-shadow:var(--jp-elevation-z20);word-wrap:break-word;border-radius:var(--jp-border-radius);font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color1);resize:both}.jupyter-wrapper .jp-Dialog-content.jp-Dialog-content-small{max-width:500px}.jupyter-wrapper .jp-Dialog-button{overflow:visible}.jupyter-wrapper button.jp-Dialog-button:focus{outline:1px solid var(--jp-brand-color1);outline-offset:4px;-moz-outline-radius:0px}.jupyter-wrapper button.jp-Dialog-button:focus::-moz-focus-inner{border:0}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus,.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus,.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus{outline-offset:4px;-moz-outline-radius:0px}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus{outline:1px solid var(--md-blue-700)}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus{outline:1px solid var(--md-red-600)}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus{outline:1px solid var(--md-grey-700)}.jupyter-wrapper button.jp-Dialog-close-button{padding:0;height:100%;min-width:unset;min-height:unset}.jupyter-wrapper .jp-Dialog-header{display:flex;justify-content:space-between;flex:0 0 auto;padding-bottom:12px;font-size:var(--jp-ui-font-size3);font-weight:400;color:var(--jp-ui-font-color0)}.jupyter-wrapper .jp-Dialog-body{display:flex;flex-direction:column;flex:1 1 auto;font-size:var(--jp-ui-font-size1);background:var(--jp-layout-color1);overflow:auto}.jupyter-wrapper .jp-Dialog-footer{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;flex:0 0 auto;margin-left:-12px;margin-right:-12px;padding:12px}.jupyter-wrapper .jp-Dialog-checkbox{padding-right:5px}.jupyter-wrapper .jp-Dialog-checkbox>input:focus-visible{outline:1px solid var(--jp-input-active-border-color);outline-offset:1px}.jupyter-wrapper .jp-Dialog-spacer{flex:1 1 auto}.jupyter-wrapper .jp-Dialog-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .jp-Dialog-body>.jp-select-wrapper{width:100%}.jupyter-wrapper .jp-Dialog-body>button{padding:0 16px}.jupyter-wrapper .jp-Dialog-body>label{line-height:1.4;color:var(--jp-ui-font-color0)}.jupyter-wrapper .jp-Dialog-button.jp-mod-styled:not(:last-child){margin-right:12px}.jupyter-wrapper .jp-HoverBox{position:fixed}.jupyter-wrapper .jp-HoverBox.jp-mod-outofview{display:none}.jupyter-wrapper .jp-IFrame{width:100%;height:100%}.jupyter-wrapper .jp-IFrame>iframe{border:none}.jupyter-wrapper body.lm-mod-override-cursor .jp-IFrame{position:relative}.jupyter-wrapper body.lm-mod-override-cursor .jp-IFrame:before{content:\"\";position:absolute;top:0;left:0;right:0;bottom:0;background:transparent}.jupyter-wrapper .jp-Input-Boolean-Dialog{flex-direction:row-reverse;align-items:end;width:100%}.jupyter-wrapper .jp-Input-Boolean-Dialog>label{flex:1 1 auto}.jupyter-wrapper .jp-MainAreaWidget>:focus{outline:none}.jupyter-wrapper .jp-MainAreaWidget .jp-MainAreaWidget-error{padding:6px}.jupyter-wrapper .jp-MainAreaWidget .jp-MainAreaWidget-error>pre{width:auto;padding:10px;background:var(--jp-error-color3);border:var(--jp-border-width) solid var(--jp-error-color1);border-radius:var(--jp-border-radius);color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);white-space:pre-wrap;word-wrap:break-word}.jupyter-wrapper .jp-MainAreaWidget{contain:strict}.jupyter-wrapper :root{--md-red-50: #ffebee;--md-red-100: #ffcdd2;--md-red-200: #ef9a9a;--md-red-300: #e57373;--md-red-400: #ef5350;--md-red-500: #f44336;--md-red-600: #e53935;--md-red-700: #d32f2f;--md-red-800: #c62828;--md-red-900: #b71c1c;--md-red-A100: #ff8a80;--md-red-A200: #ff5252;--md-red-A400: #ff1744;--md-red-A700: #d50000;--md-pink-50: #fce4ec;--md-pink-100: #f8bbd0;--md-pink-200: #f48fb1;--md-pink-300: #f06292;--md-pink-400: #ec407a;--md-pink-500: #e91e63;--md-pink-600: #d81b60;--md-pink-700: #c2185b;--md-pink-800: #ad1457;--md-pink-900: #880e4f;--md-pink-A100: #ff80ab;--md-pink-A200: #ff4081;--md-pink-A400: #f50057;--md-pink-A700: #c51162;--md-purple-50: #f3e5f5;--md-purple-100: #e1bee7;--md-purple-200: #ce93d8;--md-purple-300: #ba68c8;--md-purple-400: #ab47bc;--md-purple-500: #9c27b0;--md-purple-600: #8e24aa;--md-purple-700: #7b1fa2;--md-purple-800: #6a1b9a;--md-purple-900: #4a148c;--md-purple-A100: #ea80fc;--md-purple-A200: #e040fb;--md-purple-A400: #d500f9;--md-purple-A700: #aa00ff;--md-deep-purple-50: #ede7f6;--md-deep-purple-100: #d1c4e9;--md-deep-purple-200: #b39ddb;--md-deep-purple-300: #9575cd;--md-deep-purple-400: #7e57c2;--md-deep-purple-500: #673ab7;--md-deep-purple-600: #5e35b1;--md-deep-purple-700: #512da8;--md-deep-purple-800: #4527a0;--md-deep-purple-900: #311b92;--md-deep-purple-A100: #b388ff;--md-deep-purple-A200: #7c4dff;--md-deep-purple-A400: #651fff;--md-deep-purple-A700: #6200ea;--md-indigo-50: #e8eaf6;--md-indigo-100: #c5cae9;--md-indigo-200: #9fa8da;--md-indigo-300: #7986cb;--md-indigo-400: #5c6bc0;--md-indigo-500: #3f51b5;--md-indigo-600: #3949ab;--md-indigo-700: #303f9f;--md-indigo-800: #283593;--md-indigo-900: #1a237e;--md-indigo-A100: #8c9eff;--md-indigo-A200: #536dfe;--md-indigo-A400: #3d5afe;--md-indigo-A700: #304ffe;--md-blue-50: #e3f2fd;--md-blue-100: #bbdefb;--md-blue-200: #90caf9;--md-blue-300: #64b5f6;--md-blue-400: #42a5f5;--md-blue-500: #2196f3;--md-blue-600: #1e88e5;--md-blue-700: #1976d2;--md-blue-800: #1565c0;--md-blue-900: #0d47a1;--md-blue-A100: #82b1ff;--md-blue-A200: #448aff;--md-blue-A400: #2979ff;--md-blue-A700: #2962ff;--md-light-blue-50: #e1f5fe;--md-light-blue-100: #b3e5fc;--md-light-blue-200: #81d4fa;--md-light-blue-300: #4fc3f7;--md-light-blue-400: #29b6f6;--md-light-blue-500: #03a9f4;--md-light-blue-600: #039be5;--md-light-blue-700: #0288d1;--md-light-blue-800: #0277bd;--md-light-blue-900: #01579b;--md-light-blue-A100: #80d8ff;--md-light-blue-A200: #40c4ff;--md-light-blue-A400: #00b0ff;--md-light-blue-A700: #0091ea;--md-cyan-50: #e0f7fa;--md-cyan-100: #b2ebf2;--md-cyan-200: #80deea;--md-cyan-300: #4dd0e1;--md-cyan-400: #26c6da;--md-cyan-500: #00bcd4;--md-cyan-600: #00acc1;--md-cyan-700: #0097a7;--md-cyan-800: #00838f;--md-cyan-900: #006064;--md-cyan-A100: #84ffff;--md-cyan-A200: #18ffff;--md-cyan-A400: #00e5ff;--md-cyan-A700: #00b8d4;--md-teal-50: #e0f2f1;--md-teal-100: #b2dfdb;--md-teal-200: #80cbc4;--md-teal-300: #4db6ac;--md-teal-400: #26a69a;--md-teal-500: #009688;--md-teal-600: #00897b;--md-teal-700: #00796b;--md-teal-800: #00695c;--md-teal-900: #004d40;--md-teal-A100: #a7ffeb;--md-teal-A200: #64ffda;--md-teal-A400: #1de9b6;--md-teal-A700: #00bfa5;--md-green-50: #e8f5e9;--md-green-100: #c8e6c9;--md-green-200: #a5d6a7;--md-green-300: #81c784;--md-green-400: #66bb6a;--md-green-500: #4caf50;--md-green-600: #43a047;--md-green-700: #388e3c;--md-green-800: #2e7d32;--md-green-900: #1b5e20;--md-green-A100: #b9f6ca;--md-green-A200: #69f0ae;--md-green-A400: #00e676;--md-green-A700: #00c853;--md-light-green-50: #f1f8e9;--md-light-green-100: #dcedc8;--md-light-green-200: #c5e1a5;--md-light-green-300: #aed581;--md-light-green-400: #9ccc65;--md-light-green-500: #8bc34a;--md-light-green-600: #7cb342;--md-light-green-700: #689f38;--md-light-green-800: #558b2f;--md-light-green-900: #33691e;--md-light-green-A100: #ccff90;--md-light-green-A200: #b2ff59;--md-light-green-A400: #76ff03;--md-light-green-A700: #64dd17;--md-lime-50: #f9fbe7;--md-lime-100: #f0f4c3;--md-lime-200: #e6ee9c;--md-lime-300: #dce775;--md-lime-400: #d4e157;--md-lime-500: #cddc39;--md-lime-600: #c0ca33;--md-lime-700: #afb42b;--md-lime-800: #9e9d24;--md-lime-900: #827717;--md-lime-A100: #f4ff81;--md-lime-A200: #eeff41;--md-lime-A400: #c6ff00;--md-lime-A700: #aeea00;--md-yellow-50: #fffde7;--md-yellow-100: #fff9c4;--md-yellow-200: #fff59d;--md-yellow-300: #fff176;--md-yellow-400: #ffee58;--md-yellow-500: #ffeb3b;--md-yellow-600: #fdd835;--md-yellow-700: #fbc02d;--md-yellow-800: #f9a825;--md-yellow-900: #f57f17;--md-yellow-A100: #ffff8d;--md-yellow-A200: #ffff00;--md-yellow-A400: #ffea00;--md-yellow-A700: #ffd600;--md-amber-50: #fff8e1;--md-amber-100: #ffecb3;--md-amber-200: #ffe082;--md-amber-300: #ffd54f;--md-amber-400: #ffca28;--md-amber-500: #ffc107;--md-amber-600: #ffb300;--md-amber-700: #ffa000;--md-amber-800: #ff8f00;--md-amber-900: #ff6f00;--md-amber-A100: #ffe57f;--md-amber-A200: #ffd740;--md-amber-A400: #ffc400;--md-amber-A700: #ffab00;--md-orange-50: #fff3e0;--md-orange-100: #ffe0b2;--md-orange-200: #ffcc80;--md-orange-300: #ffb74d;--md-orange-400: #ffa726;--md-orange-500: #ff9800;--md-orange-600: #fb8c00;--md-orange-700: #f57c00;--md-orange-800: #ef6c00;--md-orange-900: #e65100;--md-orange-A100: #ffd180;--md-orange-A200: #ffab40;--md-orange-A400: #ff9100;--md-orange-A700: #ff6d00;--md-deep-orange-50: #fbe9e7;--md-deep-orange-100: #ffccbc;--md-deep-orange-200: #ffab91;--md-deep-orange-300: #ff8a65;--md-deep-orange-400: #ff7043;--md-deep-orange-500: #ff5722;--md-deep-orange-600: #f4511e;--md-deep-orange-700: #e64a19;--md-deep-orange-800: #d84315;--md-deep-orange-900: #bf360c;--md-deep-orange-A100: #ff9e80;--md-deep-orange-A200: #ff6e40;--md-deep-orange-A400: #ff3d00;--md-deep-orange-A700: #dd2c00;--md-brown-50: #efebe9;--md-brown-100: #d7ccc8;--md-brown-200: #bcaaa4;--md-brown-300: #a1887f;--md-brown-400: #8d6e63;--md-brown-500: #795548;--md-brown-600: #6d4c41;--md-brown-700: #5d4037;--md-brown-800: #4e342e;--md-brown-900: #3e2723;--md-grey-50: #fafafa;--md-grey-100: #f5f5f5;--md-grey-200: #eeeeee;--md-grey-300: #e0e0e0;--md-grey-400: #bdbdbd;--md-grey-500: #9e9e9e;--md-grey-600: #757575;--md-grey-700: #616161;--md-grey-800: #424242;--md-grey-900: #212121;--md-blue-grey-50: #eceff1;--md-blue-grey-100: #cfd8dc;--md-blue-grey-200: #b0bec5;--md-blue-grey-300: #90a4ae;--md-blue-grey-400: #78909c;--md-blue-grey-500: #607d8b;--md-blue-grey-600: #546e7a;--md-blue-grey-700: #455a64;--md-blue-grey-800: #37474f;--md-blue-grey-900: #263238}.jupyter-wrapper .jp-Spinner{position:absolute;display:flex;justify-content:center;align-items:center;z-index:10;left:0;top:0;width:100%;height:100%;background:var(--jp-layout-color0);outline:none}.jupyter-wrapper .jp-SpinnerContent{font-size:10px;margin:50px auto;text-indent:-9999em;width:3em;height:3em;border-radius:50%;background:var(--jp-brand-color3);background:linear-gradient(to right,#f37626 10%,rgba(255,255,255,0) 42%);position:relative;animation:load3 1s infinite linear,fadeIn 1s}.jupyter-wrapper .jp-SpinnerContent:before{width:50%;height:50%;background:#f37626;border-radius:100% 0 0;position:absolute;top:0;left:0;content:\"\"}.jupyter-wrapper .jp-SpinnerContent:after{background:var(--jp-layout-color0);width:75%;height:75%;border-radius:50%;content:\"\";margin:auto;position:absolute;top:0;left:0;bottom:0;right:0}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes load3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.jupyter-wrapper button.jp-mod-styled{font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);border:none;box-sizing:border-box;text-align:center;line-height:32px;height:32px;padding:0 12px;letter-spacing:.8px;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper input.jp-mod-styled{background:var(--jp-input-background);height:28px;box-sizing:border-box;border:var(--jp-border-width) solid var(--jp-border-color1);padding-left:7px;padding-right:7px;font-size:var(--jp-ui-font-size2);color:var(--jp-ui-font-color0);outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper input[type=checkbox].jp-mod-styled{appearance:checkbox;-webkit-appearance:checkbox;-moz-appearance:checkbox;height:auto}.jupyter-wrapper input.jp-mod-styled:focus{border:var(--jp-border-width) solid var(--md-blue-500);box-shadow:inset 0 0 4px var(--md-blue-300)}.jupyter-wrapper .jp-FileDialog-Checkbox{margin-top:35px;display:flex;flex-direction:row;align-items:end;width:100%}.jupyter-wrapper .jp-FileDialog-Checkbox>label{flex:1 1 auto}.jupyter-wrapper .jp-select-wrapper{display:flex;position:relative;flex-direction:column;padding:1px;background-color:var(--jp-layout-color1);height:28px;box-sizing:border-box;margin-bottom:12px}.jupyter-wrapper .jp-select-wrapper.jp-mod-focused select.jp-mod-styled{border:var(--jp-border-width) solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow);background-color:var(--jp-input-active-background)}.jupyter-wrapper select.jp-mod-styled:hover{background-color:var(--jp-layout-color1);cursor:pointer;color:var(--jp-ui-font-color0);background-color:var(--jp-input-hover-background);box-shadow:inset 0 0 1px #00000080}.jupyter-wrapper select.jp-mod-styled{flex:1 1 auto;height:32px;width:100%;font-size:var(--jp-ui-font-size2);background:var(--jp-input-background);color:var(--jp-ui-font-color0);padding:0 25px 0 8px;border:var(--jp-border-width) solid var(--jp-input-border-color);border-radius:0;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper :root{--jp-private-toolbar-height: calc( 28px + var(--jp-border-width) )}.jupyter-wrapper .jp-Toolbar{color:var(--jp-ui-font-color1);flex:0 0 auto;display:flex;flex-direction:row;border-bottom:var(--jp-border-width) solid var(--jp-toolbar-border-color);box-shadow:var(--jp-toolbar-box-shadow);background:var(--jp-toolbar-background);min-height:var(--jp-toolbar-micro-height);padding:2px;z-index:8;overflow-x:hidden}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-item.jp-Toolbar-spacer{flex-grow:1;flex-shrink:1}.jupyter-wrapper .jp-Toolbar-item.jp-Toolbar-kernelStatus{display:inline-block;width:32px;background-repeat:no-repeat;background-position:center;background-size:16px}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-item{flex:0 0 auto;display:flex;padding-left:1px;padding-right:1px;font-size:var(--jp-ui-font-size1);line-height:var(--jp-private-toolbar-height);height:100%}.jupyter-wrapper div.jp-ToolbarButton{color:transparent;border:none;box-sizing:border-box;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none;padding:0;margin:0}.jupyter-wrapper button.jp-ToolbarButtonComponent{background:var(--jp-layout-color1);border:none;box-sizing:border-box;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none;padding:0 6px;margin:0;height:24px;border-radius:var(--jp-border-radius);display:flex;align-items:center;text-align:center;font-size:14px;min-width:unset;min-height:unset}.jupyter-wrapper button.jp-ToolbarButtonComponent:disabled{opacity:.4}.jupyter-wrapper button.jp-ToolbarButtonComponent span{padding:0;flex:0 0 auto}.jupyter-wrapper button.jp-ToolbarButtonComponent .jp-ToolbarButtonComponent-label{font-size:var(--jp-ui-font-size1);line-height:100%;padding-left:2px;color:var(--jp-ui-font-color1)}.jupyter-wrapper #jp-main-dock-panel[data-mode=single-document] .jp-MainAreaWidget>.jp-Toolbar.jp-Toolbar-micro{padding:0;min-height:0}.jupyter-wrapper #jp-main-dock-panel[data-mode=single-document] .jp-MainAreaWidget>.jp-Toolbar{border:none;box-shadow:none}.jupyter-wrapper body.p-mod-override-cursor *,.jupyter-wrapper body.lm-mod-override-cursor *{cursor:inherit!important}.jupyter-wrapper .jp-JSONEditor{display:flex;flex-direction:column;width:100%}.jupyter-wrapper .jp-JSONEditor-host{flex:1 1 auto;border:var(--jp-border-width) solid var(--jp-input-border-color);border-radius:0;background:var(--jp-layout-color0);min-height:50px;padding:1px}.jupyter-wrapper .jp-JSONEditor.jp-mod-error .jp-JSONEditor-host{border-color:red;outline-color:red}.jupyter-wrapper .jp-JSONEditor-header{display:flex;flex:1 0 auto;padding:0 0 0 12px}.jupyter-wrapper .jp-JSONEditor-header label{flex:0 0 auto}.jupyter-wrapper .jp-JSONEditor-commitButton{height:16px;width:16px;background-size:18px;background-repeat:no-repeat;background-position:center}.jupyter-wrapper .jp-JSONEditor-host.jp-mod-focused{background-color:var(--jp-input-active-background);border:1px solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow)}.jupyter-wrapper .jp-Editor.jp-mod-dropTarget{border:var(--jp-border-width) solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow)}.jupyter-wrapper .jp-Statusbar-ProgressCircle svg{display:block;margin:0 auto;width:16px;height:24px;align-self:normal}.jupyter-wrapper .jp-Statusbar-ProgressCircle path{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar{height:10px;width:100px;border:solid .25px var(--jp-brand-color2);border-radius:3px;overflow:hidden;align-self:center}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar>div{background-color:var(--jp-brand-color2);background-image:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%,transparent);background-size:40px 40px;float:left;width:0%;height:100%;font-size:12px;line-height:14px;color:#fff;text-align:center;animation:jp-Statusbar-ExecutionTime-progress-bar 2s linear infinite}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar p{color:var(--jp-ui-font-color1);font-family:var(--jp-ui-font-family);font-size:var(--jp-ui-font-size1);line-height:10px;width:100px}@keyframes jp-Statusbar-ExecutionTime-progress-bar{0%{background-position:0 0}to{background-position:40px 40px}}.jupyter-wrapper .CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.jupyter-wrapper .CodeMirror-lines{padding:4px 0}.jupyter-wrapper .CodeMirror pre.CodeMirror-line,.jupyter-wrapper .CodeMirror pre.CodeMirror-line-like{padding:0 4px}.jupyter-wrapper .CodeMirror-scrollbar-filler,.jupyter-wrapper .CodeMirror-gutter-filler{background-color:#fff}.jupyter-wrapper .CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.jupyter-wrapper .CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.jupyter-wrapper .CodeMirror-guttermarker{color:#000}.jupyter-wrapper .CodeMirror-guttermarker-subtle{color:#999}.jupyter-wrapper .CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.jupyter-wrapper .CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.jupyter-wrapper .cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.jupyter-wrapper .cm-fat-cursor div.CodeMirror-cursors{z-index:1}.jupyter-wrapper .cm-fat-cursor-mark{background-color:#14ff1480;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.jupyter-wrapper .cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.jupyter-wrapper .cm-tab{display:inline-block;text-decoration:inherit}.jupyter-wrapper .CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.jupyter-wrapper .CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.jupyter-wrapper .cm-s-default .cm-header{color:#00f}.jupyter-wrapper .cm-s-default .cm-quote{color:#090}.jupyter-wrapper .cm-negative{color:#d44}.jupyter-wrapper .cm-positive{color:#292}.jupyter-wrapper .cm-header,.jupyter-wrapper .cm-strong{font-weight:700}.jupyter-wrapper .cm-em{font-style:italic}.jupyter-wrapper .cm-link{text-decoration:underline}.jupyter-wrapper .cm-strikethrough{text-decoration:line-through}.jupyter-wrapper .cm-s-default .cm-keyword{color:#708}.jupyter-wrapper .cm-s-default .cm-atom{color:#219}.jupyter-wrapper .cm-s-default .cm-number{color:#164}.jupyter-wrapper .cm-s-default .cm-def{color:#00f}.jupyter-wrapper .cm-s-default .cm-variable-2{color:#05a}.jupyter-wrapper .cm-s-default .cm-variable-3,.jupyter-wrapper .cm-s-default .cm-type{color:#085}.jupyter-wrapper .cm-s-default .cm-comment{color:#a50}.jupyter-wrapper .cm-s-default .cm-string{color:#a11}.jupyter-wrapper .cm-s-default .cm-string-2{color:#f50}.jupyter-wrapper .cm-s-default .cm-meta,.jupyter-wrapper .cm-s-default .cm-qualifier{color:#555}.jupyter-wrapper .cm-s-default .cm-builtin{color:#30a}.jupyter-wrapper .cm-s-default .cm-bracket{color:#997}.jupyter-wrapper .cm-s-default .cm-tag{color:#170}.jupyter-wrapper .cm-s-default .cm-attribute{color:#00c}.jupyter-wrapper .cm-s-default .cm-hr{color:#999}.jupyter-wrapper .cm-s-default .cm-link{color:#00c}.jupyter-wrapper .cm-s-default .cm-error,.jupyter-wrapper .cm-invalidchar{color:red}.jupyter-wrapper .CodeMirror-composing{border-bottom:2px solid}.jupyter-wrapper div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}.jupyter-wrapper div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.jupyter-wrapper .CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.jupyter-wrapper .CodeMirror-activeline-background{background:#e8f2ff}.jupyter-wrapper .CodeMirror{position:relative;overflow:hidden;background:white}.jupyter-wrapper .CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative}.jupyter-wrapper .CodeMirror-sizer{position:relative;border-right:50px solid transparent}.jupyter-wrapper .CodeMirror-vscrollbar,.jupyter-wrapper .CodeMirror-hscrollbar,.jupyter-wrapper .CodeMirror-scrollbar-filler,.jupyter-wrapper .CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.jupyter-wrapper .CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.jupyter-wrapper .CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.jupyter-wrapper .CodeMirror-scrollbar-filler{right:0;bottom:0}.jupyter-wrapper .CodeMirror-gutter-filler{left:0;bottom:0}.jupyter-wrapper .CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.jupyter-wrapper .CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.jupyter-wrapper .CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.jupyter-wrapper .CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.jupyter-wrapper .CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.jupyter-wrapper .CodeMirror-gutter-wrapper ::selection{background-color:transparent}.jupyter-wrapper .CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.jupyter-wrapper .CodeMirror-lines{cursor:text;min-height:1px}.jupyter-wrapper .CodeMirror pre.CodeMirror-line,.jupyter-wrapper .CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.jupyter-wrapper .CodeMirror-wrap pre.CodeMirror-line,.jupyter-wrapper .CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.jupyter-wrapper .CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.jupyter-wrapper .CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.jupyter-wrapper .CodeMirror-rtl pre{direction:rtl}.jupyter-wrapper .CodeMirror-code{outline:none}.jupyter-wrapper .CodeMirror-scroll,.jupyter-wrapper .CodeMirror-sizer,.jupyter-wrapper .CodeMirror-gutter,.jupyter-wrapper .CodeMirror-gutters,.jupyter-wrapper .CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.jupyter-wrapper .CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.jupyter-wrapper .CodeMirror-cursor{position:absolute;pointer-events:none}.jupyter-wrapper .CodeMirror-measure pre{position:static}.jupyter-wrapper div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.jupyter-wrapper div.CodeMirror-dragcursors,.jupyter-wrapper .CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.jupyter-wrapper .CodeMirror-selected{background:#d9d9d9}.jupyter-wrapper .CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.jupyter-wrapper .CodeMirror-crosshair{cursor:crosshair}.jupyter-wrapper .CodeMirror-line::selection,.jupyter-wrapper .CodeMirror-line>span::selection,.jupyter-wrapper .CodeMirror-line>span>span::selection{background:#d7d4f0}.jupyter-wrapper .CodeMirror-line::-moz-selection,.jupyter-wrapper .CodeMirror-line>span::-moz-selection,.jupyter-wrapper .CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.jupyter-wrapper .cm-searching{background-color:#ffa;background-color:#ff06}.jupyter-wrapper .cm-force-border{padding-right:.1px}@media print{.jupyter-wrapper .CodeMirror div.CodeMirror-cursors{visibility:hidden}}.jupyter-wrapper .cm-tab-wrap-hack:after{content:\"\"}.jupyter-wrapper span.CodeMirror-selectedtext{background:none}.jupyter-wrapper .CodeMirror-dialog{position:absolute;left:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.jupyter-wrapper .CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.jupyter-wrapper .CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.jupyter-wrapper .CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.jupyter-wrapper .CodeMirror-dialog button{font-size:70%}.jupyter-wrapper .CodeMirror-foldmarker{color:#00f;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.jupyter-wrapper .CodeMirror-foldgutter{width:.7em}.jupyter-wrapper .CodeMirror-foldgutter-open,.jupyter-wrapper .CodeMirror-foldgutter-folded{cursor:pointer}.jupyter-wrapper .CodeMirror-foldgutter-open:after{content:\"\u25be\"}.jupyter-wrapper .CodeMirror-foldgutter-folded:after{content:\"\u25b8\"}.jupyter-wrapper .CodeMirror{line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);font-family:var(--jp-code-font-family);border:0;border-radius:0;height:auto}.jupyter-wrapper .CodeMirror pre{padding:0 var(--jp-code-padding)}.jupyter-wrapper .CodeMirror.cm-fat-cursor .cm-overlay.cm-searching{opacity:.5}.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-dialog{background-color:var(--jp-layout-color0);color:var(--jp-content-font-color1)}.jupyter-wrapper .CodeMirror-lines{padding:var(--jp-code-padding) 0}.jupyter-wrapper .CodeMirror-linenumber{padding:0 8px}.jupyter-wrapper .jp-CodeMirrorEditor{cursor:text}.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)}@media screen and (min-width: 2138px) and (max-width: 4319px){.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width1) solid var(--jp-editor-cursor-color)}}@media screen and (min-width: 4320px){.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width2) solid var(--jp-editor-cursor-color)}}.jupyter-wrapper .CodeMirror.jp-mod-readOnly .CodeMirror-cursor{display:none}.jupyter-wrapper .CodeMirror-gutters{border-right:1px solid var(--jp-border-color2);background-color:var(--jp-layout-color0)}.jupyter-wrapper .jp-CollaboratorCursor{border-left:5px solid transparent;border-right:5px solid transparent;border-top:none;border-bottom:3px solid;background-clip:content-box;margin-left:-5px;margin-right:-5px}.jupyter-wrapper .CodeMirror-selectedtext.cm-searching{background-color:var(--jp-search-selected-match-background-color)!important;color:var(--jp-search-selected-match-color)!important}.jupyter-wrapper .cm-searching{background-color:var(--jp-search-unselected-match-background-color)!important;color:var(--jp-search-unselected-match-color)!important}.jupyter-wrapper .cm-trailingspace{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAsElEQVQIHQGlAFr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7+r3zKmT0/+pk9P/7+r3zAAAAAAAAAAABAAAAAAAAAAA6OPzM+/q9wAAAAAA6OPzMwAAAAAAAAAAAgAAAAAAAAAAGR8NiRQaCgAZIA0AGR8NiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQyoYJ/SY80UAAAAASUVORK5CYII=);background-position:center left;background-repeat:repeat-x}.jupyter-wrapper .CodeMirror-focused .CodeMirror-selected{background-color:var(--jp-editor-selected-focused-background)}.jupyter-wrapper .CodeMirror-selected{background-color:var(--jp-editor-selected-background)}.jupyter-wrapper .jp-CollaboratorCursor-hover{position:absolute;z-index:1;transform:translate(-50%);color:#fff;border-radius:3px;padding:1px 4px;text-align:center;font-size:var(--jp-ui-font-size1);white-space:nowrap}.jupyter-wrapper .jp-CodeMirror-ruler{border-left:1px dashed var(--jp-border-color2)}.jupyter-wrapper .CodeMirror.cm-s-jupyter{background:var(--jp-layout-color0);color:var(--jp-content-font-color1)}.jupyter-wrapper .jp-CodeConsole .CodeMirror.cm-s-jupyter,.jupyter-wrapper .jp-Notebook .CodeMirror.cm-s-jupyter{background:transparent}.jupyter-wrapper .cm-s-jupyter .CodeMirror-cursor{border-left:var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)}.jupyter-wrapper .cm-s-jupyter span.cm-keyword{color:var(--jp-mirror-editor-keyword-color);font-weight:700}.jupyter-wrapper .cm-s-jupyter span.cm-atom{color:var(--jp-mirror-editor-atom-color)}.jupyter-wrapper .cm-s-jupyter span.cm-number{color:var(--jp-mirror-editor-number-color)}.jupyter-wrapper .cm-s-jupyter span.cm-def{color:var(--jp-mirror-editor-def-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable{color:var(--jp-mirror-editor-variable-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable-2{color:var(--jp-mirror-editor-variable-2-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable-3{color:var(--jp-mirror-editor-variable-3-color)}.jupyter-wrapper .cm-s-jupyter span.cm-punctuation{color:var(--jp-mirror-editor-punctuation-color)}.jupyter-wrapper .cm-s-jupyter span.cm-property{color:var(--jp-mirror-editor-property-color)}.jupyter-wrapper .cm-s-jupyter span.cm-operator{color:var(--jp-mirror-editor-operator-color);font-weight:700}.jupyter-wrapper .cm-s-jupyter span.cm-comment{color:var(--jp-mirror-editor-comment-color);font-style:italic}.jupyter-wrapper .cm-s-jupyter span.cm-string{color:var(--jp-mirror-editor-string-color)}.jupyter-wrapper .cm-s-jupyter span.cm-string-2{color:var(--jp-mirror-editor-string-2-color)}.jupyter-wrapper .cm-s-jupyter span.cm-meta{color:var(--jp-mirror-editor-meta-color)}.jupyter-wrapper .cm-s-jupyter span.cm-qualifier{color:var(--jp-mirror-editor-qualifier-color)}.jupyter-wrapper .cm-s-jupyter span.cm-builtin{color:var(--jp-mirror-editor-builtin-color)}.jupyter-wrapper .cm-s-jupyter span.cm-bracket{color:var(--jp-mirror-editor-bracket-color)}.jupyter-wrapper .cm-s-jupyter span.cm-tag{color:var(--jp-mirror-editor-tag-color)}.jupyter-wrapper .cm-s-jupyter span.cm-attribute{color:var(--jp-mirror-editor-attribute-color)}.jupyter-wrapper .cm-s-jupyter span.cm-header{color:var(--jp-mirror-editor-header-color)}.jupyter-wrapper .cm-s-jupyter span.cm-quote{color:var(--jp-mirror-editor-quote-color)}.jupyter-wrapper .cm-s-jupyter span.cm-link{color:var(--jp-mirror-editor-link-color)}.jupyter-wrapper .cm-s-jupyter span.cm-error{color:var(--jp-mirror-editor-error-color)}.jupyter-wrapper .cm-s-jupyter span.cm-hr{color:#999}.jupyter-wrapper .cm-s-jupyter span.cm-tab{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);background-position:right;background-repeat:no-repeat}.jupyter-wrapper .cm-s-jupyter .CodeMirror-activeline-background,.jupyter-wrapper .cm-s-jupyter .CodeMirror-gutter{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret{position:relative;border-left:2px solid black;margin-left:-1px;margin-right:-1px;box-sizing:border-box}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret>div{white-space:nowrap;position:absolute;top:-1.15em;padding-bottom:.05em;left:-2px;font-size:.95em;background-color:#fa8100;font-family:var(--jp-ui-font-family);font-weight:700;line-height:normal;-webkit-user-select:none;user-select:none;color:#fff;padding-left:2px;padding-right:2px;z-index:3;transition:opacity .3s ease-in-out}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret.hide-name>div{transition-delay:.7s;opacity:0}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret:hover>div[style]{opacity:1;transition-delay:0s}.jupyter-wrapper :root{--jp-private-code-span-padding: calc( (var(--jp-code-line-height) - 1) * var(--jp-code-font-size) / 2 )}.jupyter-wrapper .jp-RenderedText{text-align:left;padding-left:var(--jp-code-padding);line-height:var(--jp-code-line-height);font-family:var(--jp-code-font-family)}.jupyter-wrapper .jp-RenderedText pre,.jupyter-wrapper .jp-RenderedJavaScript pre,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore pre{color:var(--jp-content-font-color1);font-size:var(--jp-code-font-size);border:none;margin:0;padding:0}.jupyter-wrapper .jp-RenderedText pre a:link{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre a:hover{text-decoration:underline;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre a:visited{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre .ansi-black-fg{color:#3e424d}.jupyter-wrapper .jp-RenderedText pre .ansi-red-fg{color:#e75c58}.jupyter-wrapper .jp-RenderedText pre .ansi-green-fg{color:#00a250}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-fg{color:#ddb62b}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-fg{color:#208ffb}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-fg{color:#d160c4}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-fg{color:#60c6c8}.jupyter-wrapper .jp-RenderedText pre .ansi-white-fg{color:#c5c1b4}.jupyter-wrapper .jp-RenderedText pre .ansi-black-bg{background-color:#3e424d;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-red-bg{background-color:#e75c58;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-green-bg{background-color:#00a250;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-bg{background-color:#ddb62b;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-bg{background-color:#208ffb;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-bg{background-color:#d160c4;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-bg{background-color:#60c6c8;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-white-bg{background-color:#c5c1b4;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-black-intense-fg{color:#282c36}.jupyter-wrapper .jp-RenderedText pre .ansi-red-intense-fg{color:#b22b31}.jupyter-wrapper .jp-RenderedText pre .ansi-green-intense-fg{color:#007427}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-intense-fg{color:#b27d12}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-intense-fg{color:#0065ca}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-intense-fg{color:#a03196}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-intense-fg{color:#258f8f}.jupyter-wrapper .jp-RenderedText pre .ansi-white-intense-fg{color:#a1a6b2}.jupyter-wrapper .jp-RenderedText pre .ansi-black-intense-bg{background-color:#282c36;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-red-intense-bg{background-color:#b22b31;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-green-intense-bg{background-color:#007427;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-intense-bg{background-color:#b27d12;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-intense-bg{background-color:#0065ca;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-intense-bg{background-color:#a03196;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-intense-bg{background-color:#258f8f;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-white-intense-bg{background-color:#a1a6b2;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-default-inverse-fg{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .jp-RenderedText pre .ansi-default-inverse-bg{background-color:var(--jp-inverse-layout-color0);padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-bold{font-weight:700}.jupyter-wrapper .jp-RenderedText pre .ansi-underline{text-decoration:underline}.jupyter-wrapper .jp-RenderedText[data-mime-type=\"application/vnd.jupyter.stderr\"]{background:var(--jp-rendermime-error-background);padding-top:var(--jp-code-padding)}.jupyter-wrapper .jp-RenderedLatex{color:var(--jp-content-font-color1);font-size:var(--jp-content-font-size1);line-height:var(--jp-content-line-height)}.jupyter-wrapper .jp-OutputArea-output.jp-RenderedLatex{padding:var(--jp-code-padding);text-align:left}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore{color:var(--jp-content-font-color1);font-family:var(--jp-content-font-family);font-size:var(--jp-content-font-size1);line-height:var(--jp-content-line-height);padding-right:20px}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore em{font-style:italic}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore strong{font-weight:700}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore u{text-decoration:underline}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:link{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:hover{text-decoration:underline;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:visited{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6{line-height:var(--jp-content-heading-line-height);font-weight:var(--jp-content-heading-font-weight);font-style:normal;margin:var(--jp-content-heading-margin-top) 0 var(--jp-content-heading-margin-bottom) 0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6:first-child{margin-top:calc(.5 * var(--jp-content-heading-margin-top))}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6:last-child{margin-bottom:calc(.5 * var(--jp-content-heading-margin-bottom))}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1{font-size:var(--jp-content-font-size5)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2{font-size:var(--jp-content-font-size4)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3{font-size:var(--jp-content-font-size3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4{font-size:var(--jp-content-font-size2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5{font-size:var(--jp-content-font-size1)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6{font-size:var(--jp-content-font-size0)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul:not(.list-inline),.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol:not(.list-inline){padding-left:2em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul{list-style:disc}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul{list-style:square}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul ul{list-style:circle}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol{list-style:decimal}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol{list-style:upper-alpha}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol{list-style:lower-alpha}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol ol{list-style:lower-roman}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol ol ol{list-style:decimal}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ol,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ul,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore hr{color:var(--jp-border-color2);background-color:var(--jp-border-color1);margin-top:1em;margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>pre{margin:1.5em 2em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore pre,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore code{border:0;background-color:var(--jp-layout-color0);color:var(--jp-content-font-color1);font-family:var(--jp-code-font-family);font-size:inherit;line-height:var(--jp-code-line-height);padding:0;white-space:pre-wrap}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore :not(pre)>code{background-color:var(--jp-layout-color2);padding:1px 5px}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore table{border-collapse:collapse;border-spacing:0;border:none;color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);table-layout:fixed;margin-left:auto;margin-right:auto}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore thead{border-bottom:var(--jp-border-width) solid var(--jp-border-color1);vertical-align:bottom}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore th,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tr{vertical-align:middle;padding:.5em;line-height:normal;white-space:normal;max-width:none;border:none}.jupyter-wrapper .jp-RenderedMarkdown.jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper .jp-RenderedMarkdown.jp-RenderedHTMLCommon-ignore th{max-width:none}.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore th,.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore tr{text-align:right}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore th{font-weight:700}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:nth-child(odd){background:var(--jp-layout-color0)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:nth-child(2n){background:var(--jp-rendermime-table-row-background)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:hover{background:var(--jp-rendermime-table-row-hover-background)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore table{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore p{text-align:left;margin:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore p{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img{-moz-force-broken-image-icon:1}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>img{display:block;margin-left:0;margin-right:0;margin-bottom:1em}.jupyter-wrapper [data-jp-theme-light=false] .jp-RenderedImage img.jp-needs-light-background,.jupyter-wrapper [data-jp-theme-light=true] .jp-RenderedImage img.jp-needs-dark-background{background-color:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img,.jupyter-wrapper .jp-RenderedImage img,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore svg,.jupyter-wrapper .jp-RenderedSVG svg{max-width:100%;height:auto}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedImage img.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore svg.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedSVG svg.jp-mod-unconfined{max-width:none}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert{padding:var(--jp-notebook-padding);border:var(--jp-border-width) solid transparent;border-radius:var(--jp-border-radius);margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info{color:var(--jp-info-color0);background-color:var(--jp-info-color3);border-color:var(--jp-info-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info hr{border-color:var(--jp-info-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning{color:var(--jp-warn-color0);background-color:var(--jp-warn-color3);border-color:var(--jp-warn-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning hr{border-color:var(--jp-warn-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success{color:var(--jp-success-color0);background-color:var(--jp-success-color3);border-color:var(--jp-success-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success hr{border-color:var(--jp-success-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger{color:var(--jp-error-color0);background-color:var(--jp-error-color3);border-color:var(--jp-error-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger hr{border-color:var(--jp-error-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore blockquote{margin:1em 2em;padding:0 1em;border-left:5px solid var(--jp-border-color2)}.jupyter-wrapper a.jp-InternalAnchorLink{visibility:hidden;margin-left:8px;color:var(--md-blue-800)}.jupyter-wrapper h1:hover .jp-InternalAnchorLink,.jupyter-wrapper h2:hover .jp-InternalAnchorLink,.jupyter-wrapper h3:hover .jp-InternalAnchorLink,.jupyter-wrapper h4:hover .jp-InternalAnchorLink,.jupyter-wrapper h5:hover .jp-InternalAnchorLink,.jupyter-wrapper h6:hover .jp-InternalAnchorLink{visibility:visible}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore kbd{background-color:var(--jp-rendermime-table-row-background);border:1px solid var(--jp-border-color0);border-bottom-color:var(--jp-border-color2);border-radius:3px;box-shadow:inset 0 -1px #00000040;display:inline-block;font-size:var(--jp-ui-font-size0);line-height:1em;padding:.2em .5em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>*:last-child{margin-bottom:.5em}.jupyter-wrapper .jp-MimeDocument{outline:none}.jupyter-wrapper :root{--jp-private-filebrowser-button-height: 28px;--jp-private-filebrowser-button-width: 48px}.jupyter-wrapper .jp-FileBrowser{display:flex;flex-direction:column;color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .jp-FileBrowser-toolbar.jp-Toolbar{border-bottom:none;height:auto;margin:8px 12px 0;padding:0;box-shadow:none;justify-content:flex-start}.jupyter-wrapper .jp-BreadCrumbs{flex:0 0 auto;margin:8px 12px}.jupyter-wrapper .jp-BreadCrumbs-item{margin:0 2px;padding:0 2px;border-radius:var(--jp-border-radius);cursor:pointer}.jupyter-wrapper .jp-BreadCrumbs-item:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-BreadCrumbs-item:first-child{margin-left:0}.jupyter-wrapper .jp-BreadCrumbs-item.jp-mod-dropTarget{background-color:var(--jp-brand-color2);opacity:.7}.jupyter-wrapper .jp-FileBrowser-toolbar>.jp-Toolbar-item{flex:0 0 auto;padding-left:0;padding-right:2px}.jupyter-wrapper .jp-FileBrowser-toolbar>.jp-Toolbar-item .jp-ToolbarButtonComponent{width:40px}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]{width:72px;background:var(--jp-brand-color1)}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]:hover,.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]:focus-visible{background-color:var(--jp-brand-color0)!important}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"] .jp-icon3{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-FileDialog.jp-mod-conflict input{color:var(--jp-error-color1)}.jupyter-wrapper .jp-FileDialog .jp-new-name-title{margin-top:12px}.jupyter-wrapper .jp-LastModified-hidden{display:none}.jupyter-wrapper .jp-FileBrowser-filterBox{padding:0;flex:0 0 auto;margin:8px 12px 0}.jupyter-wrapper .jp-DirListing{flex:1 1 auto;display:flex;flex-direction:column;outline:0}.jupyter-wrapper .jp-DirListing:focus-visible{outline:1px solid var(--jp-brand-color1);outline-offset:-2px}.jupyter-wrapper .jp-DirListing-header{flex:0 0 auto;display:flex;flex-direction:row;overflow:hidden;border-top:var(--jp-border-width) solid var(--jp-border-color2);border-bottom:var(--jp-border-width) solid var(--jp-border-color1);box-shadow:var(--jp-toolbar-box-shadow);z-index:2}.jupyter-wrapper .jp-DirListing-headerItem{padding:4px 12px 2px;font-weight:500}.jupyter-wrapper .jp-DirListing-headerItem:hover{background:var(--jp-layout-color2)}.jupyter-wrapper .jp-DirListing-headerItem.jp-id-name{flex:1 0 84px}.jupyter-wrapper .jp-DirListing-headerItem.jp-id-modified{flex:0 0 112px;border-left:var(--jp-border-width) solid var(--jp-border-color2);text-align:right}.jupyter-wrapper .jp-id-narrow{display:none;flex:0 0 5px;padding:4px;border-left:var(--jp-border-width) solid var(--jp-border-color2);text-align:right;color:var(--jp-border-color2)}.jupyter-wrapper .jp-DirListing-narrow .jp-id-narrow{display:block}.jupyter-wrapper .jp-DirListing-narrow .jp-id-modified,.jupyter-wrapper .jp-DirListing-narrow .jp-DirListing-itemModified{display:none}.jupyter-wrapper .jp-DirListing-headerItem.jp-mod-selected{font-weight:600}.jupyter-wrapper .jp-DirListing-content{flex:1 1 auto;margin:0;padding:0;list-style-type:none;overflow:auto;background-color:var(--jp-layout-color1)}.jupyter-wrapper .jp-DirListing-content mark{color:var(--jp-ui-font-color0);background-color:transparent;font-weight:700}.jupyter-wrapper .jp-DirListing-content .jp-DirListing-item.jp-mod-selected mark{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .jp-DirListing.jp-mod-native-drop .jp-DirListing-content{outline:5px dashed rgba(128,128,128,.5);outline-offset:-10px;cursor:copy}.jupyter-wrapper .jp-DirListing-item{display:flex;flex-direction:row;padding:4px 12px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .jp-DirListing-item[data-is-dot]{opacity:75%}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected{color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .jp-DirListing-item.jp-mod-dropTarget{background:var(--jp-brand-color3)}.jupyter-wrapper .jp-DirListing-item:hover:not(.jp-mod-selected){background:var(--jp-layout-color2)}.jupyter-wrapper .jp-DirListing-itemIcon{flex:0 0 20px;margin-right:4px}.jupyter-wrapper .jp-DirListing-itemText{flex:1 0 64px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;user-select:none}.jupyter-wrapper .jp-DirListing-itemModified{flex:0 0 125px;text-align:right}.jupyter-wrapper .jp-DirListing-editor{flex:1 0 64px;outline:none;border:none;color:var(--jp-ui-font-color1);background-color:var(--jp-layout-color1)}.jupyter-wrapper .jp-DirListing-item.jp-mod-running .jp-DirListing-itemIcon:before{color:var(--jp-success-color1);content:\"\u25cf\";font-size:8px;position:absolute;left:-8px}.jupyter-wrapper .jp-DirListing-item.jp-mod-running.jp-mod-selected .jp-DirListing-itemIcon:before{color:var(--jp-ui-inverse-font-color1)}.jupyter-wrapper .jp-DirListing-item.lm-mod-drag-image,.jupyter-wrapper .jp-DirListing-item.jp-mod-selected.lm-mod-drag-image{font-size:var(--jp-ui-font-size1);padding-left:4px;margin-left:4px;width:160px;background-color:var(--jp-ui-inverse-font-color2);box-shadow:var(--jp-elevation-z2);border-radius:0;color:var(--jp-ui-font-color1);transform:translate(-40%) translateY(-58%)}.jupyter-wrapper .jp-Document{min-width:120px;min-height:120px;outline:none}.jupyter-wrapper .jp-OutputArea{overflow-y:auto}.jupyter-wrapper .jp-OutputArea-child{display:flex;flex-direction:row}.jupyter-wrapper body[data-format=mobile] .jp-OutputArea-child{flex-direction:column}.jupyter-wrapper .jp-OutputPrompt{flex:0 0 var(--jp-cell-prompt-width);color:var(--jp-cell-outprompt-font-color);font-family:var(--jp-cell-prompt-font-family);padding:var(--jp-code-padding);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent;opacity:var(--jp-cell-prompt-opacity);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper body[data-format=mobile] .jp-OutputPrompt{flex:0 0 auto;text-align:left}.jupyter-wrapper .jp-OutputArea-output{height:auto;overflow:auto;user-select:text;-moz-user-select:text;-webkit-user-select:text;-ms-user-select:text}.jupyter-wrapper .jp-OutputArea-child .jp-OutputArea-output{flex-grow:1;flex-shrink:1}.jupyter-wrapper body[data-format=mobile] .jp-OutputArea-child .jp-OutputArea-output{margin-left:var(--jp-notebook-padding)}.jupyter-wrapper .jp-OutputArea-output.jp-mod-isolated{width:100%;display:block}.jupyter-wrapper body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated{position:relative}.jupyter-wrapper body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated:before{content:\"\";position:absolute;top:0;left:0;right:0;bottom:0;background:transparent}.jupyter-wrapper .jp-OutputArea-output pre{border:none;margin:0;padding:0;overflow-x:auto;overflow-y:auto;word-break:break-all;word-wrap:break-word;white-space:pre-wrap}.jupyter-wrapper .jp-OutputArea-output.jp-RenderedHTMLCommon-ignore table{margin-left:0;margin-right:0}.jupyter-wrapper .jp-OutputArea-output dl,.jupyter-wrapper .jp-OutputArea-output dt,.jupyter-wrapper .jp-OutputArea-output dd{display:block}.jupyter-wrapper .jp-OutputArea-output dl{width:100%;overflow:hidden;padding:0;margin:0}.jupyter-wrapper .jp-OutputArea-output dt{font-weight:700;float:left;width:20%;padding:0;margin:0}.jupyter-wrapper .jp-OutputArea-output dd{float:left;width:80%;padding:0;margin:0}.jupyter-wrapper .jp-TrimmedOutputs a{margin:10px;text-decoration:none;cursor:pointer}.jupyter-wrapper .jp-OutputArea .jp-OutputArea .jp-OutputArea-prompt{display:none}.jupyter-wrapper .jp-OutputArea-prompt:empty{padding:0;border:0}.jupyter-wrapper .jp-OutputArea-output.jp-OutputArea-executeResult{margin-left:0;flex:1 1 auto}.jupyter-wrapper .jp-OutputArea-executeResult .jp-RenderedText.jp-OutputArea-output{padding-top:var(--jp-code-padding);border-top:var(--jp-border-width) solid transparent}.jupyter-wrapper .jp-Stdin-prompt{color:var(--jp-content-font-color0);padding-right:var(--jp-code-padding);vertical-align:baseline;flex:0 0 auto}.jupyter-wrapper .jp-Stdin-input{font-family:var(--jp-code-font-family);font-size:inherit;color:inherit;background-color:inherit;width:42%;min-width:200px;vertical-align:baseline;padding:0 .25em;margin:0 .25em;flex:0 0 70%}.jupyter-wrapper .jp-Stdin-input::placeholder{opacity:0}.jupyter-wrapper .jp-Stdin-input:focus{box-shadow:none}.jupyter-wrapper .jp-Stdin-input:focus::placeholder{opacity:1}.jupyter-wrapper .jp-LinkedOutputView .jp-OutputArea{height:100%;display:block}.jupyter-wrapper .jp-LinkedOutputView .jp-OutputArea-output:only-child{height:100%}.jupyter-wrapper .jp-Collapser{flex:0 0 var(--jp-cell-collapser-width);padding:0;margin:0;border:none;outline:none;background:transparent;border-radius:var(--jp-border-radius);opacity:1}.jupyter-wrapper .jp-Collapser-child{display:block;width:100%;box-sizing:border-box;position:absolute;top:0;bottom:0}.jupyter-wrapper .jp-CellHeader,.jupyter-wrapper .jp-CellFooter{height:0px;width:100%;padding:0;margin:0;border:none;outline:none;background:transparent}.jupyter-wrapper .jp-InputArea{display:flex;flex-direction:row;overflow:hidden}.jupyter-wrapper body[data-format=mobile] .jp-InputArea{flex-direction:column}.jupyter-wrapper .jp-InputArea-editor{flex:1 1 auto;overflow:hidden}.jupyter-wrapper .jp-InputArea-editor{border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);border-radius:0;background:var(--jp-cell-editor-background)}.jupyter-wrapper body[data-format=mobile] .jp-InputArea-editor{margin-left:var(--jp-notebook-padding)}.jupyter-wrapper .jp-InputPrompt{flex:0 0 var(--jp-cell-prompt-width);color:var(--jp-cell-inprompt-font-color);font-family:var(--jp-cell-prompt-font-family);padding:var(--jp-code-padding);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent;opacity:var(--jp-cell-prompt-opacity);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper body[data-format=mobile] .jp-InputPrompt{flex:0 0 auto;text-align:left}.jupyter-wrapper .jp-Placeholder{display:flex;flex-direction:row;flex:1 1 auto}.jupyter-wrapper .jp-Placeholder-prompt{box-sizing:border-box}.jupyter-wrapper .jp-Placeholder-content{flex:1 1 auto;border:none;background:transparent;height:20px;box-sizing:border-box}.jupyter-wrapper .jp-Placeholder-content .jp-MoreHorizIcon{width:32px;height:16px;border:1px solid transparent;border-radius:var(--jp-border-radius)}.jupyter-wrapper .jp-Placeholder-content .jp-MoreHorizIcon:hover{border:1px solid var(--jp-border-color1);box-shadow:0 0 2px #00000040;background-color:var(--jp-layout-color0)}.jupyter-wrapper :root{--jp-private-cell-scrolling-output-offset: 5px}.jupyter-wrapper .jp-Cell{padding:var(--jp-cell-padding);margin:0;border:none;outline:none;background:transparent}.jupyter-wrapper .jp-Cell-inputWrapper,.jupyter-wrapper .jp-Cell-outputWrapper{display:flex;flex-direction:row;padding:0;margin:0;overflow:visible}.jupyter-wrapper .jp-Cell-inputArea,.jupyter-wrapper .jp-Cell-outputArea{flex:1 1 auto}.jupyter-wrapper .jp-Cell.jp-mod-noOutputs .jp-Cell-outputCollapser{border:none!important;background:transparent!important}.jupyter-wrapper .jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputCollapser{min-height:var(--jp-cell-collapser-min-height)}.jupyter-wrapper .jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputWrapper{margin-top:5px}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea{overflow-y:auto;max-height:24em;margin-left:var(--jp-private-cell-scrolling-output-offset)}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea:after{content:\" \";box-shadow:inset 0 0 6px 2px #0000004d;width:100%;height:100%;position:sticky;bottom:0;top:0;margin-top:-50%;float:left;display:block;pointer-events:none}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-child{padding-top:6px}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-prompt{flex:0 0 calc(var(--jp-cell-prompt-width) - var(--jp-private-cell-scrolling-output-offset))}.jupyter-wrapper .jp-MarkdownOutput{flex:1 1 auto;margin-top:0;margin-bottom:0;padding-left:var(--jp-code-padding)}.jupyter-wrapper .jp-MarkdownOutput.jp-RenderedHTMLCommon-ignore{overflow:auto}.jupyter-wrapper .jp-collapseHeadingButton{display:none;min-height:var(--jp-cell-collapser-min-height);font-size:var(--jp-code-font-size);position:absolute;right:0;top:0;bottom:0;background-color:transparent;background-size:25px;background-repeat:no-repeat;background-position-x:center;background-position-y:top;background-image:var(--jp-icon-caret-down);border:none;cursor:pointer}.jupyter-wrapper .jp-collapseHeadingButton:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-collapseHeadingButton.jp-mod-collapsed{background-image:var(--jp-icon-caret-right)}.jupyter-wrapper :is(.jp-MarkdownCell:hover,.jp-mod-active) .jp-collapseHeadingButton{display:flex}.jupyter-wrapper .jp-MarkdownCell .jp-InputPrompt{font-size:var(--jp-content-font-size1)}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"1\"]{font-size:var(--jp-content-font-size5);background-position-y:calc(.3 * var(--jp-content-font-size5))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"2\"]{font-size:var(--jp-content-font-size4);background-position-y:calc(.3 * var(--jp-content-font-size4))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"3\"]{font-size:var(--jp-content-font-size3);background-position-y:calc(.3 * var(--jp-content-font-size3))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"4\"]{font-size:var(--jp-content-font-size2);background-position-y:calc(.3 * var(--jp-content-font-size2))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"5\"]{font-size:var(--jp-content-font-size1);background-position-y:top}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"6\"]{font-size:var(--jp-content-font-size0);background-position-y:top}.jupyter-wrapper .jp-showHiddenCellsButton{margin-left:calc(var(--jp-cell-prompt-width) + 2 * var(--jp-code-padding));margin-top:var(--jp-code-padding);border:1px solid var(--jp-border-color2);background-color:var(--jp-border-color3)!important;color:var(--jp-content-font-color0)!important}.jupyter-wrapper .jp-showHiddenCellsButton:hover{background-color:var(--jp-border-color2)!important}.jupyter-wrapper :root{--jp-notebook-toolbar-padding: 2px 5px 2px 2px}.jupyter-wrapper .jp-NotebookPanel-toolbar{padding:var(--jp-notebook-toolbar-padding)}.jupyter-wrapper .jp-Toolbar-item.jp-Notebook-toolbarCellType .jp-select-wrapper.jp-mod-focused{border:none;box-shadow:none}.jupyter-wrapper .jp-Notebook-toolbarCellTypeDropdown select{height:24px;font-size:var(--jp-ui-font-size1);line-height:14px;border-radius:0;display:block}.jupyter-wrapper .jp-Notebook-toolbarCellTypeDropdown span{top:5px!important}.jupyter-wrapper .jp-Toolbar-responsive-popup{position:absolute;height:fit-content;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-end;border-bottom:var(--jp-border-width) solid var(--jp-toolbar-border-color);box-shadow:var(--jp-toolbar-box-shadow);background:var(--jp-toolbar-background);min-height:var(--jp-toolbar-micro-height);padding:var(--jp-notebook-toolbar-padding);z-index:1;right:0;top:0}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-responsive-opener{margin-left:auto}.jupyter-wrapper .jp-Notebook-ExecutionIndicator{position:relative;display:inline-block;height:100%;z-index:9997}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip{visibility:hidden;height:auto;width:max-content;width:-moz-max-content;background-color:var(--jp-layout-color2);color:var(--jp-ui-font-color1);text-align:justify;border-radius:6px;padding:0 5px;position:fixed;display:table}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.up{transform:translate(-50%) translateY(-100%) translateY(-32px)}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.down{transform:translate(calc(-100% + 16px)) translateY(5px)}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.hidden{display:none}.jupyter-wrapper .jp-Notebook-ExecutionIndicator:hover .jp-Notebook-ExecutionIndicator-tooltip{visibility:visible}.jupyter-wrapper .jp-Notebook-ExecutionIndicator span{font-size:var(--jp-ui-font-size1);font-family:var(--jp-ui-font-family);color:var(--jp-ui-font-color1);line-height:24px;display:block}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-progress-bar{display:flex;justify-content:center;height:100%}.jupyter-wrapper :root{--jp-private-notebook-dragImage-width: 304px;--jp-private-notebook-dragImage-height: 36px;--jp-private-notebook-selected-color: var(--md-blue-400);--jp-private-notebook-active-color: var(--md-green-400)}.jupyter-wrapper .jp-NotebookPanel{display:block;height:100%}.jupyter-wrapper .jp-NotebookPanel.jp-Document{min-width:240px;min-height:120px}.jupyter-wrapper .jp-Notebook{padding:var(--jp-notebook-padding);outline:none;overflow:auto}.jupyter-wrapper .jp-Notebook.jp-mod-scrollPastEnd:after{display:block;content:\"\";min-height:var(--jp-notebook-scroll-padding)}.jupyter-wrapper .jp-MainAreaWidget-ContainStrict .jp-Notebook *{contain:strict}.jupyter-wrapper .jp-Notebook .jp-Cell{overflow:visible}.jupyter-wrapper .jp-Notebook .jp-Cell .jp-InputPrompt{cursor:move;float:left}.jupyter-wrapper .jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-InputPrompt{opacity:var(--jp-cell-prompt-not-active-opacity);color:var(--jp-cell-prompt-not-active-font-color)}.jupyter-wrapper .jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-OutputPrompt{opacity:var(--jp-cell-prompt-not-active-opacity);color:var(--jp-cell-prompt-not-active-font-color)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser{background:var(--jp-brand-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt{color:var(--jp-warn-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt:before{color:var(--jp-warn-color1);content:\"\u2022\"}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active.jp-mod-dirty .jp-Collapser{background:var(--jp-warn-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell .jp-Collapser:hover{box-shadow:var(--jp-elevation-z2);background:var(--jp-brand-color1);opacity:var(--jp-cell-collapser-not-active-hover-opacity)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover{background:var(--jp-brand-color0);opacity:1}.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-selected{background:var(--jp-notebook-multiselected-color)}.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-active.jp-mod-selected:not(.jp-mod-multiSelected){background:transparent}.jupyter-wrapper .jp-Notebook.jp-mod-editMode .jp-Cell.jp-mod-active .jp-InputArea-editor{border:var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);box-shadow:var(--jp-input-box-shadow);background-color:var(--jp-cell-editor-active-background)}.jupyter-wrapper .jp-Notebook-cell.jp-mod-dropSource{opacity:.5}.jupyter-wrapper .jp-Notebook-cell.jp-mod-dropTarget,.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Notebook-cell.jp-mod-active.jp-mod-selected.jp-mod-dropTarget{border-top-color:var(--jp-private-notebook-selected-color);border-top-style:solid;border-top-width:2px}.jupyter-wrapper .jp-dragImage{display:block;flex-direction:row;width:var(--jp-private-notebook-dragImage-width);height:var(--jp-private-notebook-dragImage-height);border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);background:var(--jp-cell-editor-background);overflow:visible}.jupyter-wrapper .jp-dragImage-singlePrompt{box-shadow:2px 2px 4px #0000001f}.jupyter-wrapper .jp-dragImage .jp-dragImage-content{flex:1 1 auto;z-index:2;font-size:var(--jp-code-font-size);font-family:var(--jp-code-font-family);line-height:var(--jp-code-line-height);padding:var(--jp-code-padding);border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);background:var(--jp-cell-editor-background-color);color:var(--jp-content-font-color3);text-align:left;margin:4px 4px 4px 0}.jupyter-wrapper .jp-dragImage .jp-dragImage-prompt{flex:0 0 auto;min-width:36px;color:var(--jp-cell-inprompt-font-color);padding:var(--jp-code-padding);padding-left:12px;font-family:var(--jp-cell-prompt-font-family);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:1.9;font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent}.jupyter-wrapper .jp-dragImage-multipleBack{z-index:-1;position:absolute;height:32px;width:300px;top:8px;left:8px;background:var(--jp-layout-color2);border:var(--jp-border-width) solid var(--jp-input-border-color);box-shadow:2px 2px 4px #0000001f}.jupyter-wrapper .jp-NotebookTools{display:block;min-width:var(--jp-sidebar-min-width);color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1);overflow:auto}.jupyter-wrapper .jp-NotebookTools-tool{padding:0 12px}.jupyter-wrapper .jp-ActiveCellTool{padding:12px;background-color:var(--jp-layout-color1);border-top:none!important}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-prompt{flex:0 0 auto;padding-left:0}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-editor{flex:1 1 auto;background:var(--jp-cell-editor-background);border-color:var(--jp-cell-editor-border-color)}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-editor .CodeMirror{background:transparent}.jupyter-wrapper .jp-MetadataEditorTool{flex-direction:column;padding:12px 0}.jupyter-wrapper .jp-RankedPanel>:not(:first-child){margin-top:12px}.jupyter-wrapper .jp-KeySelector select.jp-mod-styled{font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);border:var(--jp-border-width) solid var(--jp-border-color1)}.jupyter-wrapper .jp-KeySelector label,.jupyter-wrapper .jp-MetadataEditorTool label{line-height:1.4}.jupyter-wrapper .jp-NotebookTools .jp-select-wrapper{margin-top:4px;margin-bottom:0}.jupyter-wrapper .jp-NotebookTools .jp-Collapse{margin-top:16px}.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook{--jp-content-font-size1: var(--jp-content-presentation-font-size1);--jp-code-font-size: var(--jp-code-presentation-font-size)}.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-InputPrompt,.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-OutputPrompt{flex:0 0 110px}.jupyter-wrapper :root{--jp-side-by-side-output-size: 1fr;--jp-side-by-side-resized-cell: var(--jp-side-by-side-output-size)}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-Notebook-cell{margin:3em 5%}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell{display:grid;grid-template-columns:minmax(0,1fr) min-content minmax(0,var(--jp-side-by-side-output-size));grid-template-rows:auto minmax(0,1fr) auto;grid-template-areas:\"header header header\" \"input handle output\" \"footer footer footer\"}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell{grid-template-columns:minmax(0,1fr) min-content minmax(0,var(--jp-side-by-side-resized-cell))}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellHeader{grid-area:header}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-inputWrapper{grid-area:input}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-outputWrapper{margin-top:0;grid-area:output}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellFooter{grid-area:footer}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle{grid-area:handle;-webkit-user-select:none;user-select:none;display:block;height:100%;cursor:ew-resize;padding:0 var(--jp-cell-padding)}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle:after{content:\"\";display:block;background:var(--jp-border-color2);height:100%;width:5px}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell .jp-CellResizeHandle:after{background:var(--jp-border-color0)}.jupyter-wrapper .jp-CellResizeHandle{display:none}.jupyter-wrapper .jp-Cell-Placeholder{padding-left:55px}.jupyter-wrapper .jp-Cell-Placeholder-wrapper{background:#fff;border:1px solid;border-color:#e5e6e9 #dfe0e4 #d0d1d5;border-radius:4px;-webkit-border-radius:4px;margin:10px 15px}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-inner{padding:15px;position:relative}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body{background-repeat:repeat;background-size:50% auto}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body div{background:#f6f7f8;background-image:-webkit-linear-gradient(left,#f6f7f8 0%,#edeef1 20%,#f6f7f8 40%,#f6f7f8 100%);background-repeat:no-repeat;background-size:800px 104px;height:104px;position:relative}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body div{position:absolute;right:15px;left:15px;top:15px}.jupyter-wrapper div.jp-Cell-Placeholder-h1{top:20px;height:20px;left:15px;width:150px}.jupyter-wrapper div.jp-Cell-Placeholder-h2{left:15px;top:50px;height:10px;width:100px}.jupyter-wrapper div.jp-Cell-Placeholder-content-1,.jupyter-wrapper div.jp-Cell-Placeholder-content-2,.jupyter-wrapper div.jp-Cell-Placeholder-content-3{left:15px;right:15px;height:10px}.jupyter-wrapper div.jp-Cell-Placeholder-content-1{top:100px}.jupyter-wrapper div.jp-Cell-Placeholder-content-2{top:120px}.jupyter-wrapper div.jp-Cell-Placeholder-content-3{top:140px}.jupyter-wrapper table.dataframe{table-layout:auto!important}.jupyter-wrapper .md-typeset__scrollwrap{margin:0}.jupyter-wrapper .jp-MarkdownOutput{padding:0}.jupyter-wrapper h1 .anchor-link,.jupyter-wrapper h2 .anchor-link,.jupyter-wrapper h3 .anchor-link,.jupyter-wrapper h4 .anchor-link,.jupyter-wrapper h5 .anchor-link,.jupyter-wrapper h6 .anchor-link{display:none;margin-left:.5rem;color:var(--md-default-fg-color--lighter)}.jupyter-wrapper h1 .anchor-link:hover,.jupyter-wrapper h2 .anchor-link:hover,.jupyter-wrapper h3 .anchor-link:hover,.jupyter-wrapper h4 .anchor-link:hover,.jupyter-wrapper h5 .anchor-link:hover,.jupyter-wrapper h6 .anchor-link:hover{text-decoration:none;color:var(--md-accent-fg-color)}.jupyter-wrapper h1:hover .anchor-link,.jupyter-wrapper h2:hover .anchor-link,.jupyter-wrapper h3:hover .anchor-link,.jupyter-wrapper h4:hover .anchor-link,.jupyter-wrapper h5:hover .anchor-link,.jupyter-wrapper h6:hover .anchor-link{display:inline-block}.jupyter-wrapper .jp-InputArea,.jupyter-wrapper .jp-Cell-inputArea,.jupyter-wrapper .jp-RenderedHTMLCommon{width:100%}.jupyter-wrapper .jp-Cell-inputWrapper .jp-InputPrompt{display:none}.jupyter-wrapper .jp-CodeCell .jp-Cell-inputWrapper .jp-InputPrompt{display:block}.jupyter-wrapper .jp-Cell .jp-InputPrompt{cursor:normal}.jupyter-wrapper .highlight pre{background-color:#f5f5f5;padding:10px;overflow:auto}.jupyter-wrapper .celltoolbar{border:none;background:#eee;border-radius:2px 2px 0 0;width:100%;height:29px;padding-right:4px;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;box-pack:end;justify-content:flex-start;display:-webkit-flex}.jupyter-wrapper .celltoolbar .tags_button_container{display:flex}.jupyter-wrapper .celltoolbar .tags_button_container .tag-container{display:flex;flex-direction:row;flex-grow:1;overflow:hidden;position:relative}.jupyter-wrapper .celltoolbar .tags_button_container .tag-container .cell-tag{display:inline-flex;align-items:center;background-color:#fff;white-space:nowrap;margin:3px 4px;padding:0 4px;border-radius:1px;border:1px solid #ccc;box-shadow:none;width:inherit;font-size:11px;font-family:Roboto Mono,SFMono-Regular,Consolas,Menlo,monospace;height:17px}.jupyter-wrapper .jp-InputArea-editor{width:1px}.jupyter-wrapper .jp-InputPrompt,.jupyter-wrapper .jp-OutputPrompt{overflow:unset}.jupyter-wrapper .jp-RenderedText{font-size:var(--jp-code-font-size)}.jupyter-wrapper .highlight-ipynb{overflow:auto}.jupyter-wrapper .highlight-ipynb pre{margin:0;padding:5px 10px}.jupyter-wrapper table{width:max-content}.jupyter-wrapper table.dataframe{margin-left:auto;margin-right:auto;border:none;border-collapse:collapse;border-spacing:0;color:#000;font-size:12px;table-layout:fixed}.jupyter-wrapper table.dataframe thead{border-bottom:1px solid black;vertical-align:bottom}.jupyter-wrapper table.dataframe tr,.jupyter-wrapper table.dataframe th,.jupyter-wrapper table.dataframe td{text-align:right;vertical-align:middle;padding:.5em;line-height:normal;white-space:normal;max-width:none;border:none}.jupyter-wrapper table.dataframe th{font-weight:700}.jupyter-wrapper table.dataframe tbody tr:nth-child(odd){background:#f5f5f5}.jupyter-wrapper table.dataframe tbody tr:hover{background:rgba(66,165,245,.2)}.jupyter-wrapper *+table{margin-top:1em}.jupyter-wrapper .jp-InputArea-editor{position:relative}.jupyter-wrapper .zeroclipboard-container{position:absolute;top:-3px;right:0;z-index:1}.jupyter-wrapper .zeroclipboard-container clipboard-copy{-webkit-appearance:button;-moz-appearance:button;padding:7px 5px;font:11px system-ui,sans-serif;display:inline-block;cursor:default}.jupyter-wrapper .zeroclipboard-container clipboard-copy:hover{cursor:pointer}.jupyter-wrapper .zeroclipboard-container .clipboard-copy-icon{width:15px;padding:2px 0;color:#57606a;vertical-align:text-bottom}.jupyter-wrapper .clipboard-copy-txt{display:none}[data-md-color-scheme=slate] .highlight pre{background-color:#21222c;padding:10px;overflow:auto}[data-md-color-scheme=slate] .clipboard-copy-icon{color:#555!important}[data-md-color-scheme=slate] .celltoolbar{background:#333!important}[data-md-color-scheme=slate] .celltoolbar .tags_button_container .tag-container .cell-tag{background-color:transparent!important;border:1px solid #666!important}[data-md-color-scheme=slate] table.dataframe{color:#e9ebfc}[data-md-color-scheme=slate] table.dataframe thead{border-bottom:1px solid rgba(233,235,252,.12)}[data-md-color-scheme=slate] table.dataframe tbody tr:nth-child(odd){background:#222}[data-md-color-scheme=slate] table.dataframe tbody tr:hover{background:rgba(66,165,245,.2)}table{width:max-content} .jupyter-wrapper{--jp-shadow-base-lightness: 0;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-400);--jp-border-color1: var(--md-grey-400);--jp-border-color2: var(--md-grey-300);--jp-border-color3: var(--md-grey-200);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(0, 0, 0, 1);--jp-ui-font-color1: rgba(0, 0, 0, .87);--jp-ui-font-color2: rgba(0, 0, 0, .54);--jp-ui-font-color3: rgba(0, 0, 0, .38);--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color2: rgba(255, 255, 255, .7);--jp-ui-inverse-font-color3: rgba(255, 255, 255, .5);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(0, 0, 0, 1);--jp-content-font-color1: rgba(0, 0, 0, .87);--jp-content-font-color2: rgba(0, 0, 0, .54);--jp-content-font-color3: rgba(0, 0, 0, .38);--jp-content-link-color: var(--md-blue-700);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: white;--jp-layout-color1: white;--jp-layout-color2: var(--md-grey-200);--jp-layout-color3: var(--md-grey-400);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: #111111;--jp-inverse-layout-color1: var(--md-grey-900);--jp-inverse-layout-color2: var(--md-grey-800);--jp-inverse-layout-color3: var(--md-grey-700);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-900);--jp-brand-color1: var(--md-blue-700);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-900);--jp-accent-color1: var(--md-green-700);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-900);--jp-warn-color1: var(--md-orange-700);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-900);--jp-error-color1: var(--md-red-700);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-900);--jp-success-color1: var(--md-green-700);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-900);--jp-info-color1: var(--md-cyan-700);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--md-grey-100);--jp-cell-editor-border-color: var(--md-grey-300);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: .5;--jp-cell-prompt-not-active-font-color: var(--md-grey-700);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: var(--md-blue-50);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: #fdd;--jp-rendermime-table-row-background: var(--md-grey-100);--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);--jp-dialog-background: rgba(0, 0, 0, .25);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color1);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .24);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--md-grey-300);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color1);--jp-input-hover-background: var(--jp-layout-color1);--jp-input-background: var(--md-grey-100);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: #d9d9d9;--jp-editor-selected-focused-background: #d7d4f0;--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: #008000;--jp-mirror-editor-atom-color: #88f;--jp-mirror-editor-number-color: #080;--jp-mirror-editor-def-color: #00f;--jp-mirror-editor-variable-color: var(--md-grey-900);--jp-mirror-editor-variable-2-color: #05a;--jp-mirror-editor-variable-3-color: #085;--jp-mirror-editor-punctuation-color: #05a;--jp-mirror-editor-property-color: #05a;--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ba2121;--jp-mirror-editor-string-2-color: #708;--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: #008000;--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: #170;--jp-mirror-editor-attribute-color: #00c;--jp-mirror-editor-header-color: blue;--jp-mirror-editor-quote-color: #090;--jp-mirror-editor-link-color: #00c;--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ffad8e;--jp-collaborator-color2: #dac83d;--jp-collaborator-color3: #72dd76;--jp-collaborator-color4: #00e4d0;--jp-collaborator-color5: #45d4ff;--jp-collaborator-color6: #e2b1ff;--jp-collaborator-color7: #ff9de6;--jp-vega-background: white;--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .5;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(245, 200, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-700);--jp-console-icon-background-color: var(--md-blue-700);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-800);--jp-terminal-icon-color: var(--md-grey-200);--jp-text-editor-icon-color: var(--md-grey-700);--jp-inspector-icon-color: var(--md-grey-700);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-900)} init_mathjax = function() { if (window.MathJax) { // MathJax loaded MathJax.Hub.Config({ TeX: { equationNumbers: { autoNumber: \"AMS\", useLabelIds: true } }, tex2jax: { inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ], displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ], processEscapes: true, processEnvironments: true }, displayAlign: 'center', CommonHTML: { linebreaks: { automatic: true } } }); MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]); } } init_mathjax(); document.addEventListener(\"DOMContentLoaded\", async () => { const diagrams = document.querySelectorAll(\".jp-Mermaid > pre.mermaid\"); // do not load mermaidjs if not needed if (!diagrams.length) { return; } const mermaid = (await import(\"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs\")).default; const parser = new DOMParser(); mermaid.initialize({ maxTextSize: 100000, maxEdges: 100000, startOnLoad: false, fontFamily: window .getComputedStyle(document.body) .getPropertyValue(\"--jp-ui-font-family\"), theme: document.querySelector(\"body[data-jp-theme-light='true']\") ? \"default\" : \"dark\", }); let _nextMermaidId = 0; function makeMermaidImage(svg) { const img = document.createElement(\"img\"); const doc = parser.parseFromString(svg, \"image/svg+xml\"); const svgEl = doc.querySelector(\"svg\"); const { maxWidth } = svgEl?.style || {}; const firstTitle = doc.querySelector(\"title\"); const firstDesc = doc.querySelector(\"desc\"); img.setAttribute(\"src\", `data:image/svg+xml,${encodeURIComponent(svg)}`); if (maxWidth) { img.width = parseInt(maxWidth); } if (firstTitle) { img.setAttribute(\"alt\", firstTitle.textContent); } if (firstDesc) { const caption = document.createElement(\"figcaption\"); caption.className = \"sr-only\"; caption.textContent = firstDesc.textContent; return [img, caption]; } return [img]; } async function makeMermaidError(text) { let errorMessage = \"\"; try { await mermaid.parse(text); } catch (err) { errorMessage = `${err}`; } const result = document.createElement(\"details\"); result.className = 'jp-RenderedMermaid-Details'; const summary = document.createElement(\"summary\"); summary.className = 'jp-RenderedMermaid-Summary'; const pre = document.createElement(\"pre\"); const code = document.createElement(\"code\"); code.innerText = text; pre.appendChild(code); summary.appendChild(pre); result.appendChild(summary); const warning = document.createElement(\"pre\"); warning.innerText = errorMessage; result.appendChild(warning); return [result]; } async function renderOneMarmaid(src) { const id = `jp-mermaid-${_nextMermaidId++}`; const parent = src.parentNode; let raw = src.textContent.trim(); const el = document.createElement(\"div\"); el.style.visibility = \"hidden\"; document.body.appendChild(el); let results = null; let output = null; try { let { svg } = await mermaid.render(id, raw, el); svg = cleanMermaidSvg(svg); results = makeMermaidImage(svg); output = document.createElement(\"figure\"); results.map(output.appendChild, output); } catch (err) { parent.classList.add(\"jp-mod-warning\"); results = await makeMermaidError(raw); output = results[0]; } finally { el.remove(); } parent.classList.add(\"jp-RenderedMermaid\"); parent.appendChild(output); } /** * Post-process to ensure mermaid diagrams contain only valid SVG and XHTML. */ function cleanMermaidSvg(svg) { return svg.replace(RE_VOID_ELEMENT, replaceVoidElement); } /** * A regular expression for all void elements, which may include attributes and * a slash. * * @see https://developer.mozilla.org/en-US/docs/Glossary/Void_element * * Of these, only `
    ` is generated by Mermaid in place of `\\n`, * but _any_ \"malformed\" tag will break the SVG rendering entirely. */ const RE_VOID_ELEMENT = /<\\s*(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\\s*([^>]*?)\\s*>/gi; /** * Ensure a void element is closed with a slash, preserving any attributes. */ function replaceVoidElement(match, tag, rest) { rest = rest.trim(); if (!rest.endsWith('/')) { rest = `${rest} /`; } return `<${tag} ${rest}>`; } void Promise.all([...diagrams].map(renderOneMarmaid)); }); .jp-Mermaid:not(.jp-RenderedMermaid) { display: none; } .jp-RenderedMermaid { overflow: auto; display: flex; } .jp-RenderedMermaid.jp-mod-warning { width: auto; padding: 0.5em; margin-top: 0.5em; border: var(--jp-border-width) solid var(--jp-warn-color2); border-radius: var(--jp-border-radius); color: var(--jp-ui-font-color1); font-size: var(--jp-ui-font-size1); white-space: pre-wrap; word-wrap: break-word; } .jp-RenderedMermaid figure { margin: 0; overflow: auto; max-width: 100%; } .jp-RenderedMermaid img { max-width: 100%; } .jp-RenderedMermaid-Details > pre { margin-top: 1em; } .jp-RenderedMermaid-Summary { color: var(--jp-warn-color2); } .jp-RenderedMermaid:not(.jp-mod-warning) pre { display: none; } .jp-RenderedMermaid-Summary > pre { display: inline-block; white-space: normal; } scPRINT use case on BPH \u00b6 In this use-case, also presented in Figure 5 of our manuscript , we perform an extensive analysis of a multi studies dataset of benign prostatic hyperplasia. Our biological question is to check if there exist pre-cancerous cells that exhibits behaviors of mature cancer cells at this early stage of the disease. In those cells, we want to know which genes might be implicated in cell state changes, and explore potentially novel targets in the treatment of prostate cancer and BPH. We will start with a fresh datasets coming from the cellXgene database and representing 2 studies of BPH . We will first explore these dataset to understand: what are the cell types that are present in the data what are the cell distributions (cell distributions? what are they?) what sequencers were used, etc. We also want to confirm existing target in prostate cancer through precancerous lesion analysis, and find potentially novel ones that would serve as less invasive BPH treatments than current ones. Finally we want to know how these targets interacts and are involved in biological pathways. We now showcase how to use scPRINT across its different functionalities to answer some of these questions. table of contents: \u00b6 Downloading and preprocessing Embedding and annotations Annotation cleanup Clustering and differential expression Denoising and differential expression Gene network inference In the notebook cancer_usecase_part2.ipynb you will see how to analyse cell type specific gene regulatory networks. In [1]: Copied! from scprint import scPrint from scdataloader import Preprocessor , utils from scprint.tasks import GNInfer , Embedder , Denoiser , withknn from bengrn import BenGRN , get_sroy_gt , compute_genie3 from bengrn.base import train_classifier from grnndata import utils as grnutils from grnndata import read_h5ad from anndata.utils import make_index_unique from anndata import concat import scanpy as sc from matplotlib import pyplot as plt import numpy as np import lamindb as ln % load_ext autoreload % autoreload 2 import torch torch . set_float32_matmul_precision ( 'medium' ) from scprint import scPrint from scdataloader import Preprocessor, utils from scprint.tasks import GNInfer, Embedder, Denoiser, withknn from bengrn import BenGRN, get_sroy_gt, compute_genie3 from bengrn.base import train_classifier from grnndata import utils as grnutils from grnndata import read_h5ad from anndata.utils import make_index_unique from anndata import concat import scanpy as sc from matplotlib import pyplot as plt import numpy as np import lamindb as ln %load_ext autoreload %autoreload 2 import torch torch.set_float32_matmul_precision('medium') \ud83d\udca1 connected lamindb: jkobject/scprint /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/umap/__init__.py:9: ImportWarning: Tensorflow not installed; ParametricUMAP will be unavailable warn( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/chex/_src/pytypes.py:53: DeprecationWarning: jax.core.Shape is deprecated. Use Shape = Sequence[int | Any]. Shape = jax.core.Shape /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/chex/_src/pytypes.py:54: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html PRNGKey = jax.random.KeyArray /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/_types.py:9: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html IntOrKey = Union[int, jax.random.KeyArray] /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_utils.py:40: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def validate_seed(seed: IntOrKey) -> jax.random.KeyArray: /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_kmeans.py:21: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def _initialize_random(X: jnp.ndarray, n_clusters: int, key: jax.random.KeyArray) -> jnp.ndarray: /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_kmeans.py:31: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def _initialize_plus_plus(X: jnp.ndarray, n_clusters: int, key: jax.random.KeyArray) -> jnp.ndarray: Downloading and preprocessing \u00b6 We now use lamindb to easily access cellxgene and download a dataset of normal and benign prostatic hyperplasia tissues. data is available here https://cellxgene.cziscience.com/e/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.cxg/ . We then use scDataloader's preprocessing method. This method is quite extensive and does a few things.. find our more about it on its documentation . On our end we are using the preprocessor to make sure that the the gene expression that we have are raw counts and that we have enough information to use scPRINT (i.e., enough genes expressed and enough counts per cells across the dataset). Finally, the preprocessor will also increase the size of the expression matrix to be a fixed set of genes defined by the latest version of ensemble. In [2]: Copied! cx_dataset = ln . Collection . using ( instance = \"laminlabs/cellxgene\" ) . filter ( name = \"cellxgene-census\" , version = '2023-12-15' ) . one () cx_dataset = ln.Collection.using(instance=\"laminlabs/cellxgene\").filter(name=\"cellxgene-census\", version='2023-12-15').one() In [3]: Copied! prostate_adata = cx_dataset . artifacts . filter ( key = 'cell-census/2023-12-15/h5ads/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.h5ad' ) . one () . load () sc . pl . umap ( prostate_adata ) prostate_adata = cx_dataset.artifacts.filter(key='cell-census/2023-12-15/h5ads/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.h5ad').one().load() sc.pl.umap(prostate_adata) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/asyncio/sslproto.py:320: ResourceWarning: unclosed transport _warn(f\"unclosed transport {self!r}\", ResourceWarning, source=self) ResourceWarning: Enable tracemalloc to get the object allocation traceback In [7]: Copied! # preprocessing using scDataloader prostate_adata . obs . drop ( columns = \"is_primary_data\" , inplace = True ) preprocessor = Preprocessor ( do_postp = False ) prostate_adata = preprocessor ( prostate_adata ) # preprocessing using scDataloader prostate_adata.obs.drop(columns=\"is_primary_data\", inplace=True) preprocessor = Preprocessor(do_postp=False) prostate_adata = preprocessor(prostate_adata) Dropping layers: KeysView(Layers with keys: ) checking raw counts removed 0 non primary cells, 83451 renamining filtered out 0 cells, 83451 renamining Removed 76 genes. validating /home/ml4ig1/Documents code/scPRINT/scDataLoader/scdataloader/preprocess.py:241: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]` data_utils.validate(adata, organism=adata.obs.organism_ontology_term_id[0]) startin QC Seeing 13047 outliers (15.63% of total dataset): done Embedding and annotations \u00b6 We now start to load a large version of scPRINT from a specific checkpoint. Please download the checkpoints following the instructions in the README. We will then use out Embedder class to embed the data and annotate the cells. These classes are how we parametrize and access the different functions of scPRINT . Find out more about its parameters in our documentation . In [6]: Copied! model = scPrint . load_from_checkpoint ( '../data/temp/o2uniqsx/epoch=18-step=133000.ckpt' , # make sure that you check if you have a GPU with flashattention or not (see README) # you need this else, the model will look for the file with the embeddings instead of getting them from the weights precpt_gene_emb = None ) model = scPrint.load_from_checkpoint('../data/temp/o2uniqsx/epoch=18-step=133000.ckpt', # make sure that you check if you have a GPU with flashattention or not (see README) # you need this else, the model will look for the file with the embeddings instead of getting them from the weights precpt_gene_emb = None) RuntimeError caught: scPrint is not attached to a `Trainer`. In [10]: Copied! embedder = Embedder ( # can work on random genes or most variables etc.. how = \"random expr\" , # number of genes to use max_len = 4000 , add_zero_genes = 0 , # for the dataloading num_workers = 8 , # we will only use the cell type embedding here. pred_embedding = [ \"cell_type_ontology_term_id\" ] ) #, \"disease_ontology_term_id\"]) embedder = Embedder( # can work on random genes or most variables etc.. how=\"random expr\", # number of genes to use max_len=4000, add_zero_genes=0, # for the dataloading num_workers=8, # we will only use the cell type embedding here. pred_embedding = [\"cell_type_ontology_term_id\"] )#, \"disease_ontology_term_id\"]) Using 16bit Automatic Mixed Precision (AMP) GPU available: True (cuda), used: True TPU available: False, using: 0 TPU cores IPU available: False, using: 0 IPUs HPU available: False, using: 0 HPUs In [ ]: Copied! # create the embedding prostate_adata , metrics = embedder ( model , prostate_adata , cache = False , output_expression = \"none\" ) # create the embedding prostate_adata, metrics = embedder(model, prostate_adata, cache=False, output_expression=\"none\") 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 1560/1560 [28:20<00:00, 1.09s/it] AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 424 obs: 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id' /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) couldn't log to tensorboard couldn't log to wandb couldn't log to wandb cell_type_ontology_term_id accuracy: 0.7250215374752068 disease_ontology_term_id accuracy: 0.8394506441207702 assay_ontology_term_id accuracy: 0.998988239536794 self_reported_ethnicity_ontology_term_id accuracy: 0.9504037024422495 sex_ontology_term_id accuracy: 0.9948911105323263 organism_ontology_term_id accuracy: 1.0 In [16]: Copied! prostate_adata prostate_adata Out[16]: AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 70116 obs: 'assay_ontology_term_id', 'donor_id', 'sex_ontology_term_id', 'disease_ontology_term_id', 'organism_ontology_term_id', 'suspension_type', 'cell_type_ontology_term_id', 'tissue_ontology_term_id', 'development_stage_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'cell_type', 'assay', 'disease', 'organism', 'sex', 'tissue', 'self_reported_ethnicity', 'development_stage', 'nnz', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb', 'outlier', 'mt_outlier', 'init_dataset', 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id', 'sprint_leiden' uns: 'init_dataset_colors' obsm: 'X_pca', 'X_umap', 'scprint_umap', 'scprint' Annotation cleanup \u00b6 scPRINT generates predictions over hundreds of possible labels for each cell. It is often advised to \"cleanup\" the predictions, e.g. making sure to remove low frequency cells and misslabellings. Here, we use the most straightforward approach which is to remove any annotations that appear a small number of times. A better approach would be doing majority voting over cell clusters as it would aggregate and smoothout the predictions over multiple cells. it would also remove most of the low frequency mistakes in the predictions. We will also have a look at the embeddings of scPRINT by plotting its UMAP visualization. In [30]: Copied! #cleaning up the cell types prostate_adata . obs [ 'cleaned_pred_cell_type_ontology_term_id' ] = prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . astype ( str ) prostate_adata . obs . loc [ ~ prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . isin ([ k for k , v in prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . value_counts () . items () if v > 400 ]), 'cleaned_pred_cell_type_ontology_term_id' ] = \"other\" prostate_adata . obs [ 'cleaned_pred_cell_type_ontology_term_id' ] . value_counts () . plot . pie () #cleaning up the cell types prostate_adata.obs['cleaned_pred_cell_type_ontology_term_id'] = prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].astype(str) prostate_adata.obs.loc[~prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].isin([k for k, v in prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].value_counts().items() if v > 400]), 'cleaned_pred_cell_type_ontology_term_id'] = \"other\" prostate_adata.obs['cleaned_pred_cell_type_ontology_term_id'].value_counts().plot.pie() Out[30]: In [31]: Copied! # cleaning up the diseases prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] = prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . astype ( str ) prostate_adata . obs . loc [ ~ prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . isin ([ k for k , v in prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . value_counts () . items () if v > 1000 ]), 'cleaned_pred_disease_ontology_term_id' ] = \"other\" prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () . plot . pie () # cleaning up the diseases prostate_adata.obs['cleaned_pred_disease_ontology_term_id'] = prostate_adata.obs['conv_pred_disease_ontology_term_id'].astype(str) prostate_adata.obs.loc[~prostate_adata.obs['conv_pred_disease_ontology_term_id'].isin([k for k, v in prostate_adata.obs['conv_pred_disease_ontology_term_id'].value_counts().items() if v > 1000]), 'cleaned_pred_disease_ontology_term_id'] = \"other\" prostate_adata.obs['cleaned_pred_disease_ontology_term_id'].value_counts().plot.pie() Out[31]: In [38]: Copied! sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'cleaned_pred_cell_type_ontology_term_id' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'cleaned_pred_disease_ontology_term_id' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'assay' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'disease' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'development_stage' ]) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['cleaned_pred_cell_type_ontology_term_id']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['cleaned_pred_disease_ontology_term_id']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['assay']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['disease']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['development_stage']) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) In [ ]: Copied! prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 20 ) prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id.value_counts().head(20) cleaned_pred_cell_type_ontology_term_id basal cell of epidermis 22449 mammary alveolar cell 9688 vasa recta descending limb cell 8777 CD1c-positive myeloid dendritic cell 5782 effector memory CD8-positive, alpha-beta T cell 5410 smooth muscle cell of the pulmonary artery 5007 other 4972 pancreatic acinar cell 4639 basal epithelial cell of prostatic duct 3405 serous cell of epithelium of trachea 3327 prostate gland microvascular endothelial cell 2747 paneth cell of epithelium of small intestine 2698 mast cell 2365 IgG-negative class switched memory B cell 2348 fibroblast of connective tissue of nonglandular part of prostate 2058 club cell 1794 pulmonary artery endothelial cell 1239 CD141-positive myeloid dendritic cell 1186 mucous neck cell 1039 smooth muscle cell of prostate 857 peptic cell 766 T-helper 17 cell 735 CD14-positive, CD16-negative classical monocyte 671 CD16-negative, CD56-bright natural killer cell, human 666 lung pericyte 663 alveolar type 2 fibroblast cell 646 type II pneumocyte 618 naive B cell 606 effector CD4-positive, alpha-beta T cell 506 fibroblast of connective tissue of glandular part of prostate 464 luminal epithelial cell of mammary gland 437 inflammatory macrophage 436 fibroblast of mammary gland 416 basal cell of epithelium of bronchus 409 Name: count, dtype: int64 In [39]: Copied! # we save for next time prostate_adata . write_h5ad ( \"../../data/prostate_adata_o2uniqsx.h5ad\" ) # we save for next time prostate_adata.write_h5ad(\"../../data/prostate_adata_o2uniqsx.h5ad\") In [2]: Copied! prostate_adata = sc . read_h5ad ( \"../../data/prostate_adata_o2uniqsx.h5ad\" ) prostate_adata = sc.read_h5ad(\"../../data/prostate_adata_o2uniqsx.h5ad\") Clustering and differential expression \u00b6 We will now cluster using the louvain algorithm on a kNN graph. Once we detect a cluster of interest we will perform differential expression analysis on it. Taking as example some B-cell clusters, we will use scanpy's implementation of rank_gene_groups for our differential expression In [15]: Copied! # do louvain mutliple times sc . pp . neighbors ( prostate_adata , n_neighbors = 10 , use_rep = \"scprint\" ) # using multiple resolutions can help spotting smaller clusters sc . tl . louvain ( prostate_adata , resolution = 0.5 , key_added = \"louvain_0.5\" ) sc . tl . louvain ( prostate_adata , resolution = 1.0 , key_added = \"louvain_1.0\" ) # do louvain mutliple times sc.pp.neighbors(prostate_adata, n_neighbors=10, use_rep=\"scprint\") # using multiple resolutions can help spotting smaller clusters sc.tl.louvain(prostate_adata, resolution=0.5, key_added=\"louvain_0.5\") sc.tl.louvain(prostate_adata, resolution=1.0, key_added=\"louvain_1.0\") In [20]: Copied! # check clusters sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = 'louvain_1.0' , show = False , legend_loc = \"on data\" ) # check clusters sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color='louvain_1.0', show=False, legend_loc=\"on data\") /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) Out[20]: In [21]: Copied! # check cluster 9 i = 9 loc = prostate_adata . obs [ 'louvain_1.0' ] == str ( i ) prostate_adata . obs [ loc ] . conv_pred_disease_ontology_term_id . value_counts () . head ( 2 ), prostate_adata . obs [ loc ] . conv_pred_cell_type_ontology_term_id . value_counts () . head ( 5 ) # check cluster 9 i=9 loc = prostate_adata.obs['louvain_1.0']==str(i) prostate_adata.obs[loc].conv_pred_disease_ontology_term_id.value_counts().head(2), prostate_adata.obs[loc].conv_pred_cell_type_ontology_term_id.value_counts().head(5) Out[21]: (conv_pred_disease_ontology_term_id benign prostatic hyperplasia 3554 normal 18 Name: count, dtype: int64, conv_pred_cell_type_ontology_term_id urethra urothelial cell 1703 luminal cell of prostate epithelium 703 mucous neck cell 566 basal epithelial cell of prostatic duct 372 club cell 174 Name: count, dtype: int64) In [6]: Copied! # check cluster 11 i = 11 loc = prostate_adata . obs [ 'louvain_1.0' ] == str ( i ) prostate_adata . obs [ loc ] . cleaned_pred_disease_ontology_term_id . value_counts () . head ( 2 ), prostate_adata . obs [ loc ] . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 5 ) # check cluster 11 i=11 loc = prostate_adata.obs['louvain_1.0']==str(i) prostate_adata.obs[loc].cleaned_pred_disease_ontology_term_id.value_counts().head(2), prostate_adata.obs[loc].cleaned_pred_cell_type_ontology_term_id.value_counts().head(5) Out[6]: (cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 2930 normal 68 Name: count, dtype: int64, cleaned_pred_cell_type_ontology_term_id IgG-negative class switched memory B cell 2840 other 142 CD1c-positive myeloid dendritic cell 8 basophil 7 CD4-positive, alpha-beta thymocyte 5 Name: count, dtype: int64) In [7]: Copied! # We have find a nice IgG-negative class switched memory B cell cluster. let's use it and define a clean annotation for a plot loc = loc & ( prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id == \"IgG-negative class switched memory B cell\" ) prostate_adata . obs [ loc ] . cleaned_pred_disease_ontology_term_id . value_counts () . head ( 2 ) # We have find a nice IgG-negative class switched memory B cell cluster. let's use it and define a clean annotation for a plot loc = loc&(prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id==\"IgG-negative class switched memory B cell\") prostate_adata.obs[loc].cleaned_pred_disease_ontology_term_id.value_counts().head(2) Out[7]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 2771 normal 60 Name: count, dtype: int64 In [8]: Copied! # making a \"focus\" annotation for the B-cell to generate a nice plot of the B-cell cluster only prostate_adata . obs [ 'focus' ] = \"other\" prostate_adata . obs . loc [ loc , 'focus' ] = \"memory B cell\" prostate_adata . obs . loc [ loc & ( prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] == 'benign prostatic hyperplasia' ), 'focus' ] = \"BPH associated memory B cell\" prostate_adata . obs [ 'focus' ] . value_counts () # making a \"focus\" annotation for the B-cell to generate a nice plot of the B-cell cluster only prostate_adata.obs['focus'] = \"other\" prostate_adata.obs.loc[loc, 'focus'] = \"memory B cell\" prostate_adata.obs.loc[loc & (prostate_adata.obs['cleaned_pred_disease_ontology_term_id']=='benign prostatic hyperplasia'), 'focus'] = \"BPH associated memory B cell\" prostate_adata.obs['focus'].value_counts() In [24]: Copied! import matplotlib.pyplot as plt import matplotlib.patches as patches import seaborn as sns color = sns . color_palette ()[ 1 ] fig , ax = plt . subplots ( figsize = ( 2 , 2 )) rect = patches . Rectangle (( 0 , 0 ), 1 , 1 , facecolor = color ) ax . add_patch ( rect ) ax . set_xlim ( 0 , 1 ) ax . set_ylim ( 0 , 1 ) ax . axis ( 'off' ) plt . show () import matplotlib.pyplot as plt import matplotlib.patches as patches import seaborn as sns color = sns.color_palette()[1] fig, ax = plt.subplots(figsize=(2, 2)) rect = patches.Rectangle((0, 0), 1, 1, facecolor=color) ax.add_patch(rect) ax.set_xlim(0, 1) ax.set_ylim(0, 1) ax.axis('off') plt.show() In [32]: Copied! # looking at the B-cell cluster. We can see some normal and BPH-associated memory B-cells sc . pl . embedding ( prostate_adata [( prostate_adata . obs [ 'louvain_1.0' ] == str ( i )) & ( prostate_adata . obsm [ 'scprint_umap' ][:, 0 ] > 4 )], basis = \"scprint_umap\" , color = 'focus' , show = False , size = 8 , title = \"Switched memory B-cell cluster\" , legend_loc = \"right margin\" ) # looking at the B-cell cluster. We can see some normal and BPH-associated memory B-cells sc.pl.embedding(prostate_adata[(prostate_adata.obs['louvain_1.0']==str(i)) & (prostate_adata.obsm['scprint_umap'][:,0]>4)], basis=\"scprint_umap\",color='focus', show=False, size=8, title=\"Switched memory B-cell cluster\", legend_loc=\"right margin\") ... storing 'focus' as categorical /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) Out[32]: In [ ]: Copied! # here we use a function of scdataloader to add some more gene annotations to our dataset so we can view HGNC symbols genedf = utils . load_genes ( prostate_adata . obs . organism_ontology_term_id . iloc [ 0 ]) # columns that create issues when saving anndatas prostate_adata . var = genedf . loc [ prostate_adata . var . index ] . drop ( columns = [ \"stable_id\" , \"created_at\" , \"updated_at\" ]) # here we use a function of scdataloader to add some more gene annotations to our dataset so we can view HGNC symbols genedf = utils.load_genes(prostate_adata.obs.organism_ontology_term_id.iloc[0]) # columns that create issues when saving anndatas prostate_adata.var = genedf.loc[prostate_adata.var.index].drop(columns=[\"stable_id\", \"created_at\", \"updated_at\"]) In [ ]: Copied! # now the diff expression between B-cells and the rest sc . tl . rank_genes_groups ( prostate_adata , groupby = 'cleaned_pred_cell_type_ontology_term_id' , groups = [ 'IgG-negative class switched memory B cell' ], reference = 'other' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # now the diff expression between B-cells and the rest sc.tl.rank_genes_groups(prostate_adata, groupby='cleaned_pred_cell_type_ontology_term_id', groups=['IgG-negative class switched memory B cell'], reference='other', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers ... storing 'focus' as categorical ... storing 'symbol' as categorical ... storing 'ncbi_gene_ids' as categorical ... storing 'biotype' as categorical ... storing 'description' as categorical ... storing 'synonyms' as categorical ... storing 'organism' as categorical WARNING: It seems you use rank_genes_groups on the raw count data. Please logarithmize your data before calling rank_genes_groups. /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/tools/_rank_genes_groups.py:420: RuntimeWarning: overflow encountered in expm1 self.expm1_func(mean_rest) + 1e-9 /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/tools/_rank_genes_groups.py:422: RuntimeWarning: divide by zero encountered in log2 self.stats[group_name, 'logfoldchanges'] = np.log2( Denoising and differential expression \u00b6 What we found out from our previous analysis is that there is not a lot of normal (i.e. healthy) B-cells in our cluster, most of them are BPH associated. In this case, if we wanted to compare BPH B-cells to normal B-cells we might be very underpowered... Instead of going to look for some other dataset, let's use scPRINT to increase the depth of the expression profile of the cells, virtually adding more signal to our dataset. We will use the Denoiser class (see more about the class in our documentation ) in a similar way Trainer is used in pytorch lightning to denoise the expression profile of the cells. We will then show the results of differential expression analysis before and after denoising. In [ ]: Copied! # in case you started from here prostate_adata = sc . read_h5ad ( \"../data/prostate_adata_o2uniqsx.h5ad\" ) prostate_adata # in case you started from here prostate_adata = sc.read_h5ad(\"../data/prostate_adata_o2uniqsx.h5ad\") prostate_adata AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 70116 obs: 'assay_ontology_term_id', 'donor_id', 'sex_ontology_term_id', 'disease_ontology_term_id', 'organism_ontology_term_id', 'suspension_type', 'cell_type_ontology_term_id', 'tissue_ontology_term_id', 'development_stage_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'cell_type', 'assay', 'disease', 'organism', 'sex', 'tissue', 'self_reported_ethnicity', 'development_stage', 'nnz', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb', 'outlier', 'mt_outlier', 'init_dataset', 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id', 'sprint_leiden', 'cleaned_pred_cell_type_ontology_term_id', 'cleaned_pred_disease_ontology_term_id', 'louvain_0.5', 'louvain_1.0', 'fibro' var: 'uid', 'symbol', 'ncbi_gene_ids', 'biotype', 'description', 'synonyms', 'organism_id', 'public_source_id', 'created_by_id', 'mt', 'ribo', 'hb', 'organism' uns: 'louvain', 'neighbors' obsm: 'X_pca', 'X_umap', 'scprint', 'scprint_umap' obsp: 'connectivities', 'distances' In [16]: Copied! # here we compare memory B-cell in BPH to normal memory B cells before denoising sc . tl . rank_genes_groups ( prostate_adata , groupby = 'focus' , groups = [ 'BPH associated memory B cell' ], reference = 'memory B cell' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # here we compare memory B-cell in BPH to normal memory B cells before denoising sc.tl.rank_genes_groups(prostate_adata, groupby='focus', groups=['BPH associated memory B cell'], reference='memory B cell', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers WARNING: It seems you use rank_genes_groups on the raw count data. Please logarithmize your data before calling rank_genes_groups. In [19]: Copied! # perform denoising denoise = Denoiser ( # could be on top differentially expressed genes or on random expressed genes in the cell (completed by random non expressed gene) how = \"random expr\" # the size of the minibatch (need to fit in memory) batch_size = 20 , # the number of genes to use max_len = 5000 , # the number of cells to use (here more than what we will use so we will use everything) plot_corr_size = 10_000 , doplot = False , # how much do we want to increase the depth / counts of the cells (here, 10x) predict_depth_mult = 10 , ) idx , genes , expr = denoise ( model , prostate_adata [ prostate_adata . obs [ 'focus' ] != \"other\" ]) # perform denoising denoise = Denoiser( # could be on top differentially expressed genes or on random expressed genes in the cell (completed by random non expressed gene) how=\"random expr\" # the size of the minibatch (need to fit in memory) batch_size=20, # the number of genes to use max_len=5000, # the number of cells to use (here more than what we will use so we will use everything) plot_corr_size=10_000, doplot=False, # how much do we want to increase the depth / counts of the cells (here, 10x) predict_depth_mult=10, ) idx, genes, expr = denoise(model, prostate_adata[prostate_adata.obs['focus']!=\"other\"]) 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 82/82 [00:50<00:00, 1.64it/s] In [20]: Copied! # now what we are doing here it to complete the expression profile with the denoised values. this is not done by default for now i = 0 prostate_adata . X = prostate_adata . X . tolil () for idx , val in enumerate ( prostate_adata . obs [ 'focus' ] != \"other\" ): if val : prostate_adata . X [ idx , prostate_adata . var . index . get_indexer ( np . array ( model . genes )[ genes [ i ]])] = expr [ i ] i += 1 prostate_adata . X = prostate_adata . X . tocsr () # now what we are doing here it to complete the expression profile with the denoised values. this is not done by default for now i = 0 prostate_adata.X = prostate_adata.X.tolil() for idx, val in enumerate(prostate_adata.obs['focus']!=\"other\"): if val: prostate_adata.X[idx, prostate_adata.var.index.get_indexer(np.array(model.genes)[genes[i]])] = expr[i] i += 1 prostate_adata.X = prostate_adata.X.tocsr() In [21]: Copied! # now we compare memory B-cell in BPH to normal memory B cells after denoising sc . tl . rank_genes_groups ( prostate_adata , groupby = 'focus' , groups = [ 'BPH associated memory B cell' ], reference = 'memory B cell' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # now we compare memory B-cell in BPH to normal memory B cells after denoising sc.tl.rank_genes_groups(prostate_adata, groupby='focus', groups=['BPH associated memory B cell'], reference='memory B cell', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers In [9]: Copied! prostate_adata . write_h5ad ( \"../../data/prostate_adata_denoised.h5ad\" ) prostate_adata.write_h5ad(\"../../data/prostate_adata_denoised.h5ad\") In [3]: Copied! prostate_adata = sc . read_h5ad ( \"../../data/prostate_adata_denoised.h5ad\" ) prostate_adata = sc.read_h5ad(\"../../data/prostate_adata_denoised.h5ad\") Gene network inference \u00b6 Finally we will use scPRINT to infer gene networks on another cell of interest, the fibroblasts, in both normal and BPH conditions. We will use the GRNfer class to infer gene networks. ( see the cancer_usecase_part2.ipynb for more details on how to analyse the gene networks. ) In [38]: Copied! prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 20 ) prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id.value_counts().head(20) Out[38]: cleaned_pred_cell_type_ontology_term_id basal epithelial cell of prostatic duct 25740 prostate gland microvascular endothelial cell 12165 urethra urothelial cell 10952 CD1c-positive myeloid dendritic cell 6898 other 5869 aortic smooth muscle cell 3970 effector CD8-positive, alpha-beta T cell 3925 pancreatic acinar cell 3711 luminal cell of prostate epithelium 3435 fibroblast of connective tissue of nonglandular part of prostate 3334 mucous neck cell 3260 IgG-negative class switched memory B cell 2932 basophil 1862 fibroblast of connective tissue of glandular part of prostate 1815 pancreatic ductal cell 1651 CD4-positive, alpha-beta thymocyte 1516 club cell 1226 smooth muscle cell of prostate 1000 effector memory CD8-positive, alpha-beta T cell 991 peptic cell 872 mature conventional dendritic cell 721 effector CD4-positive, alpha-beta T cell 686 mast cell 451 renal interstitial pericyte 440 retinal blood vessel endothelial cell 404 Name: count, dtype: int64 In [33]: Copied! loc = ( prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id == \"fibroblast of connective tissue of glandular part of prostate\" ) prostate_adata . obs [ loc ][ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () loc = (prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id==\"fibroblast of connective tissue of glandular part of prostate\") prostate_adata.obs[loc]['cleaned_pred_disease_ontology_term_id'].value_counts() Out[33]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 1482 normal 673 other 4 Name: count, dtype: int64 In [52]: Copied! prostate_adata . obs [ loc ][ 'louvain_1.0' ] . value_counts () . head ( 10 ) prostate_adata.obs[loc]['louvain_1.0'].value_counts().head(10) Out[52]: louvain_1.0 5 1458 4 671 17 10 8 8 7 7 0 3 9 2 6 0 3 0 1 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 2 0 18 0 Name: count, dtype: int64 In [34]: Copied! loc = loc & ( prostate_adata . obs [ 'louvain_1.0' ] == str ( 5 )) prostate_adata . obs [ loc ][ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () loc = loc & (prostate_adata.obs['louvain_1.0']==str(5)) prostate_adata.obs[loc]['cleaned_pred_disease_ontology_term_id'].value_counts() Out[34]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 790 normal 664 other 4 Name: count, dtype: int64 In [35]: Copied! prostate_adata . obs [ 'fibro' ] = None prostate_adata . obs . loc [ loc , 'fibro' ] = \"fibroblasts\" prostate_adata . obs . loc [ loc & ( prostate_adata . obs . cleaned_pred_disease_ontology_term_id == \"benign prostatic hyperplasia\" ), 'fibro' ] = \"BPH associated fibroblasts\" prostate_adata.obs['fibro'] = None prostate_adata.obs.loc[loc, 'fibro']=\"fibroblasts\" prostate_adata.obs.loc[loc & (prostate_adata.obs.cleaned_pred_disease_ontology_term_id==\"benign prostatic hyperplasia\"), 'fibro']=\"BPH associated fibroblasts\" In [37]: Copied! sc . pl . embedding ( prostate_adata [ prostate_adata . obs [ 'louvain_1.0' ] . isin ([ \"5\" , \"4\" ]) & ( prostate_adata . obsm [ 'scprint_umap' ][:, 1 ] > 10 )], basis = \"scprint_umap_rot\" , color = 'fibro' , show = False , size = 8 , title = \"Fibroblasts cluster\" , legend_loc = \"right margin\" ) sc.pl.embedding(prostate_adata[prostate_adata.obs['louvain_1.0'].isin([\"5\",\"4\"]) & (prostate_adata.obsm['scprint_umap'][:,1]>10)], basis=\"scprint_umap_rot\",color='fibro', show=False, size=8, title=\"Fibroblasts cluster\", legend_loc=\"right margin\") ... storing 'focus' as categorical ... storing 'fibro' as categorical /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) In [8]: Copied! grn_inferer = GNInfer ( # here we use the most variable genes across the fibroblasts vs the rest how = \"most var across\" , #how=\"random expr\", # we will preprocess the attention matrix with softmax preprocess = \"softmax\" , # we don't aggregate the heads here, we will do it manually head_agg = 'none' , # here if we generate the attention matrices by performing a task, like denoising or by just passing the expression profile through the model forward_mode = \"none\" , # the number of genes to use (here the 4000 most variable genes) num_genes = 4000 , # the max number of cell to use per cell type max_cells = 300 , doplot = False , batch_size = 16 , # the column in anndata the defines the cell type cell_type_col = 'fibro' , # list of layers to use layer = list ( range ( model . nlayers ))[:] ) grn_inferer = GNInfer( # here we use the most variable genes across the fibroblasts vs the rest how=\"most var across\", #how=\"random expr\", # we will preprocess the attention matrix with softmax preprocess=\"softmax\", # we don't aggregate the heads here, we will do it manually head_agg='none', # here if we generate the attention matrices by performing a task, like denoising or by just passing the expression profile through the model forward_mode=\"none\", # the number of genes to use (here the 4000 most variable genes) num_genes=4000, # the max number of cell to use per cell type max_cells=300, doplot=False, batch_size=16, # the column in anndata the defines the cell type cell_type_col='fibro', # list of layers to use layer=list(range(model.nlayers))[:] ) In [9]: Copied! # I was missing this from the model (not really necessary) model . organisms = [ 'NCBITaxon:9606' , 'NCBITaxon:10090' ] prostate_adata . obs . fibro = prostate_adata . obs . fibro . astype ( str ) prostate_adata . obs [ prostate_adata . obs . fibro == \"BPH associated fibroblasts\" ] . disease . value_counts () # I was missing this from the model (not really necessary) model.organisms = ['NCBITaxon:9606', 'NCBITaxon:10090'] prostate_adata.obs.fibro = prostate_adata.obs.fibro.astype(str) prostate_adata.obs[prostate_adata.obs.fibro==\"BPH associated fibroblasts\"].disease.value_counts() In [ ]: Copied! # compute GRNs on fibroblasts, we use all the atetetion layers grn = grn_inferer ( model , prostate_adata , cell_type = \"fibroblasts\" ) # highlight differential links on genes that are expressed in both grn . varp [ 'all' ] = grn . varp [ 'GRN' ] . copy () # now we aggregate the heads by taking their average grn . varp [ 'GRN' ] = grn . varp [ 'GRN' ] . mean ( - 1 ) grn . write_h5ad ( \"../../data/prostate_fibro_grn_all.h5ad\" ) # compute GRNs on fibroblasts, we use all the atetetion layers grn = grn_inferer(model, prostate_adata, cell_type=\"fibroblasts\") # highlight differential links on genes that are expressed in both grn.varp['all'] = grn.varp['GRN'].copy() # now we aggregate the heads by taking their average grn.varp['GRN'] = grn.varp['GRN'].mean(-1) grn.write_h5ad(\"../../data/prostate_fibro_grn_all.h5ad\") In [11]: Copied! #same on the BPH associated fibroblasts # I wanted to use only the ones that the labellers had defined as coing from BPH prostate_adata . obs . loc [( prostate_adata . obs . fibro == \"BPH associated fibroblasts\" ) & ( prostate_adata . obs . disease == \"benign prostatic hyperplasia\" ), 'fibro' ] = \"true BPH associated fibroblasts\" grn_c = grn_inferer ( model , prostate_adata , cell_type = \"true cancer associated fibroblasts\" ) # highlight differential links on genes that are expressed in both grn_c . varp [ 'all' ] = grn_c . varp [ 'GRN' ] . copy () grn_c . varp [ 'GRN' ] = grn_c . varp [ 'GRN' ] . mean ( - 1 ) grn_c . write_h5ad ( \"../../data/prostate_BPH_fibro_grn_all.h5ad\" ) #same on the BPH associated fibroblasts # I wanted to use only the ones that the labellers had defined as coing from BPH prostate_adata.obs.loc[(prostate_adata.obs.fibro==\"BPH associated fibroblasts\") & ( prostate_adata.obs.disease==\"benign prostatic hyperplasia\"), 'fibro'] = \"true BPH associated fibroblasts\" grn_c = grn_inferer(model, prostate_adata, cell_type=\"true cancer associated fibroblasts\") # highlight differential links on genes that are expressed in both grn_c.varp['all'] = grn_c.varp['GRN'].copy() grn_c.varp['GRN'] = grn_c.varp['GRN'].mean(-1) grn_c.write_h5ad(\"../../data/prostate_BPH_fibro_grn_all.h5ad\") ['pre { line-height: 125%; }\\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n.highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) }\\n.highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\\n.highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\\n.highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */\\n.highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\\n.highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\\n.highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\\n.highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\\n.highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\\n.highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\\n.highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\\n.highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\\n.highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\\n.highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\\n.highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\\n.highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\\n.highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\\n.highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\\n.highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\\n.highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\\n.highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\\n.highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\\n.highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\\n.highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\\n.highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\\n.highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\\n.highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\\n.highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\\n.highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\\n.highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\\n.highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\\n.highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\\n.highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\\n.highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\\n.highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\\n.highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\\n.highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\\n.highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\\n.highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\\n.highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\\n.highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\\n.highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\\n.highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */']","title":"scPRINT use case on BPH"},{"location":"notebooks/cancer_usecase/#scprint-use-case-on-bph","text":"In this use-case, also presented in Figure 5 of our manuscript , we perform an extensive analysis of a multi studies dataset of benign prostatic hyperplasia. Our biological question is to check if there exist pre-cancerous cells that exhibits behaviors of mature cancer cells at this early stage of the disease. In those cells, we want to know which genes might be implicated in cell state changes, and explore potentially novel targets in the treatment of prostate cancer and BPH. We will start with a fresh datasets coming from the cellXgene database and representing 2 studies of BPH . We will first explore these dataset to understand: what are the cell types that are present in the data what are the cell distributions (cell distributions? what are they?) what sequencers were used, etc. We also want to confirm existing target in prostate cancer through precancerous lesion analysis, and find potentially novel ones that would serve as less invasive BPH treatments than current ones. Finally we want to know how these targets interacts and are involved in biological pathways. We now showcase how to use scPRINT across its different functionalities to answer some of these questions.","title":"scPRINT use case on BPH"},{"location":"notebooks/cancer_usecase/#table-of-contents","text":"Downloading and preprocessing Embedding and annotations Annotation cleanup Clustering and differential expression Denoising and differential expression Gene network inference In the notebook cancer_usecase_part2.ipynb you will see how to analyse cell type specific gene regulatory networks. In [1]: Copied! from scprint import scPrint from scdataloader import Preprocessor , utils from scprint.tasks import GNInfer , Embedder , Denoiser , withknn from bengrn import BenGRN , get_sroy_gt , compute_genie3 from bengrn.base import train_classifier from grnndata import utils as grnutils from grnndata import read_h5ad from anndata.utils import make_index_unique from anndata import concat import scanpy as sc from matplotlib import pyplot as plt import numpy as np import lamindb as ln % load_ext autoreload % autoreload 2 import torch torch . set_float32_matmul_precision ( 'medium' ) from scprint import scPrint from scdataloader import Preprocessor, utils from scprint.tasks import GNInfer, Embedder, Denoiser, withknn from bengrn import BenGRN, get_sroy_gt, compute_genie3 from bengrn.base import train_classifier from grnndata import utils as grnutils from grnndata import read_h5ad from anndata.utils import make_index_unique from anndata import concat import scanpy as sc from matplotlib import pyplot as plt import numpy as np import lamindb as ln %load_ext autoreload %autoreload 2 import torch torch.set_float32_matmul_precision('medium') \ud83d\udca1 connected lamindb: jkobject/scprint /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/umap/__init__.py:9: ImportWarning: Tensorflow not installed; ParametricUMAP will be unavailable warn( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/chex/_src/pytypes.py:53: DeprecationWarning: jax.core.Shape is deprecated. Use Shape = Sequence[int | Any]. Shape = jax.core.Shape /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/chex/_src/pytypes.py:54: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html PRNGKey = jax.random.KeyArray /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/_types.py:9: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html IntOrKey = Union[int, jax.random.KeyArray] /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_utils.py:40: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def validate_seed(seed: IntOrKey) -> jax.random.KeyArray: /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_kmeans.py:21: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def _initialize_random(X: jnp.ndarray, n_clusters: int, key: jax.random.KeyArray) -> jnp.ndarray: /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scib_metrics/utils/_kmeans.py:31: DeprecationWarning: jax.random.KeyArray is deprecated. Use jax.Array for annotations, and jax.dtypes.issubdtype(arr.dtype, jax.dtypes.prng_key) for runtime detection of typed prng keys (i.e. keys created with jax.random.key). For more information, see https://jax.readthedocs.io/en/latest/jep/9263-typed-keys.html def _initialize_plus_plus(X: jnp.ndarray, n_clusters: int, key: jax.random.KeyArray) -> jnp.ndarray:","title":"table of contents:"},{"location":"notebooks/cancer_usecase/#downloading-and-preprocessing","text":"We now use lamindb to easily access cellxgene and download a dataset of normal and benign prostatic hyperplasia tissues. data is available here https://cellxgene.cziscience.com/e/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.cxg/ . We then use scDataloader's preprocessing method. This method is quite extensive and does a few things.. find our more about it on its documentation . On our end we are using the preprocessor to make sure that the the gene expression that we have are raw counts and that we have enough information to use scPRINT (i.e., enough genes expressed and enough counts per cells across the dataset). Finally, the preprocessor will also increase the size of the expression matrix to be a fixed set of genes defined by the latest version of ensemble. In [2]: Copied! cx_dataset = ln . Collection . using ( instance = \"laminlabs/cellxgene\" ) . filter ( name = \"cellxgene-census\" , version = '2023-12-15' ) . one () cx_dataset = ln.Collection.using(instance=\"laminlabs/cellxgene\").filter(name=\"cellxgene-census\", version='2023-12-15').one() In [3]: Copied! prostate_adata = cx_dataset . artifacts . filter ( key = 'cell-census/2023-12-15/h5ads/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.h5ad' ) . one () . load () sc . pl . umap ( prostate_adata ) prostate_adata = cx_dataset.artifacts.filter(key='cell-census/2023-12-15/h5ads/574e9f9e-f8b4-41ef-bf19-89a9964fd9c7.h5ad').one().load() sc.pl.umap(prostate_adata) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/asyncio/sslproto.py:320: ResourceWarning: unclosed transport _warn(f\"unclosed transport {self!r}\", ResourceWarning, source=self) ResourceWarning: Enable tracemalloc to get the object allocation traceback In [7]: Copied! # preprocessing using scDataloader prostate_adata . obs . drop ( columns = \"is_primary_data\" , inplace = True ) preprocessor = Preprocessor ( do_postp = False ) prostate_adata = preprocessor ( prostate_adata ) # preprocessing using scDataloader prostate_adata.obs.drop(columns=\"is_primary_data\", inplace=True) preprocessor = Preprocessor(do_postp=False) prostate_adata = preprocessor(prostate_adata) Dropping layers: KeysView(Layers with keys: ) checking raw counts removed 0 non primary cells, 83451 renamining filtered out 0 cells, 83451 renamining Removed 76 genes. validating /home/ml4ig1/Documents code/scPRINT/scDataLoader/scdataloader/preprocess.py:241: FutureWarning: Series.__getitem__ treating keys as positions is deprecated. In a future version, integer keys will always be treated as labels (consistent with DataFrame behavior). To access a value by position, use `ser.iloc[pos]` data_utils.validate(adata, organism=adata.obs.organism_ontology_term_id[0]) startin QC Seeing 13047 outliers (15.63% of total dataset): done","title":"Downloading and preprocessing"},{"location":"notebooks/cancer_usecase/#embedding-and-annotations","text":"We now start to load a large version of scPRINT from a specific checkpoint. Please download the checkpoints following the instructions in the README. We will then use out Embedder class to embed the data and annotate the cells. These classes are how we parametrize and access the different functions of scPRINT . Find out more about its parameters in our documentation . In [6]: Copied! model = scPrint . load_from_checkpoint ( '../data/temp/o2uniqsx/epoch=18-step=133000.ckpt' , # make sure that you check if you have a GPU with flashattention or not (see README) # you need this else, the model will look for the file with the embeddings instead of getting them from the weights precpt_gene_emb = None ) model = scPrint.load_from_checkpoint('../data/temp/o2uniqsx/epoch=18-step=133000.ckpt', # make sure that you check if you have a GPU with flashattention or not (see README) # you need this else, the model will look for the file with the embeddings instead of getting them from the weights precpt_gene_emb = None) RuntimeError caught: scPrint is not attached to a `Trainer`. In [10]: Copied! embedder = Embedder ( # can work on random genes or most variables etc.. how = \"random expr\" , # number of genes to use max_len = 4000 , add_zero_genes = 0 , # for the dataloading num_workers = 8 , # we will only use the cell type embedding here. pred_embedding = [ \"cell_type_ontology_term_id\" ] ) #, \"disease_ontology_term_id\"]) embedder = Embedder( # can work on random genes or most variables etc.. how=\"random expr\", # number of genes to use max_len=4000, add_zero_genes=0, # for the dataloading num_workers=8, # we will only use the cell type embedding here. pred_embedding = [\"cell_type_ontology_term_id\"] )#, \"disease_ontology_term_id\"]) Using 16bit Automatic Mixed Precision (AMP) GPU available: True (cuda), used: True TPU available: False, using: 0 TPU cores IPU available: False, using: 0 IPUs HPU available: False, using: 0 HPUs In [ ]: Copied! # create the embedding prostate_adata , metrics = embedder ( model , prostate_adata , cache = False , output_expression = \"none\" ) # create the embedding prostate_adata, metrics = embedder(model, prostate_adata, cache=False, output_expression=\"none\") 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 1560/1560 [28:20<00:00, 1.09s/it] AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 424 obs: 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id' /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) couldn't log to tensorboard couldn't log to wandb couldn't log to wandb cell_type_ontology_term_id accuracy: 0.7250215374752068 disease_ontology_term_id accuracy: 0.8394506441207702 assay_ontology_term_id accuracy: 0.998988239536794 self_reported_ethnicity_ontology_term_id accuracy: 0.9504037024422495 sex_ontology_term_id accuracy: 0.9948911105323263 organism_ontology_term_id accuracy: 1.0 In [16]: Copied! prostate_adata prostate_adata Out[16]: AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 70116 obs: 'assay_ontology_term_id', 'donor_id', 'sex_ontology_term_id', 'disease_ontology_term_id', 'organism_ontology_term_id', 'suspension_type', 'cell_type_ontology_term_id', 'tissue_ontology_term_id', 'development_stage_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'cell_type', 'assay', 'disease', 'organism', 'sex', 'tissue', 'self_reported_ethnicity', 'development_stage', 'nnz', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb', 'outlier', 'mt_outlier', 'init_dataset', 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id', 'sprint_leiden' uns: 'init_dataset_colors' obsm: 'X_pca', 'X_umap', 'scprint_umap', 'scprint'","title":"Embedding and annotations"},{"location":"notebooks/cancer_usecase/#annotation-cleanup","text":"scPRINT generates predictions over hundreds of possible labels for each cell. It is often advised to \"cleanup\" the predictions, e.g. making sure to remove low frequency cells and misslabellings. Here, we use the most straightforward approach which is to remove any annotations that appear a small number of times. A better approach would be doing majority voting over cell clusters as it would aggregate and smoothout the predictions over multiple cells. it would also remove most of the low frequency mistakes in the predictions. We will also have a look at the embeddings of scPRINT by plotting its UMAP visualization. In [30]: Copied! #cleaning up the cell types prostate_adata . obs [ 'cleaned_pred_cell_type_ontology_term_id' ] = prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . astype ( str ) prostate_adata . obs . loc [ ~ prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . isin ([ k for k , v in prostate_adata . obs [ 'conv_pred_cell_type_ontology_term_id' ] . value_counts () . items () if v > 400 ]), 'cleaned_pred_cell_type_ontology_term_id' ] = \"other\" prostate_adata . obs [ 'cleaned_pred_cell_type_ontology_term_id' ] . value_counts () . plot . pie () #cleaning up the cell types prostate_adata.obs['cleaned_pred_cell_type_ontology_term_id'] = prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].astype(str) prostate_adata.obs.loc[~prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].isin([k for k, v in prostate_adata.obs['conv_pred_cell_type_ontology_term_id'].value_counts().items() if v > 400]), 'cleaned_pred_cell_type_ontology_term_id'] = \"other\" prostate_adata.obs['cleaned_pred_cell_type_ontology_term_id'].value_counts().plot.pie() Out[30]: In [31]: Copied! # cleaning up the diseases prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] = prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . astype ( str ) prostate_adata . obs . loc [ ~ prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . isin ([ k for k , v in prostate_adata . obs [ 'conv_pred_disease_ontology_term_id' ] . value_counts () . items () if v > 1000 ]), 'cleaned_pred_disease_ontology_term_id' ] = \"other\" prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () . plot . pie () # cleaning up the diseases prostate_adata.obs['cleaned_pred_disease_ontology_term_id'] = prostate_adata.obs['conv_pred_disease_ontology_term_id'].astype(str) prostate_adata.obs.loc[~prostate_adata.obs['conv_pred_disease_ontology_term_id'].isin([k for k, v in prostate_adata.obs['conv_pred_disease_ontology_term_id'].value_counts().items() if v > 1000]), 'cleaned_pred_disease_ontology_term_id'] = \"other\" prostate_adata.obs['cleaned_pred_disease_ontology_term_id'].value_counts().plot.pie() Out[31]: In [38]: Copied! sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'cleaned_pred_cell_type_ontology_term_id' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'cleaned_pred_disease_ontology_term_id' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'assay' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'disease' ]) sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = [ 'development_stage' ]) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['cleaned_pred_cell_type_ontology_term_id']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['cleaned_pred_disease_ontology_term_id']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['assay']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['disease']) sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color=['development_stage']) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) In [ ]: Copied! prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 20 ) prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id.value_counts().head(20) cleaned_pred_cell_type_ontology_term_id basal cell of epidermis 22449 mammary alveolar cell 9688 vasa recta descending limb cell 8777 CD1c-positive myeloid dendritic cell 5782 effector memory CD8-positive, alpha-beta T cell 5410 smooth muscle cell of the pulmonary artery 5007 other 4972 pancreatic acinar cell 4639 basal epithelial cell of prostatic duct 3405 serous cell of epithelium of trachea 3327 prostate gland microvascular endothelial cell 2747 paneth cell of epithelium of small intestine 2698 mast cell 2365 IgG-negative class switched memory B cell 2348 fibroblast of connective tissue of nonglandular part of prostate 2058 club cell 1794 pulmonary artery endothelial cell 1239 CD141-positive myeloid dendritic cell 1186 mucous neck cell 1039 smooth muscle cell of prostate 857 peptic cell 766 T-helper 17 cell 735 CD14-positive, CD16-negative classical monocyte 671 CD16-negative, CD56-bright natural killer cell, human 666 lung pericyte 663 alveolar type 2 fibroblast cell 646 type II pneumocyte 618 naive B cell 606 effector CD4-positive, alpha-beta T cell 506 fibroblast of connective tissue of glandular part of prostate 464 luminal epithelial cell of mammary gland 437 inflammatory macrophage 436 fibroblast of mammary gland 416 basal cell of epithelium of bronchus 409 Name: count, dtype: int64 In [39]: Copied! # we save for next time prostate_adata . write_h5ad ( \"../../data/prostate_adata_o2uniqsx.h5ad\" ) # we save for next time prostate_adata.write_h5ad(\"../../data/prostate_adata_o2uniqsx.h5ad\") In [2]: Copied! prostate_adata = sc . read_h5ad ( \"../../data/prostate_adata_o2uniqsx.h5ad\" ) prostate_adata = sc.read_h5ad(\"../../data/prostate_adata_o2uniqsx.h5ad\")","title":"Annotation cleanup"},{"location":"notebooks/cancer_usecase/#clustering-and-differential-expression","text":"We will now cluster using the louvain algorithm on a kNN graph. Once we detect a cluster of interest we will perform differential expression analysis on it. Taking as example some B-cell clusters, we will use scanpy's implementation of rank_gene_groups for our differential expression In [15]: Copied! # do louvain mutliple times sc . pp . neighbors ( prostate_adata , n_neighbors = 10 , use_rep = \"scprint\" ) # using multiple resolutions can help spotting smaller clusters sc . tl . louvain ( prostate_adata , resolution = 0.5 , key_added = \"louvain_0.5\" ) sc . tl . louvain ( prostate_adata , resolution = 1.0 , key_added = \"louvain_1.0\" ) # do louvain mutliple times sc.pp.neighbors(prostate_adata, n_neighbors=10, use_rep=\"scprint\") # using multiple resolutions can help spotting smaller clusters sc.tl.louvain(prostate_adata, resolution=0.5, key_added=\"louvain_0.5\") sc.tl.louvain(prostate_adata, resolution=1.0, key_added=\"louvain_1.0\") In [20]: Copied! # check clusters sc . pl . embedding ( prostate_adata , basis = \"scprint_umap\" , color = 'louvain_1.0' , show = False , legend_loc = \"on data\" ) # check clusters sc.pl.embedding(prostate_adata, basis=\"scprint_umap\", color='louvain_1.0', show=False, legend_loc=\"on data\") /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) Out[20]: In [21]: Copied! # check cluster 9 i = 9 loc = prostate_adata . obs [ 'louvain_1.0' ] == str ( i ) prostate_adata . obs [ loc ] . conv_pred_disease_ontology_term_id . value_counts () . head ( 2 ), prostate_adata . obs [ loc ] . conv_pred_cell_type_ontology_term_id . value_counts () . head ( 5 ) # check cluster 9 i=9 loc = prostate_adata.obs['louvain_1.0']==str(i) prostate_adata.obs[loc].conv_pred_disease_ontology_term_id.value_counts().head(2), prostate_adata.obs[loc].conv_pred_cell_type_ontology_term_id.value_counts().head(5) Out[21]: (conv_pred_disease_ontology_term_id benign prostatic hyperplasia 3554 normal 18 Name: count, dtype: int64, conv_pred_cell_type_ontology_term_id urethra urothelial cell 1703 luminal cell of prostate epithelium 703 mucous neck cell 566 basal epithelial cell of prostatic duct 372 club cell 174 Name: count, dtype: int64) In [6]: Copied! # check cluster 11 i = 11 loc = prostate_adata . obs [ 'louvain_1.0' ] == str ( i ) prostate_adata . obs [ loc ] . cleaned_pred_disease_ontology_term_id . value_counts () . head ( 2 ), prostate_adata . obs [ loc ] . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 5 ) # check cluster 11 i=11 loc = prostate_adata.obs['louvain_1.0']==str(i) prostate_adata.obs[loc].cleaned_pred_disease_ontology_term_id.value_counts().head(2), prostate_adata.obs[loc].cleaned_pred_cell_type_ontology_term_id.value_counts().head(5) Out[6]: (cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 2930 normal 68 Name: count, dtype: int64, cleaned_pred_cell_type_ontology_term_id IgG-negative class switched memory B cell 2840 other 142 CD1c-positive myeloid dendritic cell 8 basophil 7 CD4-positive, alpha-beta thymocyte 5 Name: count, dtype: int64) In [7]: Copied! # We have find a nice IgG-negative class switched memory B cell cluster. let's use it and define a clean annotation for a plot loc = loc & ( prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id == \"IgG-negative class switched memory B cell\" ) prostate_adata . obs [ loc ] . cleaned_pred_disease_ontology_term_id . value_counts () . head ( 2 ) # We have find a nice IgG-negative class switched memory B cell cluster. let's use it and define a clean annotation for a plot loc = loc&(prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id==\"IgG-negative class switched memory B cell\") prostate_adata.obs[loc].cleaned_pred_disease_ontology_term_id.value_counts().head(2) Out[7]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 2771 normal 60 Name: count, dtype: int64 In [8]: Copied! # making a \"focus\" annotation for the B-cell to generate a nice plot of the B-cell cluster only prostate_adata . obs [ 'focus' ] = \"other\" prostate_adata . obs . loc [ loc , 'focus' ] = \"memory B cell\" prostate_adata . obs . loc [ loc & ( prostate_adata . obs [ 'cleaned_pred_disease_ontology_term_id' ] == 'benign prostatic hyperplasia' ), 'focus' ] = \"BPH associated memory B cell\" prostate_adata . obs [ 'focus' ] . value_counts () # making a \"focus\" annotation for the B-cell to generate a nice plot of the B-cell cluster only prostate_adata.obs['focus'] = \"other\" prostate_adata.obs.loc[loc, 'focus'] = \"memory B cell\" prostate_adata.obs.loc[loc & (prostate_adata.obs['cleaned_pred_disease_ontology_term_id']=='benign prostatic hyperplasia'), 'focus'] = \"BPH associated memory B cell\" prostate_adata.obs['focus'].value_counts() In [24]: Copied! import matplotlib.pyplot as plt import matplotlib.patches as patches import seaborn as sns color = sns . color_palette ()[ 1 ] fig , ax = plt . subplots ( figsize = ( 2 , 2 )) rect = patches . Rectangle (( 0 , 0 ), 1 , 1 , facecolor = color ) ax . add_patch ( rect ) ax . set_xlim ( 0 , 1 ) ax . set_ylim ( 0 , 1 ) ax . axis ( 'off' ) plt . show () import matplotlib.pyplot as plt import matplotlib.patches as patches import seaborn as sns color = sns.color_palette()[1] fig, ax = plt.subplots(figsize=(2, 2)) rect = patches.Rectangle((0, 0), 1, 1, facecolor=color) ax.add_patch(rect) ax.set_xlim(0, 1) ax.set_ylim(0, 1) ax.axis('off') plt.show() In [32]: Copied! # looking at the B-cell cluster. We can see some normal and BPH-associated memory B-cells sc . pl . embedding ( prostate_adata [( prostate_adata . obs [ 'louvain_1.0' ] == str ( i )) & ( prostate_adata . obsm [ 'scprint_umap' ][:, 0 ] > 4 )], basis = \"scprint_umap\" , color = 'focus' , show = False , size = 8 , title = \"Switched memory B-cell cluster\" , legend_loc = \"right margin\" ) # looking at the B-cell cluster. We can see some normal and BPH-associated memory B-cells sc.pl.embedding(prostate_adata[(prostate_adata.obs['louvain_1.0']==str(i)) & (prostate_adata.obsm['scprint_umap'][:,0]>4)], basis=\"scprint_umap\",color='focus', show=False, size=8, title=\"Switched memory B-cell cluster\", legend_loc=\"right margin\") ... storing 'focus' as categorical /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) Out[32]: In [ ]: Copied! # here we use a function of scdataloader to add some more gene annotations to our dataset so we can view HGNC symbols genedf = utils . load_genes ( prostate_adata . obs . organism_ontology_term_id . iloc [ 0 ]) # columns that create issues when saving anndatas prostate_adata . var = genedf . loc [ prostate_adata . var . index ] . drop ( columns = [ \"stable_id\" , \"created_at\" , \"updated_at\" ]) # here we use a function of scdataloader to add some more gene annotations to our dataset so we can view HGNC symbols genedf = utils.load_genes(prostate_adata.obs.organism_ontology_term_id.iloc[0]) # columns that create issues when saving anndatas prostate_adata.var = genedf.loc[prostate_adata.var.index].drop(columns=[\"stable_id\", \"created_at\", \"updated_at\"]) In [ ]: Copied! # now the diff expression between B-cells and the rest sc . tl . rank_genes_groups ( prostate_adata , groupby = 'cleaned_pred_cell_type_ontology_term_id' , groups = [ 'IgG-negative class switched memory B cell' ], reference = 'other' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # now the diff expression between B-cells and the rest sc.tl.rank_genes_groups(prostate_adata, groupby='cleaned_pred_cell_type_ontology_term_id', groups=['IgG-negative class switched memory B cell'], reference='other', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers ... storing 'focus' as categorical ... storing 'symbol' as categorical ... storing 'ncbi_gene_ids' as categorical ... storing 'biotype' as categorical ... storing 'description' as categorical ... storing 'synonyms' as categorical ... storing 'organism' as categorical WARNING: It seems you use rank_genes_groups on the raw count data. Please logarithmize your data before calling rank_genes_groups. /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/tools/_rank_genes_groups.py:420: RuntimeWarning: overflow encountered in expm1 self.expm1_func(mean_rest) + 1e-9 /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/tools/_rank_genes_groups.py:422: RuntimeWarning: divide by zero encountered in log2 self.stats[group_name, 'logfoldchanges'] = np.log2(","title":"Clustering and differential expression"},{"location":"notebooks/cancer_usecase/#denoising-and-differential-expression","text":"What we found out from our previous analysis is that there is not a lot of normal (i.e. healthy) B-cells in our cluster, most of them are BPH associated. In this case, if we wanted to compare BPH B-cells to normal B-cells we might be very underpowered... Instead of going to look for some other dataset, let's use scPRINT to increase the depth of the expression profile of the cells, virtually adding more signal to our dataset. We will use the Denoiser class (see more about the class in our documentation ) in a similar way Trainer is used in pytorch lightning to denoise the expression profile of the cells. We will then show the results of differential expression analysis before and after denoising. In [ ]: Copied! # in case you started from here prostate_adata = sc . read_h5ad ( \"../data/prostate_adata_o2uniqsx.h5ad\" ) prostate_adata # in case you started from here prostate_adata = sc.read_h5ad(\"../data/prostate_adata_o2uniqsx.h5ad\") prostate_adata AnnData object with n_obs \u00d7 n_vars = 99826 \u00d7 70116 obs: 'assay_ontology_term_id', 'donor_id', 'sex_ontology_term_id', 'disease_ontology_term_id', 'organism_ontology_term_id', 'suspension_type', 'cell_type_ontology_term_id', 'tissue_ontology_term_id', 'development_stage_ontology_term_id', 'self_reported_ethnicity_ontology_term_id', 'cell_type', 'assay', 'disease', 'organism', 'sex', 'tissue', 'self_reported_ethnicity', 'development_stage', 'nnz', 'n_genes_by_counts', 'log1p_n_genes_by_counts', 'total_counts', 'log1p_total_counts', 'pct_counts_in_top_20_genes', 'total_counts_mt', 'log1p_total_counts_mt', 'pct_counts_mt', 'total_counts_ribo', 'log1p_total_counts_ribo', 'pct_counts_ribo', 'total_counts_hb', 'log1p_total_counts_hb', 'pct_counts_hb', 'outlier', 'mt_outlier', 'init_dataset', 'pred_cell_type_ontology_term_id', 'pred_disease_ontology_term_id', 'pred_assay_ontology_term_id', 'pred_self_reported_ethnicity_ontology_term_id', 'pred_sex_ontology_term_id', 'pred_organism_ontology_term_id', 'conv_pred_cell_type_ontology_term_id', 'conv_pred_disease_ontology_term_id', 'conv_pred_assay_ontology_term_id', 'conv_pred_self_reported_ethnicity_ontology_term_id', 'sprint_leiden', 'cleaned_pred_cell_type_ontology_term_id', 'cleaned_pred_disease_ontology_term_id', 'louvain_0.5', 'louvain_1.0', 'fibro' var: 'uid', 'symbol', 'ncbi_gene_ids', 'biotype', 'description', 'synonyms', 'organism_id', 'public_source_id', 'created_by_id', 'mt', 'ribo', 'hb', 'organism' uns: 'louvain', 'neighbors' obsm: 'X_pca', 'X_umap', 'scprint', 'scprint_umap' obsp: 'connectivities', 'distances' In [16]: Copied! # here we compare memory B-cell in BPH to normal memory B cells before denoising sc . tl . rank_genes_groups ( prostate_adata , groupby = 'focus' , groups = [ 'BPH associated memory B cell' ], reference = 'memory B cell' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # here we compare memory B-cell in BPH to normal memory B cells before denoising sc.tl.rank_genes_groups(prostate_adata, groupby='focus', groups=['BPH associated memory B cell'], reference='memory B cell', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers WARNING: It seems you use rank_genes_groups on the raw count data. Please logarithmize your data before calling rank_genes_groups. In [19]: Copied! # perform denoising denoise = Denoiser ( # could be on top differentially expressed genes or on random expressed genes in the cell (completed by random non expressed gene) how = \"random expr\" # the size of the minibatch (need to fit in memory) batch_size = 20 , # the number of genes to use max_len = 5000 , # the number of cells to use (here more than what we will use so we will use everything) plot_corr_size = 10_000 , doplot = False , # how much do we want to increase the depth / counts of the cells (here, 10x) predict_depth_mult = 10 , ) idx , genes , expr = denoise ( model , prostate_adata [ prostate_adata . obs [ 'focus' ] != \"other\" ]) # perform denoising denoise = Denoiser( # could be on top differentially expressed genes or on random expressed genes in the cell (completed by random non expressed gene) how=\"random expr\" # the size of the minibatch (need to fit in memory) batch_size=20, # the number of genes to use max_len=5000, # the number of cells to use (here more than what we will use so we will use everything) plot_corr_size=10_000, doplot=False, # how much do we want to increase the depth / counts of the cells (here, 10x) predict_depth_mult=10, ) idx, genes, expr = denoise(model, prostate_adata[prostate_adata.obs['focus']!=\"other\"]) 100%|\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588| 82/82 [00:50<00:00, 1.64it/s] In [20]: Copied! # now what we are doing here it to complete the expression profile with the denoised values. this is not done by default for now i = 0 prostate_adata . X = prostate_adata . X . tolil () for idx , val in enumerate ( prostate_adata . obs [ 'focus' ] != \"other\" ): if val : prostate_adata . X [ idx , prostate_adata . var . index . get_indexer ( np . array ( model . genes )[ genes [ i ]])] = expr [ i ] i += 1 prostate_adata . X = prostate_adata . X . tocsr () # now what we are doing here it to complete the expression profile with the denoised values. this is not done by default for now i = 0 prostate_adata.X = prostate_adata.X.tolil() for idx, val in enumerate(prostate_adata.obs['focus']!=\"other\"): if val: prostate_adata.X[idx, prostate_adata.var.index.get_indexer(np.array(model.genes)[genes[i]])] = expr[i] i += 1 prostate_adata.X = prostate_adata.X.tocsr() In [21]: Copied! # now we compare memory B-cell in BPH to normal memory B cells after denoising sc . tl . rank_genes_groups ( prostate_adata , groupby = 'focus' , groups = [ 'BPH associated memory B cell' ], reference = 'memory B cell' , method = 't-test' ) # Plot the most differentially expressed genes sc . pl . rank_genes_groups ( prostate_adata , n_genes = 25 , sharey = False , gene_symbols = 'symbol' ) # super strong B cell markers # now we compare memory B-cell in BPH to normal memory B cells after denoising sc.tl.rank_genes_groups(prostate_adata, groupby='focus', groups=['BPH associated memory B cell'], reference='memory B cell', method='t-test') # Plot the most differentially expressed genes sc.pl.rank_genes_groups(prostate_adata, n_genes=25, sharey=False, gene_symbols='symbol') # super strong B cell markers In [9]: Copied! prostate_adata . write_h5ad ( \"../../data/prostate_adata_denoised.h5ad\" ) prostate_adata.write_h5ad(\"../../data/prostate_adata_denoised.h5ad\") In [3]: Copied! prostate_adata = sc . read_h5ad ( \"../../data/prostate_adata_denoised.h5ad\" ) prostate_adata = sc.read_h5ad(\"../../data/prostate_adata_denoised.h5ad\")","title":"Denoising and differential expression"},{"location":"notebooks/cancer_usecase/#gene-network-inference","text":"Finally we will use scPRINT to infer gene networks on another cell of interest, the fibroblasts, in both normal and BPH conditions. We will use the GRNfer class to infer gene networks. ( see the cancer_usecase_part2.ipynb for more details on how to analyse the gene networks. ) In [38]: Copied! prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id . value_counts () . head ( 20 ) prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id.value_counts().head(20) Out[38]: cleaned_pred_cell_type_ontology_term_id basal epithelial cell of prostatic duct 25740 prostate gland microvascular endothelial cell 12165 urethra urothelial cell 10952 CD1c-positive myeloid dendritic cell 6898 other 5869 aortic smooth muscle cell 3970 effector CD8-positive, alpha-beta T cell 3925 pancreatic acinar cell 3711 luminal cell of prostate epithelium 3435 fibroblast of connective tissue of nonglandular part of prostate 3334 mucous neck cell 3260 IgG-negative class switched memory B cell 2932 basophil 1862 fibroblast of connective tissue of glandular part of prostate 1815 pancreatic ductal cell 1651 CD4-positive, alpha-beta thymocyte 1516 club cell 1226 smooth muscle cell of prostate 1000 effector memory CD8-positive, alpha-beta T cell 991 peptic cell 872 mature conventional dendritic cell 721 effector CD4-positive, alpha-beta T cell 686 mast cell 451 renal interstitial pericyte 440 retinal blood vessel endothelial cell 404 Name: count, dtype: int64 In [33]: Copied! loc = ( prostate_adata . obs . cleaned_pred_cell_type_ontology_term_id == \"fibroblast of connective tissue of glandular part of prostate\" ) prostate_adata . obs [ loc ][ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () loc = (prostate_adata.obs.cleaned_pred_cell_type_ontology_term_id==\"fibroblast of connective tissue of glandular part of prostate\") prostate_adata.obs[loc]['cleaned_pred_disease_ontology_term_id'].value_counts() Out[33]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 1482 normal 673 other 4 Name: count, dtype: int64 In [52]: Copied! prostate_adata . obs [ loc ][ 'louvain_1.0' ] . value_counts () . head ( 10 ) prostate_adata.obs[loc]['louvain_1.0'].value_counts().head(10) Out[52]: louvain_1.0 5 1458 4 671 17 10 8 8 7 7 0 3 9 2 6 0 3 0 1 0 10 0 11 0 12 0 13 0 14 0 15 0 16 0 2 0 18 0 Name: count, dtype: int64 In [34]: Copied! loc = loc & ( prostate_adata . obs [ 'louvain_1.0' ] == str ( 5 )) prostate_adata . obs [ loc ][ 'cleaned_pred_disease_ontology_term_id' ] . value_counts () loc = loc & (prostate_adata.obs['louvain_1.0']==str(5)) prostate_adata.obs[loc]['cleaned_pred_disease_ontology_term_id'].value_counts() Out[34]: cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 790 normal 664 other 4 Name: count, dtype: int64 In [35]: Copied! prostate_adata . obs [ 'fibro' ] = None prostate_adata . obs . loc [ loc , 'fibro' ] = \"fibroblasts\" prostate_adata . obs . loc [ loc & ( prostate_adata . obs . cleaned_pred_disease_ontology_term_id == \"benign prostatic hyperplasia\" ), 'fibro' ] = \"BPH associated fibroblasts\" prostate_adata.obs['fibro'] = None prostate_adata.obs.loc[loc, 'fibro']=\"fibroblasts\" prostate_adata.obs.loc[loc & (prostate_adata.obs.cleaned_pred_disease_ontology_term_id==\"benign prostatic hyperplasia\"), 'fibro']=\"BPH associated fibroblasts\" In [37]: Copied! sc . pl . embedding ( prostate_adata [ prostate_adata . obs [ 'louvain_1.0' ] . isin ([ \"5\" , \"4\" ]) & ( prostate_adata . obsm [ 'scprint_umap' ][:, 1 ] > 10 )], basis = \"scprint_umap_rot\" , color = 'fibro' , show = False , size = 8 , title = \"Fibroblasts cluster\" , legend_loc = \"right margin\" ) sc.pl.embedding(prostate_adata[prostate_adata.obs['louvain_1.0'].isin([\"5\",\"4\"]) & (prostate_adata.obsm['scprint_umap'][:,1]>10)], basis=\"scprint_umap_rot\",color='fibro', show=False, size=8, title=\"Fibroblasts cluster\", legend_loc=\"right margin\") ... storing 'focus' as categorical ... storing 'fibro' as categorical /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/scanpy/plotting/_tools/scatterplots.py:1251: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning color_vector = pd.Categorical(values.map(color_map)) In [8]: Copied! grn_inferer = GNInfer ( # here we use the most variable genes across the fibroblasts vs the rest how = \"most var across\" , #how=\"random expr\", # we will preprocess the attention matrix with softmax preprocess = \"softmax\" , # we don't aggregate the heads here, we will do it manually head_agg = 'none' , # here if we generate the attention matrices by performing a task, like denoising or by just passing the expression profile through the model forward_mode = \"none\" , # the number of genes to use (here the 4000 most variable genes) num_genes = 4000 , # the max number of cell to use per cell type max_cells = 300 , doplot = False , batch_size = 16 , # the column in anndata the defines the cell type cell_type_col = 'fibro' , # list of layers to use layer = list ( range ( model . nlayers ))[:] ) grn_inferer = GNInfer( # here we use the most variable genes across the fibroblasts vs the rest how=\"most var across\", #how=\"random expr\", # we will preprocess the attention matrix with softmax preprocess=\"softmax\", # we don't aggregate the heads here, we will do it manually head_agg='none', # here if we generate the attention matrices by performing a task, like denoising or by just passing the expression profile through the model forward_mode=\"none\", # the number of genes to use (here the 4000 most variable genes) num_genes=4000, # the max number of cell to use per cell type max_cells=300, doplot=False, batch_size=16, # the column in anndata the defines the cell type cell_type_col='fibro', # list of layers to use layer=list(range(model.nlayers))[:] ) In [9]: Copied! # I was missing this from the model (not really necessary) model . organisms = [ 'NCBITaxon:9606' , 'NCBITaxon:10090' ] prostate_adata . obs . fibro = prostate_adata . obs . fibro . astype ( str ) prostate_adata . obs [ prostate_adata . obs . fibro == \"BPH associated fibroblasts\" ] . disease . value_counts () # I was missing this from the model (not really necessary) model.organisms = ['NCBITaxon:9606', 'NCBITaxon:10090'] prostate_adata.obs.fibro = prostate_adata.obs.fibro.astype(str) prostate_adata.obs[prostate_adata.obs.fibro==\"BPH associated fibroblasts\"].disease.value_counts() In [ ]: Copied! # compute GRNs on fibroblasts, we use all the atetetion layers grn = grn_inferer ( model , prostate_adata , cell_type = \"fibroblasts\" ) # highlight differential links on genes that are expressed in both grn . varp [ 'all' ] = grn . varp [ 'GRN' ] . copy () # now we aggregate the heads by taking their average grn . varp [ 'GRN' ] = grn . varp [ 'GRN' ] . mean ( - 1 ) grn . write_h5ad ( \"../../data/prostate_fibro_grn_all.h5ad\" ) # compute GRNs on fibroblasts, we use all the atetetion layers grn = grn_inferer(model, prostate_adata, cell_type=\"fibroblasts\") # highlight differential links on genes that are expressed in both grn.varp['all'] = grn.varp['GRN'].copy() # now we aggregate the heads by taking their average grn.varp['GRN'] = grn.varp['GRN'].mean(-1) grn.write_h5ad(\"../../data/prostate_fibro_grn_all.h5ad\") In [11]: Copied! #same on the BPH associated fibroblasts # I wanted to use only the ones that the labellers had defined as coing from BPH prostate_adata . obs . loc [( prostate_adata . obs . fibro == \"BPH associated fibroblasts\" ) & ( prostate_adata . obs . disease == \"benign prostatic hyperplasia\" ), 'fibro' ] = \"true BPH associated fibroblasts\" grn_c = grn_inferer ( model , prostate_adata , cell_type = \"true cancer associated fibroblasts\" ) # highlight differential links on genes that are expressed in both grn_c . varp [ 'all' ] = grn_c . varp [ 'GRN' ] . copy () grn_c . varp [ 'GRN' ] = grn_c . varp [ 'GRN' ] . mean ( - 1 ) grn_c . write_h5ad ( \"../../data/prostate_BPH_fibro_grn_all.h5ad\" ) #same on the BPH associated fibroblasts # I wanted to use only the ones that the labellers had defined as coing from BPH prostate_adata.obs.loc[(prostate_adata.obs.fibro==\"BPH associated fibroblasts\") & ( prostate_adata.obs.disease==\"benign prostatic hyperplasia\"), 'fibro'] = \"true BPH associated fibroblasts\" grn_c = grn_inferer(model, prostate_adata, cell_type=\"true cancer associated fibroblasts\") # highlight differential links on genes that are expressed in both grn_c.varp['all'] = grn_c.varp['GRN'].copy() grn_c.varp['GRN'] = grn_c.varp['GRN'].mean(-1) grn_c.write_h5ad(\"../../data/prostate_BPH_fibro_grn_all.h5ad\") ['pre { line-height: 125%; }\\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n.highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) }\\n.highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\\n.highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\\n.highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */\\n.highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\\n.highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\\n.highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\\n.highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\\n.highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\\n.highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\\n.highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\\n.highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\\n.highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\\n.highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\\n.highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\\n.highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\\n.highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\\n.highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\\n.highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\\n.highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\\n.highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\\n.highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\\n.highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\\n.highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\\n.highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\\n.highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\\n.highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\\n.highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\\n.highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\\n.highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\\n.highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\\n.highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\\n.highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\\n.highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\\n.highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\\n.highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\\n.highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\\n.highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\\n.highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\\n.highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\\n.highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\\n.highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\\n.highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */']","title":"Gene network inference"},{"location":"notebooks/cancer_usecase_part2/","text":"(function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global = global || self, global.ClipboardCopyElement = factory()); }(this, function () { 'use strict'; function createNode(text) { const node = document.createElement('pre'); node.style.width = '1px'; node.style.height = '1px'; node.style.position = 'fixed'; node.style.top = '5px'; node.textContent = text; return node; } function copyNode(node) { if ('clipboard' in navigator) { // eslint-disable-next-line flowtype/no-flow-fix-me-comments // $FlowFixMe Clipboard is not defined in Flow yet. return navigator.clipboard.writeText(node.textContent); } const selection = getSelection(); if (selection == null) { return Promise.reject(new Error()); } selection.removeAllRanges(); const range = document.createRange(); range.selectNodeContents(node); selection.addRange(range); document.execCommand('copy'); selection.removeAllRanges(); return Promise.resolve(); } function copyText(text) { if ('clipboard' in navigator) { // eslint-disable-next-line flowtype/no-flow-fix-me-comments // $FlowFixMe Clipboard is not defined in Flow yet. return navigator.clipboard.writeText(text); } const body = document.body; if (!body) { return Promise.reject(new Error()); } const node = createNode(text); body.appendChild(node); copyNode(node); body.removeChild(node); return Promise.resolve(); } function copy(button) { const id = button.getAttribute('for'); const text = button.getAttribute('value'); function trigger() { button.dispatchEvent(new CustomEvent('clipboard-copy', { bubbles: true })); } if (text) { copyText(text).then(trigger); } else if (id) { const root = 'getRootNode' in Element.prototype ? button.getRootNode() : button.ownerDocument; if (!(root instanceof Document || 'ShadowRoot' in window && root instanceof ShadowRoot)) return; const node = root.getElementById(id); if (node) copyTarget(node).then(trigger); } } function copyTarget(content) { if (content instanceof HTMLInputElement || content instanceof HTMLTextAreaElement) { return copyText(content.value); } else if (content instanceof HTMLAnchorElement && content.hasAttribute('href')) { return copyText(content.href); } else { return copyNode(content); } } function clicked(event) { const button = event.currentTarget; if (button instanceof HTMLElement) { copy(button); } } function keydown(event) { if (event.key === ' ' || event.key === 'Enter') { const button = event.currentTarget; if (button instanceof HTMLElement) { event.preventDefault(); copy(button); } } } function focused(event) { event.currentTarget.addEventListener('keydown', keydown); } function blurred(event) { event.currentTarget.removeEventListener('keydown', keydown); } class ClipboardCopyElement extends HTMLElement { constructor() { super(); this.addEventListener('click', clicked); this.addEventListener('focus', focused); this.addEventListener('blur', blurred); } connectedCallback() { if (!this.hasAttribute('tabindex')) { this.setAttribute('tabindex', '0'); } if (!this.hasAttribute('role')) { this.setAttribute('role', 'button'); } } get value() { return this.getAttribute('value') || ''; } set value(text) { this.setAttribute('value', text); } } if (!window.customElements.get('clipboard-copy')) { window.ClipboardCopyElement = ClipboardCopyElement; window.customElements.define('clipboard-copy', ClipboardCopyElement); } return ClipboardCopyElement; })); document.addEventListener('clipboard-copy', function(event) { const notice = event.target.querySelector('.notice') notice.hidden = false setTimeout(function() { notice.hidden = true }, 1000) }) pre { line-height: 125%; } td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } .highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) } .highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) } .highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */ .highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */ .highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */ .highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */ .highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */ .highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */ .highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */ .highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */ .highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */ .highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */ .highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */ .highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */ .highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */ .highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */ .highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */ .highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */ .highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */ .highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */ .highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */ .highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */ .highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */ .highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */ .highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */ .highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */ .highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */ .highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */ .highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */ .highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */ .highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */ .highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */ .highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */ .highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */ .highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */ .highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */ .highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */ .highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */ .highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */ .highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */ .highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */ .highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */ .highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */ @charset \"UTF-8\";.jupyter-wrapper{--md-red-50: #ffebee;--md-red-100: #ffcdd2;--md-red-200: #ef9a9a;--md-red-300: #e57373;--md-red-400: #ef5350;--md-red-500: #f44336;--md-red-600: #e53935;--md-red-700: #d32f2f;--md-red-800: #c62828;--md-red-900: #b71c1c;--md-red-A100: #ff8a80;--md-red-A200: #ff5252;--md-red-A400: #ff1744;--md-red-A700: #d50000;--md-pink-50: #fce4ec;--md-pink-100: #f8bbd0;--md-pink-200: #f48fb1;--md-pink-300: #f06292;--md-pink-400: #ec407a;--md-pink-500: #e91e63;--md-pink-600: #d81b60;--md-pink-700: #c2185b;--md-pink-800: #ad1457;--md-pink-900: #880e4f;--md-pink-A100: #ff80ab;--md-pink-A200: #ff4081;--md-pink-A400: #f50057;--md-pink-A700: #c51162;--md-purple-50: #f3e5f5;--md-purple-100: #e1bee7;--md-purple-200: #ce93d8;--md-purple-300: #ba68c8;--md-purple-400: #ab47bc;--md-purple-500: #9c27b0;--md-purple-600: #8e24aa;--md-purple-700: #7b1fa2;--md-purple-800: #6a1b9a;--md-purple-900: #4a148c;--md-purple-A100: #ea80fc;--md-purple-A200: #e040fb;--md-purple-A400: #d500f9;--md-purple-A700: #aa00ff;--md-deep-purple-50: #ede7f6;--md-deep-purple-100: #d1c4e9;--md-deep-purple-200: #b39ddb;--md-deep-purple-300: #9575cd;--md-deep-purple-400: #7e57c2;--md-deep-purple-500: #673ab7;--md-deep-purple-600: #5e35b1;--md-deep-purple-700: #512da8;--md-deep-purple-800: #4527a0;--md-deep-purple-900: #311b92;--md-deep-purple-A100: #b388ff;--md-deep-purple-A200: #7c4dff;--md-deep-purple-A400: #651fff;--md-deep-purple-A700: #6200ea;--md-indigo-50: #e8eaf6;--md-indigo-100: #c5cae9;--md-indigo-200: #9fa8da;--md-indigo-300: #7986cb;--md-indigo-400: #5c6bc0;--md-indigo-500: #3f51b5;--md-indigo-600: #3949ab;--md-indigo-700: #303f9f;--md-indigo-800: #283593;--md-indigo-900: #1a237e;--md-indigo-A100: #8c9eff;--md-indigo-A200: #536dfe;--md-indigo-A400: #3d5afe;--md-indigo-A700: #304ffe;--md-blue-50: #e3f2fd;--md-blue-100: #bbdefb;--md-blue-200: #90caf9;--md-blue-300: #64b5f6;--md-blue-400: #42a5f5;--md-blue-500: #2196f3;--md-blue-600: #1e88e5;--md-blue-700: #1976d2;--md-blue-800: #1565c0;--md-blue-900: #0d47a1;--md-blue-A100: #82b1ff;--md-blue-A200: #448aff;--md-blue-A400: #2979ff;--md-blue-A700: #2962ff;--md-light-blue-50: #e1f5fe;--md-light-blue-100: #b3e5fc;--md-light-blue-200: #81d4fa;--md-light-blue-300: #4fc3f7;--md-light-blue-400: #29b6f6;--md-light-blue-500: #03a9f4;--md-light-blue-600: #039be5;--md-light-blue-700: #0288d1;--md-light-blue-800: #0277bd;--md-light-blue-900: #01579b;--md-light-blue-A100: #80d8ff;--md-light-blue-A200: #40c4ff;--md-light-blue-A400: #00b0ff;--md-light-blue-A700: #0091ea;--md-cyan-50: #e0f7fa;--md-cyan-100: #b2ebf2;--md-cyan-200: #80deea;--md-cyan-300: #4dd0e1;--md-cyan-400: #26c6da;--md-cyan-500: #00bcd4;--md-cyan-600: #00acc1;--md-cyan-700: #0097a7;--md-cyan-800: #00838f;--md-cyan-900: #006064;--md-cyan-A100: #84ffff;--md-cyan-A200: #18ffff;--md-cyan-A400: #00e5ff;--md-cyan-A700: #00b8d4;--md-teal-50: #e0f2f1;--md-teal-100: #b2dfdb;--md-teal-200: #80cbc4;--md-teal-300: #4db6ac;--md-teal-400: #26a69a;--md-teal-500: #009688;--md-teal-600: #00897b;--md-teal-700: #00796b;--md-teal-800: #00695c;--md-teal-900: #004d40;--md-teal-A100: #a7ffeb;--md-teal-A200: #64ffda;--md-teal-A400: #1de9b6;--md-teal-A700: #00bfa5;--md-green-50: #e8f5e9;--md-green-100: #c8e6c9;--md-green-200: #a5d6a7;--md-green-300: #81c784;--md-green-400: #66bb6a;--md-green-500: #4caf50;--md-green-600: #43a047;--md-green-700: #388e3c;--md-green-800: #2e7d32;--md-green-900: #1b5e20;--md-green-A100: #b9f6ca;--md-green-A200: #69f0ae;--md-green-A400: #00e676;--md-green-A700: #00c853;--md-light-green-50: #f1f8e9;--md-light-green-100: #dcedc8;--md-light-green-200: #c5e1a5;--md-light-green-300: #aed581;--md-light-green-400: #9ccc65;--md-light-green-500: #8bc34a;--md-light-green-600: #7cb342;--md-light-green-700: #689f38;--md-light-green-800: #558b2f;--md-light-green-900: #33691e;--md-light-green-A100: #ccff90;--md-light-green-A200: #b2ff59;--md-light-green-A400: #76ff03;--md-light-green-A700: #64dd17;--md-lime-50: #f9fbe7;--md-lime-100: #f0f4c3;--md-lime-200: #e6ee9c;--md-lime-300: #dce775;--md-lime-400: #d4e157;--md-lime-500: #cddc39;--md-lime-600: #c0ca33;--md-lime-700: #afb42b;--md-lime-800: #9e9d24;--md-lime-900: #827717;--md-lime-A100: #f4ff81;--md-lime-A200: #eeff41;--md-lime-A400: #c6ff00;--md-lime-A700: #aeea00;--md-yellow-50: #fffde7;--md-yellow-100: #fff9c4;--md-yellow-200: #fff59d;--md-yellow-300: #fff176;--md-yellow-400: #ffee58;--md-yellow-500: #ffeb3b;--md-yellow-600: #fdd835;--md-yellow-700: #fbc02d;--md-yellow-800: #f9a825;--md-yellow-900: #f57f17;--md-yellow-A100: #ffff8d;--md-yellow-A200: #ffff00;--md-yellow-A400: #ffea00;--md-yellow-A700: #ffd600;--md-amber-50: #fff8e1;--md-amber-100: #ffecb3;--md-amber-200: #ffe082;--md-amber-300: #ffd54f;--md-amber-400: #ffca28;--md-amber-500: #ffc107;--md-amber-600: #ffb300;--md-amber-700: #ffa000;--md-amber-800: #ff8f00;--md-amber-900: #ff6f00;--md-amber-A100: #ffe57f;--md-amber-A200: #ffd740;--md-amber-A400: #ffc400;--md-amber-A700: #ffab00;--md-orange-50: #fff3e0;--md-orange-100: #ffe0b2;--md-orange-200: #ffcc80;--md-orange-300: #ffb74d;--md-orange-400: #ffa726;--md-orange-500: #ff9800;--md-orange-600: #fb8c00;--md-orange-700: #f57c00;--md-orange-800: #ef6c00;--md-orange-900: #e65100;--md-orange-A100: #ffd180;--md-orange-A200: #ffab40;--md-orange-A400: #ff9100;--md-orange-A700: #ff6d00;--md-deep-orange-50: #fbe9e7;--md-deep-orange-100: #ffccbc;--md-deep-orange-200: #ffab91;--md-deep-orange-300: #ff8a65;--md-deep-orange-400: #ff7043;--md-deep-orange-500: #ff5722;--md-deep-orange-600: #f4511e;--md-deep-orange-700: #e64a19;--md-deep-orange-800: #d84315;--md-deep-orange-900: #bf360c;--md-deep-orange-A100: #ff9e80;--md-deep-orange-A200: #ff6e40;--md-deep-orange-A400: #ff3d00;--md-deep-orange-A700: #dd2c00;--md-brown-50: #efebe9;--md-brown-100: #d7ccc8;--md-brown-200: #bcaaa4;--md-brown-300: #a1887f;--md-brown-400: #8d6e63;--md-brown-500: #795548;--md-brown-600: #6d4c41;--md-brown-700: #5d4037;--md-brown-800: #4e342e;--md-brown-900: #3e2723;--md-grey-50: #fafafa;--md-grey-100: #f5f5f5;--md-grey-200: #eeeeee;--md-grey-300: #e0e0e0;--md-grey-400: #bdbdbd;--md-grey-500: #9e9e9e;--md-grey-600: #757575;--md-grey-700: #616161;--md-grey-800: #424242;--md-grey-900: #212121;--md-blue-grey-50: #eceff1;--md-blue-grey-100: #cfd8dc;--md-blue-grey-200: #b0bec5;--md-blue-grey-300: #90a4ae;--md-blue-grey-400: #78909c;--md-blue-grey-500: #607d8b;--md-blue-grey-600: #546e7a;--md-blue-grey-700: #455a64;--md-blue-grey-800: #37474f;--md-blue-grey-900: #263238}.jupyter-wrapper{--jp-shadow-base-lightness: 0;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-400);--jp-border-color1: var(--md-grey-400);--jp-border-color2: var(--md-grey-300);--jp-border-color3: var(--md-grey-200);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(0, 0, 0, 1);--jp-ui-font-color1: rgba(0, 0, 0, .87);--jp-ui-font-color2: rgba(0, 0, 0, .54);--jp-ui-font-color3: rgba(0, 0, 0, .38);--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color2: rgba(255, 255, 255, .7);--jp-ui-inverse-font-color3: rgba(255, 255, 255, .5);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(0, 0, 0, 1);--jp-content-font-color1: rgba(0, 0, 0, .87);--jp-content-font-color2: rgba(0, 0, 0, .54);--jp-content-font-color3: rgba(0, 0, 0, .38);--jp-content-link-color: var(--md-blue-700);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: white;--jp-layout-color1: white;--jp-layout-color2: var(--md-grey-200);--jp-layout-color3: var(--md-grey-400);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: #111111;--jp-inverse-layout-color1: var(--md-grey-900);--jp-inverse-layout-color2: var(--md-grey-800);--jp-inverse-layout-color3: var(--md-grey-700);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-900);--jp-brand-color1: var(--md-blue-700);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-900);--jp-accent-color1: var(--md-green-700);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-900);--jp-warn-color1: var(--md-orange-700);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-900);--jp-error-color1: var(--md-red-700);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-900);--jp-success-color1: var(--md-green-700);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-900);--jp-info-color1: var(--md-cyan-700);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--md-grey-100);--jp-cell-editor-border-color: var(--md-grey-300);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: .5;--jp-cell-prompt-not-active-font-color: var(--md-grey-700);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: var(--md-blue-50);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: #fdd;--jp-rendermime-table-row-background: var(--md-grey-100);--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);--jp-dialog-background: rgba(0, 0, 0, .25);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color1);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .24);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--md-grey-300);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color1);--jp-input-hover-background: var(--jp-layout-color1);--jp-input-background: var(--md-grey-100);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: #d9d9d9;--jp-editor-selected-focused-background: #d7d4f0;--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: #008000;--jp-mirror-editor-atom-color: #88f;--jp-mirror-editor-number-color: #080;--jp-mirror-editor-def-color: #00f;--jp-mirror-editor-variable-color: var(--md-grey-900);--jp-mirror-editor-variable-2-color: #05a;--jp-mirror-editor-variable-3-color: #085;--jp-mirror-editor-punctuation-color: #05a;--jp-mirror-editor-property-color: #05a;--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ba2121;--jp-mirror-editor-string-2-color: #708;--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: #008000;--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: #170;--jp-mirror-editor-attribute-color: #00c;--jp-mirror-editor-header-color: blue;--jp-mirror-editor-quote-color: #090;--jp-mirror-editor-link-color: #00c;--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ffad8e;--jp-collaborator-color2: #dac83d;--jp-collaborator-color3: #72dd76;--jp-collaborator-color4: #00e4d0;--jp-collaborator-color5: #45d4ff;--jp-collaborator-color6: #e2b1ff;--jp-collaborator-color7: #ff9de6;--jp-vega-background: white;--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .5;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(245, 200, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-700);--jp-console-icon-background-color: var(--md-blue-700);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-800);--jp-terminal-icon-color: var(--md-grey-200);--jp-text-editor-icon-color: var(--md-grey-700);--jp-inspector-icon-color: var(--md-grey-700);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-900)}[data-md-color-scheme=slate] .jupyter-wrapper{--jp-shadow-base-lightness: 32;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-700);--jp-border-color1: var(--md-grey-700);--jp-border-color2: var(--md-grey-800);--jp-border-color3: var(--md-grey-900);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(255, 255, 255, 1);--jp-ui-font-color1: rgba(255, 255, 255, .87);--jp-ui-font-color2: rgba(255, 255, 255, .54);--jp-ui-font-color3: rgba(255, 255, 255, .38);--jp-ui-inverse-font-color0: rgba(0, 0, 0, 1);--jp-ui-inverse-font-color1: rgba(0, 0, 0, .8);--jp-ui-inverse-font-color2: rgba(0, 0, 0, .5);--jp-ui-inverse-font-color3: rgba(0, 0, 0, .3);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(255, 255, 255, 1);--jp-content-font-color1: rgba(255, 255, 255, 1);--jp-content-font-color2: rgba(255, 255, 255, .7);--jp-content-font-color3: rgba(255, 255, 255, .5);--jp-content-link-color: var(--md-blue-300);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: #111111;--jp-layout-color1: var(--md-grey-900);--jp-layout-color2: var(--md-grey-800);--jp-layout-color3: var(--md-grey-700);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: white;--jp-inverse-layout-color1: white;--jp-inverse-layout-color2: var(--md-grey-200);--jp-inverse-layout-color3: var(--md-grey-400);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-700);--jp-brand-color1: var(--md-blue-500);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-700);--jp-accent-color1: var(--md-green-500);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-700);--jp-warn-color1: var(--md-orange-500);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-700);--jp-error-color1: var(--md-red-500);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-700);--jp-success-color1: var(--md-green-500);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-700);--jp-info-color1: var(--md-cyan-500);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--jp-layout-color1);--jp-cell-editor-border-color: var(--md-grey-700);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: 1;--jp-cell-prompt-not-active-font-color: var(--md-grey-300);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: rgba(33, 150, 243, .24);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: rgba(244, 67, 54, .28);--jp-rendermime-table-row-background: var(--md-grey-900);--jp-rendermime-table-row-hover-background: rgba(3, 169, 244, .2);--jp-dialog-background: rgba(0, 0, 0, .6);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color2);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .8);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--jp-layout-color0);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color0);--jp-input-hover-background: var(--jp-layout-color2);--jp-input-background: var(--md-grey-800);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: var(--jp-layout-color2);--jp-editor-selected-focused-background: rgba(33, 150, 243, .24);--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: var(--md-green-500);--jp-mirror-editor-atom-color: var(--md-blue-300);--jp-mirror-editor-number-color: var(--md-green-400);--jp-mirror-editor-def-color: var(--md-blue-600);--jp-mirror-editor-variable-color: var(--md-grey-300);--jp-mirror-editor-variable-2-color: var(--md-blue-400);--jp-mirror-editor-variable-3-color: var(--md-green-600);--jp-mirror-editor-punctuation-color: var(--md-blue-400);--jp-mirror-editor-property-color: var(--md-blue-400);--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ff7070;--jp-mirror-editor-string-2-color: var(--md-purple-300);--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: var(--md-green-600);--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: var(--md-green-700);--jp-mirror-editor-attribute-color: var(--md-blue-700);--jp-mirror-editor-header-color: var(--md-blue-500);--jp-mirror-editor-quote-color: var(--md-green-300);--jp-mirror-editor-link-color: var(--md-blue-700);--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ad4a00;--jp-collaborator-color2: #7b6a00;--jp-collaborator-color3: #007e00;--jp-collaborator-color4: #008772;--jp-collaborator-color5: #0079b9;--jp-collaborator-color6: #8b45c6;--jp-collaborator-color7: #be208b;--jp-vega-background: var(--md-grey-400);--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .6;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(255, 225, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-scrollbar-background-color: #3f4244;--jp-scrollbar-thumb-color: 88, 96, 97;--jp-scrollbar-endpad: 3px;--jp-scrollbar-thumb-margin: 3.5px;--jp-scrollbar-thumb-radius: 9px;--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-500);--jp-console-icon-background-color: var(--md-blue-500);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-200);--jp-terminal-icon-color: var(--md-grey-800);--jp-text-editor-icon-color: var(--md-grey-200);--jp-inspector-icon-color: var(--md-grey-200);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-700)}.jupyter-wrapper [data-jp-theme-scrollbars=true]{scrollbar-color:rgb(var(--jp-scrollbar-thumb-color)) var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar{scrollbar-color:rgba(var(--jp-scrollbar-thumb-color),.5) transparent}.jupyter-wrapper .jp-scrollbar-tiny{scrollbar-color:rgba(var(--jp-scrollbar-thumb-color),.5) transparent;scrollbar-width:thin}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-corner{background:var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-thumb{background:rgb(var(--jp-scrollbar-thumb-color));border:var(--jp-scrollbar-thumb-margin) solid transparent;background-clip:content-box;border-radius:var(--jp-scrollbar-thumb-radius)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-track:horizontal{border-left:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color);border-right:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] ::-webkit-scrollbar-track:vertical{border-top:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color);border-bottom:var(--jp-scrollbar-endpad) solid var(--jp-scrollbar-background-color)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-corner,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-corner{background-color:transparent}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-thumb,.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-thumb{background:rgba(var(--jp-scrollbar-thumb-color),.5);border:var(--jp-scrollbar-thumb-margin) solid transparent;background-clip:content-box;border-radius:var(--jp-scrollbar-thumb-radius)}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-hscrollbar::-webkit-scrollbar-track:horizontal{border-left:var(--jp-scrollbar-endpad) solid transparent;border-right:var(--jp-scrollbar-endpad) solid transparent}.jupyter-wrapper [data-jp-theme-scrollbars=true] .CodeMirror-vscrollbar::-webkit-scrollbar-track:vertical{border-top:var(--jp-scrollbar-endpad) solid transparent;border-bottom:var(--jp-scrollbar-endpad) solid transparent}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar,.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-corner{background-color:transparent;height:4px;width:4px}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-thumb{background:rgba(var(--jp-scrollbar-thumb-color),.5)}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-track:horizontal{border-left:0px solid transparent;border-right:0px solid transparent}.jupyter-wrapper .jp-scrollbar-tiny::-webkit-scrollbar-track:vertical{border-top:0px solid transparent;border-bottom:0px solid transparent}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal]{min-height:16px;max-height:16px;min-width:45px;border-top:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical]{min-width:16px;max-width:16px;min-height:45px;border-left:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar-button{background-color:#f0f0f0;background-position:center center;min-height:15px;max-height:15px;min-width:15px;max-width:15px}.jupyter-wrapper .lm-ScrollBar-button:hover{background-color:#dadada}.jupyter-wrapper .lm-ScrollBar-button.lm-mod-active{background-color:#cdcdcd}.jupyter-wrapper .lm-ScrollBar-track{background:#f0f0f0}.jupyter-wrapper .lm-ScrollBar-thumb{background:#cdcdcd}.jupyter-wrapper .lm-ScrollBar-thumb:hover{background:#bababa}.jupyter-wrapper .lm-ScrollBar-thumb.lm-mod-active{background:#a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-thumb{height:100%;min-width:15px;border-left:1px solid #a0a0a0;border-right:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-thumb{width:100%;min-height:15px;border-top:1px solid #a0a0a0;border-bottom:1px solid #a0a0a0}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-button[data-action=decrement]{background-image:var(--jp-icon-caret-left);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal] .lm-ScrollBar-button[data-action=increment]{background-image:var(--jp-icon-caret-right);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-button[data-action=decrement]{background-image:var(--jp-icon-caret-up);background-size:17px}.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical] .lm-ScrollBar-button[data-action=increment]{background-image:var(--jp-icon-caret-down);background-size:17px}.jupyter-wrapper .p-Widget,.jupyter-wrapper .lm-Widget{box-sizing:border-box;position:relative;overflow:hidden;cursor:default}.jupyter-wrapper .p-Widget.p-mod-hidden,.jupyter-wrapper .lm-Widget.lm-mod-hidden{display:none!important}.jupyter-wrapper .lm-AccordionPanel[data-orientation=horizontal]>.lm-AccordionPanel-title{display:block;transform-origin:top left;transform:rotate(-90deg) translate(-100%)}.jupyter-wrapper .p-CommandPalette,.jupyter-wrapper .lm-CommandPalette{display:flex;flex-direction:column;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-CommandPalette-search,.jupyter-wrapper .lm-CommandPalette-search{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-content,.jupyter-wrapper .lm-CommandPalette-content{flex:1 1 auto;margin:0;padding:0;min-height:0;overflow:auto;list-style-type:none}.jupyter-wrapper .p-CommandPalette-header,.jupyter-wrapper .lm-CommandPalette-header{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .p-CommandPalette-item,.jupyter-wrapper .lm-CommandPalette-item{display:flex;flex-direction:row}.jupyter-wrapper .p-CommandPalette-itemIcon,.jupyter-wrapper .lm-CommandPalette-itemIcon{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-itemContent,.jupyter-wrapper .lm-CommandPalette-itemContent{flex:1 1 auto;overflow:hidden}.jupyter-wrapper .p-CommandPalette-itemShortcut,.jupyter-wrapper .lm-CommandPalette-itemShortcut{flex:0 0 auto}.jupyter-wrapper .p-CommandPalette-itemLabel,.jupyter-wrapper .lm-CommandPalette-itemLabel{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .lm-close-icon{border:1px solid transparent;background-color:transparent;position:absolute;z-index:1;right:3%;top:0;bottom:0;margin:auto;padding:7px 0;display:none;vertical-align:middle;outline:0;cursor:pointer}.jupyter-wrapper .lm-close-icon:after{content:\"X\";display:block;width:15px;height:15px;text-align:center;color:#000;font-weight:400;font-size:12px;cursor:pointer}.jupyter-wrapper .p-DockPanel,.jupyter-wrapper .lm-DockPanel,.jupyter-wrapper .p-DockPanel-widget,.jupyter-wrapper .lm-DockPanel-widget{z-index:0}.jupyter-wrapper .p-DockPanel-tabBar,.jupyter-wrapper .lm-DockPanel-tabBar{z-index:1}.jupyter-wrapper .p-DockPanel-handle,.jupyter-wrapper .lm-DockPanel-handle{z-index:2}.jupyter-wrapper .p-DockPanel-handle.p-mod-hidden,.jupyter-wrapper .lm-DockPanel-handle.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-DockPanel-handle:after,.jupyter-wrapper .lm-DockPanel-handle:after{position:absolute;top:0;left:0;width:100%;height:100%;content:\"\"}.jupyter-wrapper .p-DockPanel-handle[data-orientation=horizontal],.jupyter-wrapper .lm-DockPanel-handle[data-orientation=horizontal]{cursor:ew-resize}.jupyter-wrapper .p-DockPanel-handle[data-orientation=vertical],.jupyter-wrapper .lm-DockPanel-handle[data-orientation=vertical]{cursor:ns-resize}.jupyter-wrapper .p-DockPanel-handle[data-orientation=horizontal]:after,.jupyter-wrapper .lm-DockPanel-handle[data-orientation=horizontal]:after{left:50%;min-width:8px;transform:translate(-50%)}.jupyter-wrapper .p-DockPanel-handle[data-orientation=vertical]:after,.jupyter-wrapper .lm-DockPanel-handle[data-orientation=vertical]:after{top:50%;min-height:8px;transform:translateY(-50%)}.jupyter-wrapper .p-DockPanel-overlay,.jupyter-wrapper .lm-DockPanel-overlay{z-index:3;box-sizing:border-box;pointer-events:none}.jupyter-wrapper .p-DockPanel-overlay.p-mod-hidden,.jupyter-wrapper .lm-DockPanel-overlay.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-Menu,.jupyter-wrapper .lm-Menu{z-index:10000;position:absolute;white-space:nowrap;overflow-x:hidden;overflow-y:auto;outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-Menu-content,.jupyter-wrapper .lm-Menu-content{margin:0;padding:0;display:table;list-style-type:none}.jupyter-wrapper .p-Menu-item,.jupyter-wrapper .lm-Menu-item{display:table-row}.jupyter-wrapper .p-Menu-item.p-mod-hidden,.jupyter-wrapper .p-Menu-item.p-mod-collapsed,.jupyter-wrapper .lm-Menu-item.lm-mod-hidden,.jupyter-wrapper .lm-Menu-item.lm-mod-collapsed{display:none!important}.jupyter-wrapper .p-Menu-itemIcon,.jupyter-wrapper .p-Menu-itemSubmenuIcon,.jupyter-wrapper .lm-Menu-itemIcon,.jupyter-wrapper .lm-Menu-itemSubmenuIcon{display:table-cell;text-align:center}.jupyter-wrapper .p-Menu-itemLabel,.jupyter-wrapper .lm-Menu-itemLabel{display:table-cell;text-align:left}.jupyter-wrapper .p-Menu-itemShortcut,.jupyter-wrapper .lm-Menu-itemShortcut{display:table-cell;text-align:right}.jupyter-wrapper .p-MenuBar,.jupyter-wrapper .lm-MenuBar{outline:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-MenuBar-content,.jupyter-wrapper .lm-MenuBar-content{margin:0;padding:0;display:flex;flex-direction:row;list-style-type:none}.jupyter-wrapper .p--MenuBar-item,.jupyter-wrapper .lm-MenuBar-item{box-sizing:border-box}.jupyter-wrapper .p-MenuBar-itemIcon,.jupyter-wrapper .p-MenuBar-itemLabel,.jupyter-wrapper .lm-MenuBar-itemIcon,.jupyter-wrapper .lm-MenuBar-itemLabel{display:inline-block}.jupyter-wrapper .p-ScrollBar,.jupyter-wrapper .lm-ScrollBar{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-ScrollBar[data-orientation=horizontal],.jupyter-wrapper .lm-ScrollBar[data-orientation=horizontal]{flex-direction:row}.jupyter-wrapper .p-ScrollBar[data-orientation=vertical],.jupyter-wrapper .lm-ScrollBar[data-orientation=vertical]{flex-direction:column}.jupyter-wrapper .p-ScrollBar-button,.jupyter-wrapper .lm-ScrollBar-button{box-sizing:border-box;flex:0 0 auto}.jupyter-wrapper .p-ScrollBar-track,.jupyter-wrapper .lm-ScrollBar-track{box-sizing:border-box;position:relative;overflow:hidden;flex:1 1 auto}.jupyter-wrapper .p-ScrollBar-thumb,.jupyter-wrapper .lm-ScrollBar-thumb{box-sizing:border-box;position:absolute}.jupyter-wrapper .p-SplitPanel-child,.jupyter-wrapper .lm-SplitPanel-child{z-index:0}.jupyter-wrapper .p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel-handle{z-index:1}.jupyter-wrapper .p-SplitPanel-handle.p-mod-hidden,.jupyter-wrapper .lm-SplitPanel-handle.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel-handle:after{position:absolute;top:0;left:0;width:100%;height:100%;content:\"\"}.jupyter-wrapper .p-SplitPanel[data-orientation=horizontal]>.p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel[data-orientation=horizontal]>.lm-SplitPanel-handle{cursor:ew-resize}.jupyter-wrapper .p-SplitPanel[data-orientation=vertical]>.p-SplitPanel-handle,.jupyter-wrapper .lm-SplitPanel[data-orientation=vertical]>.lm-SplitPanel-handle{cursor:ns-resize}.jupyter-wrapper .p-SplitPanel[data-orientation=horizontal]>.p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel[data-orientation=horizontal]>.lm-SplitPanel-handle:after{left:50%;min-width:8px;transform:translate(-50%)}.jupyter-wrapper .p-SplitPanel[data-orientation=vertical]>.p-SplitPanel-handle:after,.jupyter-wrapper .lm-SplitPanel[data-orientation=vertical]>.lm-SplitPanel-handle:after{top:50%;min-height:8px;transform:translateY(-50%)}.jupyter-wrapper .p-TabBar,.jupyter-wrapper .lm-TabBar{display:flex;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .p-TabBar[data-orientation=horizontal],.jupyter-wrapper .lm-TabBar[data-orientation=horizontal]{flex-direction:row;align-items:flex-end}.jupyter-wrapper .p-TabBar[data-orientation=vertical],.jupyter-wrapper .lm-TabBar[data-orientation=vertical]{flex-direction:column;align-items:flex-end}.jupyter-wrapper .p-TabBar-content,.jupyter-wrapper .lm-TabBar-content{margin:0;padding:0;display:flex;flex:1 1 auto;list-style-type:none}.jupyter-wrapper .p-TabBar[data-orientation=horizontal]>.p-TabBar-content,.jupyter-wrapper .lm-TabBar[data-orientation=horizontal]>.lm-TabBar-content{flex-direction:row}.jupyter-wrapper .p-TabBar[data-orientation=vertical]>.p-TabBar-content,.jupyter-wrapper .lm-TabBar[data-orientation=vertical]>.lm-TabBar-content{flex-direction:column}.jupyter-wrapper .p-TabBar-tab,.jupyter-wrapper .lm-TabBar-tab{display:flex;flex-direction:row;box-sizing:border-box;overflow:hidden;touch-action:none}.jupyter-wrapper .p-TabBar-tabIcon,.jupyter-wrapper .p-TabBar-tabCloseIcon,.jupyter-wrapper .lm-TabBar-tabIcon,.jupyter-wrapper .lm-TabBar-tabCloseIcon{flex:0 0 auto}.jupyter-wrapper .p-TabBar-tabLabel,.jupyter-wrapper .lm-TabBar-tabLabel{flex:1 1 auto;overflow:hidden;white-space:nowrap}.jupyter-wrapper .lm-TabBar-tabInput{-webkit-user-select:all;user-select:all;width:100%;box-sizing:border-box}.jupyter-wrapper .p-TabBar-tab.p-mod-hidden,.jupyter-wrapper .lm-TabBar-tab.lm-mod-hidden,.jupyter-wrapper .lm-TabBar-addButton.lm-mod-hidden{display:none!important}.jupyter-wrapper .p-TabBar.p-mod-dragging .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging .lm-TabBar-tab{position:relative}.jupyter-wrapper .p-TabBar.p-mod-dragging[data-orientation=horizontal] .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging[data-orientation=horizontal] .lm-TabBar-tab{left:0;transition:left .15s ease}.jupyter-wrapper .p-TabBar.p-mod-dragging[data-orientation=vertical] .p-TabBar-tab,.jupyter-wrapper .lm-TabBar.lm-mod-dragging[data-orientation=vertical] .lm-TabBar-tab{top:0;transition:top .15s ease}.jupyter-wrapper .p-TabBar.p-mod-dragging .p-TabBar-tab.p-mod-dragging,.jupyter-wrapper .lm-TabBar.lm-mod-dragging .lm-TabBar-tab.lm-mod-dragging{transition:none}.jupyter-wrapper .lm-TabBar-tabLabel .lm-TabBar-tabInput{-webkit-user-select:all;user-select:all;width:100%;box-sizing:border-box;background:inherit}.jupyter-wrapper .p-TabPanel-tabBar,.jupyter-wrapper .lm-TabPanel-tabBar{z-index:1}.jupyter-wrapper .p-TabPanel-stackedPanel,.jupyter-wrapper .lm-TabPanel-stackedPanel{z-index:0}.jupyter-wrapper html{-webkit-box-sizing:border-box;box-sizing:border-box}.jupyter-wrapper *,.jupyter-wrapper *:before,.jupyter-wrapper *:after{-webkit-box-sizing:inherit;box-sizing:inherit}.jupyter-wrapper body{font-size:14px;font-weight:400;letter-spacing:0;line-height:1.28581;text-transform:none;color:#182026;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,Icons16,sans-serif}.jupyter-wrapper p{margin-bottom:10px;margin-top:0}.jupyter-wrapper small{font-size:12px}.jupyter-wrapper strong{font-weight:600}.jupyter-wrapper ::-moz-selection{background:rgba(125,188,255,.6)}.jupyter-wrapper ::selection{background:rgba(125,188,255,.6)}.jupyter-wrapper .bp3-heading{color:#182026;font-weight:600;margin:0 0 10px;padding:0}.jupyter-wrapper .bp3-dark .bp3-heading{color:#f5f8fa}.jupyter-wrapper h1.bp3-heading,.jupyter-wrapper .bp3-running-text h1{font-size:36px;line-height:40px}.jupyter-wrapper h2.bp3-heading,.jupyter-wrapper .bp3-running-text h2{font-size:28px;line-height:32px}.jupyter-wrapper h3.bp3-heading,.jupyter-wrapper .bp3-running-text h3{font-size:22px;line-height:25px}.jupyter-wrapper h4.bp3-heading,.jupyter-wrapper .bp3-running-text h4{font-size:18px;line-height:21px}.jupyter-wrapper h5.bp3-heading,.jupyter-wrapper .bp3-running-text h5{font-size:16px;line-height:19px}.jupyter-wrapper h6.bp3-heading,.jupyter-wrapper .bp3-running-text h6{font-size:14px;line-height:16px}.jupyter-wrapper .bp3-ui-text{font-size:14px;font-weight:400;letter-spacing:0;line-height:1.28581;text-transform:none}.jupyter-wrapper .bp3-monospace-text{font-family:monospace;text-transform:none}.jupyter-wrapper .bp3-text-muted{color:#5c7080}.jupyter-wrapper .bp3-dark .bp3-text-muted{color:#a7b6c2}.jupyter-wrapper .bp3-text-disabled{color:#5c708099}.jupyter-wrapper .bp3-dark .bp3-text-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-text-overflow-ellipsis{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal}.jupyter-wrapper .bp3-running-text{font-size:14px;line-height:1.5}.jupyter-wrapper .bp3-running-text h1{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h1{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h2{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h2{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h3{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h3{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h4{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h4{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h5{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h5{color:#f5f8fa}.jupyter-wrapper .bp3-running-text h6{color:#182026;font-weight:600;margin-bottom:20px;margin-top:40px}.jupyter-wrapper .bp3-dark .bp3-running-text h6{color:#f5f8fa}.jupyter-wrapper .bp3-running-text hr{border:none;border-bottom:1px solid rgba(16,22,26,.15);margin:20px 0}.jupyter-wrapper .bp3-dark .bp3-running-text hr{border-color:#ffffff26}.jupyter-wrapper .bp3-running-text p{margin:0 0 10px;padding:0}.jupyter-wrapper .bp3-text-large{font-size:16px}.jupyter-wrapper .bp3-text-small{font-size:12px}.jupyter-wrapper a .bp3-icon,.jupyter-wrapper a .bp3-icon-standard,.jupyter-wrapper a .bp3-icon-large,.jupyter-wrapper a code,.jupyter-wrapper .bp3-dark a code{color:inherit}.jupyter-wrapper .bp3-dark a,.jupyter-wrapper .bp3-dark a:hover{color:#48aff0}.jupyter-wrapper .bp3-dark a .bp3-icon,.jupyter-wrapper .bp3-dark a .bp3-icon-standard,.jupyter-wrapper .bp3-dark a .bp3-icon-large,.jupyter-wrapper .bp3-dark a:hover .bp3-icon,.jupyter-wrapper .bp3-dark a:hover .bp3-icon-standard,.jupyter-wrapper .bp3-dark a:hover .bp3-icon-large{color:inherit}.jupyter-wrapper .bp3-running-text code,.jupyter-wrapper .bp3-code{font-family:monospace;text-transform:none;background:rgba(255,255,255,.7);border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33;color:#5c7080;font-size:smaller;padding:2px 5px}.jupyter-wrapper .bp3-dark .bp3-running-text code,.jupyter-wrapper .bp3-running-text .bp3-dark code,.jupyter-wrapper .bp3-dark .bp3-code{background:rgba(16,22,26,.3);-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66;color:#a7b6c2}.jupyter-wrapper .bp3-running-text a>code,.jupyter-wrapper a>.bp3-code{color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-running-text a>code,.jupyter-wrapper .bp3-running-text .bp3-dark a>code,.jupyter-wrapper .bp3-dark a>.bp3-code{color:inherit}.jupyter-wrapper .bp3-running-text pre,.jupyter-wrapper .bp3-code-block{font-family:monospace;text-transform:none;background:rgba(255,255,255,.7);border-radius:3px;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26;color:#182026;display:block;font-size:13px;line-height:1.4;margin:10px 0;padding:13px 15px 12px;word-break:break-all;word-wrap:break-word}.jupyter-wrapper .bp3-dark .bp3-running-text pre,.jupyter-wrapper .bp3-running-text .bp3-dark pre,.jupyter-wrapper .bp3-dark .bp3-code-block{background:rgba(16,22,26,.3);-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-running-text pre>code,.jupyter-wrapper .bp3-code-block>code{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit;font-size:inherit;padding:0}.jupyter-wrapper .bp3-running-text kbd,.jupyter-wrapper .bp3-key{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#ffffff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;color:#5c7080;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-family:inherit;font-size:12px;height:24px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;line-height:24px;min-width:24px;padding:3px 6px;vertical-align:middle}.jupyter-wrapper .bp3-running-text kbd .bp3-icon,.jupyter-wrapper .bp3-key .bp3-icon,.jupyter-wrapper .bp3-running-text kbd .bp3-icon-standard,.jupyter-wrapper .bp3-key .bp3-icon-standard,.jupyter-wrapper .bp3-running-text kbd .bp3-icon-large,.jupyter-wrapper .bp3-key .bp3-icon-large{margin-right:5px}.jupyter-wrapper .bp3-dark .bp3-running-text kbd,.jupyter-wrapper .bp3-running-text .bp3-dark kbd,.jupyter-wrapper .bp3-dark .bp3-key{background:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66;color:#a7b6c2}.jupyter-wrapper .bp3-running-text blockquote,.jupyter-wrapper .bp3-blockquote{border-left:solid 4px rgba(167,182,194,.5);margin:0 0 10px;padding:0 20px}.jupyter-wrapper .bp3-dark .bp3-running-text blockquote,.jupyter-wrapper .bp3-running-text .bp3-dark blockquote,.jupyter-wrapper .bp3-dark .bp3-blockquote{border-color:#73869480}.jupyter-wrapper .bp3-running-text ul,.jupyter-wrapper .bp3-running-text ol,.jupyter-wrapper .bp3-list{margin:10px 0;padding-left:30px}.jupyter-wrapper .bp3-running-text ul li:not(:last-child),.jupyter-wrapper .bp3-running-text ol li:not(:last-child),.jupyter-wrapper .bp3-list li:not(:last-child){margin-bottom:5px}.jupyter-wrapper .bp3-running-text ul ol,.jupyter-wrapper .bp3-running-text ol ol,.jupyter-wrapper .bp3-list ol,.jupyter-wrapper .bp3-running-text ul ul,.jupyter-wrapper .bp3-running-text ol ul,.jupyter-wrapper .bp3-list ul{margin-top:5px}.jupyter-wrapper .bp3-list-unstyled{list-style:none;margin:0;padding:0}.jupyter-wrapper .bp3-list-unstyled li{padding:0}.jupyter-wrapper .bp3-rtl{text-align:right}.jupyter-wrapper .bp3-dark{color:#f5f8fa}.jupyter-wrapper :focus{outline:rgba(19,124,189,.6) auto 2px;outline-offset:2px;-moz-outline-radius:6px}.jupyter-wrapper .bp3-focus-disabled :focus{outline:none!important}.jupyter-wrapper .bp3-focus-disabled :focus~.bp3-control-indicator{outline:none!important}.jupyter-wrapper .bp3-alert{max-width:400px;padding:20px}.jupyter-wrapper .bp3-alert-body{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-alert-body .bp3-icon{font-size:40px;margin-right:20px;margin-top:0}.jupyter-wrapper .bp3-alert-contents{word-break:break-word}.jupyter-wrapper .bp3-alert-footer{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse;margin-top:10px}.jupyter-wrapper .bp3-alert-footer .bp3-button{margin-left:10px}.jupyter-wrapper .bp3-breadcrumbs{-webkit-box-align:center;-ms-flex-align:center;align-items:center;cursor:default;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:wrap;flex-wrap:wrap;height:30px;list-style:none;margin:0;padding:0}.jupyter-wrapper .bp3-breadcrumbs>li{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-breadcrumbs>li:after{background:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M10.71 7.29l-4-4a1.003 1.003 0 00-1.42 1.42L8.59 8 5.3 11.29c-.19.18-.3.43-.3.71a1.003 1.003 0 001.71.71l4-4c.18-.18.29-.43.29-.71 0-.28-.11-.53-.29-.71z' fill='%235C7080'/%3e%3c/svg%3e\");content:\"\";display:block;height:16px;margin:0 5px;width:16px}.jupyter-wrapper .bp3-breadcrumbs>li:last-of-type:after{display:none}.jupyter-wrapper .bp3-breadcrumb,.jupyter-wrapper .bp3-breadcrumb-current,.jupyter-wrapper .bp3-breadcrumbs-collapsed{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;font-size:16px}.jupyter-wrapper .bp3-breadcrumb,.jupyter-wrapper .bp3-breadcrumbs-collapsed{color:#5c7080}.jupyter-wrapper .bp3-breadcrumb:hover{text-decoration:none}.jupyter-wrapper .bp3-breadcrumb.bp3-disabled{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-breadcrumb .bp3-icon{margin-right:5px}.jupyter-wrapper .bp3-breadcrumb-current{color:inherit;font-weight:600}.jupyter-wrapper .bp3-breadcrumb-current .bp3-input{font-size:inherit;font-weight:inherit;vertical-align:baseline}.jupyter-wrapper .bp3-breadcrumbs-collapsed{background:#ced9e0;border:none;border-radius:3px;cursor:pointer;margin-right:2px;padding:1px 5px;vertical-align:text-bottom}.jupyter-wrapper .bp3-breadcrumbs-collapsed:before{background:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cg fill='%235C7080'%3e%3ccircle cx='2' cy='8.03' r='2'/%3e%3ccircle cx='14' cy='8.03' r='2'/%3e%3ccircle cx='8' cy='8.03' r='2'/%3e%3c/g%3e%3c/svg%3e\") center no-repeat;content:\"\";display:block;height:16px;width:16px}.jupyter-wrapper .bp3-breadcrumbs-collapsed:hover{background:#bfccd6;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-dark .bp3-breadcrumb,.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs>li:after{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-breadcrumb.bp3-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-breadcrumb-current{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-breadcrumbs-collapsed:hover{background:rgba(16,22,26,.6);color:#f5f8fa}.jupyter-wrapper .bp3-button{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;border-radius:3px;cursor:pointer;font-size:14px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;padding:5px 10px;text-align:left;vertical-align:middle;min-height:30px;min-width:30px}.jupyter-wrapper .bp3-button>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-button>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-button:before,.jupyter-wrapper .bp3-button>*{margin-right:7px}.jupyter-wrapper .bp3-button:empty:before,.jupyter-wrapper .bp3-button>:last-child{margin-right:0}.jupyter-wrapper .bp3-button:empty{padding:0!important}.jupyter-wrapper .bp3-button:disabled,.jupyter-wrapper .bp3-button.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-button.bp3-align-right,.jupyter-wrapper .bp3-align-right .bp3-button{text-align:right}.jupyter-wrapper .bp3-button.bp3-align-left,.jupyter-wrapper .bp3-align-left .bp3-button{text-align:left}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]){background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active:hover,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-button.bp3-intent-primary{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-primary:hover{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-active{background-color:#0e5a8a;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-intent-primary.bp3-disabled{background-color:#137cbd80;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-success{background-color:#0f9960;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-success:hover{background-color:#0d8050;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-active{background-color:#0a6640;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-intent-success.bp3-disabled{background-color:#0f996080;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-warning{background-color:#d9822b;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-warning:hover{background-color:#bf7326;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-active{background-color:#a66321;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-intent-warning.bp3-disabled{background-color:#d9822b80;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button.bp3-intent-danger{background-color:#db3737;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-active{color:#fff}.jupyter-wrapper .bp3-button.bp3-intent-danger:hover{background-color:#c23030;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-active{background-color:#a82a2a;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-intent-danger.bp3-disabled{background-color:#db373780;background-image:none;border-color:transparent;-webkit-box-shadow:none;box-shadow:none;color:#fff9}.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-button-spinner .bp3-spinner-head{stroke:#fff}.jupyter-wrapper .bp3-button.bp3-large,.jupyter-wrapper .bp3-large .bp3-button{min-height:40px;min-width:40px;font-size:16px;padding:5px 15px}.jupyter-wrapper .bp3-button.bp3-large:before,.jupyter-wrapper .bp3-button.bp3-large>*,.jupyter-wrapper .bp3-large .bp3-button:before,.jupyter-wrapper .bp3-large .bp3-button>*{margin-right:10px}.jupyter-wrapper .bp3-button.bp3-large:empty:before,.jupyter-wrapper .bp3-button.bp3-large>:last-child,.jupyter-wrapper .bp3-large .bp3-button:empty:before,.jupyter-wrapper .bp3-large .bp3-button>:last-child{margin-right:0}.jupyter-wrapper .bp3-button.bp3-small,.jupyter-wrapper .bp3-small .bp3-button{min-height:24px;min-width:24px;padding:0 7px}.jupyter-wrapper .bp3-button.bp3-loading{position:relative}.jupyter-wrapper .bp3-button.bp3-loading[class*=bp3-icon-]:before{visibility:hidden}.jupyter-wrapper .bp3-button.bp3-loading .bp3-button-spinner{margin:0;position:absolute}.jupyter-wrapper .bp3-button.bp3-loading>:not(.bp3-button-spinner){visibility:hidden}.jupyter-wrapper .bp3-button[class*=bp3-icon-]:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#5c7080}.jupyter-wrapper .bp3-button .bp3-icon,.jupyter-wrapper .bp3-button .bp3-icon-standard,.jupyter-wrapper .bp3-button .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-button .bp3-icon.bp3-align-right,.jupyter-wrapper .bp3-button .bp3-icon-standard.bp3-align-right,.jupyter-wrapper .bp3-button .bp3-icon-large.bp3-align-right{margin-left:7px}.jupyter-wrapper .bp3-button .bp3-icon:first-child:last-child,.jupyter-wrapper .bp3-button .bp3-spinner+.bp3-icon:last-child{margin:0 -7px}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]){background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):hover,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):disabled,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]):disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]).bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-])[class*=bp3-icon-]:before{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-button:not([class*=bp3-intent-]) .bp3-icon-large{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-],.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:active,.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-].bp3-active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-]:disabled,.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-].bp3-disabled{background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#ffffff4d}.jupyter-wrapper .bp3-dark .bp3-button[class*=bp3-intent-] .bp3-button-spinner .bp3-spinner-head{stroke:#8a9ba8}.jupyter-wrapper .bp3-button:disabled:before,.jupyter-wrapper .bp3-button:disabled .bp3-icon,.jupyter-wrapper .bp3-button:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-button:disabled .bp3-icon-large,.jupyter-wrapper .bp3-button.bp3-disabled:before,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon-standard,.jupyter-wrapper .bp3-button.bp3-disabled .bp3-icon-large,.jupyter-wrapper .bp3-button[class*=bp3-intent-]:before,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon-standard,.jupyter-wrapper .bp3-button[class*=bp3-intent-] .bp3-icon-large{color:inherit!important}.jupyter-wrapper .bp3-button.bp3-minimal{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-button.bp3-minimal:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-button.bp3-minimal:disabled:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-minimal:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-minimal.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-minimal.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined{background:none;-webkit-box-shadow:none;box-shadow:none;border:1px solid rgba(24,32,38,.2);-webkit-box-sizing:border-box;box-sizing:border-box}.jupyter-wrapper .bp3-button.bp3-outlined:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button.bp3-outlined:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-disabled:hover{border-color:#5c70801a}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined{border-color:#fff6}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-disabled:hover{border-color:#fff3}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary{border-color:#106ba399}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{border-color:#106ba333}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary{border-color:#48aff099}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-primary.bp3-disabled{border-color:#48aff033}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success{border-color:#0d805099}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{border-color:#0d805033}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success{border-color:#3dcc9199}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-success.bp3-disabled{border-color:#3dcc9133}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning{border-color:#bf732699}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{border-color:#bf732633}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning{border-color:#ffb36699}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-warning.bp3-disabled{border-color:#ffb36633}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger{border-color:#c2303099}.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{border-color:#c2303033}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger{border-color:#ff737399}.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button.bp3-outlined.bp3-intent-danger.bp3-disabled{border-color:#ff737333}.jupyter-wrapper a.bp3-button{text-align:center;text-decoration:none;-webkit-transition:none;transition:none}.jupyter-wrapper a.bp3-button,.jupyter-wrapper a.bp3-button:hover,.jupyter-wrapper a.bp3-button:active{color:#182026}.jupyter-wrapper a.bp3-button.bp3-disabled{color:#5c708099}.jupyter-wrapper .bp3-button-text{-webkit-box-flex:0;-ms-flex:0 1 auto;flex:0 1 auto}.jupyter-wrapper .bp3-button.bp3-align-left .bp3-button-text,.jupyter-wrapper .bp3-button.bp3-align-right .bp3-button-text,.jupyter-wrapper .bp3-button-group.bp3-align-left .bp3-button-text,.jupyter-wrapper .bp3-button-group.bp3-align-right .bp3-button-text{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex}.jupyter-wrapper .bp3-button-group .bp3-button{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;position:relative;z-index:4}.jupyter-wrapper .bp3-button-group .bp3-button:focus{z-index:5}.jupyter-wrapper .bp3-button-group .bp3-button:hover{z-index:6}.jupyter-wrapper .bp3-button-group .bp3-button:active,.jupyter-wrapper .bp3-button-group .bp3-button.bp3-active{z-index:7}.jupyter-wrapper .bp3-button-group .bp3-button:disabled,.jupyter-wrapper .bp3-button-group .bp3-button.bp3-disabled{z-index:3}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]{z-index:9}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:focus{z-index:10}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:hover{z-index:11}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:active,.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-].bp3-active{z-index:12}.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-]:disabled,.jupyter-wrapper .bp3-button-group .bp3-button[class*=bp3-intent-].bp3-disabled{z-index:8}.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:first-child) .bp3-button,.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0;margin-right:-1px}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button:disabled:hover.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:hover,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-minimal .bp3-button.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-button-group .bp3-popover-wrapper,.jupyter-wrapper .bp3-button-group .bp3-popover-target{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-button-group .bp3-button.bp3-fill,.jupyter-wrapper .bp3-button-group.bp3-fill .bp3-button:not(.bp3-fixed){-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-button-group.bp3-vertical{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;vertical-align:top}.jupyter-wrapper .bp3-button-group.bp3-vertical.bp3-fill{height:100%;width:unset}.jupyter-wrapper .bp3-button-group.bp3-vertical .bp3-button{margin-right:0!important;width:100%}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:first-child .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:first-child{border-radius:3px 3px 0 0}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:last-child .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:last-child{border-radius:0 0 3px 3px}.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-button-group.bp3-vertical:not(.bp3-minimal)>.bp3-button:not(:last-child){margin-bottom:-1px}.jupyter-wrapper .bp3-button-group.bp3-align-left .bp3-button{text-align:left}.jupyter-wrapper .bp3-dark .bp3-button-group:not(.bp3-minimal)>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-dark .bp3-button-group:not(.bp3-minimal)>.bp3-button:not(:last-child){margin-right:1px}.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-vertical>.bp3-popover-wrapper:not(:last-child) .bp3-button,.jupyter-wrapper .bp3-dark .bp3-button-group.bp3-vertical>.bp3-button:not(:last-child){margin-bottom:1px}.jupyter-wrapper .bp3-callout{font-size:14px;line-height:1.5;background-color:#8a9ba826;border-radius:3px;padding:10px 12px 9px;position:relative;width:100%}.jupyter-wrapper .bp3-callout[class*=bp3-icon-]{padding-left:40px}.jupyter-wrapper .bp3-callout[class*=bp3-icon-]:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;color:#5c7080;left:10px;position:absolute;top:10px}.jupyter-wrapper .bp3-callout.bp3-callout-icon{padding-left:40px}.jupyter-wrapper .bp3-callout.bp3-callout-icon>.bp3-icon:first-child{color:#5c7080;left:10px;position:absolute;top:10px}.jupyter-wrapper .bp3-callout .bp3-heading{line-height:20px;margin-bottom:5px;margin-top:0}.jupyter-wrapper .bp3-callout .bp3-heading:last-child{margin-bottom:0}.jupyter-wrapper .bp3-dark .bp3-callout{background-color:#8a9ba833}.jupyter-wrapper .bp3-dark .bp3-callout[class*=bp3-icon-]:before{color:#a7b6c2}.jupyter-wrapper .bp3-callout.bp3-intent-primary{background-color:#137cbd26}.jupyter-wrapper .bp3-callout.bp3-intent-primary[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-primary>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-primary .bp3-heading{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary{background-color:#137cbd40}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-primary .bp3-heading{color:#48aff0}.jupyter-wrapper .bp3-callout.bp3-intent-success{background-color:#0f996026}.jupyter-wrapper .bp3-callout.bp3-intent-success[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-success>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-success .bp3-heading{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success{background-color:#0f996040}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-success .bp3-heading{color:#3dcc91}.jupyter-wrapper .bp3-callout.bp3-intent-warning{background-color:#d9822b26}.jupyter-wrapper .bp3-callout.bp3-intent-warning[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-warning>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-warning .bp3-heading{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning{background-color:#d9822b40}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-warning .bp3-heading{color:#ffb366}.jupyter-wrapper .bp3-callout.bp3-intent-danger{background-color:#db373726}.jupyter-wrapper .bp3-callout.bp3-intent-danger[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-callout.bp3-intent-danger>.bp3-icon:first-child,.jupyter-wrapper .bp3-callout.bp3-intent-danger .bp3-heading{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger{background-color:#db373740}.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger[class*=bp3-icon-]:before,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger>.bp3-icon:first-child,.jupyter-wrapper .bp3-dark .bp3-callout.bp3-intent-danger .bp3-heading{color:#ff7373}.jupyter-wrapper .bp3-running-text .bp3-callout{margin:20px 0}.jupyter-wrapper .bp3-card{background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.15),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a26,0 0 #10161a00,0 0 #10161a00;padding:20px;-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),box-shadow .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),box-shadow .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-card.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a66,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-0{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.15),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a26,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-0.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-0{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),0 0 0 rgba(16,22,26,0),0 0 0 rgba(16,22,26,0);box-shadow:0 0 0 1px #10161a66,0 0 #10161a00,0 0 #10161a00}.jupyter-wrapper .bp3-elevation-1{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33}.jupyter-wrapper .bp3-elevation-1.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-1{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-elevation-2{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 1px 1px rgba(16,22,26,.2),0 2px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 1px 1px #10161a33,0 2px 6px #10161a33}.jupyter-wrapper .bp3-elevation-2.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-2{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.4),0 2px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a66,0 2px 6px #10161a66}.jupyter-wrapper .bp3-elevation-3{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33}.jupyter-wrapper .bp3-elevation-3.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-3{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-elevation-4{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33}.jupyter-wrapper .bp3-elevation-4.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-elevation-4{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66}.jupyter-wrapper .bp3-card.bp3-interactive:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;cursor:pointer}.jupyter-wrapper .bp3-card.bp3-interactive:hover.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card.bp3-interactive:hover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-card.bp3-interactive:active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;opacity:.9;-webkit-transition-duration:0;transition-duration:0}.jupyter-wrapper .bp3-card.bp3-interactive:active.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-card.bp3-interactive:active{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-collapse{height:0;overflow-y:hidden;-webkit-transition:height .2s cubic-bezier(.4,1,.75,.9);transition:height .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-collapse .bp3-collapse-body{-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-collapse .bp3-collapse-body[aria-hidden=true]{display:none}.jupyter-wrapper .bp3-context-menu .bp3-popover-target{display:block}.jupyter-wrapper .bp3-context-menu-popover-target{position:fixed}.jupyter-wrapper .bp3-dialog-container{opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;min-height:100%;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;width:100%}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-enter>.bp3-dialog,.jupyter-wrapper .bp3-dialog-container.bp3-overlay-appear>.bp3-dialog{opacity:0;-webkit-transform:scale(.5);transform:scale(.5)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-enter-active>.bp3-dialog,.jupyter-wrapper .bp3-dialog-container.bp3-overlay-appear-active>.bp3-dialog{opacity:1;-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-exit>.bp3-dialog{opacity:1;-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-dialog-container.bp3-overlay-exit-active>.bp3-dialog{opacity:0;-webkit-transform:scale(.5);transform:scale(.5);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:opacity,transform;transition-property:opacity,transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-dialog{background:#ebf1f5;border-radius:6px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:30px 0;padding-bottom:20px;pointer-events:all;-webkit-user-select:text;-moz-user-select:text;-ms-user-select:text;user-select:text;width:500px}.jupyter-wrapper .bp3-dialog:focus{outline:0}.jupyter-wrapper .bp3-dialog.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-dialog{background:#293742;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dialog-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background:#ffffff;border-radius:6px 6px 0 0;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;min-height:40px;padding-left:20px;padding-right:5px;z-index:30}.jupyter-wrapper .bp3-dialog-header .bp3-icon-large,.jupyter-wrapper .bp3-dialog-header .bp3-icon{color:#5c7080;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-right:10px}.jupyter-wrapper .bp3-dialog-header .bp3-heading{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:inherit;margin:0}.jupyter-wrapper .bp3-dialog-header .bp3-heading:last-child{margin-right:20px}.jupyter-wrapper .bp3-dark .bp3-dialog-header{background:#30404d;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.4);box-shadow:0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-dialog-header .bp3-icon-large,.jupyter-wrapper .bp3-dark .bp3-dialog-header .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dialog-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:18px;margin:20px}.jupyter-wrapper .bp3-dialog-footer{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin:0 20px}.jupyter-wrapper .bp3-dialog-footer-actions{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.jupyter-wrapper .bp3-dialog-footer-actions .bp3-button{margin-left:10px}.jupyter-wrapper .bp3-multistep-dialog-panels{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-multistep-dialog-left-panel{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-left-panel{background:#202b33}.jupyter-wrapper .bp3-multistep-dialog-right-panel{background-color:#f5f8fa;border-left:1px solid rgba(16,22,26,.15);border-radius:0 0 6px;-webkit-box-flex:3;-ms-flex:3;flex:3;min-width:0}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-right-panel{background-color:#293742;border-left:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-multistep-dialog-footer{background-color:#fff;border-radius:0 0 6px;border-top:1px solid rgba(16,22,26,.15);padding:10px}.jupyter-wrapper .bp3-dark .bp3-multistep-dialog-footer{background:#30404d;border-top:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dialog-step-container{background-color:#f5f8fa;border-bottom:1px solid rgba(16,22,26,.15)}.jupyter-wrapper .bp3-dark .bp3-dialog-step-container{background:#293742;border-bottom:1px solid rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dialog-step-container.bp3-dialog-step-viewed{background-color:#fff}.jupyter-wrapper .bp3-dark .bp3-dialog-step-container.bp3-dialog-step-viewed{background:#30404d}.jupyter-wrapper .bp3-dialog-step{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#f5f8fa;border-radius:6px;cursor:not-allowed;display:-webkit-box;display:-ms-flexbox;display:flex;margin:4px;padding:6px 14px}.jupyter-wrapper .bp3-dark .bp3-dialog-step{background:#293742}.jupyter-wrapper .bp3-dialog-step-viewed .bp3-dialog-step{background-color:#fff;cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-dialog-step-viewed .bp3-dialog-step{background:#30404d}.jupyter-wrapper .bp3-dialog-step:hover{background-color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-dialog-step:hover{background:#293742}.jupyter-wrapper .bp3-dialog-step-icon{-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#5c708099;border-radius:50%;color:#fff;display:-webkit-box;display:-ms-flexbox;display:flex;height:25px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;width:25px}.jupyter-wrapper .bp3-dark .bp3-dialog-step-icon{background-color:#a7b6c299}.jupyter-wrapper .bp3-active.bp3-dialog-step-viewed .bp3-dialog-step-icon{background-color:#2b95d6}.jupyter-wrapper .bp3-dialog-step-viewed .bp3-dialog-step-icon{background-color:#8a9ba8}.jupyter-wrapper .bp3-dialog-step-title{color:#5c708099;-webkit-box-flex:1;-ms-flex:1;flex:1;padding-left:10px}.jupyter-wrapper .bp3-dark .bp3-dialog-step-title{color:#a7b6c299}.jupyter-wrapper .bp3-active.bp3-dialog-step-viewed .bp3-dialog-step-title{color:#2b95d6}.jupyter-wrapper .bp3-dialog-step-viewed:not(.bp3-active) .bp3-dialog-step-title{color:#182026}.jupyter-wrapper .bp3-dark .bp3-dialog-step-viewed:not(.bp3-active) .bp3-dialog-step-title{color:#f5f8fa}.jupyter-wrapper .bp3-drawer{background:#ffffff;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0;padding:0}.jupyter-wrapper .bp3-drawer:focus{outline:0}.jupyter-wrapper .bp3-drawer.bp3-position-top{height:50%;left:0;right:0;top:0}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-appear{-webkit-transform:translateY(-100%);transform:translateY(-100%)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer.bp3-position-top.bp3-overlay-exit-active{-webkit-transform:translateY(-100%);transform:translateY(-100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom{bottom:0;height:50%;left:0;right:0}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-appear{-webkit-transform:translateY(100%);transform:translateY(100%)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer.bp3-position-bottom.bp3-overlay-exit-active{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-left{bottom:0;left:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-appear{-webkit-transform:translateX(-100%);transform:translate(-100%)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer.bp3-position-left.bp3-overlay-exit-active{-webkit-transform:translateX(-100%);transform:translate(-100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-right{bottom:0;right:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-appear{-webkit-transform:translateX(100%);transform:translate(100%)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer.bp3-position-right.bp3-overlay-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical){bottom:0;right:0;top:0;width:50%}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-enter,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-appear{-webkit-transform:translateX(100%);transform:translate(100%)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-appear-active{-webkit-transform:translateX(0);transform:translate(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-exit{-webkit-transform:translateX(0);transform:translate(0)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right):not(.bp3-vertical).bp3-overlay-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical{bottom:0;height:50%;left:0;right:0}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-enter,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-appear{-webkit-transform:translateY(100%);transform:translateY(100%)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-enter-active,.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-exit{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-drawer:not(.bp3-position-top):not(.bp3-position-bottom):not(.bp3-position-left):not(.bp3-position-right).bp3-vertical.bp3-overlay-exit-active{-webkit-transform:translateY(100%);transform:translateY(100%);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-drawer.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-drawer{background:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-drawer-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;border-radius:0;-webkit-box-shadow:0 1px 0 rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;min-height:40px;padding:5px 5px 5px 20px;position:relative}.jupyter-wrapper .bp3-drawer-header .bp3-icon-large,.jupyter-wrapper .bp3-drawer-header .bp3-icon{color:#5c7080;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;margin-right:10px}.jupyter-wrapper .bp3-drawer-header .bp3-heading{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:inherit;margin:0}.jupyter-wrapper .bp3-drawer-header .bp3-heading:last-child{margin-right:20px}.jupyter-wrapper .bp3-dark .bp3-drawer-header{-webkit-box-shadow:0 1px 0 rgba(16,22,26,.4);box-shadow:0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-drawer-header .bp3-icon-large,.jupyter-wrapper .bp3-dark .bp3-drawer-header .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-drawer-body{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:18px;overflow:auto}.jupyter-wrapper .bp3-drawer-footer{-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;padding:10px 20px;position:relative}.jupyter-wrapper .bp3-dark .bp3-drawer-footer{-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.4);box-shadow:inset 0 1px #10161a66}.jupyter-wrapper .bp3-editable-text{cursor:text;display:inline-block;max-width:100%;position:relative;vertical-align:top;white-space:nowrap}.jupyter-wrapper .bp3-editable-text:before{bottom:-3px;left:-3px;position:absolute;right:-3px;top:-3px;border-radius:3px;content:\"\";-webkit-transition:background-color .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9),box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-editable-text:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-editable-text.bp3-editable-text-editing:before{background-color:#fff;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-disabled:before{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-primary .bp3-editable-text-content{color:#137cbd}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(19,124,189,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd66}.jupyter-wrapper .bp3-editable-text.bp3-intent-primary.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-success .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-success .bp3-editable-text-content{color:#0f9960}.jupyter-wrapper .bp3-editable-text.bp3-intent-success:hover:before{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px rgba(15,153,96,.4);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f996066}.jupyter-wrapper .bp3-editable-text.bp3-intent-success.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-warning .bp3-editable-text-content{color:#d9822b}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning:hover:before{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px rgba(217,130,43,.4);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b66}.jupyter-wrapper .bp3-editable-text.bp3-intent-warning.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text.bp3-intent-danger .bp3-editable-text-content{color:#db3737}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger:hover:before{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px rgba(219,55,55,.4);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db373766}.jupyter-wrapper .bp3-editable-text.bp3-intent-danger.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-dark .bp3-editable-text:hover:before{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(255,255,255,.15);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #ffffff26}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-editable-text-editing:before{background-color:#10161a4d;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-disabled:before{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary .bp3-editable-text-content{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary:hover:before{-webkit-box-shadow:0 0 0 0 rgba(72,175,240,0),0 0 0 0 rgba(72,175,240,0),inset 0 0 0 1px rgba(72,175,240,.4);box-shadow:0 0 #48aff000,0 0 #48aff000,inset 0 0 0 1px #48aff066}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-primary.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #48aff0,0 0 0 3px rgba(72,175,240,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #48aff0,0 0 0 3px #48aff04d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success .bp3-editable-text-content{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success:hover:before{-webkit-box-shadow:0 0 0 0 rgba(61,204,145,0),0 0 0 0 rgba(61,204,145,0),inset 0 0 0 1px rgba(61,204,145,.4);box-shadow:0 0 #3dcc9100,0 0 #3dcc9100,inset 0 0 0 1px #3dcc9166}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-success.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #3dcc91,0 0 0 3px rgba(61,204,145,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #3dcc91,0 0 0 3px #3dcc914d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning .bp3-editable-text-content{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning:hover:before{-webkit-box-shadow:0 0 0 0 rgba(255,179,102,0),0 0 0 0 rgba(255,179,102,0),inset 0 0 0 1px rgba(255,179,102,.4);box-shadow:0 0 #ffb36600,0 0 #ffb36600,inset 0 0 0 1px #ffb36666}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-warning.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #ffb366,0 0 0 3px rgba(255,179,102,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #ffb366,0 0 0 3px #ffb3664d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger .bp3-editable-text-content{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger:hover:before{-webkit-box-shadow:0 0 0 0 rgba(255,115,115,0),0 0 0 0 rgba(255,115,115,0),inset 0 0 0 1px rgba(255,115,115,.4);box-shadow:0 0 #ff737300,0 0 #ff737300,inset 0 0 0 1px #ff737366}.jupyter-wrapper .bp3-dark .bp3-editable-text.bp3-intent-danger.bp3-editable-text-editing:before{-webkit-box-shadow:0 0 0 1px #ff7373,0 0 0 3px rgba(255,115,115,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #ff7373,0 0 0 3px #ff73734d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-editable-text-input,.jupyter-wrapper .bp3-editable-text-content{color:inherit;display:inherit;font:inherit;letter-spacing:inherit;max-width:inherit;min-width:inherit;position:relative;resize:none;text-transform:inherit;vertical-align:top}.jupyter-wrapper .bp3-editable-text-input{background:none;border:none;-webkit-box-shadow:none;box-shadow:none;padding:0;white-space:pre-wrap;width:100%}.jupyter-wrapper .bp3-editable-text-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-editable-text-input:focus{outline:none}.jupyter-wrapper .bp3-editable-text-input::-ms-clear{display:none}.jupyter-wrapper .bp3-editable-text-content{overflow:hidden;padding-right:2px;text-overflow:ellipsis;white-space:pre}.jupyter-wrapper .bp3-editable-text-editing>.bp3-editable-text-content{left:0;position:absolute;visibility:hidden}.jupyter-wrapper .bp3-editable-text-placeholder>.bp3-editable-text-content{color:#5c708099}.jupyter-wrapper .bp3-dark .bp3-editable-text-placeholder>.bp3-editable-text-content{color:#a7b6c299}.jupyter-wrapper .bp3-editable-text.bp3-multiline{display:block}.jupyter-wrapper .bp3-editable-text.bp3-multiline .bp3-editable-text-content{overflow:auto;white-space:pre-wrap;word-wrap:break-word}.jupyter-wrapper .bp3-divider{border-bottom:1px solid rgba(16,22,26,.15);border-right:1px solid rgba(16,22,26,.15);margin:5px}.jupyter-wrapper .bp3-dark .bp3-divider{border-color:#10161a66}.jupyter-wrapper .bp3-control-group{-webkit-transform:translateZ(0);transform:translateZ(0);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch}.jupyter-wrapper .bp3-control-group>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-control-group>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-control-group .bp3-button,.jupyter-wrapper .bp3-control-group .bp3-html-select,.jupyter-wrapper .bp3-control-group .bp3-input,.jupyter-wrapper .bp3-control-group .bp3-select{position:relative}.jupyter-wrapper .bp3-control-group .bp3-input{border-radius:inherit;z-index:2}.jupyter-wrapper .bp3-control-group .bp3-input:focus{border-radius:3px;z-index:14}.jupyter-wrapper .bp3-control-group .bp3-input[class*=bp3-intent]{z-index:13}.jupyter-wrapper .bp3-control-group .bp3-input[class*=bp3-intent]:focus{z-index:15}.jupyter-wrapper .bp3-control-group .bp3-input[readonly],.jupyter-wrapper .bp3-control-group .bp3-input:disabled,.jupyter-wrapper .bp3-control-group .bp3-input.bp3-disabled{z-index:1}.jupyter-wrapper .bp3-control-group .bp3-input-group[class*=bp3-intent] .bp3-input{z-index:13}.jupyter-wrapper .bp3-control-group .bp3-input-group[class*=bp3-intent] .bp3-input:focus{z-index:15}.jupyter-wrapper .bp3-control-group .bp3-button,.jupyter-wrapper .bp3-control-group .bp3-html-select select,.jupyter-wrapper .bp3-control-group .bp3-select select{-webkit-transform:translateZ(0);transform:translateZ(0);border-radius:inherit;z-index:4}.jupyter-wrapper .bp3-control-group .bp3-button:focus,.jupyter-wrapper .bp3-control-group .bp3-html-select select:focus,.jupyter-wrapper .bp3-control-group .bp3-select select:focus{z-index:5}.jupyter-wrapper .bp3-control-group .bp3-button:hover,.jupyter-wrapper .bp3-control-group .bp3-html-select select:hover,.jupyter-wrapper .bp3-control-group .bp3-select select:hover{z-index:6}.jupyter-wrapper .bp3-control-group .bp3-button:active,.jupyter-wrapper .bp3-control-group .bp3-html-select select:active,.jupyter-wrapper .bp3-control-group .bp3-select select:active{z-index:7}.jupyter-wrapper .bp3-control-group .bp3-button[readonly],.jupyter-wrapper .bp3-control-group .bp3-button:disabled,.jupyter-wrapper .bp3-control-group .bp3-button.bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[readonly],.jupyter-wrapper .bp3-control-group .bp3-html-select select:disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[readonly],.jupyter-wrapper .bp3-control-group .bp3-select select:disabled,.jupyter-wrapper .bp3-control-group .bp3-select select.bp3-disabled{z-index:3}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent],.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent],.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]{z-index:9}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:focus,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:focus,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:focus{z-index:10}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:hover,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:hover,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:hover{z-index:11}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:active,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:active,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:active{z-index:12}.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-button[class*=bp3-intent].bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-html-select select[class*=bp3-intent].bp3-disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent][readonly],.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent]:disabled,.jupyter-wrapper .bp3-control-group .bp3-select select[class*=bp3-intent].bp3-disabled{z-index:8}.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-icon,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-button,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-control-group .bp3-input-group>.bp3-input-action{z-index:16}.jupyter-wrapper .bp3-control-group .bp3-select:after,.jupyter-wrapper .bp3-control-group .bp3-html-select:after,.jupyter-wrapper .bp3-control-group .bp3-select>.bp3-icon,.jupyter-wrapper .bp3-control-group .bp3-html-select>.bp3-icon{z-index:17}.jupyter-wrapper .bp3-control-group .bp3-select:focus-within{z-index:5}.jupyter-wrapper .bp3-control-group:not(.bp3-vertical)>*:not(.bp3-divider){margin-right:-1px}.jupyter-wrapper .bp3-control-group:not(.bp3-vertical)>.bp3-divider:not(:first-child){margin-left:6px}.jupyter-wrapper .bp3-dark .bp3-control-group:not(.bp3-vertical)>*:not(.bp3-divider){margin-right:0}.jupyter-wrapper .bp3-dark .bp3-control-group:not(.bp3-vertical)>.bp3-button+.bp3-button{margin-left:1px}.jupyter-wrapper .bp3-control-group .bp3-popover-wrapper,.jupyter-wrapper .bp3-control-group .bp3-popover-target{border-radius:inherit}.jupyter-wrapper .bp3-control-group>:first-child{border-radius:3px 0 0 3px}.jupyter-wrapper .bp3-control-group>:last-child{border-radius:0 3px 3px 0;margin-right:0}.jupyter-wrapper .bp3-control-group>:only-child{border-radius:3px;margin-right:0}.jupyter-wrapper .bp3-control-group .bp3-input-group .bp3-button{border-radius:3px}.jupyter-wrapper .bp3-control-group .bp3-numeric-input:not(:first-child) .bp3-input-group{border-bottom-left-radius:0;border-top-left-radius:0}.jupyter-wrapper .bp3-control-group.bp3-fill{width:100%}.jupyter-wrapper .bp3-control-group>.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-control-group.bp3-fill>*:not(.bp3-fixed){-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto}.jupyter-wrapper .bp3-control-group.bp3-vertical{-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-control-group.bp3-vertical>*{margin-top:-1px}.jupyter-wrapper .bp3-control-group.bp3-vertical>:first-child{border-radius:3px 3px 0 0;margin-top:0}.jupyter-wrapper .bp3-control-group.bp3-vertical>:last-child{border-radius:0 0 3px 3px}.jupyter-wrapper .bp3-control{cursor:pointer;display:block;margin-bottom:10px;position:relative;text-transform:none}.jupyter-wrapper .bp3-control input:checked~.bp3-control-indicator{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-control:hover input:checked~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-control input:not(:disabled):active:checked~.bp3-control-indicator{background:#0e5a8a;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control input:disabled:checked~.bp3-control-indicator{background:rgba(19,124,189,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-control input:checked~.bp3-control-indicator{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control:hover input:checked~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control input:not(:disabled):active:checked~.bp3-control-indicator{background-color:#0e5a8a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control input:disabled:checked~.bp3-control-indicator{background:rgba(14,90,138,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-control:not(.bp3-align-right){padding-left:26px}.jupyter-wrapper .bp3-control:not(.bp3-align-right) .bp3-control-indicator{margin-left:-26px}.jupyter-wrapper .bp3-control.bp3-align-right{padding-right:26px}.jupyter-wrapper .bp3-control.bp3-align-right .bp3-control-indicator{margin-right:-26px}.jupyter-wrapper .bp3-control.bp3-disabled{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-control.bp3-inline{display:inline-block;margin-right:20px}.jupyter-wrapper .bp3-control input{left:0;opacity:0;position:absolute;top:0;z-index:-1}.jupyter-wrapper .bp3-control .bp3-control-indicator{background-clip:padding-box;background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));border:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;cursor:pointer;display:inline-block;font-size:16px;height:1em;margin-right:10px;margin-top:-3px;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;vertical-align:middle;width:1em}.jupyter-wrapper .bp3-control .bp3-control-indicator:before{content:\"\";display:block;height:1em;width:1em}.jupyter-wrapper .bp3-control:hover .bp3-control-indicator{background-color:#ebf1f5}.jupyter-wrapper .bp3-control input:not(:disabled):active~.bp3-control-indicator{background:#d8e1e8;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control input:disabled~.bp3-control-indicator{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;cursor:not-allowed}.jupyter-wrapper .bp3-control input:focus~.bp3-control-indicator{outline:rgba(19,124,189,.6) auto 2px;outline-offset:2px;-moz-outline-radius:6px}.jupyter-wrapper .bp3-control.bp3-align-right .bp3-control-indicator{float:right;margin-left:10px;margin-top:1px}.jupyter-wrapper .bp3-control.bp3-large{font-size:16px}.jupyter-wrapper .bp3-control.bp3-large:not(.bp3-align-right){padding-left:30px}.jupyter-wrapper .bp3-control.bp3-large:not(.bp3-align-right) .bp3-control-indicator{margin-left:-30px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right{padding-right:30px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right .bp3-control-indicator{margin-right:-30px}.jupyter-wrapper .bp3-control.bp3-large .bp3-control-indicator{font-size:20px}.jupyter-wrapper .bp3-control.bp3-large.bp3-align-right .bp3-control-indicator{margin-top:0}.jupyter-wrapper .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator{background-color:#137cbd;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.1)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.1),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33;color:#fff}.jupyter-wrapper .bp3-control.bp3-checkbox:hover input:indeterminate~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 -1px 0 rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 -1px #10161a33}.jupyter-wrapper .bp3-control.bp3-checkbox input:not(:disabled):active:indeterminate~.bp3-control-indicator{background:#0e5a8a;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{background:rgba(19,124,189,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox:hover input:indeterminate~.bp3-control-indicator{background-color:#106ba3;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:not(:disabled):active:indeterminate~.bp3-control-indicator{background-color:#0e5a8a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a66,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{background:rgba(14,90,138,.5);-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-control.bp3-checkbox .bp3-control-indicator{border-radius:3px}.jupyter-wrapper .bp3-control.bp3-checkbox input:checked~.bp3-control-indicator:before{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M12 5c-.28 0-.53.11-.71.29L7 9.59l-2.29-2.3a1.003 1.003 0 00-1.42 1.42l3 3c.18.18.43.29.71.29s.53-.11.71-.29l5-5A1.003 1.003 0 0012 5z' fill='white'/%3e%3c/svg%3e\")}.jupyter-wrapper .bp3-control.bp3-checkbox input:indeterminate~.bp3-control-indicator:before{background-image:url(\"data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill-rule='evenodd' clip-rule='evenodd' d='M11 7H5c-.55 0-1 .45-1 1s.45 1 1 1h6c.55 0 1-.45 1-1s-.45-1-1-1z' fill='white'/%3e%3c/svg%3e\")}.jupyter-wrapper .bp3-control.bp3-radio .bp3-control-indicator{border-radius:50%}.jupyter-wrapper .bp3-control.bp3-radio input:checked~.bp3-control-indicator:before{background-image:radial-gradient(#ffffff,#ffffff 28%,transparent 32%)}.jupyter-wrapper .bp3-control.bp3-radio input:checked:disabled~.bp3-control-indicator:before{opacity:.5}.jupyter-wrapper .bp3-control.bp3-radio input:focus~.bp3-control-indicator{-moz-outline-radius:16px}.jupyter-wrapper .bp3-control.bp3-switch input~.bp3-control-indicator{background:rgba(167,182,194,.5)}.jupyter-wrapper .bp3-control.bp3-switch:hover input~.bp3-control-indicator{background:rgba(115,134,148,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:not(:disabled):active~.bp3-control-indicator{background:rgba(92,112,128,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:disabled~.bp3-control-indicator{background:rgba(206,217,224,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:disabled~.bp3-control-indicator:before{background:rgba(255,255,255,.8)}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator{background:#137cbd}.jupyter-wrapper .bp3-control.bp3-switch:hover input:checked~.bp3-control-indicator{background:#106ba3}.jupyter-wrapper .bp3-control.bp3-switch input:checked:not(:disabled):active~.bp3-control-indicator{background:#0e5a8a}.jupyter-wrapper .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator{background:rgba(19,124,189,.5)}.jupyter-wrapper .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator:before{background:rgba(255,255,255,.8)}.jupyter-wrapper .bp3-control.bp3-switch:not(.bp3-align-right){padding-left:38px}.jupyter-wrapper .bp3-control.bp3-switch:not(.bp3-align-right) .bp3-control-indicator{margin-left:-38px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-align-right{padding-right:38px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-align-right .bp3-control-indicator{margin-right:-38px}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator{border:none;border-radius:1.75em;-webkit-box-shadow:none!important;box-shadow:none!important;min-width:1.75em;-webkit-transition:background-color .1s cubic-bezier(.4,1,.75,.9);transition:background-color .1s cubic-bezier(.4,1,.75,.9);width:auto}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator:before{background:#ffffff;border-radius:50%;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;height:calc(1em - 4px);left:0;margin:2px;position:absolute;-webkit-transition:left .1s cubic-bezier(.4,1,.75,.9);transition:left .1s cubic-bezier(.4,1,.75,.9);width:calc(1em - 4px)}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator:before{left:calc(100% - 1em)}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large:not(.bp3-align-right){padding-left:45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large:not(.bp3-align-right) .bp3-control-indicator{margin-left:-45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large.bp3-align-right{padding-right:45px}.jupyter-wrapper .bp3-control.bp3-switch.bp3-large.bp3-align-right .bp3-control-indicator{margin-right:-45px}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input~.bp3-control-indicator{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch:hover input~.bp3-control-indicator{background:rgba(16,22,26,.7)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:not(:disabled):active~.bp3-control-indicator{background:rgba(16,22,26,.9)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:disabled~.bp3-control-indicator{background:rgba(57,75,89,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:disabled~.bp3-control-indicator:before{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked~.bp3-control-indicator{background:#137cbd}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch:hover input:checked~.bp3-control-indicator{background:#106ba3}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:not(:disabled):active~.bp3-control-indicator{background:#0e5a8a}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator{background:rgba(14,90,138,.5)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked:disabled~.bp3-control-indicator:before{background:rgba(16,22,26,.4)}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch .bp3-control-indicator:before{background:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control.bp3-switch input:checked~.bp3-control-indicator:before{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-control.bp3-switch .bp3-switch-inner-text{font-size:.7em;text-align:center}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator-child:first-child{line-height:0;margin-left:.5em;margin-right:1.2em;visibility:hidden}.jupyter-wrapper .bp3-control.bp3-switch .bp3-control-indicator-child:last-child{line-height:1em;margin-left:1.2em;margin-right:.5em;visibility:visible}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator .bp3-control-indicator-child:first-child{line-height:1em;visibility:visible}.jupyter-wrapper .bp3-control.bp3-switch input:checked~.bp3-control-indicator .bp3-control-indicator-child:last-child{line-height:0;visibility:hidden}.jupyter-wrapper .bp3-dark .bp3-control{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-control.bp3-disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-control .bp3-control-indicator{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-control:hover .bp3-control-indicator{background-color:#30404d}.jupyter-wrapper .bp3-dark .bp3-control input:not(:disabled):active~.bp3-control-indicator{background:#202b33;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-control input:disabled~.bp3-control-indicator{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:checked~.bp3-control-indicator,.jupyter-wrapper .bp3-dark .bp3-control.bp3-checkbox input:disabled:indeterminate~.bp3-control-indicator{color:#a7b6c299}.jupyter-wrapper .bp3-file-input{cursor:pointer;display:inline-block;height:30px;position:relative}.jupyter-wrapper .bp3-file-input input{margin:0;min-width:200px;opacity:0}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active:hover,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input:after,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-input input:disabled+.bp3-file-upload-input:after .bp3-active,.jupyter-wrapper .bp3-dark .bp3-file-input input.bp3-disabled+.bp3-file-upload-input:after .bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-file-input.bp3-file-input-has-selection .bp3-file-upload-input{color:#182026}.jupyter-wrapper .bp3-dark .bp3-file-input.bp3-file-input-has-selection .bp3-file-upload-input{color:#f5f8fa}.jupyter-wrapper .bp3-file-input.bp3-fill{width:100%}.jupyter-wrapper .bp3-file-input.bp3-large,.jupyter-wrapper .bp3-large .bp3-file-input{height:40px}.jupyter-wrapper .bp3-file-input .bp3-file-upload-input-custom-text:after{content:attr(bp3-button-text)}.jupyter-wrapper .bp3-file-upload-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff;border:none;border-radius:3px;-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33;color:#182026;font-size:14px;font-weight:400;height:30px;line-height:30px;outline:none;padding:0 80px 0 10px;-webkit-transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);vertical-align:middle;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;color:#5c708099;left:0;position:absolute;right:0;top:0;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-file-upload-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-file-upload-input:focus,.jupyter-wrapper .bp3-file-upload-input.bp3-active{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-file-upload-input[type=search],.jupyter-wrapper .bp3-file-upload-input.bp3-round{border-radius:30px;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:10px}.jupyter-wrapper .bp3-file-upload-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-file-upload-input:disabled,.jupyter-wrapper .bp3-file-upload-input.bp3-disabled{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-file-upload-input:after{background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;min-height:24px;min-width:24px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;border-radius:3px;content:\"Browse\";line-height:24px;margin:3px;position:absolute;right:0;text-align:center;top:0;width:70px}.jupyter-wrapper .bp3-file-upload-input:after:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-file-upload-input:after .bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-file-upload-input:after:disabled,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-file-upload-input:after:disabled .bp3-active,.jupyter-wrapper .bp3-file-upload-input:after:disabled .bp3-active:hover,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled.bp3-active,.jupyter-wrapper .bp3-file-upload-input:after .bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-file-upload-input:hover:after{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-file-upload-input:active:after{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-large .bp3-file-upload-input{font-size:16px;height:40px;line-height:40px;padding-right:95px}.jupyter-wrapper .bp3-large .bp3-file-upload-input[type=search],.jupyter-wrapper .bp3-large .bp3-file-upload-input.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-large .bp3-file-upload-input:after{min-height:30px;min-width:30px;line-height:30px;margin:5px;width:85px}.jupyter-wrapper .bp3-dark .bp3-file-upload-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:disabled,.jupyter-wrapper .bp3-dark .bp3-file-upload-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:hover,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:disabled,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after:disabled .bp3-active,.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:after .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:hover:after{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-file-upload-input:active:after{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-file-upload-input:after{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-form-group{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin:0 0 15px}.jupyter-wrapper .bp3-form-group label.bp3-label{margin-bottom:5px}.jupyter-wrapper .bp3-form-group .bp3-control{margin-top:7px}.jupyter-wrapper .bp3-form-group .bp3-form-helper-text{color:#5c7080;font-size:12px;margin-top:5px}.jupyter-wrapper .bp3-form-group.bp3-intent-primary .bp3-form-helper-text{color:#106ba3}.jupyter-wrapper .bp3-form-group.bp3-intent-success .bp3-form-helper-text{color:#0d8050}.jupyter-wrapper .bp3-form-group.bp3-intent-warning .bp3-form-helper-text{color:#bf7326}.jupyter-wrapper .bp3-form-group.bp3-intent-danger .bp3-form-helper-text{color:#c23030}.jupyter-wrapper .bp3-form-group.bp3-inline{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row}.jupyter-wrapper .bp3-form-group.bp3-inline.bp3-large label.bp3-label{line-height:40px;margin:0 10px 0 0}.jupyter-wrapper .bp3-form-group.bp3-inline label.bp3-label{line-height:30px;margin:0 10px 0 0}.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-label,.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-text-muted,.jupyter-wrapper .bp3-form-group.bp3-disabled .bp3-form-helper-text{color:#5c708099!important}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-primary .bp3-form-helper-text{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-success .bp3-form-helper-text{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-warning .bp3-form-helper-text{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-intent-danger .bp3-form-helper-text{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-form-group .bp3-form-helper-text{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-label,.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-text-muted,.jupyter-wrapper .bp3-dark .bp3-form-group.bp3-disabled .bp3-form-helper-text{color:#a7b6c299!important}.jupyter-wrapper .bp3-input-group{display:block;position:relative}.jupyter-wrapper .bp3-input-group .bp3-input{position:relative;width:100%}.jupyter-wrapper .bp3-input-group .bp3-input:not(:first-child){padding-left:30px}.jupyter-wrapper .bp3-input-group .bp3-input:not(:last-child){padding-right:30px}.jupyter-wrapper .bp3-input-group .bp3-input-action,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-input-group>.bp3-button,.jupyter-wrapper .bp3-input-group>.bp3-icon{position:absolute;top:0}.jupyter-wrapper .bp3-input-group .bp3-input-action:first-child,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container:first-child,.jupyter-wrapper .bp3-input-group>.bp3-button:first-child,.jupyter-wrapper .bp3-input-group>.bp3-icon:first-child{left:0}.jupyter-wrapper .bp3-input-group .bp3-input-action:last-child,.jupyter-wrapper .bp3-input-group>.bp3-input-left-container:last-child,.jupyter-wrapper .bp3-input-group>.bp3-button:last-child,.jupyter-wrapper .bp3-input-group>.bp3-icon:last-child{right:0}.jupyter-wrapper .bp3-input-group .bp3-button{min-height:24px;min-width:24px;margin:3px;padding:0 7px}.jupyter-wrapper .bp3-input-group .bp3-button:empty{padding:0}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container,.jupyter-wrapper .bp3-input-group>.bp3-icon{z-index:1}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group>.bp3-icon{color:#5c7080}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon:empty,.jupyter-wrapper .bp3-input-group>.bp3-icon:empty{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.jupyter-wrapper .bp3-input-group>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group>.bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input-action>.bp3-spinner{margin:7px}.jupyter-wrapper .bp3-input-group .bp3-tag{margin:5px}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus),.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus){color:#5c7080}.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus),.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus){color:#a7b6c2}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-large,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:not(:hover):not(:focus) .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled{color:#5c708099!important}.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-button.bp3-minimal:disabled .bp3-icon-large,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon-standard,.jupyter-wrapper .bp3-input-group .bp3-input:not(:focus)+.bp3-input-action .bp3-button.bp3-minimal:disabled .bp3-icon-large{color:#5c708099!important}.jupyter-wrapper .bp3-input-group.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-input-group.bp3-disabled .bp3-icon{color:#5c708099}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-button{min-height:30px;min-width:30px;margin:5px}.jupyter-wrapper .bp3-input-group.bp3-large>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-large>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input-action>.bp3-spinner{margin:12px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input{font-size:16px;height:40px;line-height:40px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input[type=search],.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input:not(:first-child){padding-left:40px}.jupyter-wrapper .bp3-input-group.bp3-large .bp3-input:not(:last-child){padding-right:40px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-button,.jupyter-wrapper .bp3-input-group.bp3-small .bp3-tag{min-height:20px;min-width:20px;margin:2px}.jupyter-wrapper .bp3-input-group.bp3-small>.bp3-input-left-container>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-small>.bp3-icon,.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input-action>.bp3-spinner{margin:4px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input{font-size:12px;height:24px;line-height:24px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input[type=search],.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input.bp3-round{padding:0 12px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input:not(:first-child){padding-left:24px}.jupyter-wrapper .bp3-input-group.bp3-small .bp3-input:not(:last-child){padding-right:24px}.jupyter-wrapper .bp3-input-group.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:100%}.jupyter-wrapper .bp3-input-group.bp3-round .bp3-button,.jupyter-wrapper .bp3-input-group.bp3-round .bp3-input,.jupyter-wrapper .bp3-input-group.bp3-round .bp3-tag{border-radius:30px}.jupyter-wrapper .bp3-dark .bp3-input-group .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-disabled .bp3-icon{color:#a7b6c299}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-primary .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-primary>.bp3-icon{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-primary>.bp3-icon{color:#48aff0}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-success .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-success>.bp3-icon{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-success>.bp3-icon{color:#3dcc91}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-warning .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-warning>.bp3-icon{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-warning>.bp3-icon{color:#ffb366}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input:disabled,.jupyter-wrapper .bp3-input-group.bp3-intent-danger .bp3-input.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input-group.bp3-intent-danger>.bp3-icon{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-input-group.bp3-intent-danger>.bp3-icon{color:#ff7373}.jupyter-wrapper .bp3-input{-webkit-appearance:none;-moz-appearance:none;appearance:none;background:#ffffff;border:none;border-radius:3px;-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33;color:#182026;font-size:14px;font-weight:400;height:30px;line-height:30px;outline:none;padding:0 10px;-webkit-transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9);transition:box-shadow .1s cubic-bezier(.4,1,.75,.9),-webkit-box-shadow .1s cubic-bezier(.4,1,.75,.9);vertical-align:middle}.jupyter-wrapper .bp3-input::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input:focus,.jupyter-wrapper .bp3-input.bp3-active{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input[type=search],.jupyter-wrapper .bp3-input.bp3-round{border-radius:30px;-webkit-box-sizing:border-box;box-sizing:border-box;padding-left:10px}.jupyter-wrapper .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.15);box-shadow:inset 0 0 0 1px #10161a26}.jupyter-wrapper .bp3-input:disabled,.jupyter-wrapper .bp3-input.bp3-disabled{background:rgba(206,217,224,.5);-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;resize:none}.jupyter-wrapper .bp3-input.bp3-large{font-size:16px;height:40px;line-height:40px}.jupyter-wrapper .bp3-input.bp3-large[type=search],.jupyter-wrapper .bp3-input.bp3-large.bp3-round{padding:0 15px}.jupyter-wrapper .bp3-input.bp3-small{font-size:12px;height:24px;line-height:24px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-input.bp3-small[type=search],.jupyter-wrapper .bp3-input.bp3-small.bp3-round{padding:0 12px}.jupyter-wrapper .bp3-input.bp3-fill{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;width:100%}.jupyter-wrapper .bp3-dark .bp3-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-input.bp3-intent-primary{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-primary:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-primary[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-input.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-input.bp3-intent-primary.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary{-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px #137cbd,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #137cbd,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary[readonly]{-webkit-box-shadow:inset 0 0 0 1px #137cbd;box-shadow:inset 0 0 0 1px #137cbd}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-primary.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-success{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-success:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-success[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-input.bp3-intent-success:disabled,.jupyter-wrapper .bp3-input.bp3-intent-success.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success{-webkit-box-shadow:0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),0 0 0 0 rgba(15,153,96,0),inset 0 0 0 1px #0f9960,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #0f996000,0 0 #0f996000,0 0 #0f996000,inset 0 0 0 1px #0f9960,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success:focus{-webkit-box-shadow:0 0 0 1px #0f9960,0 0 0 1px #0f9960,0 0 0 3px rgba(15,153,96,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #0f9960,0 0 0 1px #0f9960,0 0 0 3px #0f99604d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success[readonly]{-webkit-box-shadow:inset 0 0 0 1px #0f9960;box-shadow:inset 0 0 0 1px #0f9960}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-success.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-warning{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-warning:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-warning[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-input.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-input.bp3-intent-warning.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning{-webkit-box-shadow:0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),0 0 0 0 rgba(217,130,43,0),inset 0 0 0 1px #d9822b,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #d9822b00,0 0 #d9822b00,0 0 #d9822b00,inset 0 0 0 1px #d9822b,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning:focus{-webkit-box-shadow:0 0 0 1px #d9822b,0 0 0 1px #d9822b,0 0 0 3px rgba(217,130,43,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #d9822b,0 0 0 1px #d9822b,0 0 0 3px #d9822b4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning[readonly]{-webkit-box-shadow:inset 0 0 0 1px #d9822b;box-shadow:inset 0 0 0 1px #d9822b}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-warning.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input.bp3-intent-danger{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.15),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a26,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-danger:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-input.bp3-intent-danger[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-input.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-input.bp3-intent-danger.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger{-webkit-box-shadow:0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),0 0 0 0 rgba(219,55,55,0),inset 0 0 0 1px #db3737,inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #db373700,0 0 #db373700,0 0 #db373700,inset 0 0 0 1px #db3737,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger:focus{-webkit-box-shadow:0 0 0 1px #db3737,0 0 0 1px #db3737,0 0 0 3px rgba(219,55,55,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #db3737,0 0 0 1px #db3737,0 0 0 3px #db37374d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger[readonly]{-webkit-box-shadow:inset 0 0 0 1px #db3737;box-shadow:inset 0 0 0 1px #db3737}.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-input.bp3-intent-danger.bp3-disabled{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-input::-ms-clear{display:none}.jupyter-wrapper textarea.bp3-input{max-width:100%;padding:10px}.jupyter-wrapper textarea.bp3-input,.jupyter-wrapper textarea.bp3-input.bp3-large,.jupyter-wrapper textarea.bp3-input.bp3-small{height:auto;line-height:inherit}.jupyter-wrapper textarea.bp3-input.bp3-small{padding:8px}.jupyter-wrapper .bp3-dark textarea.bp3-input{background:rgba(16,22,26,.3);-webkit-box-shadow:0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),0 0 0 0 rgba(19,124,189,0),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 #137cbd00,0 0 #137cbd00,0 0 #137cbd00,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark textarea.bp3-input::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark textarea.bp3-input:focus{-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark textarea.bp3-input[readonly]{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark textarea.bp3-input:disabled,.jupyter-wrapper .bp3-dark textarea.bp3-input.bp3-disabled{background:rgba(57,75,89,.5);-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper label.bp3-label{display:block;margin-bottom:15px;margin-top:0}.jupyter-wrapper label.bp3-label .bp3-html-select,.jupyter-wrapper label.bp3-label .bp3-input,.jupyter-wrapper label.bp3-label .bp3-select,.jupyter-wrapper label.bp3-label .bp3-slider,.jupyter-wrapper label.bp3-label .bp3-popover-wrapper{display:block;margin-top:5px;text-transform:none}.jupyter-wrapper label.bp3-label .bp3-button-group{margin-top:5px}.jupyter-wrapper label.bp3-label .bp3-select select,.jupyter-wrapper label.bp3-label .bp3-html-select select{font-weight:400;vertical-align:top;width:100%}.jupyter-wrapper label.bp3-label.bp3-disabled,.jupyter-wrapper label.bp3-label.bp3-disabled .bp3-text-muted{color:#5c708099}.jupyter-wrapper label.bp3-label.bp3-inline{line-height:30px}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-html-select,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input-group,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-select,.jupyter-wrapper label.bp3-label.bp3-inline .bp3-popover-wrapper{display:inline-block;margin:0 0 0 5px;vertical-align:top}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-button-group{margin:0 0 0 5px}.jupyter-wrapper label.bp3-label.bp3-inline .bp3-input-group .bp3-input{margin-left:0}.jupyter-wrapper label.bp3-label.bp3-inline.bp3-large{line-height:40px}.jupyter-wrapper label.bp3-label:not(.bp3-inline) .bp3-popover-target{display:block}.jupyter-wrapper .bp3-dark label.bp3-label{color:#f5f8fa}.jupyter-wrapper .bp3-dark label.bp3-label.bp3-disabled,.jupyter-wrapper .bp3-dark label.bp3-label.bp3-disabled .bp3-text-muted{color:#a7b6c299}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button{-webkit-box-flex:1;-ms-flex:1 1 14px;flex:1 1 14px;min-height:0;padding:0;width:30px}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button:first-child{border-radius:0 3px 0 0}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical>.bp3-button:last-child{border-radius:0 0 3px}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical:first-child>.bp3-button:first-child{border-radius:3px 0 0}.jupyter-wrapper .bp3-numeric-input .bp3-button-group.bp3-vertical:first-child>.bp3-button:last-child{border-radius:0 0 0 3px}.jupyter-wrapper .bp3-numeric-input.bp3-large .bp3-button-group.bp3-vertical>.bp3-button{width:40px}.jupyter-wrapper form{display:block}.jupyter-wrapper .bp3-html-select select,.jupyter-wrapper .bp3-select select{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;border:none;cursor:pointer;font-size:14px;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:left;vertical-align:middle;background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;-moz-appearance:none;-webkit-appearance:none;border-radius:3px;height:30px;padding:0 25px 0 10px;width:100%}.jupyter-wrapper .bp3-html-select select>*,.jupyter-wrapper .bp3-select select>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-html-select select>.bp3-fill,.jupyter-wrapper .bp3-select select>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-html-select select:before,.jupyter-wrapper .bp3-select select:before,.jupyter-wrapper .bp3-html-select select>*,.jupyter-wrapper .bp3-select select>*{margin-right:7px}.jupyter-wrapper .bp3-html-select select:empty:before,.jupyter-wrapper .bp3-select select:empty:before,.jupyter-wrapper .bp3-html-select select>:last-child,.jupyter-wrapper .bp3-select select>:last-child{margin-right:0}.jupyter-wrapper .bp3-html-select select:hover,.jupyter-wrapper .bp3-select select:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-html-select select:active,.jupyter-wrapper .bp3-select select:active,.jupyter-wrapper .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-select select.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-html-select select:disabled,.jupyter-wrapper .bp3-select select:disabled,.jupyter-wrapper .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-select select.bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-html-select select:disabled.bp3-active,.jupyter-wrapper .bp3-select select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select select:disabled.bp3-active:hover,.jupyter-wrapper .bp3-select select:disabled.bp3-active:hover,.jupyter-wrapper .bp3-html-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select select.bp3-disabled.bp3-active:hover,.jupyter-wrapper .bp3-select select.bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-html-select.bp3-minimal select,.jupyter-wrapper .bp3-select.bp3-minimal select{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal select:hover{background:rgba(167,182,194,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026;text-decoration:none}.jupyter-wrapper .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-active{background:rgba(115,134,148,.3);-webkit-box-shadow:none;box-shadow:none;color:#182026}.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled:hover{background:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-disabled:hover.bp3-active{background:rgba(115,134,148,.3)}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select{background:none;-webkit-box-shadow:none;box-shadow:none;color:inherit}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:hover{background:rgba(138,155,168,.15)}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-active{background:rgba(138,155,168,.3);color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled:hover,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled:hover{background:none;color:#a7b6c299;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select:disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-disabled:hover.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-disabled:hover.bp3-active{background:rgba(138,155,168,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:hover{background:rgba(19,124,189,.15);color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#106ba3}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled{background:none;color:#106ba380}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-primary .bp3-button-spinner .bp3-spinner-head{stroke:#106ba3}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:hover{background:rgba(19,124,189,.2);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-active{background:rgba(19,124,189,.3);color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled{background:none;color:#48aff080}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-primary.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-primary.bp3-disabled.bp3-active{background:rgba(19,124,189,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:hover{background:rgba(15,153,96,.15);color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#0d8050}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled{background:none;color:#0d805080}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-success .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-success .bp3-button-spinner .bp3-spinner-head{stroke:#0d8050}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:hover{background:rgba(15,153,96,.2);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-active{background:rgba(15,153,96,.3);color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled{background:none;color:#3dcc9180}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-success.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-success.bp3-disabled.bp3-active{background:rgba(15,153,96,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:hover{background:rgba(217,130,43,.15);color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#bf7326}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled{background:none;color:#bf732680}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-warning .bp3-button-spinner .bp3-spinner-head{stroke:#bf7326}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:hover{background:rgba(217,130,43,.2);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-active{background:rgba(217,130,43,.3);color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled{background:none;color:#ffb36680}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-warning.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-warning.bp3-disabled.bp3-active{background:rgba(217,130,43,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active{background:none;-webkit-box-shadow:none;box-shadow:none;color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:hover{background:rgba(219,55,55,.15);color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#c23030}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled{background:none;color:#c2303080}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-html-select.bp3-minimal select.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-select.bp3-minimal select.bp3-intent-danger .bp3-button-spinner .bp3-spinner-head{stroke:#c23030}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:hover,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:hover{background:rgba(219,55,55,.2);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-active{background:rgba(219,55,55,.3);color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled{background:none;color:#ff737380}.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-html-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select.bp3-minimal select.bp3-intent-danger.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-select.bp3-minimal .bp3-dark select.bp3-intent-danger.bp3-disabled.bp3-active{background:rgba(219,55,55,.3)}.jupyter-wrapper .bp3-html-select.bp3-large select,.jupyter-wrapper .bp3-select.bp3-large select{font-size:16px;height:40px;padding-right:35px}.jupyter-wrapper .bp3-dark .bp3-html-select select,.jupyter-wrapper .bp3-dark .bp3-select select{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select select:hover,.jupyter-wrapper .bp3-dark .bp3-select select:hover,.jupyter-wrapper .bp3-dark .bp3-html-select select:active,.jupyter-wrapper .bp3-dark .bp3-select select:active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select select:hover,.jupyter-wrapper .bp3-dark .bp3-select select:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-html-select select:active,.jupyter-wrapper .bp3-dark .bp3-select select:active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-html-select select:disabled,.jupyter-wrapper .bp3-dark .bp3-select select:disabled,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-disabled,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-html-select select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-html-select select.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-select select.bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-html-select select .bp3-button-spinner .bp3-spinner-head,.jupyter-wrapper .bp3-dark .bp3-select select .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-html-select select:disabled,.jupyter-wrapper .bp3-select select:disabled{background-color:#ced9e080;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-select .bp3-icon,.jupyter-wrapper .bp3-select:after{color:#5c7080;pointer-events:none;position:absolute;right:7px;top:7px}.jupyter-wrapper .bp3-html-select .bp3-disabled.bp3-icon,.jupyter-wrapper .bp3-select .bp3-disabled.bp3-icon,.jupyter-wrapper .bp3-disabled.bp3-select:after{color:#5c708099}.jupyter-wrapper .bp3-html-select,.jupyter-wrapper .bp3-select{display:inline-block;letter-spacing:normal;position:relative;vertical-align:middle}.jupyter-wrapper .bp3-html-select select::-ms-expand,.jupyter-wrapper .bp3-select select::-ms-expand{display:none}.jupyter-wrapper .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-select .bp3-icon{color:#5c7080}.jupyter-wrapper .bp3-html-select .bp3-icon:hover,.jupyter-wrapper .bp3-select .bp3-icon:hover{color:#182026}.jupyter-wrapper .bp3-dark .bp3-html-select .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-select .bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-html-select .bp3-icon:hover,.jupyter-wrapper .bp3-dark .bp3-select .bp3-icon:hover{color:#f5f8fa}.jupyter-wrapper .bp3-html-select.bp3-large:after,.jupyter-wrapper .bp3-html-select.bp3-large .bp3-icon,.jupyter-wrapper .bp3-select.bp3-large:after,.jupyter-wrapper .bp3-select.bp3-large .bp3-icon{right:12px;top:12px}.jupyter-wrapper .bp3-html-select.bp3-fill,.jupyter-wrapper .bp3-html-select.bp3-fill select,.jupyter-wrapper .bp3-select.bp3-fill,.jupyter-wrapper .bp3-select.bp3-fill select{width:100%}.jupyter-wrapper .bp3-dark .bp3-html-select option,.jupyter-wrapper .bp3-dark .bp3-select option{background-color:#30404d;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-html-select option:disabled,.jupyter-wrapper .bp3-dark .bp3-select option:disabled{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-html-select:after,.jupyter-wrapper .bp3-dark .bp3-select:after{color:#a7b6c2}.jupyter-wrapper .bp3-select:after{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;content:\"\ue6c6\"}.jupyter-wrapper .bp3-running-text table,.jupyter-wrapper table.bp3-html-table{border-spacing:0;font-size:14px}.jupyter-wrapper .bp3-running-text table th,.jupyter-wrapper table.bp3-html-table th,.jupyter-wrapper .bp3-running-text table td,.jupyter-wrapper table.bp3-html-table td{padding:11px;text-align:left;vertical-align:top}.jupyter-wrapper .bp3-running-text table th,.jupyter-wrapper table.bp3-html-table th{color:#182026;font-weight:600}.jupyter-wrapper .bp3-running-text table td,.jupyter-wrapper table.bp3-html-table td{color:#182026}.jupyter-wrapper .bp3-running-text table tbody tr:first-child th,.jupyter-wrapper table.bp3-html-table tbody tr:first-child th,.jupyter-wrapper .bp3-running-text table tbody tr:first-child td,.jupyter-wrapper table.bp3-html-table tbody tr:first-child td,.jupyter-wrapper .bp3-running-text table tfoot tr:first-child th,.jupyter-wrapper table.bp3-html-table tfoot tr:first-child th,.jupyter-wrapper .bp3-running-text table tfoot tr:first-child td,.jupyter-wrapper table.bp3-html-table tfoot tr:first-child td{-webkit-box-shadow:inset 0 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26}.jupyter-wrapper .bp3-dark .bp3-running-text table th,.jupyter-wrapper .bp3-running-text .bp3-dark table th,.jupyter-wrapper .bp3-dark table.bp3-html-table th,.jupyter-wrapper .bp3-dark .bp3-running-text table td,.jupyter-wrapper .bp3-running-text .bp3-dark table td,.jupyter-wrapper .bp3-dark table.bp3-html-table td{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-running-text table tbody tr:first-child th,.jupyter-wrapper .bp3-running-text .bp3-dark table tbody tr:first-child th,.jupyter-wrapper .bp3-dark table.bp3-html-table tbody tr:first-child th,.jupyter-wrapper .bp3-dark .bp3-running-text table tbody tr:first-child td,.jupyter-wrapper .bp3-running-text .bp3-dark table tbody tr:first-child td,.jupyter-wrapper .bp3-dark table.bp3-html-table tbody tr:first-child td,.jupyter-wrapper .bp3-dark .bp3-running-text table tfoot tr:first-child th,.jupyter-wrapper .bp3-running-text .bp3-dark table tfoot tr:first-child th,.jupyter-wrapper .bp3-dark table.bp3-html-table tfoot tr:first-child th,.jupyter-wrapper .bp3-dark .bp3-running-text table tfoot tr:first-child td,.jupyter-wrapper .bp3-running-text .bp3-dark table tfoot tr:first-child td,.jupyter-wrapper .bp3-dark table.bp3-html-table tfoot tr:first-child td{-webkit-box-shadow:inset 0 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 0 1px #ffffff26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-condensed th,.jupyter-wrapper table.bp3-html-table.bp3-html-table-condensed td,.jupyter-wrapper table.bp3-html-table.bp3-small th,.jupyter-wrapper table.bp3-html-table.bp3-small td{padding-bottom:6px;padding-top:6px}.jupyter-wrapper table.bp3-html-table.bp3-html-table-striped tbody tr:nth-child(odd) td{background:rgba(191,204,214,.15)}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered th:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 0 #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tbody tr td,.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tfoot tr td{-webkit-box-shadow:inset 0 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tbody tr td:not(:first-child),.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered tfoot tr td:not(:first-child){-webkit-box-shadow:inset 1px 1px 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 1px #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(16,22,26,.15);box-shadow:inset 1px 0 #10161a26}.jupyter-wrapper table.bp3-html-table.bp3-interactive tbody tr:hover td{background-color:#bfccd64d;cursor:pointer}.jupyter-wrapper table.bp3-html-table.bp3-interactive tbody tr:active td{background-color:#bfccd666}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-striped tbody tr:nth-child(odd) td{background:rgba(92,112,128,.15)}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered th:not(:first-child){-webkit-box-shadow:inset 1px 0 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 0 #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tbody tr td,.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tfoot tr td{-webkit-box-shadow:inset 0 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 0 1px #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tbody tr td:not(:first-child),.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered tfoot tr td:not(:first-child){-webkit-box-shadow:inset 1px 1px 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 1px #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td{-webkit-box-shadow:inset 1px 0 0 0 rgba(255,255,255,.15);box-shadow:inset 1px 0 #ffffff26}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-html-table-bordered.bp3-html-table-striped tbody tr:not(:first-child) td:first-child{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-interactive tbody tr:hover td{background-color:#5c70804d;cursor:pointer}.jupyter-wrapper .bp3-dark table.bp3-html-table.bp3-interactive tbody tr:active td{background-color:#5c708066}.jupyter-wrapper .bp3-key-combo{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center}.jupyter-wrapper .bp3-key-combo>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-key-combo>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-key-combo:before,.jupyter-wrapper .bp3-key-combo>*{margin-right:5px}.jupyter-wrapper .bp3-key-combo:empty:before,.jupyter-wrapper .bp3-key-combo>:last-child{margin-right:0}.jupyter-wrapper .bp3-hotkey-dialog{padding-bottom:0;top:40px}.jupyter-wrapper .bp3-hotkey-dialog .bp3-dialog-body{margin:0;padding:0}.jupyter-wrapper .bp3-hotkey-dialog .bp3-hotkey-label{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1}.jupyter-wrapper .bp3-hotkey-column{margin:auto;max-height:80vh;overflow-y:auto;padding:30px}.jupyter-wrapper .bp3-hotkey-column .bp3-heading{margin-bottom:20px}.jupyter-wrapper .bp3-hotkey-column .bp3-heading:not(:first-child){margin-top:40px}.jupyter-wrapper .bp3-hotkey{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;margin-left:0;margin-right:0}.jupyter-wrapper .bp3-hotkey:not(:last-child){margin-bottom:10px}.jupyter-wrapper .bp3-icon{display:inline-block;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;vertical-align:text-bottom}.jupyter-wrapper .bp3-icon:not(:empty):before{content:\"\"!important;content:unset!important}.jupyter-wrapper .bp3-icon>svg{display:block}.jupyter-wrapper .bp3-icon>svg:not([fill]){fill:currentColor}.jupyter-wrapper .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-icon-large.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-icon-large.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-icon-large.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-icon-large.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-dark .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-icon-large.bp3-intent-danger{color:#ff7373}.jupyter-wrapper span.bp3-icon-standard{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block}.jupyter-wrapper span.bp3-icon-large{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;display:inline-block}.jupyter-wrapper span.bp3-icon:empty{font-family:Icons20;font-size:inherit;font-style:normal;font-weight:400;line-height:1}.jupyter-wrapper span.bp3-icon:empty:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased}.jupyter-wrapper .bp3-icon-add:before{content:\"\ue63e\"}.jupyter-wrapper .bp3-icon-add-column-left:before{content:\"\ue6f9\"}.jupyter-wrapper .bp3-icon-add-column-right:before{content:\"\ue6fa\"}.jupyter-wrapper .bp3-icon-add-row-bottom:before{content:\"\ue6f8\"}.jupyter-wrapper .bp3-icon-add-row-top:before{content:\"\ue6f7\"}.jupyter-wrapper .bp3-icon-add-to-artifact:before{content:\"\ue67c\"}.jupyter-wrapper .bp3-icon-add-to-folder:before{content:\"\ue6d2\"}.jupyter-wrapper .bp3-icon-airplane:before{content:\"\ue74b\"}.jupyter-wrapper .bp3-icon-align-center:before{content:\"\ue603\"}.jupyter-wrapper .bp3-icon-align-justify:before{content:\"\ue605\"}.jupyter-wrapper .bp3-icon-align-left:before{content:\"\ue602\"}.jupyter-wrapper .bp3-icon-align-right:before{content:\"\ue604\"}.jupyter-wrapper .bp3-icon-alignment-bottom:before{content:\"\ue727\"}.jupyter-wrapper .bp3-icon-alignment-horizontal-center:before{content:\"\ue726\"}.jupyter-wrapper .bp3-icon-alignment-left:before{content:\"\ue722\"}.jupyter-wrapper .bp3-icon-alignment-right:before{content:\"\ue724\"}.jupyter-wrapper .bp3-icon-alignment-top:before{content:\"\ue725\"}.jupyter-wrapper .bp3-icon-alignment-vertical-center:before{content:\"\ue723\"}.jupyter-wrapper .bp3-icon-annotation:before{content:\"\ue6f0\"}.jupyter-wrapper .bp3-icon-application:before{content:\"\ue735\"}.jupyter-wrapper .bp3-icon-applications:before{content:\"\ue621\"}.jupyter-wrapper .bp3-icon-archive:before{content:\"\ue907\"}.jupyter-wrapper .bp3-icon-arrow-bottom-left:before{content:\"\u2199\"}.jupyter-wrapper .bp3-icon-arrow-bottom-right:before{content:\"\u2198\"}.jupyter-wrapper .bp3-icon-arrow-down:before{content:\"\u2193\"}.jupyter-wrapper .bp3-icon-arrow-left:before{content:\"\u2190\"}.jupyter-wrapper .bp3-icon-arrow-right:before{content:\"\u2192\"}.jupyter-wrapper .bp3-icon-arrow-top-left:before{content:\"\u2196\"}.jupyter-wrapper .bp3-icon-arrow-top-right:before{content:\"\u2197\"}.jupyter-wrapper .bp3-icon-arrow-up:before{content:\"\u2191\"}.jupyter-wrapper .bp3-icon-arrows-horizontal:before{content:\"\u2194\"}.jupyter-wrapper .bp3-icon-arrows-vertical:before{content:\"\u2195\"}.jupyter-wrapper .bp3-icon-asterisk:before{content:\"*\"}.jupyter-wrapper .bp3-icon-automatic-updates:before{content:\"\ue65f\"}.jupyter-wrapper .bp3-icon-badge:before{content:\"\ue6e3\"}.jupyter-wrapper .bp3-icon-ban-circle:before{content:\"\ue69d\"}.jupyter-wrapper .bp3-icon-bank-account:before{content:\"\ue76f\"}.jupyter-wrapper .bp3-icon-barcode:before{content:\"\ue676\"}.jupyter-wrapper .bp3-icon-blank:before{content:\"\ue900\"}.jupyter-wrapper .bp3-icon-blocked-person:before{content:\"\ue768\"}.jupyter-wrapper .bp3-icon-bold:before{content:\"\ue606\"}.jupyter-wrapper .bp3-icon-book:before{content:\"\ue6b8\"}.jupyter-wrapper .bp3-icon-bookmark:before{content:\"\ue61a\"}.jupyter-wrapper .bp3-icon-box:before{content:\"\ue6bf\"}.jupyter-wrapper .bp3-icon-briefcase:before{content:\"\ue674\"}.jupyter-wrapper .bp3-icon-bring-data:before{content:\"\ue90a\"}.jupyter-wrapper .bp3-icon-build:before{content:\"\ue72d\"}.jupyter-wrapper .bp3-icon-calculator:before{content:\"\ue70b\"}.jupyter-wrapper .bp3-icon-calendar:before{content:\"\ue62b\"}.jupyter-wrapper .bp3-icon-camera:before{content:\"\ue69e\"}.jupyter-wrapper .bp3-icon-caret-down:before{content:\"\u2304\"}.jupyter-wrapper .bp3-icon-caret-left:before{content:\"\u2329\"}.jupyter-wrapper .bp3-icon-caret-right:before{content:\"\u232a\"}.jupyter-wrapper .bp3-icon-caret-up:before{content:\"\u2303\"}.jupyter-wrapper .bp3-icon-cell-tower:before{content:\"\ue770\"}.jupyter-wrapper .bp3-icon-MKDOCS_changes:before{content:\"\ue623\"}.jupyter-wrapper .bp3-icon-chart:before{content:\"\ue67e\"}.jupyter-wrapper .bp3-icon-chat:before{content:\"\ue689\"}.jupyter-wrapper .bp3-icon-chevron-backward:before{content:\"\ue6df\"}.jupyter-wrapper .bp3-icon-chevron-down:before{content:\"\ue697\"}.jupyter-wrapper .bp3-icon-chevron-forward:before{content:\"\ue6e0\"}.jupyter-wrapper .bp3-icon-chevron-left:before{content:\"\ue694\"}.jupyter-wrapper .bp3-icon-chevron-right:before{content:\"\ue695\"}.jupyter-wrapper .bp3-icon-chevron-up:before{content:\"\ue696\"}.jupyter-wrapper .bp3-icon-circle:before{content:\"\ue66a\"}.jupyter-wrapper .bp3-icon-circle-arrow-down:before{content:\"\ue68e\"}.jupyter-wrapper .bp3-icon-circle-arrow-left:before{content:\"\ue68c\"}.jupyter-wrapper .bp3-icon-circle-arrow-right:before{content:\"\ue68b\"}.jupyter-wrapper .bp3-icon-circle-arrow-up:before{content:\"\ue68d\"}.jupyter-wrapper .bp3-icon-citation:before{content:\"\ue61b\"}.jupyter-wrapper .bp3-icon-clean:before{content:\"\ue7c5\"}.jupyter-wrapper .bp3-icon-clipboard:before{content:\"\ue61d\"}.jupyter-wrapper .bp3-icon-cloud:before{content:\"\u2601\"}.jupyter-wrapper .bp3-icon-cloud-download:before{content:\"\ue690\"}.jupyter-wrapper .bp3-icon-cloud-upload:before{content:\"\ue691\"}.jupyter-wrapper .bp3-icon-code:before{content:\"\ue661\"}.jupyter-wrapper .bp3-icon-code-block:before{content:\"\ue6c5\"}.jupyter-wrapper .bp3-icon-cog:before{content:\"\ue645\"}.jupyter-wrapper .bp3-icon-collapse-all:before{content:\"\ue763\"}.jupyter-wrapper .bp3-icon-column-layout:before{content:\"\ue6da\"}.jupyter-wrapper .bp3-icon-comment:before{content:\"\ue68a\"}.jupyter-wrapper .bp3-icon-comparison:before{content:\"\ue637\"}.jupyter-wrapper .bp3-icon-compass:before{content:\"\ue79c\"}.jupyter-wrapper .bp3-icon-compressed:before{content:\"\ue6c0\"}.jupyter-wrapper .bp3-icon-confirm:before{content:\"\ue639\"}.jupyter-wrapper .bp3-icon-console:before{content:\"\ue79b\"}.jupyter-wrapper .bp3-icon-contrast:before{content:\"\ue6cb\"}.jupyter-wrapper .bp3-icon-control:before{content:\"\ue67f\"}.jupyter-wrapper .bp3-icon-credit-card:before{content:\"\ue649\"}.jupyter-wrapper .bp3-icon-cross:before{content:\"\u2717\"}.jupyter-wrapper .bp3-icon-crown:before{content:\"\ue7b4\"}.jupyter-wrapper .bp3-icon-cube:before{content:\"\ue7c8\"}.jupyter-wrapper .bp3-icon-cube-add:before{content:\"\ue7c9\"}.jupyter-wrapper .bp3-icon-cube-remove:before{content:\"\ue7d0\"}.jupyter-wrapper .bp3-icon-curved-range-chart:before{content:\"\ue71b\"}.jupyter-wrapper .bp3-icon-cut:before{content:\"\ue6ef\"}.jupyter-wrapper .bp3-icon-dashboard:before{content:\"\ue751\"}.jupyter-wrapper .bp3-icon-data-lineage:before{content:\"\ue908\"}.jupyter-wrapper .bp3-icon-database:before{content:\"\ue683\"}.jupyter-wrapper .bp3-icon-delete:before{content:\"\ue644\"}.jupyter-wrapper .bp3-icon-delta:before{content:\"\u0394\"}.jupyter-wrapper .bp3-icon-derive-column:before{content:\"\ue739\"}.jupyter-wrapper .bp3-icon-desktop:before{content:\"\ue6af\"}.jupyter-wrapper .bp3-icon-diagnosis:before{content:\"\ue90d\"}.jupyter-wrapper .bp3-icon-diagram-tree:before{content:\"\ue7b3\"}.jupyter-wrapper .bp3-icon-direction-left:before{content:\"\ue681\"}.jupyter-wrapper .bp3-icon-direction-right:before{content:\"\ue682\"}.jupyter-wrapper .bp3-icon-disable:before{content:\"\ue600\"}.jupyter-wrapper .bp3-icon-document:before{content:\"\ue630\"}.jupyter-wrapper .bp3-icon-document-open:before{content:\"\ue71e\"}.jupyter-wrapper .bp3-icon-document-share:before{content:\"\ue71f\"}.jupyter-wrapper .bp3-icon-dollar:before{content:\"$\"}.jupyter-wrapper .bp3-icon-dot:before{content:\"\u2022\"}.jupyter-wrapper .bp3-icon-double-caret-horizontal:before{content:\"\ue6c7\"}.jupyter-wrapper .bp3-icon-double-caret-vertical:before{content:\"\ue6c6\"}.jupyter-wrapper .bp3-icon-double-chevron-down:before{content:\"\ue703\"}.jupyter-wrapper .bp3-icon-double-chevron-left:before{content:\"\ue6ff\"}.jupyter-wrapper .bp3-icon-double-chevron-right:before{content:\"\ue701\"}.jupyter-wrapper .bp3-icon-double-chevron-up:before{content:\"\ue702\"}.jupyter-wrapper .bp3-icon-doughnut-chart:before{content:\"\ue6ce\"}.jupyter-wrapper .bp3-icon-download:before{content:\"\ue62f\"}.jupyter-wrapper .bp3-icon-drag-handle-horizontal:before{content:\"\ue716\"}.jupyter-wrapper .bp3-icon-drag-handle-vertical:before{content:\"\ue715\"}.jupyter-wrapper .bp3-icon-draw:before{content:\"\ue66b\"}.jupyter-wrapper .bp3-icon-drive-time:before{content:\"\ue615\"}.jupyter-wrapper .bp3-icon-duplicate:before{content:\"\ue69c\"}.jupyter-wrapper .bp3-icon-edit:before{content:\"\u270e\"}.jupyter-wrapper .bp3-icon-eject:before{content:\"\u23cf\"}.jupyter-wrapper .bp3-icon-endorsed:before{content:\"\ue75f\"}.jupyter-wrapper .bp3-icon-envelope:before{content:\"\u2709\"}.jupyter-wrapper .bp3-icon-equals:before{content:\"\ue7d9\"}.jupyter-wrapper .bp3-icon-eraser:before{content:\"\ue773\"}.jupyter-wrapper .bp3-icon-error:before{content:\"\ue648\"}.jupyter-wrapper .bp3-icon-euro:before{content:\"\u20ac\"}.jupyter-wrapper .bp3-icon-MKDOCS_exchange:before{content:\"\ue636\"}.jupyter-wrapper .bp3-icon-exclude-row:before{content:\"\ue6ea\"}.jupyter-wrapper .bp3-icon-expand-all:before{content:\"\ue764\"}.jupyter-wrapper .bp3-icon-export:before{content:\"\ue633\"}.jupyter-wrapper .bp3-icon-eye-off:before{content:\"\ue6cc\"}.jupyter-wrapper .bp3-icon-eye-on:before{content:\"\ue75a\"}.jupyter-wrapper .bp3-icon-eye-open:before{content:\"\ue66f\"}.jupyter-wrapper .bp3-icon-fast-backward:before{content:\"\ue6a8\"}.jupyter-wrapper .bp3-icon-fast-forward:before{content:\"\ue6ac\"}.jupyter-wrapper .bp3-icon-feed:before{content:\"\ue656\"}.jupyter-wrapper .bp3-icon-feed-subscribed:before{content:\"\ue78f\"}.jupyter-wrapper .bp3-icon-film:before{content:\"\ue6a1\"}.jupyter-wrapper .bp3-icon-filter:before{content:\"\ue638\"}.jupyter-wrapper .bp3-icon-filter-keep:before{content:\"\ue78c\"}.jupyter-wrapper .bp3-icon-filter-list:before{content:\"\ue6ee\"}.jupyter-wrapper .bp3-icon-filter-open:before{content:\"\ue7d7\"}.jupyter-wrapper .bp3-icon-filter-remove:before{content:\"\ue78d\"}.jupyter-wrapper .bp3-icon-flag:before{content:\"\u2691\"}.jupyter-wrapper .bp3-icon-flame:before{content:\"\ue7a9\"}.jupyter-wrapper .bp3-icon-flash:before{content:\"\ue6b3\"}.jupyter-wrapper .bp3-icon-floppy-disk:before{content:\"\ue6b7\"}.jupyter-wrapper .bp3-icon-flow-branch:before{content:\"\ue7c1\"}.jupyter-wrapper .bp3-icon-flow-end:before{content:\"\ue7c4\"}.jupyter-wrapper .bp3-icon-flow-linear:before{content:\"\ue7c0\"}.jupyter-wrapper .bp3-icon-flow-review:before{content:\"\ue7c2\"}.jupyter-wrapper .bp3-icon-flow-review-branch:before{content:\"\ue7c3\"}.jupyter-wrapper .bp3-icon-flows:before{content:\"\ue659\"}.jupyter-wrapper .bp3-icon-folder-close:before{content:\"\ue652\"}.jupyter-wrapper .bp3-icon-folder-new:before{content:\"\ue7b0\"}.jupyter-wrapper .bp3-icon-folder-open:before{content:\"\ue651\"}.jupyter-wrapper .bp3-icon-folder-shared:before{content:\"\ue653\"}.jupyter-wrapper .bp3-icon-folder-shared-open:before{content:\"\ue670\"}.jupyter-wrapper .bp3-icon-follower:before{content:\"\ue760\"}.jupyter-wrapper .bp3-icon-following:before{content:\"\ue761\"}.jupyter-wrapper .bp3-icon-font:before{content:\"\ue6b4\"}.jupyter-wrapper .bp3-icon-fork:before{content:\"\ue63a\"}.jupyter-wrapper .bp3-icon-form:before{content:\"\ue795\"}.jupyter-wrapper .bp3-icon-full-circle:before{content:\"\ue685\"}.jupyter-wrapper .bp3-icon-full-stacked-chart:before{content:\"\ue75e\"}.jupyter-wrapper .bp3-icon-fullscreen:before{content:\"\ue699\"}.jupyter-wrapper .bp3-icon-function:before{content:\"\ue6e5\"}.jupyter-wrapper .bp3-icon-gantt-chart:before{content:\"\ue6f4\"}.jupyter-wrapper .bp3-icon-geolocation:before{content:\"\ue640\"}.jupyter-wrapper .bp3-icon-geosearch:before{content:\"\ue613\"}.jupyter-wrapper .bp3-icon-git-branch:before{content:\"\ue72a\"}.jupyter-wrapper .bp3-icon-git-commit:before{content:\"\ue72b\"}.jupyter-wrapper .bp3-icon-git-merge:before{content:\"\ue729\"}.jupyter-wrapper .bp3-icon-git-new-branch:before{content:\"\ue749\"}.jupyter-wrapper .bp3-icon-git-pull:before{content:\"\ue728\"}.jupyter-wrapper .bp3-icon-git-push:before{content:\"\ue72c\"}.jupyter-wrapper .bp3-icon-git-repo:before{content:\"\ue748\"}.jupyter-wrapper .bp3-icon-glass:before{content:\"\ue6b1\"}.jupyter-wrapper .bp3-icon-globe:before{content:\"\ue666\"}.jupyter-wrapper .bp3-icon-globe-network:before{content:\"\ue7b5\"}.jupyter-wrapper .bp3-icon-graph:before{content:\"\ue673\"}.jupyter-wrapper .bp3-icon-graph-remove:before{content:\"\ue609\"}.jupyter-wrapper .bp3-icon-greater-than:before{content:\"\ue7e1\"}.jupyter-wrapper .bp3-icon-greater-than-or-equal-to:before{content:\"\ue7e2\"}.jupyter-wrapper .bp3-icon-grid:before{content:\"\ue6d0\"}.jupyter-wrapper .bp3-icon-grid-view:before{content:\"\ue6e4\"}.jupyter-wrapper .bp3-icon-group-objects:before{content:\"\ue60a\"}.jupyter-wrapper .bp3-icon-grouped-bar-chart:before{content:\"\ue75d\"}.jupyter-wrapper .bp3-icon-hand:before{content:\"\ue6de\"}.jupyter-wrapper .bp3-icon-hand-down:before{content:\"\ue6bb\"}.jupyter-wrapper .bp3-icon-hand-left:before{content:\"\ue6bc\"}.jupyter-wrapper .bp3-icon-hand-right:before{content:\"\ue6b9\"}.jupyter-wrapper .bp3-icon-hand-up:before{content:\"\ue6ba\"}.jupyter-wrapper .bp3-icon-header:before{content:\"\ue6b5\"}.jupyter-wrapper .bp3-icon-header-one:before{content:\"\ue793\"}.jupyter-wrapper .bp3-icon-header-two:before{content:\"\ue794\"}.jupyter-wrapper .bp3-icon-headset:before{content:\"\ue6dc\"}.jupyter-wrapper .bp3-icon-heart:before{content:\"\u2665\"}.jupyter-wrapper .bp3-icon-heart-broken:before{content:\"\ue7a2\"}.jupyter-wrapper .bp3-icon-heat-grid:before{content:\"\ue6f3\"}.jupyter-wrapper .bp3-icon-heatmap:before{content:\"\ue614\"}.jupyter-wrapper .bp3-icon-help:before{content:\"?\"}.jupyter-wrapper .bp3-icon-helper-management:before{content:\"\ue66d\"}.jupyter-wrapper .bp3-icon-highlight:before{content:\"\ue6ed\"}.jupyter-wrapper .bp3-icon-history:before{content:\"\ue64a\"}.jupyter-wrapper .bp3-icon-home:before{content:\"\u2302\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart:before{content:\"\ue70c\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart-asc:before{content:\"\ue75c\"}.jupyter-wrapper .bp3-icon-horizontal-bar-chart-desc:before{content:\"\ue71d\"}.jupyter-wrapper .bp3-icon-horizontal-distribution:before{content:\"\ue720\"}.jupyter-wrapper .bp3-icon-id-number:before{content:\"\ue771\"}.jupyter-wrapper .bp3-icon-image-rotate-left:before{content:\"\ue73a\"}.jupyter-wrapper .bp3-icon-image-rotate-right:before{content:\"\ue73b\"}.jupyter-wrapper .bp3-icon-import:before{content:\"\ue632\"}.jupyter-wrapper .bp3-icon-inbox:before{content:\"\ue629\"}.jupyter-wrapper .bp3-icon-inbox-filtered:before{content:\"\ue7d1\"}.jupyter-wrapper .bp3-icon-inbox-geo:before{content:\"\ue7d2\"}.jupyter-wrapper .bp3-icon-inbox-search:before{content:\"\ue7d3\"}.jupyter-wrapper .bp3-icon-inbox-update:before{content:\"\ue7d4\"}.jupyter-wrapper .bp3-icon-info-sign:before{content:\"\u2139\"}.jupyter-wrapper .bp3-icon-inheritance:before{content:\"\ue7d5\"}.jupyter-wrapper .bp3-icon-inner-join:before{content:\"\ue7a3\"}.jupyter-wrapper .bp3-icon-insert:before{content:\"\ue66c\"}.jupyter-wrapper .bp3-icon-intersection:before{content:\"\ue765\"}.jupyter-wrapper .bp3-icon-ip-address:before{content:\"\ue772\"}.jupyter-wrapper .bp3-icon-issue:before{content:\"\ue774\"}.jupyter-wrapper .bp3-icon-issue-closed:before{content:\"\ue776\"}.jupyter-wrapper .bp3-icon-issue-new:before{content:\"\ue775\"}.jupyter-wrapper .bp3-icon-italic:before{content:\"\ue607\"}.jupyter-wrapper .bp3-icon-join-table:before{content:\"\ue738\"}.jupyter-wrapper .bp3-icon-key:before{content:\"\ue78e\"}.jupyter-wrapper .bp3-icon-key-backspace:before{content:\"\ue707\"}.jupyter-wrapper .bp3-icon-key-command:before{content:\"\ue705\"}.jupyter-wrapper .bp3-icon-key-control:before{content:\"\ue704\"}.jupyter-wrapper .bp3-icon-key-delete:before{content:\"\ue708\"}.jupyter-wrapper .bp3-icon-key-enter:before{content:\"\ue70a\"}.jupyter-wrapper .bp3-icon-key-escape:before{content:\"\ue709\"}.jupyter-wrapper .bp3-icon-key-option:before{content:\"\ue742\"}.jupyter-wrapper .bp3-icon-key-shift:before{content:\"\ue706\"}.jupyter-wrapper .bp3-icon-key-tab:before{content:\"\ue757\"}.jupyter-wrapper .bp3-icon-known-vehicle:before{content:\"\ue73c\"}.jupyter-wrapper .bp3-icon-lab-test:before{content:\"\ue90e\"}.jupyter-wrapper .bp3-icon-label:before{content:\"\ue665\"}.jupyter-wrapper .bp3-icon-layer:before{content:\"\ue6cf\"}.jupyter-wrapper .bp3-icon-layers:before{content:\"\ue618\"}.jupyter-wrapper .bp3-icon-layout:before{content:\"\ue60c\"}.jupyter-wrapper .bp3-icon-layout-auto:before{content:\"\ue60d\"}.jupyter-wrapper .bp3-icon-layout-balloon:before{content:\"\ue6d3\"}.jupyter-wrapper .bp3-icon-layout-circle:before{content:\"\ue60e\"}.jupyter-wrapper .bp3-icon-layout-grid:before{content:\"\ue610\"}.jupyter-wrapper .bp3-icon-layout-group-by:before{content:\"\ue611\"}.jupyter-wrapper .bp3-icon-layout-hierarchy:before{content:\"\ue60f\"}.jupyter-wrapper .bp3-icon-layout-linear:before{content:\"\ue6c3\"}.jupyter-wrapper .bp3-icon-layout-skew-grid:before{content:\"\ue612\"}.jupyter-wrapper .bp3-icon-layout-sorted-clusters:before{content:\"\ue6d4\"}.jupyter-wrapper .bp3-icon-learning:before{content:\"\ue904\"}.jupyter-wrapper .bp3-icon-left-join:before{content:\"\ue7a4\"}.jupyter-wrapper .bp3-icon-less-than:before{content:\"\ue7e3\"}.jupyter-wrapper .bp3-icon-less-than-or-equal-to:before{content:\"\ue7e4\"}.jupyter-wrapper .bp3-icon-lifesaver:before{content:\"\ue7c7\"}.jupyter-wrapper .bp3-icon-lightbulb:before{content:\"\ue6b0\"}.jupyter-wrapper .bp3-icon-link:before{content:\"\ue62d\"}.jupyter-wrapper .bp3-icon-list:before{content:\"\u2630\"}.jupyter-wrapper .bp3-icon-list-columns:before{content:\"\ue7b9\"}.jupyter-wrapper .bp3-icon-list-detail-view:before{content:\"\ue743\"}.jupyter-wrapper .bp3-icon-locate:before{content:\"\ue619\"}.jupyter-wrapper .bp3-icon-lock:before{content:\"\ue625\"}.jupyter-wrapper .bp3-icon-log-in:before{content:\"\ue69a\"}.jupyter-wrapper .bp3-icon-log-out:before{content:\"\ue64c\"}.jupyter-wrapper .bp3-icon-manual:before{content:\"\ue6f6\"}.jupyter-wrapper .bp3-icon-manually-entered-data:before{content:\"\ue74a\"}.jupyter-wrapper .bp3-icon-map:before{content:\"\ue662\"}.jupyter-wrapper .bp3-icon-map-create:before{content:\"\ue741\"}.jupyter-wrapper .bp3-icon-map-marker:before{content:\"\ue67d\"}.jupyter-wrapper .bp3-icon-maximize:before{content:\"\ue635\"}.jupyter-wrapper .bp3-icon-media:before{content:\"\ue62c\"}.jupyter-wrapper .bp3-icon-menu:before{content:\"\ue762\"}.jupyter-wrapper .bp3-icon-menu-closed:before{content:\"\ue655\"}.jupyter-wrapper .bp3-icon-menu-open:before{content:\"\ue654\"}.jupyter-wrapper .bp3-icon-merge-columns:before{content:\"\ue74f\"}.jupyter-wrapper .bp3-icon-merge-links:before{content:\"\ue60b\"}.jupyter-wrapper .bp3-icon-minimize:before{content:\"\ue634\"}.jupyter-wrapper .bp3-icon-minus:before{content:\"\u2212\"}.jupyter-wrapper .bp3-icon-mobile-phone:before{content:\"\ue717\"}.jupyter-wrapper .bp3-icon-mobile-video:before{content:\"\ue69f\"}.jupyter-wrapper .bp3-icon-moon:before{content:\"\ue754\"}.jupyter-wrapper .bp3-icon-more:before{content:\"\ue62a\"}.jupyter-wrapper .bp3-icon-mountain:before{content:\"\ue7b1\"}.jupyter-wrapper .bp3-icon-move:before{content:\"\ue693\"}.jupyter-wrapper .bp3-icon-mugshot:before{content:\"\ue6db\"}.jupyter-wrapper .bp3-icon-multi-select:before{content:\"\ue680\"}.jupyter-wrapper .bp3-icon-music:before{content:\"\ue6a6\"}.jupyter-wrapper .bp3-icon-new-drawing:before{content:\"\ue905\"}.jupyter-wrapper .bp3-icon-new-grid-item:before{content:\"\ue747\"}.jupyter-wrapper .bp3-icon-new-layer:before{content:\"\ue902\"}.jupyter-wrapper .bp3-icon-new-layers:before{content:\"\ue903\"}.jupyter-wrapper .bp3-icon-new-link:before{content:\"\ue65c\"}.jupyter-wrapper .bp3-icon-new-object:before{content:\"\ue65d\"}.jupyter-wrapper .bp3-icon-new-person:before{content:\"\ue6e9\"}.jupyter-wrapper .bp3-icon-new-prescription:before{content:\"\ue78b\"}.jupyter-wrapper .bp3-icon-new-text-box:before{content:\"\ue65b\"}.jupyter-wrapper .bp3-icon-ninja:before{content:\"\ue675\"}.jupyter-wrapper .bp3-icon-not-equal-to:before{content:\"\ue7e0\"}.jupyter-wrapper .bp3-icon-notifications:before{content:\"\ue624\"}.jupyter-wrapper .bp3-icon-notifications-updated:before{content:\"\ue7b8\"}.jupyter-wrapper .bp3-icon-numbered-list:before{content:\"\ue746\"}.jupyter-wrapper .bp3-icon-numerical:before{content:\"\ue756\"}.jupyter-wrapper .bp3-icon-office:before{content:\"\ue69b\"}.jupyter-wrapper .bp3-icon-offline:before{content:\"\ue67a\"}.jupyter-wrapper .bp3-icon-oil-field:before{content:\"\ue73f\"}.jupyter-wrapper .bp3-icon-one-column:before{content:\"\ue658\"}.jupyter-wrapper .bp3-icon-outdated:before{content:\"\ue7a8\"}.jupyter-wrapper .bp3-icon-page-layout:before{content:\"\ue660\"}.jupyter-wrapper .bp3-icon-panel-stats:before{content:\"\ue777\"}.jupyter-wrapper .bp3-icon-panel-table:before{content:\"\ue778\"}.jupyter-wrapper .bp3-icon-paperclip:before{content:\"\ue664\"}.jupyter-wrapper .bp3-icon-paragraph:before{content:\"\ue76c\"}.jupyter-wrapper .bp3-icon-path:before{content:\"\ue753\"}.jupyter-wrapper .bp3-icon-path-search:before{content:\"\ue65e\"}.jupyter-wrapper .bp3-icon-pause:before{content:\"\ue6a9\"}.jupyter-wrapper .bp3-icon-people:before{content:\"\ue63d\"}.jupyter-wrapper .bp3-icon-percentage:before{content:\"\ue76a\"}.jupyter-wrapper .bp3-icon-person:before{content:\"\ue63c\"}.jupyter-wrapper .bp3-icon-phone:before{content:\"\u260e\"}.jupyter-wrapper .bp3-icon-pie-chart:before{content:\"\ue684\"}.jupyter-wrapper .bp3-icon-pin:before{content:\"\ue646\"}.jupyter-wrapper .bp3-icon-pivot:before{content:\"\ue6f1\"}.jupyter-wrapper .bp3-icon-pivot-table:before{content:\"\ue6eb\"}.jupyter-wrapper .bp3-icon-play:before{content:\"\ue6ab\"}.jupyter-wrapper .bp3-icon-plus:before{content:\"+\"}.jupyter-wrapper .bp3-icon-polygon-filter:before{content:\"\ue6d1\"}.jupyter-wrapper .bp3-icon-power:before{content:\"\ue6d9\"}.jupyter-wrapper .bp3-icon-predictive-analysis:before{content:\"\ue617\"}.jupyter-wrapper .bp3-icon-prescription:before{content:\"\ue78a\"}.jupyter-wrapper .bp3-icon-presentation:before{content:\"\ue687\"}.jupyter-wrapper .bp3-icon-print:before{content:\"\u2399\"}.jupyter-wrapper .bp3-icon-projects:before{content:\"\ue622\"}.jupyter-wrapper .bp3-icon-properties:before{content:\"\ue631\"}.jupyter-wrapper .bp3-icon-property:before{content:\"\ue65a\"}.jupyter-wrapper .bp3-icon-publish-function:before{content:\"\ue752\"}.jupyter-wrapper .bp3-icon-pulse:before{content:\"\ue6e8\"}.jupyter-wrapper .bp3-icon-random:before{content:\"\ue698\"}.jupyter-wrapper .bp3-icon-record:before{content:\"\ue6ae\"}.jupyter-wrapper .bp3-icon-redo:before{content:\"\ue6c4\"}.jupyter-wrapper .bp3-icon-refresh:before{content:\"\ue643\"}.jupyter-wrapper .bp3-icon-regression-chart:before{content:\"\ue758\"}.jupyter-wrapper .bp3-icon-remove:before{content:\"\ue63f\"}.jupyter-wrapper .bp3-icon-remove-column:before{content:\"\ue755\"}.jupyter-wrapper .bp3-icon-remove-column-left:before{content:\"\ue6fd\"}.jupyter-wrapper .bp3-icon-remove-column-right:before{content:\"\ue6fe\"}.jupyter-wrapper .bp3-icon-remove-row-bottom:before{content:\"\ue6fc\"}.jupyter-wrapper .bp3-icon-remove-row-top:before{content:\"\ue6fb\"}.jupyter-wrapper .bp3-icon-repeat:before{content:\"\ue692\"}.jupyter-wrapper .bp3-icon-reset:before{content:\"\ue7d6\"}.jupyter-wrapper .bp3-icon-resolve:before{content:\"\ue672\"}.jupyter-wrapper .bp3-icon-rig:before{content:\"\ue740\"}.jupyter-wrapper .bp3-icon-right-join:before{content:\"\ue7a5\"}.jupyter-wrapper .bp3-icon-ring:before{content:\"\ue6f2\"}.jupyter-wrapper .bp3-icon-rotate-document:before{content:\"\ue6e1\"}.jupyter-wrapper .bp3-icon-rotate-page:before{content:\"\ue6e2\"}.jupyter-wrapper .bp3-icon-satellite:before{content:\"\ue76b\"}.jupyter-wrapper .bp3-icon-saved:before{content:\"\ue6b6\"}.jupyter-wrapper .bp3-icon-scatter-plot:before{content:\"\ue73e\"}.jupyter-wrapper .bp3-icon-search:before{content:\"\ue64b\"}.jupyter-wrapper .bp3-icon-search-around:before{content:\"\ue608\"}.jupyter-wrapper .bp3-icon-search-template:before{content:\"\ue628\"}.jupyter-wrapper .bp3-icon-search-text:before{content:\"\ue663\"}.jupyter-wrapper .bp3-icon-segmented-control:before{content:\"\ue6ec\"}.jupyter-wrapper .bp3-icon-select:before{content:\"\ue616\"}.jupyter-wrapper .bp3-icon-selection:before{content:\"\u29bf\"}.jupyter-wrapper .bp3-icon-send-to:before{content:\"\ue66e\"}.jupyter-wrapper .bp3-icon-send-to-graph:before{content:\"\ue736\"}.jupyter-wrapper .bp3-icon-send-to-map:before{content:\"\ue737\"}.jupyter-wrapper .bp3-icon-series-add:before{content:\"\ue796\"}.jupyter-wrapper .bp3-icon-series-configuration:before{content:\"\ue79a\"}.jupyter-wrapper .bp3-icon-series-derived:before{content:\"\ue799\"}.jupyter-wrapper .bp3-icon-series-filtered:before{content:\"\ue798\"}.jupyter-wrapper .bp3-icon-series-search:before{content:\"\ue797\"}.jupyter-wrapper .bp3-icon-settings:before{content:\"\ue6a2\"}.jupyter-wrapper .bp3-icon-share:before{content:\"\ue62e\"}.jupyter-wrapper .bp3-icon-shield:before{content:\"\ue7b2\"}.jupyter-wrapper .bp3-icon-shop:before{content:\"\ue6c2\"}.jupyter-wrapper .bp3-icon-shopping-cart:before{content:\"\ue6c1\"}.jupyter-wrapper .bp3-icon-signal-search:before{content:\"\ue909\"}.jupyter-wrapper .bp3-icon-sim-card:before{content:\"\ue718\"}.jupyter-wrapper .bp3-icon-slash:before{content:\"\ue769\"}.jupyter-wrapper .bp3-icon-small-cross:before{content:\"\ue6d7\"}.jupyter-wrapper .bp3-icon-small-minus:before{content:\"\ue70e\"}.jupyter-wrapper .bp3-icon-small-plus:before{content:\"\ue70d\"}.jupyter-wrapper .bp3-icon-small-tick:before{content:\"\ue6d8\"}.jupyter-wrapper .bp3-icon-snowflake:before{content:\"\ue7b6\"}.jupyter-wrapper .bp3-icon-social-media:before{content:\"\ue671\"}.jupyter-wrapper .bp3-icon-sort:before{content:\"\ue64f\"}.jupyter-wrapper .bp3-icon-sort-alphabetical:before{content:\"\ue64d\"}.jupyter-wrapper .bp3-icon-sort-alphabetical-desc:before{content:\"\ue6c8\"}.jupyter-wrapper .bp3-icon-sort-asc:before{content:\"\ue6d5\"}.jupyter-wrapper .bp3-icon-sort-desc:before{content:\"\ue6d6\"}.jupyter-wrapper .bp3-icon-sort-numerical:before{content:\"\ue64e\"}.jupyter-wrapper .bp3-icon-sort-numerical-desc:before{content:\"\ue6c9\"}.jupyter-wrapper .bp3-icon-split-columns:before{content:\"\ue750\"}.jupyter-wrapper .bp3-icon-square:before{content:\"\ue686\"}.jupyter-wrapper .bp3-icon-stacked-chart:before{content:\"\ue6e7\"}.jupyter-wrapper .bp3-icon-star:before{content:\"\u2605\"}.jupyter-wrapper .bp3-icon-star-empty:before{content:\"\u2606\"}.jupyter-wrapper .bp3-icon-step-backward:before{content:\"\ue6a7\"}.jupyter-wrapper .bp3-icon-step-chart:before{content:\"\ue70f\"}.jupyter-wrapper .bp3-icon-step-forward:before{content:\"\ue6ad\"}.jupyter-wrapper .bp3-icon-stop:before{content:\"\ue6aa\"}.jupyter-wrapper .bp3-icon-stopwatch:before{content:\"\ue901\"}.jupyter-wrapper .bp3-icon-strikethrough:before{content:\"\ue7a6\"}.jupyter-wrapper .bp3-icon-style:before{content:\"\ue601\"}.jupyter-wrapper .bp3-icon-swap-horizontal:before{content:\"\ue745\"}.jupyter-wrapper .bp3-icon-swap-vertical:before{content:\"\ue744\"}.jupyter-wrapper .bp3-icon-symbol-circle:before{content:\"\ue72e\"}.jupyter-wrapper .bp3-icon-symbol-cross:before{content:\"\ue731\"}.jupyter-wrapper .bp3-icon-symbol-diamond:before{content:\"\ue730\"}.jupyter-wrapper .bp3-icon-symbol-square:before{content:\"\ue72f\"}.jupyter-wrapper .bp3-icon-symbol-triangle-down:before{content:\"\ue733\"}.jupyter-wrapper .bp3-icon-symbol-triangle-up:before{content:\"\ue732\"}.jupyter-wrapper .bp3-icon-tag:before{content:\"\ue61c\"}.jupyter-wrapper .bp3-icon-take-action:before{content:\"\ue6ca\"}.jupyter-wrapper .bp3-icon-taxi:before{content:\"\ue79e\"}.jupyter-wrapper .bp3-icon-text-highlight:before{content:\"\ue6dd\"}.jupyter-wrapper .bp3-icon-th:before{content:\"\ue667\"}.jupyter-wrapper .bp3-icon-th-derived:before{content:\"\ue669\"}.jupyter-wrapper .bp3-icon-th-disconnect:before{content:\"\ue7d8\"}.jupyter-wrapper .bp3-icon-th-filtered:before{content:\"\ue7c6\"}.jupyter-wrapper .bp3-icon-th-list:before{content:\"\ue668\"}.jupyter-wrapper .bp3-icon-thumbs-down:before{content:\"\ue6be\"}.jupyter-wrapper .bp3-icon-thumbs-up:before{content:\"\ue6bd\"}.jupyter-wrapper .bp3-icon-tick:before{content:\"\u2713\"}.jupyter-wrapper .bp3-icon-tick-circle:before{content:\"\ue779\"}.jupyter-wrapper .bp3-icon-time:before{content:\"\u23f2\"}.jupyter-wrapper .bp3-icon-timeline-area-chart:before{content:\"\ue6cd\"}.jupyter-wrapper .bp3-icon-timeline-bar-chart:before{content:\"\ue620\"}.jupyter-wrapper .bp3-icon-timeline-events:before{content:\"\ue61e\"}.jupyter-wrapper .bp3-icon-timeline-line-chart:before{content:\"\ue61f\"}.jupyter-wrapper .bp3-icon-tint:before{content:\"\ue6b2\"}.jupyter-wrapper .bp3-icon-torch:before{content:\"\ue677\"}.jupyter-wrapper .bp3-icon-tractor:before{content:\"\ue90c\"}.jupyter-wrapper .bp3-icon-train:before{content:\"\ue79f\"}.jupyter-wrapper .bp3-icon-translate:before{content:\"\ue759\"}.jupyter-wrapper .bp3-icon-trash:before{content:\"\ue63b\"}.jupyter-wrapper .bp3-icon-tree:before{content:\"\ue7b7\"}.jupyter-wrapper .bp3-icon-trending-down:before{content:\"\ue71a\"}.jupyter-wrapper .bp3-icon-trending-up:before{content:\"\ue719\"}.jupyter-wrapper .bp3-icon-truck:before{content:\"\ue90b\"}.jupyter-wrapper .bp3-icon-two-columns:before{content:\"\ue657\"}.jupyter-wrapper .bp3-icon-unarchive:before{content:\"\ue906\"}.jupyter-wrapper .bp3-icon-underline:before{content:\"\u2381\"}.jupyter-wrapper .bp3-icon-undo:before{content:\"\u238c\"}.jupyter-wrapper .bp3-icon-ungroup-objects:before{content:\"\ue688\"}.jupyter-wrapper .bp3-icon-unknown-vehicle:before{content:\"\ue73d\"}.jupyter-wrapper .bp3-icon-unlock:before{content:\"\ue626\"}.jupyter-wrapper .bp3-icon-unpin:before{content:\"\ue650\"}.jupyter-wrapper .bp3-icon-unresolve:before{content:\"\ue679\"}.jupyter-wrapper .bp3-icon-updated:before{content:\"\ue7a7\"}.jupyter-wrapper .bp3-icon-upload:before{content:\"\ue68f\"}.jupyter-wrapper .bp3-icon-user:before{content:\"\ue627\"}.jupyter-wrapper .bp3-icon-variable:before{content:\"\ue6f5\"}.jupyter-wrapper .bp3-icon-vertical-bar-chart-asc:before{content:\"\ue75b\"}.jupyter-wrapper .bp3-icon-vertical-bar-chart-desc:before{content:\"\ue71c\"}.jupyter-wrapper .bp3-icon-vertical-distribution:before{content:\"\ue721\"}.jupyter-wrapper .bp3-icon-video:before{content:\"\ue6a0\"}.jupyter-wrapper .bp3-icon-volume-down:before{content:\"\ue6a4\"}.jupyter-wrapper .bp3-icon-volume-off:before{content:\"\ue6a3\"}.jupyter-wrapper .bp3-icon-volume-up:before{content:\"\ue6a5\"}.jupyter-wrapper .bp3-icon-walk:before{content:\"\ue79d\"}.jupyter-wrapper .bp3-icon-warning-sign:before{content:\"\ue647\"}.jupyter-wrapper .bp3-icon-waterfall-chart:before{content:\"\ue6e6\"}.jupyter-wrapper .bp3-icon-widget:before{content:\"\ue678\"}.jupyter-wrapper .bp3-icon-widget-button:before{content:\"\ue790\"}.jupyter-wrapper .bp3-icon-widget-footer:before{content:\"\ue792\"}.jupyter-wrapper .bp3-icon-widget-header:before{content:\"\ue791\"}.jupyter-wrapper .bp3-icon-wrench:before{content:\"\ue734\"}.jupyter-wrapper .bp3-icon-zoom-in:before{content:\"\ue641\"}.jupyter-wrapper .bp3-icon-zoom-out:before{content:\"\ue642\"}.jupyter-wrapper .bp3-icon-zoom-to-fit:before{content:\"\ue67b\"}.jupyter-wrapper .bp3-submenu>.bp3-popover-wrapper{display:block}.jupyter-wrapper .bp3-submenu .bp3-popover-target{display:block}.jupyter-wrapper .bp3-submenu.bp3-popover{-webkit-box-shadow:none;box-shadow:none;padding:0 5px}.jupyter-wrapper .bp3-submenu.bp3-popover>.bp3-popover-content{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33}.jupyter-wrapper .bp3-dark .bp3-submenu.bp3-popover,.jupyter-wrapper .bp3-submenu.bp3-popover.bp3-dark{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-dark .bp3-submenu.bp3-popover>.bp3-popover-content,.jupyter-wrapper .bp3-submenu.bp3-popover.bp3-dark>.bp3-popover-content{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-menu{background:#ffffff;border-radius:3px;color:#182026;list-style:none;margin:0;min-width:180px;padding:5px;text-align:left}.jupyter-wrapper .bp3-menu-divider{border-top:1px solid rgba(16,22,26,.15);display:block;margin:5px}.jupyter-wrapper .bp3-dark .bp3-menu-divider{border-top-color:#ffffff26}.jupyter-wrapper .bp3-menu-item{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;border-radius:2px;color:inherit;line-height:20px;padding:5px 7px;text-decoration:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-menu-item>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-menu-item>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item>*{margin-right:7px}.jupyter-wrapper .bp3-menu-item:empty:before,.jupyter-wrapper .bp3-menu-item>:last-child{margin-right:0}.jupyter-wrapper .bp3-menu-item>.bp3-fill{word-break:break-word}.jupyter-wrapper .bp3-menu-item:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item{background-color:#a7b6c24d;cursor:pointer;text-decoration:none}.jupyter-wrapper .bp3-menu-item.bp3-disabled{background-color:inherit;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-dark .bp3-menu-item{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-menu-item{background-color:#8a9ba826;color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled{background-color:inherit;color:#a7b6c299}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary{color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary .bp3-menu-item-label{color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active{background-color:#137cbd}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active{background-color:#106ba3}.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-primary.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-success{color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success .bp3-menu-item-label{color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active{background-color:#0f9960}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active{background-color:#0d8050}.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-success.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning{color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning .bp3-menu-item-label{color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active{background-color:#d9822b}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active{background-color:#bf7326}.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-warning.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger{color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger .bp3-icon{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger .bp3-menu-item-label{color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active{background-color:#db3737}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active{background-color:#c23030}.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover:before,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover:after,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger:active .bp3-menu-item-label,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active:before,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active:after,.jupyter-wrapper .bp3-menu-item.bp3-intent-danger.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-menu-item:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-right:7px}.jupyter-wrapper .bp3-menu-item:before,.jupyter-wrapper .bp3-menu-item>.bp3-icon{color:#5c7080;margin-top:2px}.jupyter-wrapper .bp3-menu-item .bp3-menu-item-label{color:#5c7080}.jupyter-wrapper .bp3-menu-item:hover,.jupyter-wrapper .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-menu-item{color:inherit}.jupyter-wrapper .bp3-menu-item.bp3-active,.jupyter-wrapper .bp3-menu-item:active{background-color:#7386944d}.jupyter-wrapper .bp3-menu-item.bp3-disabled{background-color:inherit!important;color:#5c708099!important;cursor:not-allowed!important;outline:none!important}.jupyter-wrapper .bp3-menu-item.bp3-disabled:before,.jupyter-wrapper .bp3-menu-item.bp3-disabled>.bp3-icon,.jupyter-wrapper .bp3-menu-item.bp3-disabled .bp3-menu-item-label{color:#5c708099!important}.jupyter-wrapper .bp3-large .bp3-menu-item{font-size:16px;line-height:22px;padding:9px 7px}.jupyter-wrapper .bp3-large .bp3-menu-item .bp3-icon{margin-top:3px}.jupyter-wrapper .bp3-large .bp3-menu-item:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;margin-right:10px;margin-top:1px}.jupyter-wrapper button.bp3-menu-item{background:none;border:none;text-align:left;width:100%}.jupyter-wrapper .bp3-menu-header{border-top:1px solid rgba(16,22,26,.15);display:block;margin:5px;cursor:default;padding-left:2px}.jupyter-wrapper .bp3-dark .bp3-menu-header{border-top-color:#ffffff26}.jupyter-wrapper .bp3-menu-header:first-of-type{border-top:none}.jupyter-wrapper .bp3-menu-header>h6{color:#182026;font-weight:600;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;line-height:17px;margin:0;padding:10px 7px 0 1px}.jupyter-wrapper .bp3-menu-header:first-of-type>h6{padding-top:0}.jupyter-wrapper .bp3-large .bp3-menu-header>h6{font-size:18px;padding-bottom:5px;padding-top:15px}.jupyter-wrapper .bp3-large .bp3-menu-header:first-of-type>h6{padding-top:0}.jupyter-wrapper .bp3-dark .bp3-menu{background:#30404d;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary .bp3-menu-item-label{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active{background-color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active{background-color:#106ba3}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-primary.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-primary.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success .bp3-menu-item-label{color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active{background-color:#0f9960}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active{background-color:#0d8050}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-success.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-success.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning .bp3-menu-item-label{color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active{background-color:#d9822b}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active{background-color:#bf7326}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-warning.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-warning.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger .bp3-icon{color:inherit}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger .bp3-menu-item-label{color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active{background-color:#db3737}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active{background-color:#c23030}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover:before,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover:after,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:hover .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-submenu .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-submenu .bp3-dark .bp3-popover-target.bp3-popover-open>.bp3-intent-danger.bp3-menu-item .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger:active .bp3-menu-item-label,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active:after,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-intent-danger.bp3-active .bp3-menu-item-label{color:#fff}.jupyter-wrapper .bp3-dark .bp3-menu-item:before,.jupyter-wrapper .bp3-dark .bp3-menu-item>.bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-menu-item .bp3-menu-item-label{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-active,.jupyter-wrapper .bp3-dark .bp3-menu-item:active{background-color:#8a9ba84d}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled{color:#a7b6c299!important}.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled:before,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-menu-item.bp3-disabled .bp3-menu-item-label{color:#a7b6c299!important}.jupyter-wrapper .bp3-dark .bp3-menu-divider,.jupyter-wrapper .bp3-dark .bp3-menu-header{border-color:#ffffff26}.jupyter-wrapper .bp3-dark .bp3-menu-header>h6{color:#f5f8fa}.jupyter-wrapper .bp3-label .bp3-menu{margin-top:5px}.jupyter-wrapper .bp3-navbar{background-color:#fff;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 0 #10161a00,0 1px 1px #10161a33;height:50px;padding:0 15px;position:relative;width:100%;z-index:10}.jupyter-wrapper .bp3-navbar.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-navbar{background-color:#394b59}.jupyter-wrapper .bp3-navbar.bp3-dark{-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:inset 0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-navbar{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 0 0 rgba(16,22,26,0),0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 0 #10161a00,0 1px 1px #10161a66}.jupyter-wrapper .bp3-navbar.bp3-fixed-top{left:0;position:fixed;right:0;top:0}.jupyter-wrapper .bp3-navbar-heading{font-size:16px;margin-right:15px}.jupyter-wrapper .bp3-navbar-group{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:50px}.jupyter-wrapper .bp3-navbar-group.bp3-align-left{float:left}.jupyter-wrapper .bp3-navbar-group.bp3-align-right{float:right}.jupyter-wrapper .bp3-navbar-divider{border-left:1px solid rgba(16,22,26,.15);height:20px;margin:0 10px}.jupyter-wrapper .bp3-dark .bp3-navbar-divider{border-left-color:#ffffff26}.jupyter-wrapper .bp3-non-ideal-state{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;-webkit-box-align:center;-ms-flex-align:center;align-items:center;height:100%;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;text-align:center;width:100%}.jupyter-wrapper .bp3-non-ideal-state>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-non-ideal-state>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-non-ideal-state:before,.jupyter-wrapper .bp3-non-ideal-state>*{margin-bottom:20px}.jupyter-wrapper .bp3-non-ideal-state:empty:before,.jupyter-wrapper .bp3-non-ideal-state>:last-child{margin-bottom:0}.jupyter-wrapper .bp3-non-ideal-state>*{max-width:400px}.jupyter-wrapper .bp3-non-ideal-state-visual{color:#5c708099;font-size:60px}.jupyter-wrapper .bp3-dark .bp3-non-ideal-state-visual{color:#a7b6c299}.jupyter-wrapper .bp3-overflow-list{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-wrap:nowrap;flex-wrap:nowrap;min-width:0}.jupyter-wrapper .bp3-overflow-list-spacer{-ms-flex-negative:1;flex-shrink:1;width:1px}.jupyter-wrapper body.bp3-overlay-open{overflow:hidden}.jupyter-wrapper .bp3-overlay{bottom:0;left:0;position:static;right:0;top:0;z-index:20}.jupyter-wrapper .bp3-overlay:not(.bp3-overlay-open){pointer-events:none}.jupyter-wrapper .bp3-overlay.bp3-overlay-container{overflow:hidden;position:fixed}.jupyter-wrapper .bp3-overlay.bp3-overlay-container.bp3-overlay-inline{position:absolute}.jupyter-wrapper .bp3-overlay.bp3-overlay-scroll-container{overflow:auto;position:fixed}.jupyter-wrapper .bp3-overlay.bp3-overlay-scroll-container.bp3-overlay-inline{position:absolute}.jupyter-wrapper .bp3-overlay.bp3-overlay-inline{display:inline;overflow:visible}.jupyter-wrapper .bp3-overlay-content{position:fixed;z-index:20}.jupyter-wrapper .bp3-overlay-inline .bp3-overlay-content,.jupyter-wrapper .bp3-overlay-scroll-container .bp3-overlay-content{position:absolute}.jupyter-wrapper .bp3-overlay-backdrop{bottom:0;left:0;position:fixed;right:0;top:0;opacity:1;background-color:#10161ab3;overflow:auto;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;z-index:20}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-enter,.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-appear{opacity:0}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-enter-active,.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-appear-active{opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-exit{opacity:1}.jupyter-wrapper .bp3-overlay-backdrop.bp3-overlay-exit-active{opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-overlay-backdrop:focus{outline:none}.jupyter-wrapper .bp3-overlay-inline .bp3-overlay-backdrop{position:absolute}.jupyter-wrapper .bp3-panel-stack{overflow:hidden;position:relative}.jupyter-wrapper .bp3-panel-stack-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-shadow:0 1px rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;height:30px;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack-header{-webkit-box-shadow:0 1px rgba(255,255,255,.15);box-shadow:0 1px #ffffff26}.jupyter-wrapper .bp3-panel-stack-header>span{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1}.jupyter-wrapper .bp3-panel-stack-header .bp3-heading{margin:0 5px}.jupyter-wrapper .bp3-button.bp3-panel-stack-header-back{margin-left:5px;padding-left:0;white-space:nowrap}.jupyter-wrapper .bp3-button.bp3-panel-stack-header-back .bp3-icon{margin:0 2px}.jupyter-wrapper .bp3-panel-stack-view{bottom:0;left:0;position:absolute;right:0;top:0;background-color:#fff;border-right:1px solid rgba(16,22,26,.15);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:-1px;overflow-y:auto;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack-view{background-color:#30404d}.jupyter-wrapper .bp3-panel-stack-view:nth-last-child(n+4){display:none}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-enter,.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-appear{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-enter-active,.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack-push .bp3-panel-stack-exit-active{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-enter,.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-appear{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-enter-active,.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack-pop .bp3-panel-stack-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2{overflow:hidden;position:relative}.jupyter-wrapper .bp3-panel-stack2-header{-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-shadow:0 1px rgba(16,22,26,.15);box-shadow:0 1px #10161a26;display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-negative:0;flex-shrink:0;height:30px;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack2-header{-webkit-box-shadow:0 1px rgba(255,255,255,.15);box-shadow:0 1px #ffffff26}.jupyter-wrapper .bp3-panel-stack2-header>span{-webkit-box-align:stretch;-ms-flex-align:stretch;align-items:stretch;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:1;-ms-flex:1;flex:1}.jupyter-wrapper .bp3-panel-stack2-header .bp3-heading{margin:0 5px}.jupyter-wrapper .bp3-button.bp3-panel-stack2-header-back{margin-left:5px;padding-left:0;white-space:nowrap}.jupyter-wrapper .bp3-button.bp3-panel-stack2-header-back .bp3-icon{margin:0 2px}.jupyter-wrapper .bp3-panel-stack2-view{bottom:0;left:0;position:absolute;right:0;top:0;background-color:#fff;border-right:1px solid rgba(16,22,26,.15);display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;margin-right:-1px;overflow-y:auto;z-index:1}.jupyter-wrapper .bp3-dark .bp3-panel-stack2-view{background-color:#30404d}.jupyter-wrapper .bp3-panel-stack2-view:nth-last-child(n+4){display:none}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-enter,.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-appear{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-enter-active,.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack2-push .bp3-panel-stack2-exit-active{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-enter,.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-appear{-webkit-transform:translateX(-50%);transform:translate(-50%);opacity:0}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-enter-active,.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-appear-active{-webkit-transform:translate(0%);transform:translate(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-exit{-webkit-transform:translate(0%);transform:translate(0);opacity:1}.jupyter-wrapper .bp3-panel-stack2-pop .bp3-panel-stack2-exit-active{-webkit-transform:translateX(100%);transform:translate(100%);opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.4s;transition-duration:.4s;-webkit-transition-property:opacity,-webkit-transform;transition-property:opacity,-webkit-transform;transition-property:transform,opacity;transition-property:transform,opacity,-webkit-transform;-webkit-transition-timing-function:ease;transition-timing-function:ease}.jupyter-wrapper .bp3-popover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;-webkit-transform:scale(1);transform:scale(1);border-radius:3px;display:inline-block;z-index:20}.jupyter-wrapper .bp3-popover .bp3-popover-arrow{height:30px;position:absolute;width:30px}.jupyter-wrapper .bp3-popover .bp3-popover-arrow:before{height:20px;margin:5px;width:20px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover{margin-bottom:17px;margin-top:-17px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow{bottom:-11px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover{margin-left:17px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow{left:-11px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(0);transform:rotate(0)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover{margin-top:17px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow{top:-11px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover{margin-left:-17px;margin-right:17px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow{right:-11px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow svg{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.jupyter-wrapper .bp3-tether-element-attached-middle>.bp3-popover>.bp3-popover-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.jupyter-wrapper .bp3-tether-element-attached-center>.bp3-popover>.bp3-popover-arrow{right:50%;-webkit-transform:translateX(50%);transform:translate(50%)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-top>.bp3-popover>.bp3-popover-arrow{top:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-right>.bp3-popover>.bp3-popover-arrow{right:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-left>.bp3-popover>.bp3-popover-arrow{left:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-bottom>.bp3-popover>.bp3-popover-arrow{bottom:-.3934px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:top left;transform-origin:top left}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:top center;transform-origin:top center}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:top right;transform-origin:top right}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:center left;transform-origin:center left}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:center center;transform-origin:center center}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:center right;transform-origin:center right}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-left>.bp3-popover{-webkit-transform-origin:bottom left;transform-origin:bottom left}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-center>.bp3-popover{-webkit-transform-origin:bottom center;transform-origin:bottom center}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-right>.bp3-popover{-webkit-transform-origin:bottom right;transform-origin:bottom right}.jupyter-wrapper .bp3-popover .bp3-popover-content{background:#ffffff;color:inherit}.jupyter-wrapper .bp3-popover .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.2);box-shadow:1px 1px 6px #10161a33}.jupyter-wrapper .bp3-popover .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.1}.jupyter-wrapper .bp3-popover .bp3-popover-arrow-fill{fill:#fff}.jupyter-wrapper .bp3-popover-enter>.bp3-popover,.jupyter-wrapper .bp3-popover-appear>.bp3-popover{-webkit-transform:scale(.3);transform:scale(.3)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-popover,.jupyter-wrapper .bp3-popover-appear-active>.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-popover-exit>.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-popover{-webkit-transform:scale(.3);transform:scale(.3);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-popover .bp3-popover-content{border-radius:3px;position:relative}.jupyter-wrapper .bp3-popover.bp3-popover-content-sizing .bp3-popover-content{max-width:350px;padding:20px}.jupyter-wrapper .bp3-popover-target+.bp3-overlay .bp3-popover.bp3-popover-content-sizing{width:350px}.jupyter-wrapper .bp3-popover.bp3-minimal{margin:0!important}.jupyter-wrapper .bp3-popover.bp3-minimal .bp3-popover-arrow{display:none}.jupyter-wrapper .bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-enter>.bp3-popover.bp3-minimal.bp3-popover,.jupyter-wrapper .bp3-popover-appear>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-popover.bp3-minimal.bp3-popover,.jupyter-wrapper .bp3-popover-appear-active>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover-exit>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-popover.bp3-minimal.bp3-popover{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-popover{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-content,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-content{background:#30404d;color:inherit}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow:before,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.4);box-shadow:1px 1px 6px #10161a66}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow-border,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.2}.jupyter-wrapper .bp3-popover.bp3-dark .bp3-popover-arrow-fill,.jupyter-wrapper .bp3-dark .bp3-popover .bp3-popover-arrow-fill{fill:#30404d}.jupyter-wrapper .bp3-popover-arrow:before{border-radius:2px;content:\"\";display:block;position:absolute;-webkit-transform:rotate(45deg);transform:rotate(45deg)}.jupyter-wrapper .bp3-tether-pinned .bp3-popover-arrow{display:none}.jupyter-wrapper .bp3-popover-backdrop{background:rgba(255,255,255,0)}.jupyter-wrapper .bp3-transition-container{opacity:1;display:-webkit-box;display:-ms-flexbox;display:flex;z-index:20}.jupyter-wrapper .bp3-transition-container.bp3-popover-enter,.jupyter-wrapper .bp3-transition-container.bp3-popover-appear{opacity:0}.jupyter-wrapper .bp3-transition-container.bp3-popover-enter-active,.jupyter-wrapper .bp3-transition-container.bp3-popover-appear-active{opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-transition-container.bp3-popover-exit{opacity:1}.jupyter-wrapper .bp3-transition-container.bp3-popover-exit-active{opacity:0;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:opacity;transition-property:opacity;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-transition-container:focus{outline:none}.jupyter-wrapper .bp3-transition-container.bp3-popover-leave .bp3-popover-content{pointer-events:none}.jupyter-wrapper .bp3-transition-container[data-x-out-of-boundaries]{display:none}.jupyter-wrapper span.bp3-popover-target{display:inline-block}.jupyter-wrapper .bp3-popover-wrapper.bp3-fill{width:100%}.jupyter-wrapper .bp3-portal{left:0;position:absolute;right:0;top:0}@-webkit-keyframes linear-progress-bar-stripes{0%{background-position:0 0}to{background-position:30px 0}}@keyframes linear-progress-bar-stripes{0%{background-position:0 0}to{background-position:30px 0}}.jupyter-wrapper .bp3-progress-bar{background:rgba(92,112,128,.2);border-radius:40px;display:block;height:8px;overflow:hidden;position:relative;width:100%}.jupyter-wrapper .bp3-progress-bar .bp3-progress-meter{background:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%);background-color:#5c7080cc;background-size:30px 30px;border-radius:40px;height:100%;position:absolute;-webkit-transition:width .2s cubic-bezier(.4,1,.75,.9);transition:width .2s cubic-bezier(.4,1,.75,.9);width:100%}.jupyter-wrapper .bp3-progress-bar:not(.bp3-no-animation):not(.bp3-no-stripes) .bp3-progress-meter{animation:linear-progress-bar-stripes .3s linear infinite reverse}.jupyter-wrapper .bp3-progress-bar.bp3-no-stripes .bp3-progress-meter{background-image:none}.jupyter-wrapper .bp3-dark .bp3-progress-bar{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-dark .bp3-progress-bar .bp3-progress-meter{background-color:#8a9ba8}.jupyter-wrapper .bp3-progress-bar.bp3-intent-primary .bp3-progress-meter{background-color:#137cbd}.jupyter-wrapper .bp3-progress-bar.bp3-intent-success .bp3-progress-meter{background-color:#0f9960}.jupyter-wrapper .bp3-progress-bar.bp3-intent-warning .bp3-progress-meter{background-color:#d9822b}.jupyter-wrapper .bp3-progress-bar.bp3-intent-danger .bp3-progress-meter{background-color:#db3737}@-webkit-keyframes skeleton-glow{0%{background:rgba(206,217,224,.2);border-color:#ced9e033}to{background:rgba(92,112,128,.2);border-color:#5c708033}}@keyframes skeleton-glow{0%{background:rgba(206,217,224,.2);border-color:#ced9e033}to{background:rgba(92,112,128,.2);border-color:#5c708033}}.jupyter-wrapper .bp3-skeleton{-webkit-animation:1s linear infinite alternate skeleton-glow;animation:1s linear infinite alternate skeleton-glow;background:rgba(206,217,224,.2);background-clip:padding-box!important;border-color:#ced9e033!important;border-radius:2px;-webkit-box-shadow:none!important;box-shadow:none!important;color:transparent!important;cursor:default;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-skeleton:before,.jupyter-wrapper .bp3-skeleton:after,.jupyter-wrapper .bp3-skeleton *{visibility:hidden!important}.jupyter-wrapper .bp3-slider{height:40px;min-width:150px;width:100%;cursor:default;outline:none;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-slider:hover{cursor:pointer}.jupyter-wrapper .bp3-slider:active{cursor:-webkit-grabbing;cursor:grabbing}.jupyter-wrapper .bp3-slider.bp3-disabled{cursor:not-allowed;opacity:.5}.jupyter-wrapper .bp3-slider.bp3-slider-unlabeled{height:16px}.jupyter-wrapper .bp3-slider-track,.jupyter-wrapper .bp3-slider-progress{height:6px;left:0;right:0;top:5px;position:absolute}.jupyter-wrapper .bp3-slider-track{border-radius:3px;overflow:hidden}.jupyter-wrapper .bp3-slider-progress{background:rgba(92,112,128,.2)}.jupyter-wrapper .bp3-dark .bp3-slider-progress{background:rgba(16,22,26,.5)}.jupyter-wrapper .bp3-slider-progress.bp3-intent-primary{background-color:#137cbd}.jupyter-wrapper .bp3-slider-progress.bp3-intent-success{background-color:#0f9960}.jupyter-wrapper .bp3-slider-progress.bp3-intent-warning{background-color:#d9822b}.jupyter-wrapper .bp3-slider-progress.bp3-intent-danger{background-color:#db3737}.jupyter-wrapper .bp3-slider-handle{background-color:#f5f8fa;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.8)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.8),rgba(255,255,255,0));-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;color:#182026;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;cursor:pointer;height:16px;left:0;position:absolute;top:0;width:16px}.jupyter-wrapper .bp3-slider-handle:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a}.jupyter-wrapper .bp3-slider-handle:active,.jupyter-wrapper .bp3-slider-handle.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-slider-handle:disabled,.jupyter-wrapper .bp3-slider-handle.bp3-disabled{background-color:#ced9e080;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#5c708099;cursor:not-allowed;outline:none}.jupyter-wrapper .bp3-slider-handle:disabled.bp3-active,.jupyter-wrapper .bp3-slider-handle:disabled.bp3-active:hover,.jupyter-wrapper .bp3-slider-handle.bp3-disabled.bp3-active,.jupyter-wrapper .bp3-slider-handle.bp3-disabled.bp3-active:hover{background:rgba(206,217,224,.7)}.jupyter-wrapper .bp3-slider-handle:focus{z-index:1}.jupyter-wrapper .bp3-slider-handle:hover{background-clip:padding-box;background-color:#ebf1f5;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 -1px 0 rgba(16,22,26,.1);box-shadow:inset 0 0 0 1px #10161a33,inset 0 -1px #10161a1a;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a33,0 1px 1px #10161a33;cursor:-webkit-grab;cursor:grab;z-index:2}.jupyter-wrapper .bp3-slider-handle.bp3-active{background-color:#d8e1e8;background-image:none;-webkit-box-shadow:inset 0 0 0 1px rgba(16,22,26,.2),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:inset 0 0 0 1px #10161a33,inset 0 1px 2px #10161a33;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),inset 0 1px 1px rgba(16,22,26,.1);box-shadow:0 0 0 1px #10161a33,inset 0 1px 1px #10161a1a;cursor:-webkit-grabbing;cursor:grabbing}.jupyter-wrapper .bp3-disabled .bp3-slider-handle{background:#bfccd6;-webkit-box-shadow:none;box-shadow:none;pointer-events:none}.jupyter-wrapper .bp3-dark .bp3-slider-handle{background-color:#394b59;background-image:-webkit-gradient(linear,left top,left bottom,from(rgba(255,255,255,.05)),to(rgba(255,255,255,0)));background-image:linear-gradient(to bottom,rgba(255,255,255,.05),rgba(255,255,255,0));-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66;color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover,.jupyter-wrapper .bp3-dark .bp3-slider-handle:active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-slider-handle:active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{background-color:#202b33;background-image:none;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.6),inset 0 1px 2px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a99,inset 0 1px 2px #10161a33}.jupyter-wrapper .bp3-dark .bp3-slider-handle:disabled,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-disabled{background-color:#394b5980;background-image:none;-webkit-box-shadow:none;box-shadow:none;color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-slider-handle:disabled.bp3-active,.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-disabled.bp3-active{background:rgba(57,75,89,.7)}.jupyter-wrapper .bp3-dark .bp3-slider-handle .bp3-button-spinner .bp3-spinner-head{background:rgba(16,22,26,.5);stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-slider-handle,.jupyter-wrapper .bp3-dark .bp3-slider-handle:hover{background-color:#394b59}.jupyter-wrapper .bp3-dark .bp3-slider-handle.bp3-active{background-color:#293742}.jupyter-wrapper .bp3-dark .bp3-disabled .bp3-slider-handle{background:#5c7080;border-color:#5c7080;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-slider-handle .bp3-slider-label{background:#394b59;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;color:#f5f8fa;margin-left:8px}.jupyter-wrapper .bp3-dark .bp3-slider-handle .bp3-slider-label{background:#e1e8ed;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66;color:#394b59}.jupyter-wrapper .bp3-disabled .bp3-slider-handle .bp3-slider-label{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-slider-handle.bp3-start,.jupyter-wrapper .bp3-slider-handle.bp3-end{width:8px}.jupyter-wrapper .bp3-slider-handle.bp3-start{border-bottom-right-radius:0;border-top-right-radius:0}.jupyter-wrapper .bp3-slider-handle.bp3-end{border-bottom-left-radius:0;border-top-left-radius:0;margin-left:8px}.jupyter-wrapper .bp3-slider-handle.bp3-end .bp3-slider-label{margin-left:0}.jupyter-wrapper .bp3-slider-label{-webkit-transform:translate(-50%,20px);transform:translate(-50%,20px);display:inline-block;font-size:12px;line-height:1;padding:2px 5px;position:absolute;vertical-align:top}.jupyter-wrapper .bp3-slider.bp3-vertical{height:150px;min-width:40px;width:40px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-track,.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-progress{bottom:0;height:auto;left:5px;top:0;width:6px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-progress{top:auto}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-label{-webkit-transform:translate(20px,50%);transform:translate(20px,50%)}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle{top:auto}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle .bp3-slider-label{margin-left:0;margin-top:-8px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-end,.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start{height:8px;margin-left:0;width:16px}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start{border-bottom-right-radius:3px;border-top-left-radius:0}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-start .bp3-slider-label{-webkit-transform:translate(20px);transform:translate(20px)}.jupyter-wrapper .bp3-slider.bp3-vertical .bp3-slider-handle.bp3-end{border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:3px;margin-bottom:8px}@-webkit-keyframes pt-spinner-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}@keyframes pt-spinner-animation{0%{-webkit-transform:rotate(0deg);transform:rotate(0)}to{-webkit-transform:rotate(360deg);transform:rotate(360deg)}}.jupyter-wrapper .bp3-spinner{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;overflow:visible;vertical-align:middle}.jupyter-wrapper .bp3-spinner svg{display:block}.jupyter-wrapper .bp3-spinner path{fill-opacity:0}.jupyter-wrapper .bp3-spinner .bp3-spinner-head{stroke:#5c7080cc;stroke-linecap:round;-webkit-transform-origin:center;transform-origin:center;-webkit-transition:stroke-dashoffset .2s cubic-bezier(.4,1,.75,.9);transition:stroke-dashoffset .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-spinner .bp3-spinner-track{stroke:#5c708033}.jupyter-wrapper .bp3-spinner-animation{-webkit-animation:pt-spinner-animation .5s linear infinite;animation:pt-spinner-animation .5s linear infinite}.jupyter-wrapper .bp3-no-spin>.bp3-spinner-animation{-webkit-animation:none;animation:none}.jupyter-wrapper .bp3-dark .bp3-spinner .bp3-spinner-head{stroke:#8a9ba8}.jupyter-wrapper .bp3-dark .bp3-spinner .bp3-spinner-track{stroke:#10161a80}.jupyter-wrapper .bp3-spinner.bp3-intent-primary .bp3-spinner-head{stroke:#137cbd}.jupyter-wrapper .bp3-spinner.bp3-intent-success .bp3-spinner-head{stroke:#0f9960}.jupyter-wrapper .bp3-spinner.bp3-intent-warning .bp3-spinner-head{stroke:#d9822b}.jupyter-wrapper .bp3-spinner.bp3-intent-danger .bp3-spinner-head{stroke:#db3737}.jupyter-wrapper .bp3-tabs.bp3-vertical{display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab{border-radius:3px;padding:0 10px;width:100%}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab[aria-selected=true]{background-color:#137cbd33;-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-list .bp3-tab-indicator-wrapper .bp3-tab-indicator{background-color:#137cbd33;border-radius:3px;bottom:0;height:auto;left:0;right:0;top:0}.jupyter-wrapper .bp3-tabs.bp3-vertical>.bp3-tab-panel{margin-top:0;padding-left:20px}.jupyter-wrapper .bp3-tab-list{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end;border:none;display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;list-style:none;margin:0;padding:0;position:relative}.jupyter-wrapper .bp3-tab-list>*:not(:last-child){margin-right:20px}.jupyter-wrapper .bp3-tab{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;color:#182026;cursor:pointer;-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;font-size:14px;line-height:30px;max-width:100%;position:relative;vertical-align:top}.jupyter-wrapper .bp3-tab a{color:inherit;display:block;text-decoration:none}.jupyter-wrapper .bp3-tab-indicator-wrapper~.bp3-tab{background-color:transparent!important;-webkit-box-shadow:none!important;box-shadow:none!important}.jupyter-wrapper .bp3-tab[aria-disabled=true]{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tab[aria-selected=true]{border-radius:0;-webkit-box-shadow:inset 0 -3px 0 #106ba3;box-shadow:inset 0 -3px #106ba3}.jupyter-wrapper .bp3-tab[aria-selected=true],.jupyter-wrapper .bp3-tab:not([aria-disabled=true]):hover{color:#106ba3}.jupyter-wrapper .bp3-tab:focus{-moz-outline-radius:0}.jupyter-wrapper .bp3-large>.bp3-tab{font-size:16px;line-height:40px}.jupyter-wrapper .bp3-tab-panel{margin-top:20px}.jupyter-wrapper .bp3-tab-panel[aria-hidden=true]{display:none}.jupyter-wrapper .bp3-tab-indicator-wrapper{left:0;pointer-events:none;position:absolute;top:0;-webkit-transform:translateX(0),translateY(0);transform:translate(0),translateY(0);-webkit-transition:height,width,-webkit-transform;transition:height,width,-webkit-transform;transition:height,transform,width;transition:height,transform,width,-webkit-transform;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tab-indicator-wrapper .bp3-tab-indicator{background-color:#106ba3;bottom:0;height:3px;left:0;position:absolute;right:0}.jupyter-wrapper .bp3-tab-indicator-wrapper.bp3-no-animation{-webkit-transition:none;transition:none}.jupyter-wrapper .bp3-dark .bp3-tab{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tab[aria-disabled=true]{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tab[aria-selected=true]{-webkit-box-shadow:inset 0 -3px 0 #48aff0;box-shadow:inset 0 -3px #48aff0}.jupyter-wrapper .bp3-dark .bp3-tab[aria-selected=true],.jupyter-wrapper .bp3-dark .bp3-tab:not([aria-disabled=true]):hover{color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-tab-indicator{background-color:#48aff0}.jupyter-wrapper .bp3-flex-expander{-webkit-box-flex:1;-ms-flex:1 1;flex:1 1}.jupyter-wrapper .bp3-tag{display:-webkit-inline-box;display:-ms-inline-flexbox;display:inline-flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;background-color:#5c7080;border:none;border-radius:3px;-webkit-box-shadow:none;box-shadow:none;color:#f5f8fa;font-size:12px;line-height:16px;max-width:100%;min-height:20px;min-width:20px;padding:2px 6px;position:relative}.jupyter-wrapper .bp3-tag.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-interactive:hover{background-color:#5c7080d9}.jupyter-wrapper .bp3-tag.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-interactive:active{background-color:#5c7080b3}.jupyter-wrapper .bp3-tag>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag:before,.jupyter-wrapper .bp3-tag>*{margin-right:4px}.jupyter-wrapper .bp3-tag:empty:before,.jupyter-wrapper .bp3-tag>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag:focus{outline:rgba(19,124,189,.6) auto 2px;outline-offset:0;-moz-outline-radius:6px}.jupyter-wrapper .bp3-tag.bp3-round{border-radius:30px;padding-left:8px;padding-right:8px}.jupyter-wrapper .bp3-dark .bp3-tag{background-color:#bfccd6;color:#182026}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive:hover{background-color:#bfccd6d9}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-interactive:active{background-color:#bfccd6b3}.jupyter-wrapper .bp3-dark .bp3-tag>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tag .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tag .bp3-icon-large{fill:currentColor}.jupyter-wrapper .bp3-tag>.bp3-icon,.jupyter-wrapper .bp3-tag .bp3-icon-standard,.jupyter-wrapper .bp3-tag .bp3-icon-large{fill:#fff}.jupyter-wrapper .bp3-tag.bp3-large,.jupyter-wrapper .bp3-large .bp3-tag{font-size:14px;line-height:20px;min-height:30px;min-width:30px;padding:5px 10px}.jupyter-wrapper .bp3-tag.bp3-large:before,.jupyter-wrapper .bp3-tag.bp3-large>*,.jupyter-wrapper .bp3-large .bp3-tag:before,.jupyter-wrapper .bp3-large .bp3-tag>*{margin-right:7px}.jupyter-wrapper .bp3-tag.bp3-large:empty:before,.jupyter-wrapper .bp3-tag.bp3-large>:last-child,.jupyter-wrapper .bp3-large .bp3-tag:empty:before,.jupyter-wrapper .bp3-large .bp3-tag>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag.bp3-large.bp3-round,.jupyter-wrapper .bp3-large .bp3-tag.bp3-round{padding-left:12px;padding-right:12px}.jupyter-wrapper .bp3-tag.bp3-intent-primary{background:#137cbd;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbdd9}.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-primary.bp3-interactive:active{background-color:#137cbdb3}.jupyter-wrapper .bp3-tag.bp3-intent-success{background:#0f9960;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive:hover{background-color:#0f9960d9}.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-success.bp3-interactive:active{background-color:#0f9960b3}.jupyter-wrapper .bp3-tag.bp3-intent-warning{background:#d9822b;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822bd9}.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-warning.bp3-interactive:active{background-color:#d9822bb3}.jupyter-wrapper .bp3-tag.bp3-intent-danger{background:#db3737;color:#fff}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive:hover{background-color:#db3737d9}.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-intent-danger.bp3-interactive:active{background-color:#db3737b3}.jupyter-wrapper .bp3-tag.bp3-fill{display:-webkit-box;display:-ms-flexbox;display:flex;width:100%}.jupyter-wrapper .bp3-tag.bp3-minimal>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal .bp3-icon-large{fill:#5c7080}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]){background-color:#8a9ba833;color:#182026}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:hover{background-color:#5c70804d}.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:active{background-color:#5c708066}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]){color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:hover{background-color:#bfccd64d}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]).bp3-interactive:active{background-color:#bfccd666}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-])>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]) .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal:not([class*=bp3-intent-]) .bp3-icon-large{fill:#a7b6c2}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary{background-color:#137cbd26;color:#106ba3}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbd40}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:active{background-color:#137cbd59}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-primary .bp3-icon-large{fill:#137cbd}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary{background-color:#137cbd40;color:#48aff0}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:hover{background-color:#137cbd59}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-primary.bp3-interactive:active{background-color:#137cbd73}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success{background-color:#0f996026;color:#0d8050}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:hover{background-color:#0f996040}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:active{background-color:#0f996059}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-success .bp3-icon-large{fill:#0f9960}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success{background-color:#0f996040;color:#3dcc91}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:hover{background-color:#0f996059}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-success.bp3-interactive:active{background-color:#0f996073}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning{background-color:#d9822b26;color:#bf7326}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822b40}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:active{background-color:#d9822b59}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-warning .bp3-icon-large{fill:#d9822b}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning{background-color:#d9822b40;color:#ffb366}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:hover{background-color:#d9822b59}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-warning.bp3-interactive:active{background-color:#d9822b73}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger{background-color:#db373726;color:#c23030}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:hover{background-color:#db373740}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:active{background-color:#db373759}.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger>.bp3-icon,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger .bp3-icon-standard,.jupyter-wrapper .bp3-tag.bp3-minimal.bp3-intent-danger .bp3-icon-large{fill:#db3737}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger{background-color:#db373740;color:#ff7373}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive{cursor:pointer}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:hover{background-color:#db373759}.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive.bp3-active,.jupyter-wrapper .bp3-dark .bp3-tag.bp3-minimal.bp3-intent-danger.bp3-interactive:active{background-color:#db373773}.jupyter-wrapper .bp3-tag-remove{background:none;border:none;color:inherit;cursor:pointer;display:-webkit-box;display:-ms-flexbox;display:flex;margin-bottom:-2px;margin-right:-6px!important;margin-top:-2px;opacity:.5;padding:2px 2px 2px 0}.jupyter-wrapper .bp3-tag-remove:hover{background:none;opacity:.8;text-decoration:none}.jupyter-wrapper .bp3-tag-remove:active{opacity:1}.jupyter-wrapper .bp3-tag-remove:empty:before{font-family:Icons16,sans-serif;font-size:16px;font-style:normal;font-weight:400;line-height:1;-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;content:\"\ue6d7\"}.jupyter-wrapper .bp3-large .bp3-tag-remove{margin-right:-10px!important;padding:0 5px 0 0}.jupyter-wrapper .bp3-large .bp3-tag-remove:empty:before{font-family:Icons20,sans-serif;font-size:20px;font-style:normal;font-weight:400;line-height:1}.jupyter-wrapper .bp3-tag-input{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;cursor:text;height:auto;line-height:inherit;min-height:30px;padding-left:5px;padding-right:0}.jupyter-wrapper .bp3-tag-input>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag-input>.bp3-tag-input-values{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-icon{color:#5c7080;margin-left:2px;margin-right:7px;margin-top:7px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-orient:horizontal;-webkit-box-direction:normal;-ms-flex-direction:row;flex-direction:row;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-ms-flex-item-align:stretch;align-self:stretch;-ms-flex-wrap:wrap;flex-wrap:wrap;margin-right:7px;margin-top:5px;min-width:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{-webkit-box-flex:0;-ms-flex-positive:0;flex-grow:0;-ms-flex-negative:0;flex-shrink:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>.bp3-fill{-webkit-box-flex:1;-ms-flex-positive:1;flex-grow:1;-ms-flex-negative:1;flex-shrink:1}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:before,.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{margin-right:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:empty:before,.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values:first-child .bp3-input-ghost:first-child{padding-left:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag-input-values>*{margin-bottom:5px}.jupyter-wrapper .bp3-tag-input .bp3-tag{overflow-wrap:break-word}.jupyter-wrapper .bp3-tag-input .bp3-tag.bp3-active{outline:rgba(19,124,189,.6) auto 2px;outline-offset:0;-moz-outline-radius:6px}.jupyter-wrapper .bp3-tag-input .bp3-input-ghost{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;line-height:20px;width:80px}.jupyter-wrapper .bp3-tag-input .bp3-input-ghost:disabled,.jupyter-wrapper .bp3-tag-input .bp3-input-ghost.bp3-disabled{cursor:not-allowed}.jupyter-wrapper .bp3-tag-input .bp3-button,.jupyter-wrapper .bp3-tag-input .bp3-spinner{margin:3px 3px 3px 0}.jupyter-wrapper .bp3-tag-input .bp3-button{min-height:24px;min-width:24px;padding:0 7px}.jupyter-wrapper .bp3-tag-input.bp3-large{height:auto;min-height:40px}.jupyter-wrapper .bp3-tag-input.bp3-large:before,.jupyter-wrapper .bp3-tag-input.bp3-large>*{margin-right:10px}.jupyter-wrapper .bp3-tag-input.bp3-large:empty:before,.jupyter-wrapper .bp3-tag-input.bp3-large>:last-child{margin-right:0}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-tag-input-icon{margin-left:5px;margin-top:10px}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-input-ghost{line-height:30px}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-button{min-height:30px;min-width:30px;padding:5px 10px;margin:5px 5px 5px 0}.jupyter-wrapper .bp3-tag-input.bp3-large .bp3-spinner{margin:8px 8px 8px 0}.jupyter-wrapper .bp3-tag-input.bp3-active{background-color:#fff;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-primary{-webkit-box-shadow:0 0 0 1px #106ba3,0 0 0 3px rgba(16,107,163,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #106ba3,0 0 0 3px #106ba34d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-success{-webkit-box-shadow:0 0 0 1px #0d8050,0 0 0 3px rgba(13,128,80,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #0d8050,0 0 0 3px #0d80504d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-warning{-webkit-box-shadow:0 0 0 1px #bf7326,0 0 0 3px rgba(191,115,38,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #bf7326,0 0 0 3px #bf73264d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-tag-input.bp3-active.bp3-intent-danger{-webkit-box-shadow:0 0 0 1px #c23030,0 0 0 3px rgba(194,48,48,.3),inset 0 1px 1px rgba(16,22,26,.2);box-shadow:0 0 0 1px #c23030,0 0 0 3px #c230304d,inset 0 1px 1px #10161a33}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-tag-input-icon,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-tag-input-icon{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost{color:#f5f8fa}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-webkit-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-webkit-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-moz-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-moz-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost:-ms-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost:-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::-ms-input-placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::-ms-input-placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input .bp3-input-ghost::placeholder,.jupyter-wrapper .bp3-tag-input.bp3-dark .bp3-input-ghost::placeholder{color:#a7b6c299}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active{background-color:#10161a4d;-webkit-box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px rgba(19,124,189,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #137cbd,0 0 0 1px #137cbd,0 0 0 3px #137cbd4d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-primary,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-primary{-webkit-box-shadow:0 0 0 1px #106ba3,0 0 0 3px rgba(16,107,163,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #106ba3,0 0 0 3px #106ba34d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-success,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-success{-webkit-box-shadow:0 0 0 1px #0d8050,0 0 0 3px rgba(13,128,80,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #0d8050,0 0 0 3px #0d80504d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-warning,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-warning{-webkit-box-shadow:0 0 0 1px #bf7326,0 0 0 3px rgba(191,115,38,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #bf7326,0 0 0 3px #bf73264d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-dark .bp3-tag-input.bp3-active.bp3-intent-danger,.jupyter-wrapper .bp3-tag-input.bp3-dark.bp3-active.bp3-intent-danger{-webkit-box-shadow:0 0 0 1px #c23030,0 0 0 3px rgba(194,48,48,.3),inset 0 0 0 1px rgba(16,22,26,.3),inset 0 1px 1px rgba(16,22,26,.4);box-shadow:0 0 0 1px #c23030,0 0 0 3px #c230304d,inset 0 0 0 1px #10161a4d,inset 0 1px 1px #10161a66}.jupyter-wrapper .bp3-input-ghost{background:none;border:none;-webkit-box-shadow:none;box-shadow:none;padding:0}.jupyter-wrapper .bp3-input-ghost::-webkit-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::-moz-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost:-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::-ms-input-placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost::placeholder{color:#5c708099;opacity:1}.jupyter-wrapper .bp3-input-ghost:focus{outline:none!important}.jupyter-wrapper .bp3-toast{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start;background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;display:-webkit-box;display:-ms-flexbox;display:flex;margin:20px 0 0;max-width:500px;min-width:300px;pointer-events:all;position:relative!important}.jupyter-wrapper .bp3-toast.bp3-toast-enter,.jupyter-wrapper .bp3-toast.bp3-toast-appear{-webkit-transform:translateY(-40px);transform:translateY(-40px)}.jupyter-wrapper .bp3-toast.bp3-toast-enter-active,.jupyter-wrapper .bp3-toast.bp3-toast-appear-active{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-toast.bp3-toast-enter~.bp3-toast,.jupyter-wrapper .bp3-toast.bp3-toast-appear~.bp3-toast{-webkit-transform:translateY(-40px);transform:translateY(-40px)}.jupyter-wrapper .bp3-toast.bp3-toast-enter-active~.bp3-toast,.jupyter-wrapper .bp3-toast.bp3-toast-appear-active~.bp3-toast{-webkit-transform:translateY(0);transform:translateY(0);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.54,1.12,.38,1.11);transition-timing-function:cubic-bezier(.54,1.12,.38,1.11)}.jupyter-wrapper .bp3-toast.bp3-toast-exit{opacity:1;-webkit-filter:blur(0);filter:blur(0)}.jupyter-wrapper .bp3-toast.bp3-toast-exit-active{opacity:0;-webkit-filter:blur(10px);filter:blur(10px);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.3s;transition-duration:.3s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:opacity,filter;transition-property:opacity,filter,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-toast.bp3-toast-exit~.bp3-toast{-webkit-transform:translateY(0);transform:translateY(0)}.jupyter-wrapper .bp3-toast.bp3-toast-exit-active~.bp3-toast{-webkit-transform:translateY(-40px);transform:translateY(-40px);-webkit-transition-delay:50ms;transition-delay:50ms;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-toast .bp3-button-group{-webkit-box-flex:0;-ms-flex:0 0 auto;flex:0 0 auto;padding:5px 5px 5px 0}.jupyter-wrapper .bp3-toast>.bp3-icon{color:#5c7080;margin:12px 0 12px 12px}.jupyter-wrapper .bp3-toast.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-toast{background-color:#394b59;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-toast.bp3-dark>.bp3-icon,.jupyter-wrapper .bp3-dark .bp3-toast>.bp3-icon{color:#a7b6c2}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] a{color:#ffffffb3}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] a:hover{color:#fff}.jupyter-wrapper .bp3-toast[class*=bp3-intent-]>.bp3-icon{color:#fff}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:before,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button .bp3-icon,.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:active{color:#ffffffb3!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:focus{outline-color:#ffffff80}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:hover{background-color:#ffffff26!important;color:#fff!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:active{background-color:#ffffff4d!important;color:#fff!important}.jupyter-wrapper .bp3-toast[class*=bp3-intent-] .bp3-button:after{background:rgba(255,255,255,.3)!important}.jupyter-wrapper .bp3-toast.bp3-intent-primary{background-color:#137cbd;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-success{background-color:#0f9960;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-warning{background-color:#d9822b;color:#fff}.jupyter-wrapper .bp3-toast.bp3-intent-danger{background-color:#db3737;color:#fff}.jupyter-wrapper .bp3-toast-message{-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;padding:11px;word-break:break-word}.jupyter-wrapper .bp3-toast-container{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box!important;display:-ms-flexbox!important;display:flex!important;-webkit-box-orient:vertical;-webkit-box-direction:normal;-ms-flex-direction:column;flex-direction:column;left:0;overflow:hidden;padding:0 20px 20px;pointer-events:none;right:0;z-index:40}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-in-portal{position:fixed}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-inline{position:absolute}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-top{top:0}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-bottom{bottom:0;-webkit-box-orient:vertical;-webkit-box-direction:reverse;-ms-flex-direction:column-reverse;flex-direction:column-reverse;top:auto}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-left{-webkit-box-align:start;-ms-flex-align:start;align-items:flex-start}.jupyter-wrapper .bp3-toast-container.bp3-toast-container-right{-webkit-box-align:end;-ms-flex-align:end;align-items:flex-end}.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-enter:not(.bp3-toast-enter-active),.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-enter:not(.bp3-toast-enter-active)~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-appear:not(.bp3-toast-appear-active),.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-appear:not(.bp3-toast-appear-active)~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-exit-active~.bp3-toast,.jupyter-wrapper .bp3-toast-container-bottom .bp3-toast.bp3-toast-leave-active~.bp3-toast{-webkit-transform:translateY(60px);transform:translateY(60px)}.jupyter-wrapper .bp3-tooltip{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 2px 4px rgba(16,22,26,.2),0 8px 24px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 2px 4px #10161a33,0 8px 24px #10161a33;-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow{height:22px;position:absolute;width:22px}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow:before{height:14px;margin:4px;width:14px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip{margin-bottom:11px;margin-top:-11px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow{bottom:-8px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(-90deg);transform:rotate(-90deg)}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip{margin-left:11px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow{left:-8px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(0);transform:rotate(0)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip{margin-top:11px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow{top:-8px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip{margin-left:-11px;margin-right:11px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow{right:-8px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow svg{-webkit-transform:rotate(180deg);transform:rotate(180deg)}.jupyter-wrapper .bp3-tether-element-attached-middle>.bp3-tooltip>.bp3-popover-arrow{top:50%;-webkit-transform:translateY(-50%);transform:translateY(-50%)}.jupyter-wrapper .bp3-tether-element-attached-center>.bp3-tooltip>.bp3-popover-arrow{right:50%;-webkit-transform:translateX(50%);transform:translate(50%)}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-target-attached-top>.bp3-tooltip>.bp3-popover-arrow{top:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-right.bp3-tether-target-attached-right>.bp3-tooltip>.bp3-popover-arrow{right:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-left.bp3-tether-target-attached-left>.bp3-tooltip>.bp3-popover-arrow{left:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-target-attached-bottom>.bp3-tooltip>.bp3-popover-arrow{bottom:-.22183px}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:top left;transform-origin:top left}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:top center;transform-origin:top center}.jupyter-wrapper .bp3-tether-element-attached-top.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:top right;transform-origin:top right}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:center left;transform-origin:center left}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:center center;transform-origin:center center}.jupyter-wrapper .bp3-tether-element-attached-middle.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:center right;transform-origin:center right}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-left>.bp3-tooltip{-webkit-transform-origin:bottom left;transform-origin:bottom left}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-center>.bp3-tooltip{-webkit-transform-origin:bottom center;transform-origin:bottom center}.jupyter-wrapper .bp3-tether-element-attached-bottom.bp3-tether-element-attached-right>.bp3-tooltip{-webkit-transform-origin:bottom right;transform-origin:bottom right}.jupyter-wrapper .bp3-tooltip .bp3-popover-content{background:#394b59;color:#f5f8fa}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.2);box-shadow:1px 1px 6px #10161a33}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.1}.jupyter-wrapper .bp3-tooltip .bp3-popover-arrow-fill{fill:#394b59}.jupyter-wrapper .bp3-popover-enter>.bp3-tooltip,.jupyter-wrapper .bp3-popover-appear>.bp3-tooltip{-webkit-transform:scale(.8);transform:scale(.8)}.jupyter-wrapper .bp3-popover-enter-active>.bp3-tooltip,.jupyter-wrapper .bp3-popover-appear-active>.bp3-tooltip{-webkit-transform:scale(1);transform:scale(1);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-popover-exit>.bp3-tooltip{-webkit-transform:scale(1);transform:scale(1)}.jupyter-wrapper .bp3-popover-exit-active>.bp3-tooltip{-webkit-transform:scale(.8);transform:scale(.8);-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.1s;transition-duration:.1s;-webkit-transition-property:-webkit-transform;transition-property:-webkit-transform;transition-property:transform;transition-property:transform,-webkit-transform;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tooltip .bp3-popover-content{padding:10px 12px}.jupyter-wrapper .bp3-tooltip.bp3-dark,.jupyter-wrapper .bp3-dark .bp3-tooltip{-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 2px 4px rgba(16,22,26,.4),0 8px 24px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 2px 4px #10161a66,0 8px 24px #10161a66}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-content,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-content{background:#e1e8ed;color:#394b59}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow:before,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow:before{-webkit-box-shadow:1px 1px 6px rgba(16,22,26,.4);box-shadow:1px 1px 6px #10161a66}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow-border,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow-border{fill:#10161a;fill-opacity:.2}.jupyter-wrapper .bp3-tooltip.bp3-dark .bp3-popover-arrow-fill,.jupyter-wrapper .bp3-dark .bp3-tooltip .bp3-popover-arrow-fill{fill:#e1e8ed}.jupyter-wrapper .bp3-tooltip.bp3-intent-primary .bp3-popover-content{background:#137cbd;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-primary .bp3-popover-arrow-fill{fill:#137cbd}.jupyter-wrapper .bp3-tooltip.bp3-intent-success .bp3-popover-content{background:#0f9960;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-success .bp3-popover-arrow-fill{fill:#0f9960}.jupyter-wrapper .bp3-tooltip.bp3-intent-warning .bp3-popover-content{background:#d9822b;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-warning .bp3-popover-arrow-fill{fill:#d9822b}.jupyter-wrapper .bp3-tooltip.bp3-intent-danger .bp3-popover-content{background:#db3737;color:#fff}.jupyter-wrapper .bp3-tooltip.bp3-intent-danger .bp3-popover-arrow-fill{fill:#db3737}.jupyter-wrapper .bp3-tooltip-indicator{border-bottom:dotted 1px;cursor:help}.jupyter-wrapper .bp3-tree .bp3-icon,.jupyter-wrapper .bp3-tree .bp3-icon-standard,.jupyter-wrapper .bp3-tree .bp3-icon-large{color:#5c7080}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-primary{color:#137cbd}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-success{color:#0f9960}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-warning{color:#d9822b}.jupyter-wrapper .bp3-tree .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-tree .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-tree .bp3-icon-large.bp3-intent-danger{color:#db3737}.jupyter-wrapper .bp3-tree-node-list{list-style:none;margin:0;padding-left:0}.jupyter-wrapper .bp3-tree-root{background-color:transparent;cursor:default;padding-left:0;position:relative}.jupyter-wrapper .bp3-tree-node-content-0{padding-left:0}.jupyter-wrapper .bp3-tree-node-content-1{padding-left:23px}.jupyter-wrapper .bp3-tree-node-content-2{padding-left:46px}.jupyter-wrapper .bp3-tree-node-content-3{padding-left:69px}.jupyter-wrapper .bp3-tree-node-content-4{padding-left:92px}.jupyter-wrapper .bp3-tree-node-content-5{padding-left:115px}.jupyter-wrapper .bp3-tree-node-content-6{padding-left:138px}.jupyter-wrapper .bp3-tree-node-content-7{padding-left:161px}.jupyter-wrapper .bp3-tree-node-content-8{padding-left:184px}.jupyter-wrapper .bp3-tree-node-content-9{padding-left:207px}.jupyter-wrapper .bp3-tree-node-content-10{padding-left:230px}.jupyter-wrapper .bp3-tree-node-content-11{padding-left:253px}.jupyter-wrapper .bp3-tree-node-content-12{padding-left:276px}.jupyter-wrapper .bp3-tree-node-content-13{padding-left:299px}.jupyter-wrapper .bp3-tree-node-content-14{padding-left:322px}.jupyter-wrapper .bp3-tree-node-content-15{padding-left:345px}.jupyter-wrapper .bp3-tree-node-content-16{padding-left:368px}.jupyter-wrapper .bp3-tree-node-content-17{padding-left:391px}.jupyter-wrapper .bp3-tree-node-content-18{padding-left:414px}.jupyter-wrapper .bp3-tree-node-content-19{padding-left:437px}.jupyter-wrapper .bp3-tree-node-content-20{padding-left:460px}.jupyter-wrapper .bp3-tree-node-content{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex;height:30px;padding-right:5px;width:100%}.jupyter-wrapper .bp3-tree-node-content:hover{background-color:#bfccd666}.jupyter-wrapper .bp3-tree-node-caret,.jupyter-wrapper .bp3-tree-node-caret-none{min-width:30px}.jupyter-wrapper .bp3-tree-node-caret{color:#5c7080;cursor:pointer;padding:7px;-webkit-transform:rotate(0deg);transform:rotate(0);-webkit-transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:-webkit-transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9);transition:transform .2s cubic-bezier(.4,1,.75,.9),-webkit-transform .2s cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-tree-node-caret:hover{color:#182026}.jupyter-wrapper .bp3-dark .bp3-tree-node-caret{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tree-node-caret:hover{color:#f5f8fa}.jupyter-wrapper .bp3-tree-node-caret.bp3-tree-node-caret-open{-webkit-transform:rotate(90deg);transform:rotate(90deg)}.jupyter-wrapper .bp3-tree-node-caret.bp3-icon-standard:before{content:\"\ue695\"}.jupyter-wrapper .bp3-tree-node-icon{margin-right:7px;position:relative}.jupyter-wrapper .bp3-tree-node-label{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;word-wrap:normal;-webkit-box-flex:1;-ms-flex:1 1 auto;flex:1 1 auto;position:relative;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-tree-node-label span{display:inline}.jupyter-wrapper .bp3-tree-node-secondary-label{padding:0 5px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .bp3-tree-node-secondary-label .bp3-popover-wrapper,.jupyter-wrapper .bp3-tree-node-secondary-label .bp3-popover-target{-webkit-box-align:center;-ms-flex-align:center;align-items:center;display:-webkit-box;display:-ms-flexbox;display:flex}.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-content{background-color:inherit;color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-caret,.jupyter-wrapper .bp3-tree-node.bp3-disabled .bp3-tree-node-icon{color:#5c708099;cursor:not-allowed}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content{background-color:#137cbd}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon-standard,.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-icon-large{color:#fff}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-tree-node-caret:before{color:#ffffffb3}.jupyter-wrapper .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content .bp3-tree-node-caret:hover:before{color:#fff}.jupyter-wrapper .bp3-dark .bp3-tree-node-content:hover{background-color:#5c70804d}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large{color:#a7b6c2}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-primary,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-primary{color:#137cbd}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-success,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-success{color:#0f9960}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-warning,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-warning{color:#d9822b}.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-standard.bp3-intent-danger,.jupyter-wrapper .bp3-dark .bp3-tree .bp3-icon-large.bp3-intent-danger{color:#db3737}.jupyter-wrapper .bp3-dark .bp3-tree-node.bp3-tree-node-selected>.bp3-tree-node-content{background-color:#137cbd}.jupyter-wrapper .bp3-omnibar{-webkit-filter:blur(0);filter:blur(0);opacity:1;background-color:#fff;border-radius:3px;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.1),0 4px 8px rgba(16,22,26,.2),0 18px 46px 6px rgba(16,22,26,.2);box-shadow:0 0 0 1px #10161a1a,0 4px 8px #10161a33,0 18px 46px 6px #10161a33;left:calc(50% - 250px);top:20vh;width:500px;z-index:21}.jupyter-wrapper .bp3-omnibar.bp3-overlay-enter,.jupyter-wrapper .bp3-omnibar.bp3-overlay-appear{-webkit-filter:blur(20px);filter:blur(20px);opacity:.2}.jupyter-wrapper .bp3-omnibar.bp3-overlay-enter-active,.jupyter-wrapper .bp3-omnibar.bp3-overlay-appear-active{-webkit-filter:blur(0);filter:blur(0);opacity:1;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:filter,opacity;transition-property:filter,opacity,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-omnibar.bp3-overlay-exit{-webkit-filter:blur(0);filter:blur(0);opacity:1}.jupyter-wrapper .bp3-omnibar.bp3-overlay-exit-active{-webkit-filter:blur(20px);filter:blur(20px);opacity:.2;-webkit-transition-delay:0;transition-delay:0;-webkit-transition-duration:.2s;transition-duration:.2s;-webkit-transition-property:opacity,-webkit-filter;transition-property:opacity,-webkit-filter;transition-property:filter,opacity;transition-property:filter,opacity,-webkit-filter;-webkit-transition-timing-function:cubic-bezier(.4,1,.75,.9);transition-timing-function:cubic-bezier(.4,1,.75,.9)}.jupyter-wrapper .bp3-omnibar .bp3-input{background-color:transparent;border-radius:0}.jupyter-wrapper .bp3-omnibar .bp3-input,.jupyter-wrapper .bp3-omnibar .bp3-input:focus{-webkit-box-shadow:none;box-shadow:none}.jupyter-wrapper .bp3-omnibar .bp3-menu{background-color:transparent;border-radius:0;-webkit-box-shadow:inset 0 1px 0 rgba(16,22,26,.15);box-shadow:inset 0 1px #10161a26;max-height:calc(60vh - 40px);overflow:auto}.jupyter-wrapper .bp3-omnibar .bp3-menu:empty{display:none}.jupyter-wrapper .bp3-dark .bp3-omnibar,.jupyter-wrapper .bp3-omnibar.bp3-dark{background-color:#30404d;-webkit-box-shadow:0 0 0 1px rgba(16,22,26,.2),0 4px 8px rgba(16,22,26,.4),0 18px 46px 6px rgba(16,22,26,.4);box-shadow:0 0 0 1px #10161a33,0 4px 8px #10161a66,0 18px 46px 6px #10161a66}.jupyter-wrapper .bp3-omnibar-overlay .bp3-overlay-backdrop{background-color:#10161a33}.jupyter-wrapper .bp3-multi-select{min-width:150px}.jupyter-wrapper .bp3-multi-select-popover .bp3-menu{max-height:300px;max-width:400px;overflow:auto}.jupyter-wrapper .bp3-select-popover .bp3-popover-content{padding:5px}.jupyter-wrapper .bp3-select-popover .bp3-input-group{margin-bottom:0}.jupyter-wrapper .bp3-select-popover .bp3-menu{max-height:300px;max-width:400px;overflow:auto;padding:0}.jupyter-wrapper .bp3-select-popover .bp3-menu:not(:first-child){padding-top:5px}.jupyter-wrapper :root{--jp-icon-add-above: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5MikiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik00Ljc1IDQuOTMwNjZINi42MjVWNi44MDU2NkM2LjYyNSA3LjAxMTkxIDYuNzkzNzUgNy4xODA2NiA3IDcuMTgwNjZDNy4yMDYyNSA3LjE4MDY2IDcuMzc1IDcuMDExOTEgNy4zNzUgNi44MDU2NlY0LjkzMDY2SDkuMjVDOS40NTYyNSA0LjkzMDY2IDkuNjI1IDQuNzYxOTEgOS42MjUgNC41NTU2NkM5LjYyNSA0LjM0OTQxIDkuNDU2MjUgNC4xODA2NiA5LjI1IDQuMTgwNjZINy4zNzVWMi4zMDU2NkM3LjM3NSAyLjA5OTQxIDcuMjA2MjUgMS45MzA2NiA3IDEuOTMwNjZDNi43OTM3NSAxLjkzMDY2IDYuNjI1IDIuMDk5NDEgNi42MjUgMi4zMDU2NlY0LjE4MDY2SDQuNzVDNC41NDM3NSA0LjE4MDY2IDQuMzc1IDQuMzQ5NDEgNC4zNzUgNC41NTU2NkM0LjM3NSA0Ljc2MTkxIDQuNTQzNzUgNC45MzA2NiA0Ljc1IDQuOTMwNjZaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC43Ii8+CjwvZz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTExLjUgOS41VjExLjVMMi41IDExLjVWOS41TDExLjUgOS41Wk0xMiA4QzEyLjU1MjMgOCAxMyA4LjQ0NzcyIDEzIDlWMTJDMTMgMTIuNTUyMyAxMi41NTIzIDEzIDEyIDEzTDIgMTNDMS40NDc3MiAxMyAxIDEyLjU1MjMgMSAxMlY5QzEgOC40NDc3MiAxLjQ0NzcxIDggMiA4TDEyIDhaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5MiI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KC0xIDAgMCAxIDEwIDEuNTU1NjYpIi8+CjwvY2xpcFBhdGg+CjwvZGVmcz4KPC9zdmc+Cg==);--jp-icon-add-below: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPGcgY2xpcC1wYXRoPSJ1cmwoI2NsaXAwXzEzN18xOTQ5OCkiPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGQ9Ik05LjI1IDEwLjA2OTNMNy4zNzUgMTAuMDY5M0w3LjM3NSA4LjE5NDM0QzcuMzc1IDcuOTg4MDkgNy4yMDYyNSA3LjgxOTM0IDcgNy44MTkzNEM2Ljc5Mzc1IDcuODE5MzQgNi42MjUgNy45ODgwOSA2LjYyNSA4LjE5NDM0TDYuNjI1IDEwLjA2OTNMNC43NSAxMC4wNjkzQzQuNTQzNzUgMTAuMDY5MyA0LjM3NSAxMC4yMzgxIDQuMzc1IDEwLjQ0NDNDNC4zNzUgMTAuNjUwNiA0LjU0Mzc1IDEwLjgxOTMgNC43NSAxMC44MTkzTDYuNjI1IDEwLjgxOTNMNi42MjUgMTIuNjk0M0M2LjYyNSAxMi45MDA2IDYuNzkzNzUgMTMuMDY5MyA3IDEzLjA2OTNDNy4yMDYyNSAxMy4wNjkzIDcuMzc1IDEyLjkwMDYgNy4zNzUgMTIuNjk0M0w3LjM3NSAxMC44MTkzTDkuMjUgMTAuODE5M0M5LjQ1NjI1IDEwLjgxOTMgOS42MjUgMTAuNjUwNiA5LjYyNSAxMC40NDQzQzkuNjI1IDEwLjIzODEgOS40NTYyNSAxMC4wNjkzIDkuMjUgMTAuMDY5M1oiIGZpbGw9IiM2MTYxNjEiIHN0cm9rZT0iIzYxNjE2MSIgc3Ryb2tlLXdpZHRoPSIwLjciLz4KPC9nPgo8cGF0aCBjbGFzcz0ianAtaWNvbjMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMi41IDUuNUwyLjUgMy41TDExLjUgMy41TDExLjUgNS41TDIuNSA1LjVaTTIgN0MxLjQ0NzcyIDcgMSA2LjU1MjI4IDEgNkwxIDNDMSAyLjQ0NzcyIDEuNDQ3NzIgMiAyIDJMMTIgMkMxMi41NTIzIDIgMTMgMi40NDc3MiAxMyAzTDEzIDZDMTMgNi41NTIyOSAxMi41NTIzIDcgMTIgN0wyIDdaIiBmaWxsPSIjNjE2MTYxIi8+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzEzN18xOTQ5OCI+CjxyZWN0IGNsYXNzPSJqcC1pY29uMyIgd2lkdGg9IjYiIGhlaWdodD0iNiIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0ibWF0cml4KDEgMS43NDg0NmUtMDcgMS43NDg0NmUtMDcgLTEgNCAxMy40NDQzKSIvPgo8L2NsaXBQYXRoPgo8L2RlZnM+Cjwvc3ZnPgo=);--jp-icon-add: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDEzaC02djZoLTJ2LTZINXYtMmg2VjVoMnY2aDZ2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-bell: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE2IDE2IiB2ZXJzaW9uPSIxLjEiPgogICA8cGF0aCBjbGFzcz0ianAtaWNvbjIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzMzMzMzIgogICAgICBkPSJtOCAwLjI5Yy0xLjQgMC0yLjcgMC43My0zLjYgMS44LTEuMiAxLjUtMS40IDMuNC0xLjUgNS4yLTAuMTggMi4yLTAuNDQgNC0yLjMgNS4zbDAuMjggMS4zaDVjMC4wMjYgMC42NiAwLjMyIDEuMSAwLjcxIDEuNSAwLjg0IDAuNjEgMiAwLjYxIDIuOCAwIDAuNTItMC40IDAuNi0xIDAuNzEtMS41aDVsMC4yOC0xLjNjLTEuOS0wLjk3LTIuMi0zLjMtMi4zLTUuMy0wLjEzLTEuOC0wLjI2LTMuNy0xLjUtNS4yLTAuODUtMS0yLjItMS44LTMuNi0xLjh6bTAgMS40YzAuODggMCAxLjkgMC41NSAyLjUgMS4zIDAuODggMS4xIDEuMSAyLjcgMS4yIDQuNCAwLjEzIDEuNyAwLjIzIDMuNiAxLjMgNS4yaC0xMGMxLjEtMS42IDEuMi0zLjQgMS4zLTUuMiAwLjEzLTEuNyAwLjMtMy4zIDEuMi00LjQgMC41OS0wLjcyIDEuNi0xLjMgMi41LTEuM3ptLTAuNzQgMTJoMS41Yy0wLjAwMTUgMC4yOCAwLjAxNSAwLjc5LTAuNzQgMC43OS0wLjczIDAuMDAxNi0wLjcyLTAuNTMtMC43NC0wLjc5eiIgLz4KPC9zdmc+Cg==);--jp-icon-bug-dot: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiPgogICAgICAgIDxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTcuMTkgOEgyMFYxMEgxNy45MUMxNy45NiAxMC4zMyAxOCAxMC42NiAxOCAxMVYxMkgyMFYxNEgxOC41SDE4VjE0LjAyNzVDMTUuNzUgMTQuMjc2MiAxNCAxNi4xODM3IDE0IDE4LjVDMTQgMTkuMjA4IDE0LjE2MzUgMTkuODc3OSAxNC40NTQ5IDIwLjQ3MzlDMTMuNzA2MyAyMC44MTE3IDEyLjg3NTcgMjEgMTIgMjFDOS43OCAyMSA3Ljg1IDE5Ljc5IDYuODEgMThINFYxNkg2LjA5QzYuMDQgMTUuNjcgNiAxNS4zNCA2IDE1VjE0SDRWMTJINlYxMUM2IDEwLjY2IDYuMDQgMTAuMzMgNi4wOSAxMEg0VjhINi44MUM3LjI2IDcuMjIgNy44OCA2LjU1IDguNjIgNi4wNEw3IDQuNDFMOC40MSAzTDEwLjU5IDUuMTdDMTEuMDQgNS4wNiAxMS41MSA1IDEyIDVDMTIuNDkgNSAxMi45NiA1LjA2IDEzLjQyIDUuMTdMMTUuNTkgM0wxNyA0LjQxTDE1LjM3IDYuMDRDMTYuMTIgNi41NSAxNi43NCA3LjIyIDE3LjE5IDhaTTEwIDE2SDE0VjE0SDEwVjE2Wk0xMCAxMkgxNFYxMEgxMFYxMloiIGZpbGw9IiM2MTYxNjEiLz4KICAgICAgICA8cGF0aCBkPSJNMjIgMTguNUMyMiAyMC40MzMgMjAuNDMzIDIyIDE4LjUgMjJDMTYuNTY3IDIyIDE1IDIwLjQzMyAxNSAxOC41QzE1IDE2LjU2NyAxNi41NjcgMTUgMTguNSAxNUMyMC40MzMgMTUgMjIgMTYuNTY3IDIyIDE4LjVaIiBmaWxsPSIjNjE2MTYxIi8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-bug: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yMCA4aC0yLjgxYy0uNDUtLjc4LTEuMDctMS40NS0xLjgyLTEuOTZMMTcgNC40MSAxNS41OSAzbC0yLjE3IDIuMTdDMTIuOTYgNS4wNiAxMi40OSA1IDEyIDVjLS40OSAwLS45Ni4wNi0xLjQxLjE3TDguNDEgMyA3IDQuNDFsMS42MiAxLjYzQzcuODggNi41NSA3LjI2IDcuMjIgNi44MSA4SDR2MmgyLjA5Yy0uMDUuMzMtLjA5LjY2LS4wOSAxdjFINHYyaDJ2MWMwIC4zNC4wNC42Ny4wOSAxSDR2MmgyLjgxYzEuMDQgMS43OSAyLjk3IDMgNS4xOSAzczQuMTUtMS4yMSA1LjE5LTNIMjB2LTJoLTIuMDljLjA1LS4zMy4wOS0uNjYuMDktMXYtMWgydi0yaC0ydi0xYzAtLjM0LS4wNC0uNjctLjA5LTFIMjBWOHptLTYgOGgtNHYtMmg0djJ6bTAtNGgtNHYtMmg0djJ6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-build: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE0LjkgMTcuNDVDMTYuMjUgMTcuNDUgMTcuMzUgMTYuMzUgMTcuMzUgMTVDMTcuMzUgMTMuNjUgMTYuMjUgMTIuNTUgMTQuOSAxMi41NUMxMy41NCAxMi41NSAxMi40NSAxMy42NSAxMi40NSAxNUMxMi40NSAxNi4zNSAxMy41NCAxNy40NSAxNC45IDE3LjQ1Wk0yMC4xIDE1LjY4TDIxLjU4IDE2Ljg0QzIxLjcxIDE2Ljk1IDIxLjc1IDE3LjEzIDIxLjY2IDE3LjI5TDIwLjI2IDE5LjcxQzIwLjE3IDE5Ljg2IDIwIDE5LjkyIDE5LjgzIDE5Ljg2TDE4LjA5IDE5LjE2QzE3LjczIDE5LjQ0IDE3LjMzIDE5LjY3IDE2LjkxIDE5Ljg1TDE2LjY0IDIxLjdDMTYuNjIgMjEuODcgMTYuNDcgMjIgMTYuMyAyMkgxMy41QzEzLjMyIDIyIDEzLjE4IDIxLjg3IDEzLjE1IDIxLjdMMTIuODkgMTkuODVDMTIuNDYgMTkuNjcgMTIuMDcgMTkuNDQgMTEuNzEgMTkuMTZMOS45NjAwMiAxOS44NkM5LjgxMDAyIDE5LjkyIDkuNjIwMDIgMTkuODYgOS41NDAwMiAxOS43MUw4LjE0MDAyIDE3LjI5QzguMDUwMDIgMTcuMTMgOC4wOTAwMiAxNi45NSA4LjIyMDAyIDE2Ljg0TDkuNzAwMDIgMTUuNjhMOS42NTAwMSAxNUw5LjcwMDAyIDE0LjMxTDguMjIwMDIgMTMuMTZDOC4wOTAwMiAxMy4wNSA4LjA1MDAyIDEyLjg2IDguMTQwMDIgMTIuNzFMOS41NDAwMiAxMC4yOUM5LjYyMDAyIDEwLjEzIDkuODEwMDIgMTAuMDcgOS45NjAwMiAxMC4xM0wxMS43MSAxMC44NEMxMi4wNyAxMC41NiAxMi40NiAxMC4zMiAxMi44OSAxMC4xNUwxMy4xNSA4LjI4OTk4QzEzLjE4IDguMTI5OTggMTMuMzIgNy45OTk5OCAxMy41IDcuOTk5OThIMTYuM0MxNi40NyA3Ljk5OTk4IDE2LjYyIDguMTI5OTggMTYuNjQgOC4yODk5OEwxNi45MSAxMC4xNUMxNy4zMyAxMC4zMiAxNy43MyAxMC41NiAxOC4wOSAxMC44NEwxOS44MyAxMC4xM0MyMCAxMC4wNyAyMC4xNyAxMC4xMyAyMC4yNiAxMC4yOUwyMS42NiAxMi43MUMyMS43NSAxMi44NiAyMS43MSAxMy4wNSAyMS41OCAxMy4xNkwyMC4xIDE0LjMxTDIwLjE1IDE1TDIwLjEgMTUuNjhaIi8+CiAgICA8cGF0aCBkPSJNNy4zMjk2NiA3LjQ0NDU0QzguMDgzMSA3LjAwOTU0IDguMzM5MzIgNi4wNTMzMiA3LjkwNDMyIDUuMjk5ODhDNy40NjkzMiA0LjU0NjQzIDYuNTA4MSA0LjI4MTU2IDUuNzU0NjYgNC43MTY1NkM1LjM5MTc2IDQuOTI2MDggNS4xMjY5NSA1LjI3MTE4IDUuMDE4NDkgNS42NzU5NEM0LjkxMDA0IDYuMDgwNzEgNC45NjY4MiA2LjUxMTk4IDUuMTc2MzQgNi44NzQ4OEM1LjYxMTM0IDcuNjI4MzIgNi41NzYyMiA3Ljg3OTU0IDcuMzI5NjYgNy40NDQ1NFpNOS42NTcxOCA0Ljc5NTkzTDEwLjg2NzIgNC45NTE3OUMxMC45NjI4IDQuOTc3NDEgMTEuMDQwMiA1LjA3MTMzIDExLjAzODIgNS4xODc5M0wxMS4wMzg4IDYuOTg4OTNDMTEuMDQ1NSA3LjEwMDU0IDEwLjk2MTYgNy4xOTUxOCAxMC44NTUgNy4yMTA1NEw5LjY2MDAxIDcuMzgwODNMOS4yMzkxNSA4LjEzMTg4TDkuNjY5NjEgOS4yNTc0NUM5LjcwNzI5IDkuMzYyNzEgOS42NjkzNCA5LjQ3Njk5IDkuNTc0MDggOS41MzE5OUw4LjAxNTIzIDEwLjQzMkM3LjkxMTMxIDEwLjQ5MiA3Ljc5MzM3IDEwLjQ2NzcgNy43MjEwNSAxMC4zODI0TDYuOTg3NDggOS40MzE4OEw2LjEwOTMxIDkuNDMwODNMNS4zNDcwNCAxMC4zOTA1QzUuMjg5MDkgMTAuNDcwMiA1LjE3MzgzIDEwLjQ5MDUgNS4wNzE4NyAxMC40MzM5TDMuNTEyNDUgOS41MzI5M0MzLjQxMDQ5IDkuNDc2MzMgMy4zNzY0NyA5LjM1NzQxIDMuNDEwNzUgOS4yNTY3OUwzLjg2MzQ3IDguMTQwOTNMMy42MTc0OSA3Ljc3NDg4TDMuNDIzNDcgNy4zNzg4M0wyLjIzMDc1IDcuMjEyOTdDMi4xMjY0NyA3LjE5MjM1IDIuMDQwNDkgNy4xMDM0MiAyLjA0MjQ1IDYuOTg2ODJMMi4wNDE4NyA1LjE4NTgyQzIuMDQzODMgNS4wNjkyMiAyLjExOTA5IDQuOTc5NTggMi4yMTcwNCA0Ljk2OTIyTDMuNDIwNjUgNC43OTM5M0wzLjg2NzQ5IDQuMDI3ODhMMy40MTEwNSAyLjkxNzMxQzMuMzczMzcgMi44MTIwNCAzLjQxMTMxIDIuNjk3NzYgMy41MTUyMyAyLjYzNzc2TDUuMDc0MDggMS43Mzc3NkM1LjE2OTM0IDEuNjgyNzYgNS4yODcyOSAxLjcwNzA0IDUuMzU5NjEgMS43OTIzMUw2LjExOTE1IDIuNzI3ODhMNi45ODAwMSAyLjczODkzTDcuNzI0OTYgMS43ODkyMkM3Ljc5MTU2IDEuNzA0NTggNy45MTU0OCAxLjY3OTIyIDguMDA4NzkgMS43NDA4Mkw5LjU2ODIxIDIuNjQxODJDOS42NzAxNyAyLjY5ODQyIDkuNzEyODUgMi44MTIzNCA5LjY4NzIzIDIuOTA3OTdMOS4yMTcxOCA0LjAzMzgzTDkuNDYzMTYgNC4zOTk4OEw5LjY1NzE4IDQuNzk1OTNaIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-caret-down-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iOS45LDEzLjYgMy42LDcuNCA0LjQsNi42IDkuOSwxMi4yIDE1LjQsNi43IDE2LjEsNy40ICIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-caret-down-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNS45TDksOS43bDMuOC0zLjhsMS4yLDEuMmwtNC45LDVsLTQuOS01TDUuMiw1Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-caret-down: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik01LjIsNy41TDksMTEuMmwzLjgtMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-caret-left: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik0xMC44LDEyLjhMNy4xLDlsMy44LTMuOGwwLDcuNkgxMC44eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-caret-right: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiIHNoYXBlLXJlbmRlcmluZz0iZ2VvbWV0cmljUHJlY2lzaW9uIj4KICAgIDxwYXRoIGQ9Ik03LjIsNS4yTDEwLjksOWwtMy44LDMuOFY1LjJINy4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-caret-up-empty-thin: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwb2x5Z29uIGNsYXNzPSJzdDEiIHBvaW50cz0iMTUuNCwxMy4zIDkuOSw3LjcgNC40LDEzLjIgMy42LDEyLjUgOS45LDYuMyAxNi4xLDEyLjYgIi8+Cgk8L2c+Cjwvc3ZnPgo=);--jp-icon-caret-up: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSIgc2hhcGUtcmVuZGVyaW5nPSJnZW9tZXRyaWNQcmVjaXNpb24iPgoJCTxwYXRoIGQ9Ik01LjIsMTAuNUw5LDYuOGwzLjgsMy44SDUuMnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-case-sensitive: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgogIDxnIGNsYXNzPSJqcC1pY29uLWFjY2VudDIiIGZpbGw9IiNGRkYiPgogICAgPHBhdGggZD0iTTcuNiw4aDAuOWwzLjUsOGgtMS4xTDEwLDE0SDZsLTAuOSwySDRMNy42LDh6IE04LDkuMUw2LjQsMTNoMy4yTDgsOS4xeiIvPgogICAgPHBhdGggZD0iTTE2LjYsOS44Yy0wLjIsMC4xLTAuNCwwLjEtMC43LDAuMWMtMC4yLDAtMC40LTAuMS0wLjYtMC4yYy0wLjEtMC4xLTAuMi0wLjQtMC4yLTAuNyBjLTAuMywwLjMtMC42LDAuNS0wLjksMC43Yy0wLjMsMC4xLTAuNywwLjItMS4xLDAuMmMtMC4zLDAtMC41LDAtMC43LTAuMWMtMC4yLTAuMS0wLjQtMC4yLTAuNi0wLjNjLTAuMi0wLjEtMC4zLTAuMy0wLjQtMC41IGMtMC4xLTAuMi0wLjEtMC40LTAuMS0wLjdjMC0wLjMsMC4xLTAuNiwwLjItMC44YzAuMS0wLjIsMC4zLTAuNCwwLjQtMC41QzEyLDcsMTIuMiw2LjksMTIuNSw2LjhjMC4yLTAuMSwwLjUtMC4xLDAuNy0wLjIgYzAuMy0wLjEsMC41LTAuMSwwLjctMC4xYzAuMiwwLDAuNC0wLjEsMC42LTAuMWMwLjIsMCwwLjMtMC4xLDAuNC0wLjJjMC4xLTAuMSwwLjItMC4yLDAuMi0wLjRjMC0xLTEuMS0xLTEuMy0xIGMtMC40LDAtMS40LDAtMS40LDEuMmgtMC45YzAtMC40LDAuMS0wLjcsMC4yLTFjMC4xLTAuMiwwLjMtMC40LDAuNS0wLjZjMC4yLTAuMiwwLjUtMC4zLDAuOC0wLjNDMTMuMyw0LDEzLjYsNCwxMy45LDQgYzAuMywwLDAuNSwwLDAuOCwwLjFjMC4zLDAsMC41LDAuMSwwLjcsMC4yYzAuMiwwLjEsMC40LDAuMywwLjUsMC41QzE2LDUsMTYsNS4yLDE2LDUuNnYyLjljMCwwLjIsMCwwLjQsMCwwLjUgYzAsMC4xLDAuMSwwLjIsMC4zLDAuMmMwLjEsMCwwLjIsMCwwLjMsMFY5Ljh6IE0xNS4yLDYuOWMtMS4yLDAuNi0zLjEsMC4yLTMuMSwxLjRjMCwxLjQsMy4xLDEsMy4xLTAuNVY2Ljl6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-check: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik05IDE2LjE3TDQuODMgMTJsLTEuNDIgMS40MUw5IDE5IDIxIDdsLTEuNDEtMS40MXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-circle-empty: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDJDNi40NyAyIDIgNi40NyAyIDEyczQuNDcgMTAgMTAgMTAgMTAtNC40NyAxMC0xMFMxNy41MyAyIDEyIDJ6bTAgMThjLTQuNDEgMC04LTMuNTktOC04czMuNTktOCA4LTggOCAzLjU5IDggOC0zLjU5IDgtOCA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-circle: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iOSIgY3k9IjkiIHI9IjgiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-clear: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8bWFzayBpZD0iZG9udXRIb2xlIj4KICAgIDxyZWN0IHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0id2hpdGUiIC8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSI4IiBmaWxsPSJibGFjayIvPgogIDwvbWFzaz4KCiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxyZWN0IGhlaWdodD0iMTgiIHdpZHRoPSIyIiB4PSIxMSIgeT0iMyIgdHJhbnNmb3JtPSJyb3RhdGUoMzE1LCAxMiwgMTIpIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIxMCIgbWFzaz0idXJsKCNkb251dEhvbGUpIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-close: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1ub25lIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIGpwLWljb24zLWhvdmVyIiBmaWxsPSJub25lIj4KICAgIDxjaXJjbGUgY3g9IjEyIiBjeT0iMTIiIHI9IjExIi8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIGpwLWljb24tYWNjZW50Mi1ob3ZlciIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMTkgNi40MUwxNy41OSA1IDEyIDEwLjU5IDYuNDEgNSA1IDYuNDEgMTAuNTkgMTIgNSAxNy41OSA2LjQxIDE5IDEyIDEzLjQxIDE3LjU5IDE5IDE5IDE3LjU5IDEzLjQxIDEyeiIvPgogIDwvZz4KCiAgPGcgY2xhc3M9ImpwLWljb24tbm9uZSBqcC1pY29uLWJ1c3kiIGZpbGw9Im5vbmUiPgogICAgPGNpcmNsZSBjeD0iMTIiIGN5PSIxMiIgcj0iNyIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-code: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTExLjQgMTguNkw2LjggMTRMMTEuNCA5LjRMMTAgOEw0IDE0TDEwIDIwTDExLjQgMTguNlpNMTYuNiAxOC42TDIxLjIgMTRMMTYuNiA5LjRMMTggOEwyNCAxNEwxOCAyMEwxNi42IDE4LjZWMTguNloiLz4KCTwvZz4KPC9zdmc+Cg==);--jp-icon-console: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwMCAyMDAiPgogIDxnIGNsYXNzPSJqcC1jb25zb2xlLWljb24tYmFja2dyb3VuZC1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMjg4RDEiPgogICAgPHBhdGggZD0iTTIwIDE5LjhoMTYwdjE1OS45SDIweiIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtY29uc29sZS1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIj4KICAgIDxwYXRoIGQ9Ik0xMDUgMTI3LjNoNDB2MTIuOGgtNDB6TTUxLjEgNzdMNzQgOTkuOWwtMjMuMyAyMy4zIDEwLjUgMTAuNSAyMy4zLTIzLjNMOTUgOTkuOSA4NC41IDg5LjQgNjEuNiA2Ni41eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-copy: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTExLjksMUgzLjJDMi40LDEsMS43LDEuNywxLjcsMi41djEwLjJoMS41VjIuNWg4LjdWMXogTTE0LjEsMy45aC04Yy0wLjgsMC0xLjUsMC43LTEuNSwxLjV2MTAuMmMwLDAuOCwwLjcsMS41LDEuNSwxLjVoOCBjMC44LDAsMS41LTAuNywxLjUtMS41VjUuNEMxNS41LDQuNiwxNC45LDMuOSwxNC4xLDMuOXogTTE0LjEsMTUuNWgtOFY1LjRoOFYxNS41eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-copyright: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGVuYWJsZS1iYWNrZ3JvdW5kPSJuZXcgMCAwIDI0IDI0IiBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCI+CiAgPGcgY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0xMS44OCw5LjE0YzEuMjgsMC4wNiwxLjYxLDEuMTUsMS42MywxLjY2aDEuNzljLTAuMDgtMS45OC0xLjQ5LTMuMTktMy40NS0zLjE5QzkuNjQsNy42MSw4LDksOCwxMi4xNCBjMCwxLjk0LDAuOTMsNC4yNCwzLjg0LDQuMjRjMi4yMiwwLDMuNDEtMS42NSwzLjQ0LTIuOTVoLTEuNzljLTAuMDMsMC41OS0wLjQ1LDEuMzgtMS42MywxLjQ0QzEwLjU1LDE0LjgzLDEwLDEzLjgxLDEwLDEyLjE0IEMxMCw5LjI1LDExLjI4LDkuMTYsMTEuODgsOS4xNHogTTEyLDJDNi40OCwyLDIsNi40OCwyLDEyczQuNDgsMTAsMTAsMTBzMTAtNC40OCwxMC0xMFMxNy41MiwyLDEyLDJ6IE0xMiwyMGMtNC40MSwwLTgtMy41OS04LTggczMuNTktOCw4LThzOCwzLjU5LDgsOFMxNi40MSwyMCwxMiwyMHoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-cut: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkuNjQgNy42NGMuMjMtLjUuMzYtMS4wNS4zNi0xLjY0IDAtMi4yMS0xLjc5LTQtNC00UzIgMy43OSAyIDZzMS43OSA0IDQgNGMuNTkgMCAxLjE0LS4xMyAxLjY0LS4zNkwxMCAxMmwtMi4zNiAyLjM2QzcuMTQgMTQuMTMgNi41OSAxNCA2IDE0Yy0yLjIxIDAtNCAxLjc5LTQgNHMxLjc5IDQgNCA0IDQtMS43OSA0LTRjMC0uNTktLjEzLTEuMTQtLjM2LTEuNjRMMTIgMTRsNyA3aDN2LTFMOS42NCA3LjY0ek02IDhjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTAgMTJjLTEuMSAwLTItLjg5LTItMnMuOS0yIDItMiAyIC44OSAyIDItLjkgMi0yIDJ6bTYtNy41Yy0uMjggMC0uNS0uMjItLjUtLjVzLjIyLS41LjUtLjUuNS4yMi41LjUtLjIyLjUtLjUuNXpNMTkgM2wtNiA2IDIgMiA3LTdWM3oiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-delete: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2cHgiIGhlaWdodD0iMTZweCI+CiAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIiAvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsPSIjNjI2MjYyIiBkPSJNNiAxOWMwIDEuMS45IDIgMiAyaDhjMS4xIDAgMi0uOSAyLTJWN0g2djEyek0xOSA0aC0zLjVsLTEtMWgtNWwtMSAxSDV2MmgxNFY0eiIgLz4KPC9zdmc+Cg==);--jp-icon-download: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE5IDloLTRWM0g5djZINWw3IDcgNy03ek01IDE4djJoMTR2LTJINXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-duplicate: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiIGNsaXAtcnVsZT0iZXZlbm9kZCIgZD0iTTIuNzk5OTggMC44NzVIOC44OTU4MkM5LjIwMDYxIDAuODc1IDkuNDQ5OTggMS4xMzkxNCA5LjQ0OTk4IDEuNDYxOThDOS40NDk5OCAxLjc4NDgyIDkuMjAwNjEgMi4wNDg5NiA4Ljg5NTgyIDIuMDQ4OTZIMy4zNTQxNUMzLjA0OTM2IDIuMDQ4OTYgMi43OTk5OCAyLjMxMzEgMi43OTk5OCAyLjYzNTk0VjkuNjc5NjlDMi43OTk5OCAxMC4wMDI1IDIuNTUwNjEgMTAuMjY2NyAyLjI0NTgyIDEwLjI2NjdDMS45NDEwMyAxMC4yNjY3IDEuNjkxNjUgMTAuMDAyNSAxLjY5MTY1IDkuNjc5NjlWMi4wNDg5NkMxLjY5MTY1IDEuNDAzMjggMi4xOTA0IDAuODc1IDIuNzk5OTggMC44NzVaTTUuMzY2NjUgMTEuOVY0LjU1SDExLjA4MzNWMTEuOUg1LjM2NjY1Wk00LjE0MTY1IDQuMTQxNjdDNC4xNDE2NSAzLjY5MDYzIDQuNTA3MjggMy4zMjUgNC45NTgzMiAzLjMyNUgxMS40OTE3QzExLjk0MjcgMy4zMjUgMTIuMzA4MyAzLjY5MDYzIDEyLjMwODMgNC4xNDE2N1YxMi4zMDgzQzEyLjMwODMgMTIuNzU5NCAxMS45NDI3IDEzLjEyNSAxMS40OTE3IDEzLjEyNUg0Ljk1ODMyQzQuNTA3MjggMTMuMTI1IDQuMTQxNjUgMTIuNzU5NCA0LjE0MTY1IDEyLjMwODNWNC4xNDE2N1oiIGZpbGw9IiM2MTYxNjEiLz4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNOS40MzU3NCA4LjI2NTA3SDguMzY0MzFWOS4zMzY1QzguMzY0MzEgOS40NTQzNSA4LjI2Nzg4IDkuNTUwNzggOC4xNTAwMiA5LjU1MDc4QzguMDMyMTcgOS41NTA3OCA3LjkzNTc0IDkuNDU0MzUgNy45MzU3NCA5LjMzNjVWOC4yNjUwN0g2Ljg2NDMxQzYuNzQ2NDUgOC4yNjUwNyA2LjY1MDAyIDguMTY4NjQgNi42NTAwMiA4LjA1MDc4QzYuNjUwMDIgNy45MzI5MiA2Ljc0NjQ1IDcuODM2NSA2Ljg2NDMxIDcuODM2NUg3LjkzNTc0VjYuNzY1MDdDNy45MzU3NCA2LjY0NzIxIDguMDMyMTcgNi41NTA3OCA4LjE1MDAyIDYuNTUwNzhDOC4yNjc4OCA2LjU1MDc4IDguMzY0MzEgNi42NDcyMSA4LjM2NDMxIDYuNzY1MDdWNy44MzY1SDkuNDM1NzRDOS41NTM2IDcuODM2NSA5LjY1MDAyIDcuOTMyOTIgOS42NTAwMiA4LjA1MDc4QzkuNjUwMDIgOC4xNjg2NCA5LjU1MzYgOC4yNjUwNyA5LjQzNTc0IDguMjY1MDdaIiBmaWxsPSIjNjE2MTYxIiBzdHJva2U9IiM2MTYxNjEiIHN0cm9rZS13aWR0aD0iMC41Ii8+Cjwvc3ZnPgo=);--jp-icon-edit: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMgMTcuMjVWMjFoMy43NUwxNy44MSA5Ljk0bC0zLjc1LTMuNzVMMyAxNy4yNXpNMjAuNzEgNy4wNGMuMzktLjM5LjM5LTEuMDIgMC0xLjQxbC0yLjM0LTIuMzRjLS4zOS0uMzktMS4wMi0uMzktMS40MSAwbC0xLjgzIDEuODMgMy43NSAzLjc1IDEuODMtMS44M3oiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-ellipses: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPGNpcmNsZSBjeD0iNSIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxMiIgY3k9IjEyIiByPSIyIi8+CiAgICA8Y2lyY2xlIGN4PSIxOSIgY3k9IjEyIiByPSIyIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-extension: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwLjUgMTFIMTlWN2MwLTEuMS0uOS0yLTItMmgtNFYzLjVDMTMgMi4xMiAxMS44OCAxIDEwLjUgMVM4IDIuMTIgOCAzLjVWNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAydjMuOEgzLjVjMS40OSAwIDIuNyAxLjIxIDIuNyAyLjdzLTEuMjEgMi43LTIuNyAyLjdIMlYyMGMwIDEuMS45IDIgMiAyaDMuOHYtMS41YzAtMS40OSAxLjIxLTIuNyAyLjctMi43IDEuNDkgMCAyLjcgMS4yMSAyLjcgMi43VjIySDE3YzEuMSAwIDItLjkgMi0ydi00aDEuNWMxLjM4IDAgMi41LTEuMTIgMi41LTIuNVMyMS44OCAxMSAyMC41IDExeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-fast-forward: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTQgMThsOC41LTZMNCA2djEyem05LTEydjEybDguNS02TDEzIDZ6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-file-upload: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTkgMTZoNnYtNmg0bC03LTctNyA3aDR6bS00IDJoMTR2Mkg1eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-file: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuMyA4LjJsLTUuNS01LjVjLS4zLS4zLS43LS41LTEuMi0uNUgzLjljLS44LjEtMS42LjktMS42IDEuOHYxNC4xYzAgLjkuNyAxLjYgMS42IDEuNmgxNC4yYy45IDAgMS42LS43IDEuNi0xLjZWOS40Yy4xLS41LS4xLS45LS40LTEuMnptLTUuOC0zLjNsMy40IDMuNmgtMy40VjQuOXptMy45IDEyLjdINC43Yy0uMSAwLS4yIDAtLjItLjJWNC43YzAtLjIuMS0uMy4yLS4zaDcuMnY0LjRzMCAuOC4zIDEuMWMuMy4zIDEuMS4zIDEuMS4zaDQuM3Y3LjJzLS4xLjItLjIuMnoiLz4KPC9zdmc+Cg==);--jp-icon-filter-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEwIDE4aDR2LTJoLTR2MnpNMyA2djJoMThWNkgzem0zIDdoMTJ2LTJINnYyeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-folder-favorite: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgwVjB6IiBmaWxsPSJub25lIi8+PHBhdGggY2xhc3M9ImpwLWljb24zIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxNjE2MSIgZD0iTTIwIDZoLThsLTItMkg0Yy0xLjEgMC0yIC45LTIgMnYxMmMwIDEuMS45IDIgMiAyaDE2YzEuMSAwIDItLjkgMi0yVjhjMC0xLjEtLjktMi0yLTJ6bS0yLjA2IDExTDE1IDE1LjI4IDEyLjA2IDE3bC43OC0zLjMzLTIuNTktMi4yNCAzLjQxLS4yOUwxNSA4bDEuMzQgMy4xNCAzLjQxLjI5LTIuNTkgMi4yNC43OCAzLjMzeiIvPgo8L3N2Zz4K);--jp-icon-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY4YzAtMS4xLS45LTItMi0yaC04bC0yLTJ6Ii8+Cjwvc3ZnPgo=);--jp-icon-home: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjRweCIgdmlld0JveD0iMCAwIDI0IDI0IiB3aWR0aD0iMjRweCIgZmlsbD0iIzAwMDAwMCI+CiAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPjxwYXRoIGNsYXNzPSJqcC1pY29uMyBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xMCAyMHYtNmg0djZoNXYtOGgzTDEyIDMgMiAxMmgzdjh6Ii8+Cjwvc3ZnPgo=);--jp-icon-html5: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uMCBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiMwMDAiIGQ9Ik0xMDguNCAwaDIzdjIyLjhoMjEuMlYwaDIzdjY5aC0yM1Y0NmgtMjF2MjNoLTIzLjJNMjA2IDIzaC0yMC4zVjBoNjMuN3YyM0gyMjl2NDZoLTIzbTUzLjUtNjloMjQuMWwxNC44IDI0LjNMMzEzLjIgMGgyNC4xdjY5aC0yM1YzNC44bC0xNi4xIDI0LjgtMTYuMS0yNC44VjY5aC0yMi42bTg5LjItNjloMjN2NDYuMmgzMi42VjY5aC01NS42Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2U0NGQyNiIgZD0iTTEwNy42IDQ3MWwtMzMtMzcwLjRoMzYyLjhsLTMzIDM3MC4yTDI1NS43IDUxMiIvPgogIDxwYXRoIGNsYXNzPSJqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNmMTY1MjkiIGQ9Ik0yNTYgNDgwLjVWMTMxaDE0OC4zTDM3NiA0NDciLz4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNlYmViZWIiIGQ9Ik0xNDIgMTc2LjNoMTE0djQ1LjRoLTY0LjJsNC4yIDQ2LjVoNjB2NDUuM0gxNTQuNG0yIDIyLjhIMjAybDMuMiAzNi4zIDUwLjggMTMuNnY0Ny40bC05My4yLTI2Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZS1pbnZlcnNlIiBmaWxsPSIjZmZmIiBkPSJNMzY5LjYgMTc2LjNIMjU1Ljh2NDUuNGgxMDkuNm0tNC4xIDQ2LjVIMjU1Ljh2NDUuNGg1NmwtNS4zIDU5LTUwLjcgMTMuNnY0Ny4ybDkzLTI1LjgiLz4KPC9zdmc+Cg==);--jp-icon-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1icmFuZDQganAtaWNvbi1zZWxlY3RhYmxlLWludmVyc2UiIGZpbGw9IiNGRkYiIGQ9Ik0yLjIgMi4yaDE3LjV2MTcuNUgyLjJ6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzNGNTFCNSIgZD0iTTIuMiAyLjJ2MTcuNWgxNy41bC4xLTE3LjVIMi4yem0xMi4xIDIuMmMxLjIgMCAyLjIgMSAyLjIgMi4ycy0xIDIuMi0yLjIgMi4yLTIuMi0xLTIuMi0yLjIgMS0yLjIgMi4yLTIuMnpNNC40IDE3LjZsMy4zLTguOCAzLjMgNi42IDIuMi0zLjIgNC40IDUuNEg0LjR6Ii8+Cjwvc3ZnPgo=);--jp-icon-inspector: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaW5zcGVjdG9yLWljb24tY29sb3IganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNEg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMThjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY2YzAtMS4xLS45LTItMi0yem0tNSAxNEg0di00aDExdjR6bTAtNUg0VjloMTF2NHptNSA1aC00VjloNHY5eiIvPgo8L3N2Zz4K);--jp-icon-json: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtanNvbi1pY29uLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0Y5QTgyNSI+CiAgICA8cGF0aCBkPSJNMjAuMiAxMS44Yy0xLjYgMC0xLjcuNS0xLjcgMSAwIC40LjEuOS4xIDEuMy4xLjUuMS45LjEgMS4zIDAgMS43LTEuNCAyLjMtMy41IDIuM2gtLjl2LTEuOWguNWMxLjEgMCAxLjQgMCAxLjQtLjggMC0uMyAwLS42LS4xLTEgMC0uNC0uMS0uOC0uMS0xLjIgMC0xLjMgMC0xLjggMS4zLTItMS4zLS4yLTEuMy0uNy0xLjMtMiAwLS40LjEtLjguMS0xLjIuMS0uNC4xLS43LjEtMSAwLS44LS40LS43LTEuNC0uOGgtLjVWNC4xaC45YzIuMiAwIDMuNS43IDMuNSAyLjMgMCAuNC0uMS45LS4xIDEuMy0uMS41LS4xLjktLjEgMS4zIDAgLjUuMiAxIDEuNyAxdjEuOHpNMS44IDEwLjFjMS42IDAgMS43LS41IDEuNy0xIDAtLjQtLjEtLjktLjEtMS4zLS4xLS41LS4xLS45LS4xLTEuMyAwLTEuNiAxLjQtMi4zIDMuNS0yLjNoLjl2MS45aC0uNWMtMSAwLTEuNCAwLTEuNC44IDAgLjMgMCAuNi4xIDEgMCAuMi4xLjYuMSAxIDAgMS4zIDAgMS44LTEuMyAyQzYgMTEuMiA2IDExLjcgNiAxM2MwIC40LS4xLjgtLjEgMS4yLS4xLjMtLjEuNy0uMSAxIDAgLjguMy44IDEuNC44aC41djEuOWgtLjljLTIuMSAwLTMuNS0uNi0zLjUtMi4zIDAtLjQuMS0uOS4xLTEuMy4xLS41LjEtLjkuMS0xLjMgMC0uNS0uMi0xLTEuNy0xdi0xLjl6Ii8+CiAgICA8Y2lyY2xlIGN4PSIxMSIgY3k9IjEzLjgiIHI9IjIuMSIvPgogICAgPGNpcmNsZSBjeD0iMTEiIGN5PSI4LjIiIHI9IjIuMSIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-julia: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDMyNSAzMDAiPgogIDxnIGNsYXNzPSJqcC1icmFuZDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjY2IzYzMzIj4KICAgIDxwYXRoIGQ9Ik0gMTUwLjg5ODQzOCAyMjUgQyAxNTAuODk4NDM4IDI2Ni40MjE4NzUgMTE3LjMyMDMxMiAzMDAgNzUuODk4NDM4IDMwMCBDIDM0LjQ3NjU2MiAzMDAgMC44OTg0MzggMjY2LjQyMTg3NSAwLjg5ODQzOCAyMjUgQyAwLjg5ODQzOCAxODMuNTc4MTI1IDM0LjQ3NjU2MiAxNTAgNzUuODk4NDM4IDE1MCBDIDExNy4zMjAzMTIgMTUwIDE1MC44OTg0MzggMTgzLjU3ODEyNSAxNTAuODk4NDM4IDIyNSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzM4OTgyNiI+CiAgICA8cGF0aCBkPSJNIDIzNy41IDc1IEMgMjM3LjUgMTE2LjQyMTg3NSAyMDMuOTIxODc1IDE1MCAxNjIuNSAxNTAgQyAxMjEuMDc4MTI1IDE1MCA4Ny41IDExNi40MjE4NzUgODcuNSA3NSBDIDg3LjUgMzMuNTc4MTI1IDEyMS4wNzgxMjUgMCAxNjIuNSAwIEMgMjAzLjkyMTg3NSAwIDIzNy41IDMzLjU3ODEyNSAyMzcuNSA3NSIvPgogIDwvZz4KICA8ZyBjbGFzcz0ianAtYnJhbmQwIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzk1NThiMiI+CiAgICA8cGF0aCBkPSJNIDMyNC4xMDE1NjIgMjI1IEMgMzI0LjEwMTU2MiAyNjYuNDIxODc1IDI5MC41MjM0MzggMzAwIDI0OS4xMDE1NjIgMzAwIEMgMjA3LjY3OTY4OCAzMDAgMTc0LjEwMTU2MiAyNjYuNDIxODc1IDE3NC4xMDE1NjIgMjI1IEMgMTc0LjEwMTU2MiAxODMuNTc4MTI1IDIwNy42Nzk2ODggMTUwIDI0OS4xMDE1NjIgMTUwIEMgMjkwLjUyMzQzOCAxNTAgMzI0LjEwMTU2MiAxODMuNTc4MTI1IDMyNC4xMDE1NjIgMjI1Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-jupyter-favicon: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTUyIiBoZWlnaHQ9IjE2NSIgdmlld0JveD0iMCAwIDE1MiAxNjUiIHZlcnNpb249IjEuMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgPGcgY2xhc3M9ImpwLWp1cHl0ZXItaWNvbi1jb2xvciIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA3ODk0NywgMTEwLjU4MjkyNykiIGQ9Ik03NS45NDIyODQyLDI5LjU4MDQ1NjEgQzQzLjMwMjM5NDcsMjkuNTgwNDU2MSAxNC43OTY3ODMyLDE3LjY1MzQ2MzQgMCwwIEM1LjUxMDgzMjExLDE1Ljg0MDY4MjkgMTUuNzgxNTM4OSwyOS41NjY3NzMyIDI5LjM5MDQ5NDcsMzkuMjc4NDE3MSBDNDIuOTk5Nyw0OC45ODk4NTM3IDU5LjI3MzcsNTQuMjA2NzgwNSA3NS45NjA1Nzg5LDU0LjIwNjc4MDUgQzkyLjY0NzQ1NzksNTQuMjA2NzgwNSAxMDguOTIxNDU4LDQ4Ljk4OTg1MzcgMTIyLjUzMDY2MywzOS4yNzg0MTcxIEMxMzYuMTM5NDUzLDI5LjU2Njc3MzIgMTQ2LjQxMDI4NCwxNS44NDA2ODI5IDE1MS45MjExNTgsMCBDMTM3LjA4Nzg2OCwxNy42NTM0NjM0IDEwOC41ODI1ODksMjkuNTgwNDU2MSA3NS45NDIyODQyLDI5LjU4MDQ1NjEgTDc1Ljk0MjI4NDIsMjkuNTgwNDU2MSBaIiAvPgogICAgPHBhdGggdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMzczNjgsIDAuNzA0ODc4KSIgZD0iTTc1Ljk3ODQ1NzksMjQuNjI2NDA3MyBDMTA4LjYxODc2MywyNC42MjY0MDczIDEzNy4xMjQ0NTgsMzYuNTUzNDQxNSAxNTEuOTIxMTU4LDU0LjIwNjc4MDUgQzE0Ni40MTAyODQsMzguMzY2MjIyIDEzNi4xMzk0NTMsMjQuNjQwMTMxNyAxMjIuNTMwNjYzLDE0LjkyODQ4NzggQzEwOC45MjE0NTgsNS4yMTY4NDM5IDkyLjY0NzQ1NzksMCA3NS45NjA1Nzg5LDAgQzU5LjI3MzcsMCA0Mi45OTk3LDUuMjE2ODQzOSAyOS4zOTA0OTQ3LDE0LjkyODQ4NzggQzE1Ljc4MTUzODksMjQuNjQwMTMxNyA1LjUxMDgzMjExLDM4LjM2NjIyMiAwLDU0LjIwNjc4MDUgQzE0LjgzMzA4MTYsMzYuNTg5OTI5MyA0My4zMzg1Njg0LDI0LjYyNjQwNzMgNzUuOTc4NDU3OSwyNC42MjY0MDczIEw3NS45Nzg0NTc5LDI0LjYyNjQwNzMgWiIgLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-jupyter: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzkiIGhlaWdodD0iNTEiIHZpZXdCb3g9IjAgMCAzOSA1MSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgtMTYzOCAtMjI4MSkiPgogICAgIDxnIGNsYXNzPSJqcC1qdXB5dGVyLWljb24tY29sb3IiIGZpbGw9IiNGMzc3MjYiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5Ljc0IDIzMTEuOTgpIiBkPSJNIDE4LjI2NDYgNy4xMzQxMUMgMTAuNDE0NSA3LjEzNDExIDMuNTU4NzIgNC4yNTc2IDAgMEMgMS4zMjUzOSAzLjgyMDQgMy43OTU1NiA3LjEzMDgxIDcuMDY4NiA5LjQ3MzAzQyAxMC4zNDE3IDExLjgxNTIgMTQuMjU1NyAxMy4wNzM0IDE4LjI2OSAxMy4wNzM0QyAyMi4yODIzIDEzLjA3MzQgMjYuMTk2MyAxMS44MTUyIDI5LjQ2OTQgOS40NzMwM0MgMzIuNzQyNCA3LjEzMDgxIDM1LjIxMjYgMy44MjA0IDM2LjUzOCAwQyAzMi45NzA1IDQuMjU3NiAyNi4xMTQ4IDcuMTM0MTEgMTguMjY0NiA3LjEzNDExWiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM5LjczIDIyODUuNDgpIiBkPSJNIDE4LjI3MzMgNS45MzkzMUMgMjYuMTIzNSA1LjkzOTMxIDMyLjk3OTMgOC44MTU4MyAzNi41MzggMTMuMDczNEMgMzUuMjEyNiA5LjI1MzAzIDMyLjc0MjQgNS45NDI2MiAyOS40Njk0IDMuNjAwNEMgMjYuMTk2MyAxLjI1ODE4IDIyLjI4MjMgMCAxOC4yNjkgMEMgMTQuMjU1NyAwIDEwLjM0MTcgMS4yNTgxOCA3LjA2ODYgMy42MDA0QyAzLjc5NTU2IDUuOTQyNjIgMS4zMjUzOSA5LjI1MzAzIDAgMTMuMDczNEMgMy41Njc0NSA4LjgyNDYzIDEwLjQyMzIgNS45MzkzMSAxOC4yNzMzIDUuOTM5MzFaIi8+CiAgICA8L2c+CiAgICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjY5LjMgMjI4MS4zMSkiIGQ9Ik0gNS44OTM1MyAyLjg0NEMgNS45MTg4OSAzLjQzMTY1IDUuNzcwODUgNC4wMTM2NyA1LjQ2ODE1IDQuNTE2NDVDIDUuMTY1NDUgNS4wMTkyMiA0LjcyMTY4IDUuNDIwMTUgNC4xOTI5OSA1LjY2ODUxQyAzLjY2NDMgNS45MTY4OCAzLjA3NDQ0IDYuMDAxNTEgMi40OTgwNSA1LjkxMTcxQyAxLjkyMTY2IDUuODIxOSAxLjM4NDYzIDUuNTYxNyAwLjk1NDg5OCA1LjE2NDAxQyAwLjUyNTE3IDQuNzY2MzMgMC4yMjIwNTYgNC4yNDkwMyAwLjA4MzkwMzcgMy42Nzc1N0MgLTAuMDU0MjQ4MyAzLjEwNjExIC0wLjAyMTIzIDIuNTA2MTcgMC4xNzg3ODEgMS45NTM2NEMgMC4zNzg3OTMgMS40MDExIDAuNzM2ODA5IDAuOTIwODE3IDEuMjA3NTQgMC41NzM1MzhDIDEuNjc4MjYgMC4yMjYyNTkgMi4yNDA1NSAwLjAyNzU5MTkgMi44MjMyNiAwLjAwMjY3MjI5QyAzLjYwMzg5IC0wLjAzMDcxMTUgNC4zNjU3MyAwLjI0OTc4OSA0Ljk0MTQyIDAuNzgyNTUxQyA1LjUxNzExIDEuMzE1MzEgNS44NTk1NiAyLjA1Njc2IDUuODkzNTMgMi44NDRaIi8+CiAgICAgIDxwYXRoIHRyYW5zZm9ybT0idHJhbnNsYXRlKDE2MzkuOCAyMzIzLjgxKSIgZD0iTSA3LjQyNzg5IDMuNTgzMzhDIDcuNDYwMDggNC4zMjQzIDcuMjczNTUgNS4wNTgxOSA2Ljg5MTkzIDUuNjkyMTNDIDYuNTEwMzEgNi4zMjYwNyA1Ljk1MDc1IDYuODMxNTYgNS4yODQxMSA3LjE0NDZDIDQuNjE3NDcgNy40NTc2MyAzLjg3MzcxIDcuNTY0MTQgMy4xNDcwMiA3LjQ1MDYzQyAyLjQyMDMyIDcuMzM3MTIgMS43NDMzNiA3LjAwODcgMS4yMDE4NCA2LjUwNjk1QyAwLjY2MDMyOCA2LjAwNTIgMC4yNzg2MSA1LjM1MjY4IDAuMTA1MDE3IDQuNjMyMDJDIC0wLjA2ODU3NTcgMy45MTEzNSAtMC4wMjYyMzYxIDMuMTU0OTQgMC4yMjY2NzUgMi40NTg1NkMgMC40Nzk1ODcgMS43NjIxNyAwLjkzMTY5NyAxLjE1NzEzIDEuNTI1NzYgMC43MjAwMzNDIDIuMTE5ODMgMC4yODI5MzUgMi44MjkxNCAwLjAzMzQzOTUgMy41NjM4OSAwLjAwMzEzMzQ0QyA0LjU0NjY3IC0wLjAzNzQwMzMgNS41MDUyOSAwLjMxNjcwNiA2LjIyOTYxIDAuOTg3ODM1QyA2Ljk1MzkzIDEuNjU4OTYgNy4zODQ4NCAyLjU5MjM1IDcuNDI3ODkgMy41ODMzOEwgNy40Mjc4OSAzLjU4MzM4WiIvPgogICAgICA8cGF0aCB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxNjM4LjM2IDIyODYuMDYpIiBkPSJNIDIuMjc0NzEgNC4zOTYyOUMgMS44NDM2MyA0LjQxNTA4IDEuNDE2NzEgNC4zMDQ0NSAxLjA0Nzk5IDQuMDc4NDNDIDAuNjc5MjY4IDMuODUyNCAwLjM4NTMyOCAzLjUyMTE0IDAuMjAzMzcxIDMuMTI2NTZDIDAuMDIxNDEzNiAyLjczMTk4IC0wLjA0MDM3OTggMi4yOTE4MyAwLjAyNTgxMTYgMS44NjE4MUMgMC4wOTIwMDMxIDEuNDMxOCAwLjI4MzIwNCAxLjAzMTI2IDAuNTc1MjEzIDAuNzEwODgzQyAwLjg2NzIyMiAwLjM5MDUxIDEuMjQ2OTEgMC4xNjQ3MDggMS42NjYyMiAwLjA2MjA1OTJDIDIuMDg1NTMgLTAuMDQwNTg5NyAyLjUyNTYxIC0wLjAxNTQ3MTQgMi45MzA3NiAwLjEzNDIzNUMgMy4zMzU5MSAwLjI4Mzk0MSAzLjY4NzkyIDAuNTUxNTA1IDMuOTQyMjIgMC45MDMwNkMgNC4xOTY1MiAxLjI1NDYyIDQuMzQxNjkgMS42NzQzNiA0LjM1OTM1IDIuMTA5MTZDIDQuMzgyOTkgMi42OTEwNyA0LjE3Njc4IDMuMjU4NjkgMy43ODU5NyAzLjY4NzQ2QyAzLjM5NTE2IDQuMTE2MjQgMi44NTE2NiA0LjM3MTE2IDIuMjc0NzEgNC4zOTYyOUwgMi4yNzQ3MSA0LjM5NjI5WiIvPgogICAgPC9nPgogIDwvZz4+Cjwvc3ZnPgo=);--jp-icon-jupyterlab-wordmark: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyMDAiIHZpZXdCb3g9IjAgMCAxODYwLjggNDc1Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0RTRFNEUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDQ4MC4xMzY0MDEsIDY0LjI3MTQ5MykiPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC4wMDAwMDAsIDU4Ljg3NTU2NikiPgogICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgwLjA4NzYwMywgMC4xNDAyOTQpIj4KICAgICAgICA8cGF0aCBkPSJNLTQyNi45LDE2OS44YzAsNDguNy0zLjcsNjQuNy0xMy42LDc2LjRjLTEwLjgsMTAtMjUsMTUuNS0zOS43LDE1LjVsMy43LDI5IGMyMi44LDAuMyw0NC44LTcuOSw2MS45LTIzLjFjMTcuOC0xOC41LDI0LTQ0LjEsMjQtODMuM1YwSC00Mjd2MTcwLjFMLTQyNi45LDE2OS44TC00MjYuOSwxNjkuOHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMTU1LjA0NTI5NiwgNTYuODM3MTA0KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuNTYyNDUzLCAxLjc5OTg0MikiPgogICAgICAgIDxwYXRoIGQ9Ik0tMzEyLDE0OGMwLDIxLDAsMzkuNSwxLjcsNTUuNGgtMzEuOGwtMi4xLTMzLjNoLTAuOGMtNi43LDExLjYtMTYuNCwyMS4zLTI4LDI3LjkgYy0xMS42LDYuNi0yNC44LDEwLTM4LjIsOS44Yy0zMS40LDAtNjktMTcuNy02OS04OVYwaDM2LjR2MTEyLjdjMCwzOC43LDExLjYsNjQuNyw0NC42LDY0LjdjMTAuMy0wLjIsMjAuNC0zLjUsMjguOS05LjQgYzguNS01LjksMTUuMS0xNC4zLDE4LjktMjMuOWMyLjItNi4xLDMuMy0xMi41LDMuMy0xOC45VjAuMmgzNi40VjE0OEgtMzEyTC0zMTIsMTQ4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgzOTAuMDEzMzIyLCA1My40Nzk2MzgpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS43MDY0NTgsIDAuMjMxNDI1KSI+CiAgICAgICAgPHBhdGggZD0iTS00NzguNiw3MS40YzAtMjYtMC44LTQ3LTEuNy02Ni43aDMyLjdsMS43LDM0LjhoMC44YzcuMS0xMi41LDE3LjUtMjIuOCwzMC4xLTI5LjcgYzEyLjUtNywyNi43LTEwLjMsNDEtOS44YzQ4LjMsMCw4NC43LDQxLjcsODQuNywxMDMuM2MwLDczLjEtNDMuNywxMDkuMi05MSwxMDkuMmMtMTIuMSwwLjUtMjQuMi0yLjItMzUtNy44IGMtMTAuOC01LjYtMTkuOS0xMy45LTI2LjYtMjQuMmgtMC44VjI5MWgtMzZ2LTIyMEwtNDc4LjYsNzEuNEwtNDc4LjYsNzEuNHogTS00NDIuNiwxMjUuNmMwLjEsNS4xLDAuNiwxMC4xLDEuNywxNS4xIGMzLDEyLjMsOS45LDIzLjMsMTkuOCwzMS4xYzkuOSw3LjgsMjIuMSwxMi4xLDM0LjcsMTIuMWMzOC41LDAsNjAuNy0zMS45LDYwLjctNzguNWMwLTQwLjctMjEuMS03NS42LTU5LjUtNzUuNiBjLTEyLjksMC40LTI1LjMsNS4xLTM1LjMsMTMuNGMtOS45LDguMy0xNi45LDE5LjctMTkuNiwzMi40Yy0xLjUsNC45LTIuMywxMC0yLjUsMTUuMVYxMjUuNkwtNDQyLjYsMTI1LjZMLTQ0Mi42LDEyNS42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSg2MDYuNzQwNzI2LCA1Ni44MzcxMDQpIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMC43NTEyMjYsIDEuOTg5Mjk5KSI+CiAgICAgICAgPHBhdGggZD0iTS00NDAuOCwwbDQzLjcsMTIwLjFjNC41LDEzLjQsOS41LDI5LjQsMTIuOCw0MS43aDAuOGMzLjctMTIuMiw3LjktMjcuNywxMi44LTQyLjQgbDM5LjctMTE5LjJoMzguNUwtMzQ2LjksMTQ1Yy0yNiw2OS43LTQzLjcsMTA1LjQtNjguNiwxMjcuMmMtMTIuNSwxMS43LTI3LjksMjAtNDQuNiwyMy45bC05LjEtMzEuMSBjMTEuNy0zLjksMjIuNS0xMC4xLDMxLjgtMTguMWMxMy4yLTExLjEsMjMuNy0yNS4yLDMwLjYtNDEuMmMxLjUtMi44LDIuNS01LjcsMi45LTguOGMtMC4zLTMuMy0xLjItNi42LTIuNS05LjdMLTQ4MC4yLDAuMSBoMzkuN0wtNDQwLjgsMEwtNDQwLjgsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoODIyLjc0ODEwNCwgMC4wMDAwMDApIj4KICAgICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoMS40NjQwNTAsIDAuMzc4OTE0KSI+CiAgICAgICAgPHBhdGggZD0iTS00MTMuNywwdjU4LjNoNTJ2MjguMmgtNTJWMTk2YzAsMjUsNywzOS41LDI3LjMsMzkuNWM3LjEsMC4xLDE0LjItMC43LDIxLjEtMi41IGwxLjcsMjcuN2MtMTAuMywzLjctMjEuMyw1LjQtMzIuMiw1Yy03LjMsMC40LTE0LjYtMC43LTIxLjMtMy40Yy02LjgtMi43LTEyLjktNi44LTE3LjktMTIuMWMtMTAuMy0xMC45LTE0LjEtMjktMTQuMS01Mi45IFY4Ni41aC0zMVY1OC4zaDMxVjkuNkwtNDEzLjcsMEwtNDEzLjcsMHoiLz4KICAgICAgPC9nPgogICAgPC9nPgogICAgPGcgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOTc0LjQzMzI4NiwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDAuOTkwMDM0LCAwLjYxMDMzOSkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDQ1LjgsMTEzYzAuOCw1MCwzMi4yLDcwLjYsNjguNiw3MC42YzE5LDAuNiwzNy45LTMsNTUuMy0xMC41bDYuMiwyNi40IGMtMjAuOSw4LjktNDMuNSwxMy4xLTY2LjIsMTIuNmMtNjEuNSwwLTk4LjMtNDEuMi05OC4zLTEwMi41Qy00ODAuMiw0OC4yLTQ0NC43LDAtMzg2LjUsMGM2NS4yLDAsODIuNyw1OC4zLDgyLjcsOTUuNyBjLTAuMSw1LjgtMC41LDExLjUtMS4yLDE3LjJoLTE0MC42SC00NDUuOEwtNDQ1LjgsMTEzeiBNLTMzOS4yLDg2LjZjMC40LTIzLjUtOS41LTYwLjEtNTAuNC02MC4xIGMtMzYuOCwwLTUyLjgsMzQuNC01NS43LDYwLjFILTMzOS4yTC0zMzkuMiw4Ni42TC0zMzkuMiw4Ni42eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxMjAxLjk2MTA1OCwgNTMuNDc5NjM4KSI+CiAgICAgIDxnIHRyYW5zZm9ybT0idHJhbnNsYXRlKDEuMTc5NjQwLCAwLjcwNTA2OCkiPgogICAgICAgIDxwYXRoIGQ9Ik0tNDc4LjYsNjhjMC0yMy45LTAuNC00NC41LTEuNy02My40aDMxLjhsMS4yLDM5LjloMS43YzkuMS0yNy4zLDMxLTQ0LjUsNTUuMy00NC41IGMzLjUtMC4xLDcsMC40LDEwLjMsMS4ydjM0LjhjLTQuMS0wLjktOC4yLTEuMy0xMi40LTEuMmMtMjUuNiwwLTQzLjcsMTkuNy00OC43LDQ3LjRjLTEsNS43LTEuNiwxMS41LTEuNywxNy4ydjEwOC4zaC0zNlY2OCBMLTQ3OC42LDY4eiIvPgogICAgICA8L2c+CiAgICA8L2c+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi13YXJuMCIgZmlsbD0iI0YzNzcyNiI+CiAgICA8cGF0aCBkPSJNMTM1Mi4zLDMyNi4yaDM3VjI4aC0zN1YzMjYuMnogTTE2MDQuOCwzMjYuMmMtMi41LTEzLjktMy40LTMxLjEtMy40LTQ4Ljd2LTc2IGMwLTQwLjctMTUuMS04My4xLTc3LjMtODMuMWMtMjUuNiwwLTUwLDcuMS02Ni44LDE4LjFsOC40LDI0LjRjMTQuMy05LjIsMzQtMTUuMSw1My0xNS4xYzQxLjYsMCw0Ni4yLDMwLjIsNDYuMiw0N3Y0LjIgYy03OC42LTAuNC0xMjIuMywyNi41LTEyMi4zLDc1LjZjMCwyOS40LDIxLDU4LjQsNjIuMiw1OC40YzI5LDAsNTAuOS0xNC4zLDYyLjItMzAuMmgxLjNsMi45LDI1LjZIMTYwNC44eiBNMTU2NS43LDI1Ny43IGMwLDMuOC0wLjgsOC0yLjEsMTEuOGMtNS45LDE3LjItMjIuNywzNC00OS4yLDM0Yy0xOC45LDAtMzQuOS0xMS4zLTM0LjktMzUuM2MwLTM5LjUsNDUuOC00Ni42LDg2LjItNDUuOFYyNTcuN3ogTTE2OTguNSwzMjYuMiBsMS43LTMzLjZoMS4zYzE1LjEsMjYuOSwzOC43LDM4LjIsNjguMSwzOC4yYzQ1LjQsMCw5MS4yLTM2LjEsOTEuMi0xMDguOGMwLjQtNjEuNy0zNS4zLTEwMy43LTg1LjctMTAzLjcgYy0zMi44LDAtNTYuMywxNC43LTY5LjMsMzcuNGgtMC44VjI4aC0zNi42djI0NS43YzAsMTguMS0wLjgsMzguNi0xLjcsNTIuNUgxNjk4LjV6IE0xNzA0LjgsMjA4LjJjMC01LjksMS4zLTEwLjksMi4xLTE1LjEgYzcuNi0yOC4xLDMxLjEtNDUuNCw1Ni4zLTQ1LjRjMzkuNSwwLDYwLjUsMzQuOSw2MC41LDc1LjZjMCw0Ni42LTIzLjEsNzguMS02MS44LDc4LjFjLTI2LjksMC00OC4zLTE3LjYtNTUuNS00My4zIGMtMC44LTQuMi0xLjctOC44LTEuNy0xMy40VjIwOC4yeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgZmlsbD0iIzYxNjE2MSIgZD0iTTE1IDlIOXY2aDZWOXptLTIgNGgtMnYtMmgydjJ6bTgtMlY5aC0yVjdjMC0xLjEtLjktMi0yLTJoLTJWM2gtMnYyaC0yVjNIOXYySDdjLTEuMSAwLTIgLjktMiAydjJIM3YyaDJ2MkgzdjJoMnYyYzAgMS4xLjkgMiAyIDJoMnYyaDJ2LTJoMnYyaDJ2LTJoMmMxLjEgMCAyLS45IDItMnYtMmgydi0yaC0ydi0yaDJ6bS00IDZIN1Y3aDEwdjEweiIvPgo8L3N2Zz4K);--jp-icon-keyboard: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMjAgNUg0Yy0xLjEgMC0xLjk5LjktMS45OSAyTDIgMTdjMCAxLjEuOSAyIDIgMmgxNmMxLjEgMCAyLS45IDItMlY3YzAtMS4xLS45LTItMi0yem0tOSAzaDJ2MmgtMlY4em0wIDNoMnYyaC0ydi0yek04IDhoMnYySDhWOHptMCAzaDJ2Mkg4di0yem0tMSAySDV2LTJoMnYyem0wLTNINVY4aDJ2MnptOSA3SDh2LTJoOHYyem0wLTRoLTJ2LTJoMnYyem0wLTNoLTJWOGgydjJ6bTMgM2gtMnYtMmgydjJ6bTAtM2gtMlY4aDJ2MnoiLz4KPC9zdmc+Cg==);--jp-icon-launch: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMzIgMzIiIHdpZHRoPSIzMiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik0yNiwyOEg2YTIuMDAyNywyLjAwMjcsMCwwLDEtMi0yVjZBMi4wMDI3LDIuMDAyNywwLDAsMSw2LDRIMTZWNkg2VjI2SDI2VjE2aDJWMjZBMi4wMDI3LDIuMDAyNywwLDAsMSwyNiwyOFoiLz4KICAgIDxwb2x5Z29uIHBvaW50cz0iMjAgMiAyMCA0IDI2LjU4NiA0IDE4IDEyLjU4NiAxOS40MTQgMTQgMjggNS40MTQgMjggMTIgMzAgMTIgMzAgMiAyMCAyIi8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-launcher: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkgMTlINVY1aDdWM0g1YTIgMiAwIDAwLTIgMnYxNGEyIDIgMCAwMDIgMmgxNGMxLjEgMCAyLS45IDItMnYtN2gtMnY3ek0xNCAzdjJoMy41OWwtOS44MyA5LjgzIDEuNDEgMS40MUwxOSA2LjQxVjEwaDJWM2gtN3oiLz4KPC9zdmc+Cg==);--jp-icon-line-form: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGZpbGw9IndoaXRlIiBkPSJNNS44OCA0LjEyTDEzLjc2IDEybC03Ljg4IDcuODhMOCAyMmwxMC0xMEw4IDJ6Ii8+Cjwvc3ZnPgo=);--jp-icon-link: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTMuOSAxMmMwLTEuNzEgMS4zOS0zLjEgMy4xLTMuMWg0VjdIN2MtMi43NiAwLTUgMi4yNC01IDVzMi4yNCA1IDUgNWg0di0xLjlIN2MtMS43MSAwLTMuMS0xLjM5LTMuMS0zLjF6TTggMTNoOHYtMkg4djJ6bTktNmgtNHYxLjloNGMxLjcxIDAgMy4xIDEuMzkgMy4xIDMuMXMtMS4zOSAzLjEtMy4xIDMuMWgtNFYxN2g0YzIuNzYgMCA1LTIuMjQgNS01cy0yLjI0LTUtNS01eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-list: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xOSA1djE0SDVWNWgxNG0xLjEtMkgzLjljLS41IDAtLjkuNC0uOS45djE2LjJjMCAuNC40LjkuOS45aDE2LjJjLjQgMCAuOS0uNS45LS45VjMuOWMwLS41LS41LS45LS45LS45ek0xMSA3aDZ2MmgtNlY3em0wIDRoNnYyaC02di0yem0wIDRoNnYyaC02ek03IDdoMnYySDd6bTAgNGgydjJIN3ptMCA0aDJ2Mkg3eiIvPgo8L3N2Zz4=);--jp-icon-listings-info: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCA1MC45NzggNTAuOTc4IiBzdHlsZT0iZW5hYmxlLWJhY2tncm91bmQ6bmV3IDAgMCA1MC45NzggNTAuOTc4OyIgeG1sOnNwYWNlPSJwcmVzZXJ2ZSI+Cgk8Zz4KCQk8cGF0aCBzdHlsZT0iZmlsbDojMDEwMDAyOyIgZD0iTTQzLjUyLDcuNDU4QzM4LjcxMSwyLjY0OCwzMi4zMDcsMCwyNS40ODksMEMxOC42NywwLDEyLjI2NiwyLjY0OCw3LjQ1OCw3LjQ1OAoJCQljLTkuOTQzLDkuOTQxLTkuOTQzLDI2LjExOSwwLDM2LjA2MmM0LjgwOSw0LjgwOSwxMS4yMTIsNy40NTYsMTguMDMxLDcuNDU4YzAsMCwwLjAwMSwwLDAuMDAyLDAKCQkJYzYuODE2LDAsMTMuMjIxLTIuNjQ4LDE4LjAyOS03LjQ1OGM0LjgwOS00LjgwOSw3LjQ1Ny0xMS4yMTIsNy40NTctMTguMDNDNTAuOTc3LDE4LjY3LDQ4LjMyOCwxMi4yNjYsNDMuNTIsNy40NTh6CgkJCSBNNDIuMTA2LDQyLjEwNWMtNC40MzIsNC40MzEtMTAuMzMyLDYuODcyLTE2LjYxNSw2Ljg3MmgtMC4wMDJjLTYuMjg1LTAuMDAxLTEyLjE4Ny0yLjQ0MS0xNi42MTctNi44NzIKCQkJYy05LjE2Mi05LjE2My05LjE2Mi0yNC4wNzEsMC0zMy4yMzNDMTMuMzAzLDQuNDQsMTkuMjA0LDIsMjUuNDg5LDJjNi4yODQsMCwxMi4xODYsMi40NCwxNi42MTcsNi44NzIKCQkJYzQuNDMxLDQuNDMxLDYuODcxLDEwLjMzMiw2Ljg3MSwxNi42MTdDNDguOTc3LDMxLjc3Miw0Ni41MzYsMzcuNjc1LDQyLjEwNiw0Mi4xMDV6Ii8+CgkJPHBhdGggc3R5bGU9ImZpbGw6IzAxMDAwMjsiIGQ9Ik0yMy41NzgsMzIuMjE4Yy0wLjAyMy0xLjczNCwwLjE0My0zLjA1OSwwLjQ5Ni0zLjk3MmMwLjM1My0wLjkxMywxLjExLTEuOTk3LDIuMjcyLTMuMjUzCgkJCWMwLjQ2OC0wLjUzNiwwLjkyMy0xLjA2MiwxLjM2Ny0xLjU3NWMwLjYyNi0wLjc1MywxLjEwNC0xLjQ3OCwxLjQzNi0yLjE3NWMwLjMzMS0wLjcwNywwLjQ5NS0xLjU0MSwwLjQ5NS0yLjUKCQkJYzAtMS4wOTYtMC4yNi0yLjA4OC0wLjc3OS0yLjk3OWMtMC41NjUtMC44NzktMS41MDEtMS4zMzYtMi44MDYtMS4zNjljLTEuODAyLDAuMDU3LTIuOTg1LDAuNjY3LTMuNTUsMS44MzIKCQkJYy0wLjMwMSwwLjUzNS0wLjUwMywxLjE0MS0wLjYwNywxLjgxNGMtMC4xMzksMC43MDctMC4yMDcsMS40MzItMC4yMDcsMi4xNzRoLTIuOTM3Yy0wLjA5MS0yLjIwOCwwLjQwNy00LjExNCwxLjQ5My01LjcxOQoJCQljMS4wNjItMS42NCwyLjg1NS0yLjQ4MSw1LjM3OC0yLjUyN2MyLjE2LDAuMDIzLDMuODc0LDAuNjA4LDUuMTQxLDEuNzU4YzEuMjc4LDEuMTYsMS45MjksMi43NjQsMS45NSw0LjgxMQoJCQljMCwxLjE0Mi0wLjEzNywyLjExMS0wLjQxLDIuOTExYy0wLjMwOSwwLjg0NS0wLjczMSwxLjU5My0xLjI2OCwyLjI0M2MtMC40OTIsMC42NS0xLjA2OCwxLjMxOC0xLjczLDIuMDAyCgkJCWMtMC42NSwwLjY5Ny0xLjMxMywxLjQ3OS0xLjk4NywyLjM0NmMtMC4yMzksMC4zNzctMC40MjksMC43NzctMC41NjUsMS4xOTljLTAuMTYsMC45NTktMC4yMTcsMS45NTEtMC4xNzEsMi45NzkKCQkJQzI2LjU4OSwzMi4yMTgsMjMuNTc4LDMyLjIxOCwyMy41NzgsMzIuMjE4eiBNMjMuNTc4LDM4LjIydi0zLjQ4NGgzLjA3NnYzLjQ4NEgyMy41Nzh6Ii8+Cgk8L2c+Cjwvc3ZnPgo=);--jp-icon-markdown: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDAganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjN0IxRkEyIiBkPSJNNSAxNC45aDEybC02LjEgNnptOS40LTYuOGMwLTEuMy0uMS0yLjktLjEtNC41LS40IDEuNC0uOSAyLjktMS4zIDQuM2wtMS4zIDQuM2gtMkw4LjUgNy45Yy0uNC0xLjMtLjctMi45LTEtNC4zLS4xIDEuNi0uMSAzLjItLjIgNC42TDcgMTIuNEg0LjhsLjctMTFoMy4zTDEwIDVjLjQgMS4yLjcgMi43IDEgMy45LjMtMS4yLjctMi42IDEtMy45bDEuMi0zLjdoMy4zbC42IDExaC0yLjRsLS4zLTQuMnoiLz4KPC9zdmc+Cg==);--jp-icon-move-down: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMTIuNDcxIDcuNTI4OTlDMTIuNzYzMiA3LjIzNjg0IDEyLjc2MzIgNi43NjMxNiAxMi40NzEgNi40NzEwMVY2LjQ3MTAxQzEyLjE3OSA2LjE3OTA1IDExLjcwNTcgNi4xNzg4NCAxMS40MTM1IDYuNDcwNTRMNy43NSAxMC4xMjc1VjEuNzVDNy43NSAxLjMzNTc5IDcuNDE0MjEgMSA3IDFWMUM2LjU4NTc5IDEgNi4yNSAxLjMzNTc5IDYuMjUgMS43NVYxMC4xMjc1TDIuNTk3MjYgNi40NjgyMkMyLjMwMzM4IDYuMTczODEgMS44MjY0MSA2LjE3MzU5IDEuNTMyMjYgNi40Njc3NFY2LjQ2Nzc0QzEuMjM4MyA2Ljc2MTcgMS4yMzgzIDcuMjM4MyAxLjUzMjI2IDcuNTMyMjZMNi4yOTI4OSAxMi4yOTI5QzYuNjgzNDIgMTIuNjgzNCA3LjMxNjU4IDEyLjY4MzQgNy43MDcxMSAxMi4yOTI5TDEyLjQ3MSA3LjUyODk5WiIgZmlsbD0iIzYxNjE2MSIvPgo8L3N2Zz4K);--jp-icon-move-up: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTQiIGhlaWdodD0iMTQiIHZpZXdCb3g9IjAgMCAxNCAxNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggY2xhc3M9ImpwLWljb24zIiBkPSJNMS41Mjg5OSA2LjQ3MTAxQzEuMjM2ODQgNi43NjMxNiAxLjIzNjg0IDcuMjM2ODQgMS41Mjg5OSA3LjUyODk5VjcuNTI4OTlDMS44MjA5NSA3LjgyMDk1IDIuMjk0MjYgNy44MjExNiAyLjU4NjQ5IDcuNTI5NDZMNi4yNSAzLjg3MjVWMTIuMjVDNi4yNSAxMi42NjQyIDYuNTg1NzkgMTMgNyAxM1YxM0M3LjQxNDIxIDEzIDcuNzUgMTIuNjY0MiA3Ljc1IDEyLjI1VjMuODcyNUwxMS40MDI3IDcuNTMxNzhDMTEuNjk2NiA3LjgyNjE5IDEyLjE3MzYgNy44MjY0MSAxMi40Njc3IDcuNTMyMjZWNy41MzIyNkMxMi43NjE3IDcuMjM4MyAxMi43NjE3IDYuNzYxNyAxMi40Njc3IDYuNDY3NzRMNy43MDcxMSAxLjcwNzExQzcuMzE2NTggMS4zMTY1OCA2LjY4MzQyIDEuMzE2NTggNi4yOTI4OSAxLjcwNzExTDEuNTI4OTkgNi40NzEwMVoiIGZpbGw9IiM2MTYxNjEiLz4KPC9zdmc+Cg==);--jp-icon-new-folder: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIwIDZoLThsLTItMkg0Yy0xLjExIDAtMS45OS44OS0xLjk5IDJMMiAxOGMwIDEuMTEuODkgMiAyIDJoMTZjMS4xMSAwIDItLjg5IDItMlY4YzAtMS4xMS0uODktMi0yLTJ6bS0xIDhoLTN2M2gtMnYtM2gtM3YtMmgzVjloMnYzaDN2MnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-not-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI1IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMTkgMTcuMTg0NCAyLjk2OTY4IDE0LjMwMzIgMS44NjA5NCAxMS40NDA5WiIvPgogICAgPHBhdGggY2xhc3M9ImpwLWljb24yIiBzdHJva2U9IiMzMzMzMzMiIHN0cm9rZS13aWR0aD0iMiIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOS4zMTU5MiA5LjMyMDMxKSIgZD0iTTcuMzY4NDIgMEwwIDcuMzY0NzkiLz4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDkuMzE1OTIgMTYuNjgzNikgc2NhbGUoMSAtMSkiIGQ9Ik03LjM2ODQyIDBMMCA3LjM2NDc5Ii8+Cjwvc3ZnPgo=);--jp-icon-notebook: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtbm90ZWJvb2staWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiNFRjZDMDAiPgogICAgPHBhdGggZD0iTTE4LjcgMy4zdjE1LjRIMy4zVjMuM2gxNS40bTEuNS0xLjVIMS44djE4LjNoMTguM2wuMS0xOC4zeiIvPgogICAgPHBhdGggZD0iTTE2LjUgMTYuNWwtNS40LTQuMy01LjYgNC4zdi0xMWgxMXoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-numbering: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjIiIGhlaWdodD0iMjIiIHZpZXdCb3g9IjAgMCAyOCAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTQgMTlINlYxOS41SDVWMjAuNUg2VjIxSDRWMjJIN1YxOEg0VjE5Wk01IDEwSDZWNkg0VjdINVYxMFpNNCAxM0g1LjhMNCAxNS4xVjE2SDdWMTVINS4yTDcgMTIuOVYxMkg0VjEzWk05IDdWOUgyM1Y3SDlaTTkgMjFIMjNWMTlIOVYyMVpNOSAxNUgyM1YxM0g5VjE1WiIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-offline-bolt: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyIDIuMDJjLTUuNTEgMC05Ljk4IDQuNDctOS45OCA5Ljk4czQuNDcgOS45OCA5Ljk4IDkuOTggOS45OC00LjQ3IDkuOTgtOS45OFMxNy41MSAyLjAyIDEyIDIuMDJ6TTExLjQ4IDIwdi02LjI2SDhMMTMgNHY2LjI2aDMuMzVMMTEuNDggMjB6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-palette: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE4IDEzVjIwSDRWNkg5LjAyQzkuMDcgNS4yOSA5LjI0IDQuNjIgOS41IDRINEMyLjkgNCAyIDQuOSAyIDZWMjBDMiAyMS4xIDIuOSAyMiA0IDIySDE4QzE5LjEgMjIgMjAgMjEuMSAyMCAyMFYxNUwxOCAxM1pNMTkuMyA4Ljg5QzE5Ljc0IDguMTkgMjAgNy4zOCAyMCA2LjVDMjAgNC4wMSAxNy45OSAyIDE1LjUgMkMxMy4wMSAyIDExIDQuMDEgMTEgNi41QzExIDguOTkgMTMuMDEgMTEgMTUuNDkgMTFDMTYuMzcgMTEgMTcuMTkgMTAuNzQgMTcuODggMTAuM0wyMSAxMy40MkwyMi40MiAxMkwxOS4zIDguODlaTTE1LjUgOUMxNC4xMiA5IDEzIDcuODggMTMgNi41QzEzIDUuMTIgMTQuMTIgNCAxNS41IDRDMTYuODggNCAxOCA1LjEyIDE4IDYuNUMxOCA3Ljg4IDE2Ljg4IDkgMTUuNSA5WiIvPgogICAgPHBhdGggZmlsbC1ydWxlPSJldmVub2RkIiBjbGlwLXJ1bGU9ImV2ZW5vZGQiIGQ9Ik00IDZIOS4wMTg5NEM5LjAwNjM5IDYuMTY1MDIgOSA2LjMzMTc2IDkgNi41QzkgOC44MTU3NyAxMC4yMTEgMTAuODQ4NyAxMi4wMzQzIDEySDlWMTRIMTZWMTIuOTgxMUMxNi41NzAzIDEyLjkzNzcgMTcuMTIgMTIuODIwNyAxNy42Mzk2IDEyLjYzOTZMMTggMTNWMjBINFY2Wk04IDhINlYxMEg4VjhaTTYgMTJIOFYxNEg2VjEyWk04IDE2SDZWMThIOFYxNlpNOSAxNkgxNlYxOEg5VjE2WiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-paste: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE5IDJoLTQuMThDMTQuNC44NCAxMy4zIDAgMTIgMGMtMS4zIDAtMi40Ljg0LTIuODIgMkg1Yy0xLjEgMC0yIC45LTIgMnYxNmMwIDEuMS45IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjRjMC0xLjEtLjktMi0yLTJ6bS03IDBjLjU1IDAgMSAuNDUgMSAxcy0uNDUgMS0xIDEtMS0uNDUtMS0xIC40NS0xIDEtMXptNyAxOEg1VjRoMnYzaDEwVjRoMnYxNnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);--jp-icon-pdf: url(data:image/svg+xml;base64,PHN2ZwogICB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyMiAyMiIgd2lkdGg9IjE2Ij4KICAgIDxwYXRoIHRyYW5zZm9ybT0icm90YXRlKDQ1KSIgY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI0ZGMkEyQSIKICAgICAgIGQ9Im0gMjIuMzQ0MzY5LC0zLjAxNjM2NDIgaCA1LjYzODYwNCB2IDEuNTc5MjQzMyBoIC0zLjU0OTIyNyB2IDEuNTA4NjkyOTkgaCAzLjMzNzU3NiBWIDEuNjUwODE1NCBoIC0zLjMzNzU3NiB2IDMuNDM1MjYxMyBoIC0yLjA4OTM3NyB6IG0gLTcuMTM2NDQ0LDEuNTc5MjQzMyB2IDQuOTQzOTU0MyBoIDAuNzQ4OTIgcSAxLjI4MDc2MSwwIDEuOTUzNzAzLC0wLjYzNDk1MzUgMC42NzgzNjksLTAuNjM0OTUzNSAwLjY3ODM2OSwtMS44NDUxNjQxIDAsLTEuMjA0NzgzNTUgLTAuNjcyOTQyLC0xLjgzNDMxMDExIC0wLjY3Mjk0MiwtMC42Mjk1MjY1OSAtMS45NTkxMywtMC42Mjk1MjY1OSB6IG0gLTIuMDg5Mzc3LC0xLjU3OTI0MzMgaCAyLjIwMzM0MyBxIDEuODQ1MTY0LDAgMi43NDYwMzksMC4yNjU5MjA3IDAuOTA2MzAxLDAuMjYwNDkzNyAxLjU1MjEwOCwwLjg5MDAyMDMgMC41Njk4MywwLjU0ODEyMjMgMC44NDY2MDUsMS4yNjQ0ODAwNiAwLjI3Njc3NCwwLjcxNjM1NzgxIDAuMjc2Nzc0LDEuNjIyNjU4OTQgMCwwLjkxNzE1NTEgLTAuMjc2Nzc0LDEuNjM4OTM5OSAtMC4yNzY3NzUsMC43MTYzNTc4IC0wLjg0NjYwNSwxLjI2NDQ4IC0wLjY1MTIzNCwwLjYyOTUyNjYgLTEuNTYyOTYyLDAuODk1NDQ3MyAtMC45MTE3MjgsMC4yNjA0OTM3IC0yLjczNTE4NSwwLjI2MDQ5MzcgaCAtMi4yMDMzNDMgeiBtIC04LjE0NTg1NjUsMCBoIDMuNDY3ODIzIHEgMS41NDY2ODE2LDAgMi4zNzE1Nzg1LDAuNjg5MjIzIDAuODMwMzI0LDAuNjgzNzk2MSAwLjgzMDMyNCwxLjk1MzcwMzE0IDAsMS4yNzUzMzM5NyAtMC44MzAzMjQsMS45NjQ1NTcwNiBRIDkuOTg3MTk2MSwyLjI3NDkxNSA4LjQ0MDUxNDUsMi4yNzQ5MTUgSCA3LjA2MjA2ODQgViA1LjA4NjA3NjcgSCA0Ljk3MjY5MTUgWiBtIDIuMDg5Mzc2OSwxLjUxNDExOTkgdiAyLjI2MzAzOTQzIGggMS4xNTU5NDEgcSAwLjYwNzgxODgsMCAwLjkzODg2MjksLTAuMjkzMDU1NDcgMC4zMzEwNDQxLC0wLjI5ODQ4MjQxIDAuMzMxMDQ0MSwtMC44NDExNzc3MiAwLC0wLjU0MjY5NTMxIC0wLjMzMTA0NDEsLTAuODM1NzUwNzQgLTAuMzMxMDQ0MSwtMC4yOTMwNTU1IC0wLjkzODg2MjksLTAuMjkzMDU1NSB6IgovPgo8L3N2Zz4K);--jp-icon-python: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iLTEwIC0xMCAxMzEuMTYxMzYxNjk0MzM1OTQgMTMyLjM4ODk5OTkzODk2NDg0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMzA2OTk4IiBkPSJNIDU0LjkxODc4NSw5LjE5Mjc0MjFlLTQgQyA1MC4zMzUxMzIsMC4wMjIyMTcyNyA0NS45NTc4NDYsMC40MTMxMzY5NyA0Mi4xMDYyODUsMS4wOTQ2NjkzIDMwLjc2MDA2OSwzLjA5OTE3MzEgMjguNzAwMDM2LDcuMjk0NzcxNCAyOC43MDAwMzUsMTUuMDMyMTY5IHYgMTAuMjE4NzUgaCAyNi44MTI1IHYgMy40MDYyNSBoIC0yNi44MTI1IC0xMC4wNjI1IGMgLTcuNzkyNDU5LDAgLTE0LjYxNTc1ODgsNC42ODM3MTcgLTE2Ljc0OTk5OTgsMTMuNTkzNzUgLTIuNDYxODE5OTgsMTAuMjEyOTY2IC0yLjU3MTAxNTA4LDE2LjU4NjAyMyAwLDI3LjI1IDEuOTA1OTI4Myw3LjkzNzg1MiA2LjQ1NzU0MzIsMTMuNTkzNzQ4IDE0LjI0OTk5OTgsMTMuNTkzNzUgaCA5LjIxODc1IHYgLTEyLjI1IGMgMCwtOC44NDk5MDIgNy42NTcxNDQsLTE2LjY1NjI0OCAxNi43NSwtMTYuNjU2MjUgaCAyNi43ODEyNSBjIDcuNDU0OTUxLDAgMTMuNDA2MjUzLC02LjEzODE2NCAxMy40MDYyNSwtMTMuNjI1IHYgLTI1LjUzMTI1IGMgMCwtNy4yNjYzMzg2IC02LjEyOTk4LC0xMi43MjQ3NzcxIC0xMy40MDYyNSwtMTMuOTM3NDk5NyBDIDY0LjI4MTU0OCwwLjMyNzk0Mzk3IDU5LjUwMjQzOCwtMC4wMjAzNzkwMyA1NC45MTg3ODUsOS4xOTI3NDIxZS00IFogbSAtMTQuNSw4LjIxODc1MDEyNTc5IGMgMi43Njk1NDcsMCA1LjAzMTI1LDIuMjk4NjQ1NiA1LjAzMTI1LDUuMTI0OTk5NiAtMmUtNiwyLjgxNjMzNiAtMi4yNjE3MDMsNS4wOTM3NSAtNS4wMzEyNSw1LjA5Mzc1IC0yLjc3OTQ3NiwtMWUtNiAtNS4wMzEyNSwtMi4yNzc0MTUgLTUuMDMxMjUsLTUuMDkzNzUgLTEwZS03LC0yLjgyNjM1MyAyLjI1MTc3NCwtNS4xMjQ5OTk2IDUuMDMxMjUsLTUuMTI0OTk5NiB6Ii8+CiAgPHBhdGggY2xhc3M9ImpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iI2ZmZDQzYiIgZD0ibSA4NS42Mzc1MzUsMjguNjU3MTY5IHYgMTEuOTA2MjUgYyAwLDkuMjMwNzU1IC03LjgyNTg5NSwxNi45OTk5OTkgLTE2Ljc1LDE3IGggLTI2Ljc4MTI1IGMgLTcuMzM1ODMzLDAgLTEzLjQwNjI0OSw2LjI3ODQ4MyAtMTMuNDA2MjUsMTMuNjI1IHYgMjUuNTMxMjQ3IGMgMCw3LjI2NjM0NCA2LjMxODU4OCwxMS41NDAzMjQgMTMuNDA2MjUsMTMuNjI1MDA0IDguNDg3MzMxLDIuNDk1NjEgMTYuNjI2MjM3LDIuOTQ2NjMgMjYuNzgxMjUsMCA2Ljc1MDE1NSwtMS45NTQzOSAxMy40MDYyNTMsLTUuODg3NjEgMTMuNDA2MjUsLTEzLjYyNTAwNCBWIDg2LjUwMDkxOSBoIC0yNi43ODEyNSB2IC0zLjQwNjI1IGggMjYuNzgxMjUgMTMuNDA2MjU0IGMgNy43OTI0NjEsMCAxMC42OTYyNTEsLTUuNDM1NDA4IDEzLjQwNjI0MSwtMTMuNTkzNzUgMi43OTkzMywtOC4zOTg4ODYgMi42ODAyMiwtMTYuNDc1Nzc2IDAsLTI3LjI1IC0xLjkyNTc4LC03Ljc1NzQ0MSAtNS42MDM4NywtMTMuNTkzNzUgLTEzLjQwNjI0MSwtMTMuNTkzNzUgeiBtIC0xNS4wNjI1LDY0LjY1NjI1IGMgMi43Nzk0NzgsM2UtNiA1LjAzMTI1LDIuMjc3NDE3IDUuMDMxMjUsNS4wOTM3NDcgLTJlLTYsMi44MjYzNTQgLTIuMjUxNzc1LDUuMTI1MDA0IC01LjAzMTI1LDUuMTI1MDA0IC0yLjc2OTU1LDAgLTUuMDMxMjUsLTIuMjk4NjUgLTUuMDMxMjUsLTUuMTI1MDA0IDJlLTYsLTIuODE2MzMgMi4yNjE2OTcsLTUuMDkzNzQ3IDUuMDMxMjUsLTUuMDkzNzQ3IHoiLz4KPC9zdmc+Cg==);--jp-icon-r-kernel: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjE5NkYzIiBkPSJNNC40IDIuNWMxLjItLjEgMi45LS4zIDQuOS0uMyAyLjUgMCA0LjEuNCA1LjIgMS4zIDEgLjcgMS41IDEuOSAxLjUgMy41IDAgMi0xLjQgMy41LTIuOSA0LjEgMS4yLjQgMS43IDEuNiAyLjIgMyAuNiAxLjkgMSAzLjkgMS4zIDQuNmgtMy44Yy0uMy0uNC0uOC0xLjctMS4yLTMuN3MtMS4yLTIuNi0yLjYtMi42aC0uOXY2LjRINC40VjIuNXptMy43IDYuOWgxLjRjMS45IDAgMi45LS45IDIuOS0yLjNzLTEtMi4zLTIuOC0yLjNjLS43IDAtMS4zIDAtMS42LjJ2NC41aC4xdi0uMXoiLz4KPC9zdmc+Cg==);--jp-icon-react: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMTUwIDE1MCA1NDEuOSAyOTUuMyI+CiAgPGcgY2xhc3M9ImpwLWljb24tYnJhbmQyIGpwLWljb24tc2VsZWN0YWJsZSIgZmlsbD0iIzYxREFGQiI+CiAgICA8cGF0aCBkPSJNNjY2LjMgMjk2LjVjMC0zMi41LTQwLjctNjMuMy0xMDMuMS04Mi40IDE0LjQtNjMuNiA4LTExNC4yLTIwLjItMTMwLjQtNi41LTMuOC0xNC4xLTUuNi0yMi40LTUuNnYyMi4zYzQuNiAwIDguMy45IDExLjQgMi42IDEzLjYgNy44IDE5LjUgMzcuNSAxNC45IDc1LjctMS4xIDkuNC0yLjkgMTkuMy01LjEgMjkuNC0xOS42LTQuOC00MS04LjUtNjMuNS0xMC45LTEzLjUtMTguNS0yNy41LTM1LjMtNDEuNi01MCAzMi42LTMwLjMgNjMuMi00Ni45IDg0LTQ2LjlWNzhjLTI3LjUgMC02My41IDE5LjYtOTkuOSA1My42LTM2LjQtMzMuOC03Mi40LTUzLjItOTkuOS01My4ydjIyLjNjMjAuNyAwIDUxLjQgMTYuNSA4NCA0Ni42LTE0IDE0LjctMjggMzEuNC00MS4zIDQ5LjktMjIuNiAyLjQtNDQgNi4xLTYzLjYgMTEtMi4zLTEwLTQtMTkuNy01LjItMjktNC43LTM4LjIgMS4xLTY3LjkgMTQuNi03NS44IDMtMS44IDYuOS0yLjYgMTEuNS0yLjZWNzguNWMtOC40IDAtMTYgMS44LTIyLjYgNS42LTI4LjEgMTYuMi0zNC40IDY2LjctMTkuOSAxMzAuMS02Mi4yIDE5LjItMTAyLjcgNDkuOS0xMDIuNyA4Mi4zIDAgMzIuNSA0MC43IDYzLjMgMTAzLjEgODIuNC0xNC40IDYzLjYtOCAxMTQuMiAyMC4yIDEzMC40IDYuNSAzLjggMTQuMSA1LjYgMjIuNSA1LjYgMjcuNSAwIDYzLjUtMTkuNiA5OS45LTUzLjYgMzYuNCAzMy44IDcyLjQgNTMuMiA5OS45IDUzLjIgOC40IDAgMTYtMS44IDIyLjYtNS42IDI4LjEtMTYuMiAzNC40LTY2LjcgMTkuOS0xMzAuMSA2Mi0xOS4xIDEwMi41LTQ5LjkgMTAyLjUtODIuM3ptLTEzMC4yLTY2LjdjLTMuNyAxMi45LTguMyAyNi4yLTEzLjUgMzkuNS00LjEtOC04LjQtMTYtMTMuMS0yNC00LjYtOC05LjUtMTUuOC0xNC40LTIzLjQgMTQuMiAyLjEgMjcuOSA0LjcgNDEgNy45em0tNDUuOCAxMDYuNWMtNy44IDEzLjUtMTUuOCAyNi4zLTI0LjEgMzguMi0xNC45IDEuMy0zMCAyLTQ1LjIgMi0xNS4xIDAtMzAuMi0uNy00NS0xLjktOC4zLTExLjktMTYuNC0yNC42LTI0LjItMzgtNy42LTEzLjEtMTQuNS0yNi40LTIwLjgtMzkuOCA2LjItMTMuNCAxMy4yLTI2LjggMjAuNy0zOS45IDcuOC0xMy41IDE1LjgtMjYuMyAyNC4xLTM4LjIgMTQuOS0xLjMgMzAtMiA0NS4yLTIgMTUuMSAwIDMwLjIuNyA0NSAxLjkgOC4zIDExLjkgMTYuNCAyNC42IDI0LjIgMzggNy42IDEzLjEgMTQuNSAyNi40IDIwLjggMzkuOC02LjMgMTMuNC0xMy4yIDI2LjgtMjAuNyAzOS45em0zMi4zLTEzYzUuNCAxMy40IDEwIDI2LjggMTMuOCAzOS44LTEzLjEgMy4yLTI2LjkgNS45LTQxLjIgOCA0LjktNy43IDkuOC0xNS42IDE0LjQtMjMuNyA0LjYtOCA4LjktMTYuMSAxMy0yNC4xek00MjEuMiA0MzBjLTkuMy05LjYtMTguNi0yMC4zLTI3LjgtMzIgOSAuNCAxOC4yLjcgMjcuNS43IDkuNCAwIDE4LjctLjIgMjcuOC0uNy05IDExLjctMTguMyAyMi40LTI3LjUgMzJ6bS03NC40LTU4LjljLTE0LjItMi4xLTI3LjktNC43LTQxLTcuOSAzLjctMTIuOSA4LjMtMjYuMiAxMy41LTM5LjUgNC4xIDggOC40IDE2IDEzLjEgMjQgNC43IDggOS41IDE1LjggMTQuNCAyMy40ek00MjAuNyAxNjNjOS4zIDkuNiAxOC42IDIwLjMgMjcuOCAzMi05LS40LTE4LjItLjctMjcuNS0uNy05LjQgMC0xOC43LjItMjcuOC43IDktMTEuNyAxOC4zLTIyLjQgMjcuNS0zMnptLTc0IDU4LjljLTQuOSA3LjctOS44IDE1LjYtMTQuNCAyMy43LTQuNiA4LTguOSAxNi0xMyAyNC01LjQtMTMuNC0xMC0yNi44LTEzLjgtMzkuOCAxMy4xLTMuMSAyNi45LTUuOCA0MS4yLTcuOXptLTkwLjUgMTI1LjJjLTM1LjQtMTUuMS01OC4zLTM0LjktNTguMy01MC42IDAtMTUuNyAyMi45LTM1LjYgNTguMy01MC42IDguNi0zLjcgMTgtNyAyNy43LTEwLjEgNS43IDE5LjYgMTMuMiA0MCAyMi41IDYwLjktOS4yIDIwLjgtMTYuNiA0MS4xLTIyLjIgNjAuNi05LjktMy4xLTE5LjMtNi41LTI4LTEwLjJ6TTMxMCA0OTBjLTEzLjYtNy44LTE5LjUtMzcuNS0xNC45LTc1LjcgMS4xLTkuNCAyLjktMTkuMyA1LjEtMjkuNCAxOS42IDQuOCA0MSA4LjUgNjMuNSAxMC45IDEzLjUgMTguNSAyNy41IDM1LjMgNDEuNiA1MC0zMi42IDMwLjMtNjMuMiA0Ni45LTg0IDQ2LjktNC41LS4xLTguMy0xLTExLjMtMi43em0yMzcuMi03Ni4yYzQuNyAzOC4yLTEuMSA2Ny45LTE0LjYgNzUuOC0zIDEuOC02LjkgMi42LTExLjUgMi42LTIwLjcgMC01MS40LTE2LjUtODQtNDYuNiAxNC0xNC43IDI4LTMxLjQgNDEuMy00OS45IDIyLjYtMi40IDQ0LTYuMSA2My42LTExIDIuMyAxMC4xIDQuMSAxOS44IDUuMiAyOS4xem0zOC41LTY2LjdjLTguNiAzLjctMTggNy0yNy43IDEwLjEtNS43LTE5LjYtMTMuMi00MC0yMi41LTYwLjkgOS4yLTIwLjggMTYuNi00MS4xIDIyLjItNjAuNiA5LjkgMy4xIDE5LjMgNi41IDI4LjEgMTAuMiAzNS40IDE1LjEgNTguMyAzNC45IDU4LjMgNTAuNi0uMSAxNS43LTIzIDM1LjYtNTguNCA1MC42ek0zMjAuOCA3OC40eiIvPgogICAgPGNpcmNsZSBjeD0iNDIwLjkiIGN5PSIyOTYuNSIgcj0iNDUuNyIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-redo: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgd2lkdGg9IjE2Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgICA8cGF0aCBkPSJNMCAwaDI0djI0SDB6IiBmaWxsPSJub25lIi8+PHBhdGggZD0iTTE4LjQgMTAuNkMxNi41NSA4Ljk5IDE0LjE1IDggMTEuNSA4Yy00LjY1IDAtOC41OCAzLjAzLTkuOTYgNy4yMkwzLjkgMTZjMS4wNS0zLjE5IDQuMDUtNS41IDcuNi01LjUgMS45NSAwIDMuNzMuNzIgNS4xMiAxLjg4TDEzIDE2aDlWN2wtMy42IDMuNnoiLz4KICA8L2c+Cjwvc3ZnPgo=);--jp-icon-refresh: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDE4IDE4Ij4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTkgMTMuNWMtMi40OSAwLTQuNS0yLjAxLTQuNS00LjVTNi41MSA0LjUgOSA0LjVjMS4yNCAwIDIuMzYuNTIgMy4xNyAxLjMzTDEwIDhoNVYzbC0xLjc2IDEuNzZDMTIuMTUgMy42OCAxMC42NiAzIDkgMyA1LjY5IDMgMy4wMSA1LjY5IDMuMDEgOVM1LjY5IDE1IDkgMTVjMi45NyAwIDUuNDMtMi4xNiA1LjktNWgtMS41MmMtLjQ2IDItMi4yNCAzLjUtNC4zOCAzLjV6Ii8+CiAgICA8L2c+Cjwvc3ZnPgo=);--jp-icon-regex: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIwIDIwIj4KICA8ZyBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiM0MTQxNDEiPgogICAgPHJlY3QgeD0iMiIgeT0iMiIgd2lkdGg9IjE2IiBoZWlnaHQ9IjE2Ii8+CiAgPC9nPgoKICA8ZyBjbGFzcz0ianAtaWNvbi1hY2NlbnQyIiBmaWxsPSIjRkZGIj4KICAgIDxjaXJjbGUgY2xhc3M9InN0MiIgY3g9IjUuNSIgY3k9IjE0LjUiIHI9IjEuNSIvPgogICAgPHJlY3QgeD0iMTIiIHk9IjQiIGNsYXNzPSJzdDIiIHdpZHRoPSIxIiBoZWlnaHQ9IjgiLz4KICAgIDxyZWN0IHg9IjguNSIgeT0iNy41IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjg2NiAtMC41IDAuNSAwLjg2NiAtMi4zMjU1IDcuMzIxOSkiIGNsYXNzPSJzdDIiIHdpZHRoPSI4IiBoZWlnaHQ9IjEiLz4KICAgIDxyZWN0IHg9IjEyIiB5PSI0IiB0cmFuc2Zvcm09Im1hdHJpeCgwLjUgLTAuODY2IDAuODY2IDAuNSAtMC42Nzc5IDE0LjgyNTIpIiBjbGFzcz0ic3QyIiB3aWR0aD0iMSIgaGVpZ2h0PSI4Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-run: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTggNXYxNGwxMS03eiIvPgogICAgPC9nPgo8L3N2Zz4K);--jp-icon-running: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDUxMiA1MTIiPgogIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICA8cGF0aCBkPSJNMjU2IDhDMTE5IDggOCAxMTkgOCAyNTZzMTExIDI0OCAyNDggMjQ4IDI0OC0xMTEgMjQ4LTI0OFMzOTMgOCAyNTYgOHptOTYgMzI4YzAgOC44LTcuMiAxNi0xNiAxNkgxNzZjLTguOCAwLTE2LTcuMi0xNi0xNlYxNzZjMC04LjggNy4yLTE2IDE2LTE2aDE2MGM4LjggMCAxNiA3LjIgMTYgMTZ2MTYweiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-save: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTE3IDNINWMtMS4xMSAwLTIgLjktMiAydjE0YzAgMS4xLjg5IDIgMiAyaDE0YzEuMSAwIDItLjkgMi0yVjdsLTQtNHptLTUgMTZjLTEuNjYgMC0zLTEuMzQtMy0zczEuMzQtMyAzLTMgMyAxLjM0IDMgMy0xLjM0IDMtMyAzem0zLTEwSDVWNWgxMHY0eiIvPgogICAgPC9nPgo8L3N2Zz4K);--jp-icon-search: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMTggMTgiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjEsMTAuOWgtMC43bC0wLjItMC4yYzAuOC0wLjksMS4zLTIuMiwxLjMtMy41YzAtMy0yLjQtNS40LTUuNC01LjRTMS44LDQuMiwxLjgsNy4xczIuNCw1LjQsNS40LDUuNCBjMS4zLDAsMi41LTAuNSwzLjUtMS4zbDAuMiwwLjJ2MC43bDQuMSw0LjFsMS4yLTEuMkwxMi4xLDEwLjl6IE03LjEsMTAuOWMtMi4xLDAtMy43LTEuNy0zLjctMy43czEuNy0zLjcsMy43LTMuN3MzLjcsMS43LDMuNywzLjcgUzkuMiwxMC45LDcuMSwxMC45eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-settings: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIiBkPSJNMTkuNDMgMTIuOThjLjA0LS4zMi4wNy0uNjQuMDctLjk4cy0uMDMtLjY2LS4wNy0uOThsMi4xMS0xLjY1Yy4xOS0uMTUuMjQtLjQyLjEyLS42NGwtMi0zLjQ2Yy0uMTItLjIyLS4zOS0uMy0uNjEtLjIybC0yLjQ5IDFjLS41Mi0uNC0xLjA4LS43My0xLjY5LS45OGwtLjM4LTIuNjVBLjQ4OC40ODggMCAwMDE0IDJoLTRjLS4yNSAwLS40Ni4xOC0uNDkuNDJsLS4zOCAyLjY1Yy0uNjEuMjUtMS4xNy41OS0xLjY5Ljk4bC0yLjQ5LTFjLS4yMy0uMDktLjQ5IDAtLjYxLjIybC0yIDMuNDZjLS4xMy4yMi0uMDcuNDkuMTIuNjRsMi4xMSAxLjY1Yy0uMDQuMzItLjA3LjY1LS4wNy45OHMuMDMuNjYuMDcuOThsLTIuMTEgMS42NWMtLjE5LjE1LS4yNC40Mi0uMTIuNjRsMiAzLjQ2Yy4xMi4yMi4zOS4zLjYxLjIybDIuNDktMWMuNTIuNCAxLjA4LjczIDEuNjkuOThsLjM4IDIuNjVjLjAzLjI0LjI0LjQyLjQ5LjQyaDRjLjI1IDAgLjQ2LS4xOC40OS0uNDJsLjM4LTIuNjVjLjYxLS4yNSAxLjE3LS41OSAxLjY5LS45OGwyLjQ5IDFjLjIzLjA5LjQ5IDAgLjYxLS4yMmwyLTMuNDZjLjEyLS4yMi4wNy0uNDktLjEyLS42NGwtMi4xMS0xLjY1ek0xMiAxNS41Yy0xLjkzIDAtMy41LTEuNTctMy41LTMuNXMxLjU3LTMuNSAzLjUtMy41IDMuNSAxLjU3IDMuNSAzLjUtMS41NyAzLjUtMy41IDMuNXoiLz4KPC9zdmc+Cg==);--jp-icon-share: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTSAxOCAyIEMgMTYuMzU0OTkgMiAxNSAzLjM1NDk5MDQgMTUgNSBDIDE1IDUuMTkwOTUyOSAxNS4wMjE3OTEgNS4zNzcxMjI0IDE1LjA1NjY0MSA1LjU1ODU5MzggTCA3LjkyMTg3NSA5LjcyMDcwMzEgQyA3LjM5ODUzOTkgOS4yNzc4NTM5IDYuNzMyMDc3MSA5IDYgOSBDIDQuMzU0OTkwNCA5IDMgMTAuMzU0OTkgMyAxMiBDIDMgMTMuNjQ1MDEgNC4zNTQ5OTA0IDE1IDYgMTUgQyA2LjczMjA3NzEgMTUgNy4zOTg1Mzk5IDE0LjcyMjE0NiA3LjkyMTg3NSAxNC4yNzkyOTcgTCAxNS4wNTY2NDEgMTguNDM5NDUzIEMgMTUuMDIxNTU1IDE4LjYyMTUxNCAxNSAxOC44MDgzODYgMTUgMTkgQyAxNSAyMC42NDUwMSAxNi4zNTQ5OSAyMiAxOCAyMiBDIDE5LjY0NTAxIDIyIDIxIDIwLjY0NTAxIDIxIDE5IEMgMjEgMTcuMzU0OTkgMTkuNjQ1MDEgMTYgMTggMTYgQyAxNy4yNjc0OCAxNiAxNi42MDE1OTMgMTYuMjc5MzI4IDE2LjA3ODEyNSAxNi43MjI2NTYgTCA4Ljk0MzM1OTQgMTIuNTU4NTk0IEMgOC45NzgyMDk1IDEyLjM3NzEyMiA5IDEyLjE5MDk1MyA5IDEyIEMgOSAxMS44MDkwNDcgOC45NzgyMDk1IDExLjYyMjg3OCA4Ljk0MzM1OTQgMTEuNDQxNDA2IEwgMTYuMDc4MTI1IDcuMjc5Mjk2OSBDIDE2LjYwMTQ2IDcuNzIyMTQ2MSAxNy4yNjc5MjMgOCAxOCA4IEMgMTkuNjQ1MDEgOCAyMSA2LjY0NTAwOTYgMjEgNSBDIDIxIDMuMzU0OTkwNCAxOS42NDUwMSAyIDE4IDIgeiBNIDE4IDQgQyAxOC41NjQxMjkgNCAxOSA0LjQzNTg3MDYgMTkgNSBDIDE5IDUuNTY0MTI5NCAxOC41NjQxMjkgNiAxOCA2IEMgMTcuNDM1ODcxIDYgMTcgNS41NjQxMjk0IDE3IDUgQyAxNyA0LjQzNTg3MDYgMTcuNDM1ODcxIDQgMTggNCB6IE0gNiAxMSBDIDYuNTY0MTI5NCAxMSA3IDExLjQzNTg3MSA3IDEyIEMgNyAxMi41NjQxMjkgNi41NjQxMjk0IDEzIDYgMTMgQyA1LjQzNTg3MDYgMTMgNSAxMi41NjQxMjkgNSAxMiBDIDUgMTEuNDM1ODcxIDUuNDM1ODcwNiAxMSA2IDExIHogTSAxOCAxOCBDIDE4LjU2NDEyOSAxOCAxOSAxOC40MzU4NzEgMTkgMTkgQyAxOSAxOS41NjQxMjkgMTguNTY0MTI5IDIwIDE4IDIwIEMgMTcuNDM1ODcxIDIwIDE3IDE5LjU2NDEyOSAxNyAxOSBDIDE3IDE4LjQzNTg3MSAxNy40MzU4NzEgMTggMTggMTggeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-spreadsheet: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8cGF0aCBjbGFzcz0ianAtaWNvbi1jb250cmFzdDEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNENBRjUwIiBkPSJNMi4yIDIuMnYxNy42aDE3LjZWMi4ySDIuMnptMTUuNCA3LjdoLTUuNVY0LjRoNS41djUuNXpNOS45IDQuNHY1LjVINC40VjQuNGg1LjV6bS01LjUgNy43aDUuNXY1LjVINC40di01LjV6bTcuNyA1LjV2LTUuNWg1LjV2NS41aC01LjV6Ii8+Cjwvc3ZnPgo=);--jp-icon-stop: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik02IDZoMTJ2MTJINnoiLz4KICAgIDwvZz4KPC9zdmc+Cg==);--jp-icon-tab: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTIxIDNIM2MtMS4xIDAtMiAuOS0yIDJ2MTRjMCAxLjEuOSAyIDIgMmgxOGMxLjEgMCAyLS45IDItMlY1YzAtMS4xLS45LTItMi0yem0wIDE2SDNWNWgxMHY0aDh2MTB6Ii8+CiAgPC9nPgo8L3N2Zz4K);--jp-icon-table-rows: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMSw4SDNWNGgxOFY4eiBNMjEsMTBIM3Y0aDE4VjEweiBNMjEsMTZIM3Y0aDE4VjE2eiIvPgogICAgPC9nPgo8L3N2Zz4=);--jp-icon-tag: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjgiIGhlaWdodD0iMjgiIHZpZXdCb3g9IjAgMCA0MyAyOCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KCTxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CgkJPHBhdGggZD0iTTI4LjgzMzIgMTIuMzM0TDMyLjk5OTggMTYuNTAwN0wzNy4xNjY1IDEyLjMzNEgyOC44MzMyWiIvPgoJCTxwYXRoIGQ9Ik0xNi4yMDk1IDIxLjYxMDRDMTUuNjg3MyAyMi4xMjk5IDE0Ljg0NDMgMjIuMTI5OSAxNC4zMjQ4IDIxLjYxMDRMNi45ODI5IDE0LjcyNDVDNi41NzI0IDE0LjMzOTQgNi4wODMxMyAxMy42MDk4IDYuMDQ3ODYgMTMuMDQ4MkM1Ljk1MzQ3IDExLjUyODggNi4wMjAwMiA4LjYxOTQ0IDYuMDY2MjEgNy4wNzY5NUM2LjA4MjgxIDYuNTE0NzcgNi41NTU0OCA2LjA0MzQ3IDcuMTE4MDQgNi4wMzA1NUM5LjA4ODYzIDUuOTg0NzMgMTMuMjYzOCA1LjkzNTc5IDEzLjY1MTggNi4zMjQyNUwyMS43MzY5IDEzLjYzOUMyMi4yNTYgMTQuMTU4NSAyMS43ODUxIDE1LjQ3MjQgMjEuMjYyIDE1Ljk5NDZMMTYuMjA5NSAyMS42MTA0Wk05Ljc3NTg1IDguMjY1QzkuMzM1NTEgNy44MjU2NiA4LjYyMzUxIDcuODI1NjYgOC4xODI4IDguMjY1QzcuNzQzNDYgOC43MDU3MSA3Ljc0MzQ2IDkuNDE3MzMgOC4xODI4IDkuODU2NjdDOC42MjM4MiAxMC4yOTY0IDkuMzM1ODIgMTAuMjk2NCA5Ljc3NTg1IDkuODU2NjdDMTAuMjE1NiA5LjQxNzMzIDEwLjIxNTYgOC43MDUzMyA5Ljc3NTg1IDguMjY1WiIvPgoJPC9nPgo8L3N2Zz4K);--jp-icon-terminal: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0IiA+CiAgICA8cmVjdCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1iYWNrZ3JvdW5kLWNvbG9yIGpwLWljb24tc2VsZWN0YWJsZSIgd2lkdGg9IjIwIiBoZWlnaHQ9IjIwIiB0cmFuc2Zvcm09InRyYW5zbGF0ZSgyIDIpIiBmaWxsPSIjMzMzMzMzIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtdGVybWluYWwtaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUtaW52ZXJzZSIgZD0iTTUuMDU2NjQgOC43NjE3MkM1LjA1NjY0IDguNTk3NjYgNS4wMzEyNSA4LjQ1MzEyIDQuOTgwNDcgOC4zMjgxMkM0LjkzMzU5IDguMTk5MjIgNC44NTU0NyA4LjA4MjAzIDQuNzQ2MDkgNy45NzY1NkM0LjY0MDYyIDcuODcxMDkgNC41IDcuNzc1MzkgNC4zMjQyMiA3LjY4OTQ1QzQuMTUyMzQgNy41OTk2MSAzLjk0MzM2IDcuNTExNzIgMy42OTcyNyA3LjQyNTc4QzMuMzAyNzMgNy4yODUxNiAyLjk0MzM2IDcuMTM2NzIgMi42MTkxNCA2Ljk4MDQ3QzIuMjk0OTIgNi44MjQyMiAyLjAxNzU4IDYuNjQyNTggMS43ODcxMSA2LjQzNTU1QzEuNTYwNTUgNi4yMjg1MiAxLjM4NDc3IDUuOTg4MjggMS4yNTk3NyA1LjcxNDg0QzEuMTM0NzcgNS40Mzc1IDEuMDcyMjcgNS4xMDkzOCAxLjA3MjI3IDQuNzMwNDdDMS4wNzIyNyA0LjM5ODQ0IDEuMTI4OTEgNC4wOTU3IDEuMjQyMTkgMy44MjIyN0MxLjM1NTQ3IDMuNTQ0OTIgMS41MTU2MiAzLjMwNDY5IDEuNzIyNjYgMy4xMDE1NkMxLjkyOTY5IDIuODk4NDQgMi4xNzk2OSAyLjczNDM3IDIuNDcyNjYgMi42MDkzOEMyLjc2NTYyIDIuNDg0MzggMy4wOTE4IDIuNDA0MyAzLjQ1MTE3IDIuMzY5MTRWMS4xMDkzOEg0LjM4ODY3VjIuMzgwODZDNC43NDAyMyAyLjQyNzczIDUuMDU2NjQgMi41MjM0NCA1LjMzNzg5IDIuNjY3OTdDNS42MTkxNCAyLjgxMjUgNS44NTc0MiAzLjAwMTk1IDYuMDUyNzMgMy4yMzYzM0M2LjI1MTk1IDMuNDY2OCA2LjQwNDMgMy43NDAyMyA2LjUwOTc3IDQuMDU2NjRDNi42MTkxNCA0LjM2OTE0IDYuNjczODMgNC43MjA3IDYuNjczODMgNS4xMTEzM0g1LjA0NDkyQzUuMDQ0OTIgNC42Mzg2NyA0LjkzNzUgNC4yODEyNSA0LjcyMjY2IDQuMDM5MDZDNC41MDc4MSAzLjc5Mjk3IDQuMjE2OCAzLjY2OTkyIDMuODQ5NjEgMy42Njk5MkMzLjY1MDM5IDMuNjY5OTIgMy40NzY1NiAzLjY5NzI3IDMuMzI4MTIgMy43NTE5NUMzLjE4MzU5IDMuODAyNzMgMy4wNjQ0NSAzLjg3Njk1IDIuOTcwNyAzLjk3NDYxQzIuODc2OTUgNC4wNjgzNiAyLjgwNjY0IDQuMTc5NjkgMi43NTk3NyA0LjMwODU5QzIuNzE2OCA0LjQzNzUgMi42OTUzMSA0LjU3ODEyIDIuNjk1MzEgNC43MzA0N0MyLjY5NTMxIDQuODgyODEgMi43MTY4IDUuMDE5NTMgMi43NTk3NyA1LjE0MDYyQzIuODA2NjQgNS4yNTc4MSAyLjg4MjgxIDUuMzY3MTkgMi45ODgyOCA1LjQ2ODc1QzMuMDk3NjYgNS41NzAzMSAzLjI0MDIzIDUuNjY3OTcgMy40MTYwMiA1Ljc2MTcyQzMuNTkxOCA1Ljg1MTU2IDMuODEwNTUgNS45NDMzNiA0LjA3MjI3IDYuMDM3MTFDNC40NjY4IDYuMTg1NTUgNC44MjQyMiA2LjMzOTg0IDUuMTQ0NTMgNi41QzUuNDY0ODQgNi42NTYyNSA1LjczODI4IDYuODM5ODQgNS45NjQ4NCA3LjA1MDc4QzYuMTk1MzEgNy4yNTc4MSA2LjM3MTA5IDcuNSA2LjQ5MjE5IDcuNzc3MzRDNi42MTcxOSA4LjA1MDc4IDYuNjc5NjkgOC4zNzUgNi42Nzk2OSA4Ljc1QzYuNjc5NjkgOS4wOTM3NSA2LjYyMzA1IDkuNDA0MyA2LjUwOTc3IDkuNjgxNjRDNi4zOTY0OCA5Ljk1NTA4IDYuMjM0MzggMTAuMTkxNCA2LjAyMzQ0IDEwLjM5MDZDNS44MTI1IDEwLjU4OTggNS41NTg1OSAxMC43NSA1LjI2MTcyIDEwLjg3MTFDNC45NjQ4NCAxMC45ODgzIDQuNjMyODEgMTEuMDY0NSA0LjI2NTYyIDExLjA5OTZWMTIuMjQ4SDMuMzMzOThWMTEuMDk5NkMzLjAwMTk1IDExLjA2ODQgMi42Nzk2OSAxMC45OTYxIDIuMzY3MTkgMTAuODgyOEMyLjA1NDY5IDEwLjc2NTYgMS43NzczNCAxMC41OTc3IDEuNTM1MTYgMTAuMzc4OUMxLjI5Njg4IDEwLjE2MDIgMS4xMDU0NyA5Ljg4NDc3IDAuOTYwOTM4IDkuNTUyNzNDMC44MTY0MDYgOS4yMTY4IDAuNzQ0MTQxIDguODE0NDUgMC43NDQxNDEgOC4zNDU3SDIuMzc4OTFDMi4zNzg5MSA4LjYyNjk1IDIuNDE5OTIgOC44NjMyOCAyLjUwMTk1IDkuMDU0NjlDMi41ODM5OCA5LjI0MjE5IDIuNjg5NDUgOS4zOTI1OCAyLjgxODM2IDkuNTA1ODZDMi45NTExNyA5LjYxNTIzIDMuMTAxNTYgOS42OTMzNiAzLjI2OTUzIDkuNzQwMjNDMy40Mzc1IDkuNzg3MTEgMy42MDkzOCA5LjgxMDU1IDMuNzg1MTYgOS44MTA1NUM0LjIwMzEyIDkuODEwNTUgNC41MTk1MyA5LjcxMjg5IDQuNzM0MzggOS41MTc1OEM0Ljk0OTIyIDkuMzIyMjcgNS4wNTY2NCA5LjA3MDMxIDUuMDU2NjQgOC43NjE3MlpNMTMuNDE4IDEyLjI3MTVIOC4wNzQyMlYxMUgxMy40MThWMTIuMjcxNVoiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDMuOTUyNjQgNikiIGZpbGw9IndoaXRlIi8+Cjwvc3ZnPgo=);--jp-icon-text-editor: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8cGF0aCBjbGFzcz0ianAtdGV4dC1lZGl0b3ItaWNvbi1jb2xvciBqcC1pY29uLXNlbGVjdGFibGUiIGZpbGw9IiM2MTYxNjEiIGQ9Ik0xNSAxNUgzdjJoMTJ2LTJ6bTAtOEgzdjJoMTJWN3pNMyAxM2gxOHYtMkgzdjJ6bTAgOGgxOHYtMkgzdjJ6TTMgM3YyaDE4VjNIM3oiLz4KPC9zdmc+Cg==);--jp-icon-toc: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgdmlld0JveD0iMCAwIDI0IDI0Ij4KICA8ZyBjbGFzcz0ianAtaWNvbjMganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjNjE2MTYxIj4KICAgIDxwYXRoIGQ9Ik03LDVIMjFWN0g3VjVNNywxM1YxMUgyMVYxM0g3TTQsNC41QTEuNSwxLjUgMCAwLDEgNS41LDZBMS41LDEuNSAwIDAsMSA0LDcuNUExLjUsMS41IDAgMCwxIDIuNSw2QTEuNSwxLjUgMCAwLDEgNCw0LjVNNCwxMC41QTEuNSwxLjUgMCAwLDEgNS41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMy41QTEuNSwxLjUgMCAwLDEgMi41LDEyQTEuNSwxLjUgMCAwLDEgNCwxMC41TTcsMTlWMTdIMjFWMTlIN000LDE2LjVBMS41LDEuNSAwIDAsMSA1LjUsMThBMS41LDEuNSAwIDAsMSA0LDE5LjVBMS41LDEuNSAwIDAsMSAyLjUsMThBMS41LDEuNSAwIDAsMSA0LDE2LjVaIiAvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-tree-view: url(data:image/svg+xml;base64,PHN2ZyBoZWlnaHQ9IjI0IiB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICAgIDxnIGNsYXNzPSJqcC1pY29uMyIgZmlsbD0iIzYxNjE2MSI+CiAgICAgICAgPHBhdGggZD0iTTAgMGgyNHYyNEgweiIgZmlsbD0ibm9uZSIvPgogICAgICAgIDxwYXRoIGQ9Ik0yMiAxMVYzaC03djNIOVYzSDJ2OGg3VjhoMnYxMGg0djNoN3YtOGgtN3YzaC0yVjhoMnYzeiIvPgogICAgPC9nPgo8L3N2Zz4=);--jp-icon-trusted: url(data:image/svg+xml;base64,PHN2ZyBmaWxsPSJub25lIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDI0IDI1Ij4KICAgIDxwYXRoIGNsYXNzPSJqcC1pY29uMiIgc3Ryb2tlPSIjMzMzMzMzIiBzdHJva2Utd2lkdGg9IjIiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDIgMykiIGQ9Ik0xLjg2MDk0IDExLjQ0MDlDMC44MjY0NDggOC43NzAyNyAwLjg2Mzc3OSA2LjA1NzY0IDEuMjQ5MDcgNC4xOTkzMkMyLjQ4MjA2IDMuOTMzNDcgNC4wODA2OCAzLjQwMzQ3IDUuNjAxMDIgMi44NDQ5QzcuMjM1NDkgMi4yNDQ0IDguODU2NjYgMS41ODE1IDkuOTg3NiAxLjA5NTM5QzExLjA1OTcgMS41ODM0MSAxMi42MDk0IDIuMjQ0NCAxNC4yMTggMi44NDMzOUMxNS43NTAzIDMuNDEzOTQgMTcuMzk5NSAzLjk1MjU4IDE4Ljc1MzkgNC4yMTM4NUMxOS4xMzY0IDYuMDcxNzcgMTkuMTcwOSA4Ljc3NzIyIDE4LjEzOSAxMS40NDA5QzE3LjAzMDMgMTQuMzAzMiAxNC42NjY4IDE3LjE4NDQgOS45OTk5OSAxOC45MzU0QzUuMzMzMiAxNy4xODQ0IDIuOTY5NjggMTQuMzAzMiAxLjg2MDk0IDExLjQ0MDlaIi8+CiAgICA8cGF0aCBjbGFzcz0ianAtaWNvbjIiIGZpbGw9IiMzMzMzMzMiIHN0cm9rZT0iIzMzMzMzMyIgdHJhbnNmb3JtPSJ0cmFuc2xhdGUoOCA5Ljg2NzE5KSIgZD0iTTIuODYwMTUgNC44NjUzNUwwLjcyNjU0OSAyLjk5OTU5TDAgMy42MzA0NUwyLjg2MDE1IDYuMTMxNTdMOCAwLjYzMDg3Mkw3LjI3ODU3IDBMMi44NjAxNSA0Ljg2NTM1WiIvPgo8L3N2Zz4K);--jp-icon-undo: url(data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHdpZHRoPSIxNiIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTEyLjUgOGMtMi42NSAwLTUuMDUuOTktNi45IDIuNkwyIDd2OWg5bC0zLjYyLTMuNjJjMS4zOS0xLjE2IDMuMTYtMS44OCA1LjEyLTEuODggMy41NCAwIDYuNTUgMi4zMSA3LjYgNS41bDIuMzctLjc4QzIxLjA4IDExLjAzIDE3LjE1IDggMTIuNSA4eiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-user: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMTYiIHZpZXdCb3g9IjAgMCAyNCAyNCIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KICA8ZyBjbGFzcz0ianAtaWNvbjMiIGZpbGw9IiM2MTYxNjEiPgogICAgPHBhdGggZD0iTTE2IDdhNCA0IDAgMTEtOCAwIDQgNCAwIDAxOCAwek0xMiAxNGE3IDcgMCAwMC03IDdoMTRhNyA3IDAgMDAtNy03eiIvPgogIDwvZz4KPC9zdmc+);--jp-icon-users: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZlcnNpb249IjEuMSIgdmlld0JveD0iMCAwIDM2IDI0IiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciPgogPGcgY2xhc3M9ImpwLWljb24zIiB0cmFuc2Zvcm09Im1hdHJpeCgxLjczMjcgMCAwIDEuNzMyNyAtMy42MjgyIC4wOTk1NzcpIiBmaWxsPSIjNjE2MTYxIj4KICA8cGF0aCB0cmFuc2Zvcm09Im1hdHJpeCgxLjUsMCwwLDEuNSwwLC02KSIgZD0ibTEyLjE4NiA3LjUwOThjLTEuMDUzNSAwLTEuOTc1NyAwLjU2NjUtMi40Nzg1IDEuNDEwMiAwLjc1MDYxIDAuMzEyNzcgMS4zOTc0IDAuODI2NDggMS44NzMgMS40NzI3aDMuNDg2M2MwLTEuNTkyLTEuMjg4OS0yLjg4MjgtMi44ODA5LTIuODgyOHoiLz4KICA8cGF0aCBkPSJtMjAuNDY1IDIuMzg5NWEyLjE4ODUgMi4xODg1IDAgMCAxLTIuMTg4NCAyLjE4ODUgMi4xODg1IDIuMTg4NSAwIDAgMS0yLjE4ODUtMi4xODg1IDIuMTg4NSAyLjE4ODUgMCAwIDEgMi4xODg1LTIuMTg4NSAyLjE4ODUgMi4xODg1IDAgMCAxIDIuMTg4NCAyLjE4ODV6Ii8+CiAgPHBhdGggdHJhbnNmb3JtPSJtYXRyaXgoMS41LDAsMCwxLjUsMCwtNikiIGQ9Im0zLjU4OTggOC40MjE5Yy0xLjExMjYgMC0yLjAxMzcgMC45MDExMS0yLjAxMzcgMi4wMTM3aDIuODE0NWMwLjI2Nzk3LTAuMzczMDkgMC41OTA3LTAuNzA0MzUgMC45NTg5OC0wLjk3ODUyLTAuMzQ0MzMtMC42MTY4OC0xLjAwMzEtMS4wMzUyLTEuNzU5OC0xLjAzNTJ6Ii8+CiAgPHBhdGggZD0ibTYuOTE1NCA0LjYyM2ExLjUyOTQgMS41Mjk0IDAgMCAxLTEuNTI5NCAxLjUyOTQgMS41Mjk0IDEuNTI5NCAwIDAgMS0xLjUyOTQtMS41Mjk0IDEuNTI5NCAxLjUyOTQgMCAwIDEgMS41Mjk0LTEuNTI5NCAxLjUyOTQgMS41Mjk0IDAgMCAxIDEuNTI5NCAxLjUyOTR6Ii8+CiAgPHBhdGggZD0ibTYuMTM1IDEzLjUzNWMwLTMuMjM5MiAyLjYyNTktNS44NjUgNS44NjUtNS44NjUgMy4yMzkyIDAgNS44NjUgMi42MjU5IDUuODY1IDUuODY1eiIvPgogIDxjaXJjbGUgY3g9IjEyIiBjeT0iMy43Njg1IiByPSIyLjk2ODUiLz4KIDwvZz4KPC9zdmc+Cg==);--jp-icon-vega: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbjEganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjMjEyMTIxIj4KICAgIDxwYXRoIGQ9Ik0xMC42IDUuNGwyLjItMy4ySDIuMnY3LjNsNC02LjZ6Ii8+CiAgICA8cGF0aCBkPSJNMTUuOCAyLjJsLTQuNCA2LjZMNyA2LjNsLTQuOCA4djUuNWgxNy42VjIuMmgtNHptLTcgMTUuNEg1LjV2LTQuNGgzLjN2NC40em00LjQgMEg5LjhWOS44aDMuNHY3Ljh6bTQuNCAwaC0zLjRWNi41aDMuNHYxMS4xeiIvPgogIDwvZz4KPC9zdmc+Cg==);--jp-icon-yaml: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgdmlld0JveD0iMCAwIDIyIDIyIj4KICA8ZyBjbGFzcz0ianAtaWNvbi1jb250cmFzdDIganAtaWNvbi1zZWxlY3RhYmxlIiBmaWxsPSIjRDgxQjYwIj4KICAgIDxwYXRoIGQ9Ik03LjIgMTguNnYtNS40TDMgNS42aDMuM2wxLjQgMy4xYy4zLjkuNiAxLjYgMSAyLjUuMy0uOC42LTEuNiAxLTIuNWwxLjQtMy4xaDMuNGwtNC40IDcuNnY1LjVsLTIuOS0uMXoiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxNi41IiByPSIyLjEiLz4KICAgIDxjaXJjbGUgY2xhc3M9InN0MCIgY3g9IjE3LjYiIGN5PSIxMSIgcj0iMi4xIi8+CiAgPC9nPgo8L3N2Zz4K)}.jupyter-wrapper .jp-AddAboveIcon{background-image:var(--jp-icon-add-above)}.jupyter-wrapper .jp-AddBelowIcon{background-image:var(--jp-icon-add-below)}.jupyter-wrapper .jp-AddIcon{background-image:var(--jp-icon-add)}.jupyter-wrapper .jp-BellIcon{background-image:var(--jp-icon-bell)}.jupyter-wrapper .jp-BugDotIcon{background-image:var(--jp-icon-bug-dot)}.jupyter-wrapper .jp-BugIcon{background-image:var(--jp-icon-bug)}.jupyter-wrapper .jp-BuildIcon{background-image:var(--jp-icon-build)}.jupyter-wrapper .jp-CaretDownEmptyIcon{background-image:var(--jp-icon-caret-down-empty)}.jupyter-wrapper .jp-CaretDownEmptyThinIcon{background-image:var(--jp-icon-caret-down-empty-thin)}.jupyter-wrapper .jp-CaretDownIcon{background-image:var(--jp-icon-caret-down)}.jupyter-wrapper .jp-CaretLeftIcon{background-image:var(--jp-icon-caret-left)}.jupyter-wrapper .jp-CaretRightIcon{background-image:var(--jp-icon-caret-right)}.jupyter-wrapper .jp-CaretUpEmptyThinIcon{background-image:var(--jp-icon-caret-up-empty-thin)}.jupyter-wrapper .jp-CaretUpIcon{background-image:var(--jp-icon-caret-up)}.jupyter-wrapper .jp-CaseSensitiveIcon{background-image:var(--jp-icon-case-sensitive)}.jupyter-wrapper .jp-CheckIcon{background-image:var(--jp-icon-check)}.jupyter-wrapper .jp-CircleEmptyIcon{background-image:var(--jp-icon-circle-empty)}.jupyter-wrapper .jp-CircleIcon{background-image:var(--jp-icon-circle)}.jupyter-wrapper .jp-ClearIcon{background-image:var(--jp-icon-clear)}.jupyter-wrapper .jp-CloseIcon{background-image:var(--jp-icon-close)}.jupyter-wrapper .jp-CodeIcon{background-image:var(--jp-icon-code)}.jupyter-wrapper .jp-ConsoleIcon{background-image:var(--jp-icon-console)}.jupyter-wrapper .jp-CopyIcon{background-image:var(--jp-icon-copy)}.jupyter-wrapper .jp-CopyrightIcon{background-image:var(--jp-icon-copyright)}.jupyter-wrapper .jp-CutIcon{background-image:var(--jp-icon-cut)}.jupyter-wrapper .jp-DeleteIcon{background-image:var(--jp-icon-delete)}.jupyter-wrapper .jp-DownloadIcon{background-image:var(--jp-icon-download)}.jupyter-wrapper .jp-DuplicateIcon{background-image:var(--jp-icon-duplicate)}.jupyter-wrapper .jp-EditIcon{background-image:var(--jp-icon-edit)}.jupyter-wrapper .jp-EllipsesIcon{background-image:var(--jp-icon-ellipses)}.jupyter-wrapper .jp-ExtensionIcon{background-image:var(--jp-icon-extension)}.jupyter-wrapper .jp-FastForwardIcon{background-image:var(--jp-icon-fast-forward)}.jupyter-wrapper .jp-FileIcon{background-image:var(--jp-icon-file)}.jupyter-wrapper .jp-FileUploadIcon{background-image:var(--jp-icon-file-upload)}.jupyter-wrapper .jp-FilterListIcon{background-image:var(--jp-icon-filter-list)}.jupyter-wrapper .jp-FolderFavoriteIcon{background-image:var(--jp-icon-folder-favorite)}.jupyter-wrapper .jp-FolderIcon{background-image:var(--jp-icon-folder)}.jupyter-wrapper .jp-HomeIcon{background-image:var(--jp-icon-home)}.jupyter-wrapper .jp-Html5Icon{background-image:var(--jp-icon-html5)}.jupyter-wrapper .jp-ImageIcon{background-image:var(--jp-icon-image)}.jupyter-wrapper .jp-InspectorIcon{background-image:var(--jp-icon-inspector)}.jupyter-wrapper .jp-JsonIcon{background-image:var(--jp-icon-json)}.jupyter-wrapper .jp-JuliaIcon{background-image:var(--jp-icon-julia)}.jupyter-wrapper .jp-JupyterFaviconIcon{background-image:var(--jp-icon-jupyter-favicon)}.jupyter-wrapper .jp-JupyterIcon{background-image:var(--jp-icon-jupyter)}.jupyter-wrapper .jp-JupyterlabWordmarkIcon{background-image:var(--jp-icon-jupyterlab-wordmark)}.jupyter-wrapper .jp-KernelIcon{background-image:var(--jp-icon-kernel)}.jupyter-wrapper .jp-KeyboardIcon{background-image:var(--jp-icon-keyboard)}.jupyter-wrapper .jp-LaunchIcon{background-image:var(--jp-icon-launch)}.jupyter-wrapper .jp-LauncherIcon{background-image:var(--jp-icon-launcher)}.jupyter-wrapper .jp-LineFormIcon{background-image:var(--jp-icon-line-form)}.jupyter-wrapper .jp-LinkIcon{background-image:var(--jp-icon-link)}.jupyter-wrapper .jp-ListIcon{background-image:var(--jp-icon-list)}.jupyter-wrapper .jp-ListingsInfoIcon{background-image:var(--jp-icon-listings-info)}.jupyter-wrapper .jp-MarkdownIcon{background-image:var(--jp-icon-markdown)}.jupyter-wrapper .jp-MoveDownIcon{background-image:var(--jp-icon-move-down)}.jupyter-wrapper .jp-MoveUpIcon{background-image:var(--jp-icon-move-up)}.jupyter-wrapper .jp-NewFolderIcon{background-image:var(--jp-icon-new-folder)}.jupyter-wrapper .jp-NotTrustedIcon{background-image:var(--jp-icon-not-trusted)}.jupyter-wrapper .jp-NotebookIcon{background-image:var(--jp-icon-notebook)}.jupyter-wrapper .jp-NumberingIcon{background-image:var(--jp-icon-numbering)}.jupyter-wrapper .jp-OfflineBoltIcon{background-image:var(--jp-icon-offline-bolt)}.jupyter-wrapper .jp-PaletteIcon{background-image:var(--jp-icon-palette)}.jupyter-wrapper .jp-PasteIcon{background-image:var(--jp-icon-paste)}.jupyter-wrapper .jp-PdfIcon{background-image:var(--jp-icon-pdf)}.jupyter-wrapper .jp-PythonIcon{background-image:var(--jp-icon-python)}.jupyter-wrapper .jp-RKernelIcon{background-image:var(--jp-icon-r-kernel)}.jupyter-wrapper .jp-ReactIcon{background-image:var(--jp-icon-react)}.jupyter-wrapper .jp-RedoIcon{background-image:var(--jp-icon-redo)}.jupyter-wrapper .jp-RefreshIcon{background-image:var(--jp-icon-refresh)}.jupyter-wrapper .jp-RegexIcon{background-image:var(--jp-icon-regex)}.jupyter-wrapper .jp-RunIcon{background-image:var(--jp-icon-run)}.jupyter-wrapper .jp-RunningIcon{background-image:var(--jp-icon-running)}.jupyter-wrapper .jp-SaveIcon{background-image:var(--jp-icon-save)}.jupyter-wrapper .jp-SearchIcon{background-image:var(--jp-icon-search)}.jupyter-wrapper .jp-SettingsIcon{background-image:var(--jp-icon-settings)}.jupyter-wrapper .jp-ShareIcon{background-image:var(--jp-icon-share)}.jupyter-wrapper .jp-SpreadsheetIcon{background-image:var(--jp-icon-spreadsheet)}.jupyter-wrapper .jp-StopIcon{background-image:var(--jp-icon-stop)}.jupyter-wrapper .jp-TabIcon{background-image:var(--jp-icon-tab)}.jupyter-wrapper .jp-TableRowsIcon{background-image:var(--jp-icon-table-rows)}.jupyter-wrapper .jp-TagIcon{background-image:var(--jp-icon-tag)}.jupyter-wrapper .jp-TerminalIcon{background-image:var(--jp-icon-terminal)}.jupyter-wrapper .jp-TextEditorIcon{background-image:var(--jp-icon-text-editor)}.jupyter-wrapper .jp-TocIcon{background-image:var(--jp-icon-toc)}.jupyter-wrapper .jp-TreeViewIcon{background-image:var(--jp-icon-tree-view)}.jupyter-wrapper .jp-TrustedIcon{background-image:var(--jp-icon-trusted)}.jupyter-wrapper .jp-UndoIcon{background-image:var(--jp-icon-undo)}.jupyter-wrapper .jp-UserIcon{background-image:var(--jp-icon-user)}.jupyter-wrapper .jp-UsersIcon{background-image:var(--jp-icon-users)}.jupyter-wrapper .jp-VegaIcon{background-image:var(--jp-icon-vega)}.jupyter-wrapper .jp-YamlIcon{background-image:var(--jp-icon-yaml)}.jupyter-wrapper .jp-Icon,.jupyter-wrapper .jp-MaterialIcon{background-position:center;background-repeat:no-repeat;background-size:16px;min-width:16px;min-height:16px}.jupyter-wrapper .jp-Icon-cover{background-position:center;background-repeat:no-repeat;background-size:cover}.jupyter-wrapper .jp-Icon-16{background-size:16px;min-width:16px;min-height:16px}.jupyter-wrapper .jp-Icon-18{background-size:18px;min-width:18px;min-height:18px}.jupyter-wrapper .jp-Icon-20{background-size:20px;min-width:20px;min-height:20px}.jupyter-wrapper .lm-TabBar .lm-TabBar-addButton{align-items:center;display:flex;padding:4px 4px 5px;margin-right:1px;background-color:var(--jp-layout-color2)}.jupyter-wrapper .lm-TabBar .lm-TabBar-addButton:hover{background-color:var(--jp-layout-color1)}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab{width:var(--jp-private-horizontal-tab-width)}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-content{flex:unset}.jupyter-wrapper .lm-DockPanel-tabBar[data-orientation=horizontal]{flex:1 1 auto}.jupyter-wrapper .jp-icon0[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon1[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon2[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon3[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon4[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon0[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon1[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon2[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon3[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon4[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-accent0[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-accent1[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-accent2[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-accent3[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-accent4[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-accent0[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-accent1[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-accent2[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-accent3[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-accent4[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-none[fill]{fill:none}.jupyter-wrapper .jp-icon-none[stroke]{stroke:none}.jupyter-wrapper .jp-icon-brand0[fill]{fill:var(--jp-brand-color0)}.jupyter-wrapper .jp-icon-brand1[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper .jp-icon-brand2[fill]{fill:var(--jp-brand-color2)}.jupyter-wrapper .jp-icon-brand3[fill]{fill:var(--jp-brand-color3)}.jupyter-wrapper .jp-icon-brand4[fill]{fill:var(--jp-brand-color4)}.jupyter-wrapper .jp-icon-brand0[stroke]{stroke:var(--jp-brand-color0)}.jupyter-wrapper .jp-icon-brand1[stroke]{stroke:var(--jp-brand-color1)}.jupyter-wrapper .jp-icon-brand2[stroke]{stroke:var(--jp-brand-color2)}.jupyter-wrapper .jp-icon-brand3[stroke]{stroke:var(--jp-brand-color3)}.jupyter-wrapper .jp-icon-brand4[stroke]{stroke:var(--jp-brand-color4)}.jupyter-wrapper .jp-icon-warn0[fill]{fill:var(--jp-warn-color0)}.jupyter-wrapper .jp-icon-warn1[fill]{fill:var(--jp-warn-color1)}.jupyter-wrapper .jp-icon-warn2[fill]{fill:var(--jp-warn-color2)}.jupyter-wrapper .jp-icon-warn3[fill]{fill:var(--jp-warn-color3)}.jupyter-wrapper .jp-icon-warn0[stroke]{stroke:var(--jp-warn-color0)}.jupyter-wrapper .jp-icon-warn1[stroke]{stroke:var(--jp-warn-color1)}.jupyter-wrapper .jp-icon-warn2[stroke]{stroke:var(--jp-warn-color2)}.jupyter-wrapper .jp-icon-warn3[stroke]{stroke:var(--jp-warn-color3)}.jupyter-wrapper .jp-icon-contrast0[fill]{fill:var(--jp-icon-contrast-color0)}.jupyter-wrapper .jp-icon-contrast1[fill]{fill:var(--jp-icon-contrast-color1)}.jupyter-wrapper .jp-icon-contrast2[fill]{fill:var(--jp-icon-contrast-color2)}.jupyter-wrapper .jp-icon-contrast3[fill]{fill:var(--jp-icon-contrast-color3)}.jupyter-wrapper .jp-icon-contrast0[stroke]{stroke:var(--jp-icon-contrast-color0)}.jupyter-wrapper .jp-icon-contrast1[stroke]{stroke:var(--jp-icon-contrast-color1)}.jupyter-wrapper .jp-icon-contrast2[stroke]{stroke:var(--jp-icon-contrast-color2)}.jupyter-wrapper .jp-icon-contrast3[stroke]{stroke:var(--jp-icon-contrast-color3)}.jupyter-wrapper .jp-jupyter-icon-color[fill]{fill:var(--jp-jupyter-icon-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-notebook-icon-color[fill]{fill:var(--jp-notebook-icon-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-json-icon-color[fill]{fill:var(--jp-json-icon-color, var(--jp-warn-color1))}.jupyter-wrapper .jp-console-icon-color[fill]{fill:var(--jp-console-icon-color, white)}.jupyter-wrapper .jp-console-icon-background-color[fill]{fill:var(--jp-console-icon-background-color, var(--jp-brand-color1))}.jupyter-wrapper .jp-terminal-icon-color[fill]{fill:var(--jp-terminal-icon-color, var(--jp-layout-color2))}.jupyter-wrapper .jp-terminal-icon-background-color[fill]{fill:var(--jp-terminal-icon-background-color, var(--jp-inverse-layout2))}.jupyter-wrapper .jp-text-editor-icon-color[fill]{fill:var(--jp-text-editor-icon-color, var(--jp-inverse-layout3))}.jupyter-wrapper .jp-inspector-icon-color[fill]{fill:var(--jp-inspector-icon-color, var(--jp-inverse-layout3))}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected .jp-icon-selectable-inverse[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-selectable-inverse[fill],.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-hover :hover .jp-icon-selectable[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-active .jp-icon-hover :hover .jp-icon-selectable-inverse[fill]{fill:#fff}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon3[fill]{fill:none}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper #tab-manager .lm-TabBar-tab.jp-mod-dirty.jp-mod-active>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:#fff}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon3[fill]{fill:none}.jupyter-wrapper .lm-DockPanel-tabBar .lm-TabBar-tab.lm-mod-closable.jp-mod-dirty>.lm-TabBar-tabCloseIcon>:not(:hover)>.jp-icon-busy[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper #jp-main-statusbar .jp-mod-selected .jp-icon-selectable[fill]{fill:#fff}.jupyter-wrapper #jp-main-statusbar .jp-mod-selected .jp-icon-selectable-inverse[fill]{fill:var(--jp-brand-color1)}.jupyter-wrapper :root{--jp-warn-color0: var(--md-orange-700)}.jupyter-wrapper .jp-DragIcon{margin-right:4px}.jupyter-wrapper .jp-icon-alt .jp-icon0[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon1[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon2[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon3[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon4[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon0[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon1[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon2[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon3[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon4[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent0[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent1[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent2[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent3[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent4[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent0[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent1[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent2[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent3[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-alt .jp-icon-accent4[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hoverShow:not(:hover) .jp-icon-hoverShow-content{display:none!important}.jupyter-wrapper .jp-icon-hover :hover .jp-icon0-hover[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon1-hover[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon2-hover[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon3-hover[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon4-hover[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon0-hover[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon1-hover[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon2-hover[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon3-hover[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon4-hover[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent0-hover[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent1-hover[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent2-hover[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent3-hover[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent4-hover[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent0-hover[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent1-hover[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent2-hover[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent3-hover[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-accent4-hover[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-none-hover[fill]{fill:none}.jupyter-wrapper .jp-icon-hover :hover .jp-icon-none-hover[stroke]{stroke:none}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[fill]{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[fill]{fill:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[fill]{fill:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[fill]{fill:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon0-hover[stroke]{stroke:var(--jp-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon1-hover[stroke]{stroke:var(--jp-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon2-hover[stroke]{stroke:var(--jp-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon3-hover[stroke]{stroke:var(--jp-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon4-hover[stroke]{stroke:var(--jp-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[fill]{fill:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[fill]{fill:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[fill]{fill:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[fill]{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[fill]{fill:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent0-hover[stroke]{stroke:var(--jp-inverse-layout-color0)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent1-hover[stroke]{stroke:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent2-hover[stroke]{stroke:var(--jp-inverse-layout-color2)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent3-hover[stroke]{stroke:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-icon-hover.jp-icon-alt :hover .jp-icon-accent4-hover[stroke]{stroke:var(--jp-inverse-layout-color4)}.jupyter-wrapper .jp-switch{display:flex;align-items:center;padding-left:4px;padding-right:4px;font-size:var(--jp-ui-font-size1);background-color:transparent;color:var(--jp-ui-font-color1);border:none;height:20px}.jupyter-wrapper .jp-switch:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-switch-label{margin-right:5px}.jupyter-wrapper .jp-switch-track{cursor:pointer;background-color:var(--jp-switch-color, var(--jp-border-color1));-webkit-transition:.4s;transition:.4s;border-radius:34px;height:16px;width:35px;position:relative}.jupyter-wrapper .jp-switch-track:before{content:\"\";position:absolute;height:10px;width:10px;margin:3px;left:0;background-color:var(--jp-ui-inverse-font-color1);-webkit-transition:.4s;transition:.4s;border-radius:50%}.jupyter-wrapper .jp-switch[aria-checked=true] .jp-switch-track{background-color:var(--jp-switch-true-position-color, var(--jp-warn-color0))}.jupyter-wrapper .jp-switch[aria-checked=true] .jp-switch-track:before{left:19px}.jupyter-wrapper html{box-sizing:unset}.jupyter-wrapper *,.jupyter-wrapper *:before,.jupyter-wrapper *:after{box-sizing:unset}.jupyter-wrapper body{color:unset;font-family:var(--jp-ui-font-family)}.jupyter-wrapper :focus{outline:unset;outline-offset:unset;-moz-outline-radius:unset}.jupyter-wrapper .jp-Button{border-radius:var(--jp-border-radius);padding:0 12px;font-size:var(--jp-ui-font-size1)}.jupyter-wrapper button.jp-Button.bp3-button.bp3-minimal:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-Button.minimal{color:unset!important}.jupyter-wrapper .jp-Button.jp-ToolbarButtonComponent{text-transform:none}.jupyter-wrapper .jp-InputGroup input{box-sizing:border-box;border-radius:0;background-color:transparent;color:var(--jp-ui-font-color0);box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color)}.jupyter-wrapper .jp-InputGroup input:focus{box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-active-box-shadow-color),inset 0 0 0 3px var(--jp-input-active-box-shadow-color)}.jupyter-wrapper .jp-InputGroup input::placeholder,.jupyter-wrapper input::placeholder{color:var(--jp-ui-font-color3)}.jupyter-wrapper .jp-BPIcon{display:inline-block;vertical-align:middle;margin:auto}.jupyter-wrapper .bp3-icon.jp-BPIcon>svg:not([fill]){fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-InputGroupAction{padding:6px}.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select{background-color:initial;border:none;border-radius:0;box-shadow:none;color:var(--jp-ui-font-color0);display:block;font-size:var(--jp-ui-font-size1);height:24px;line-height:14px;padding:0 25px 0 10px;text-align:left;-moz-appearance:none;-webkit-appearance:none}.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select:hover,.jupyter-wrapper .jp-HTMLSelect.jp-DefaultStyle select>option{background-color:var(--jp-layout-color2);color:var(--jp-ui-font-color0)}.jupyter-wrapper select{box-sizing:border-box}.jupyter-wrapper .jp-Collapse{display:flex;flex-direction:column;align-items:stretch;border-top:1px solid var(--jp-border-color2);border-bottom:1px solid var(--jp-border-color2)}.jupyter-wrapper .jp-Collapse-header{padding:1px 12px;color:var(--jp-ui-font-color1);background-color:var(--jp-layout-color1);font-size:var(--jp-ui-font-size2)}.jupyter-wrapper .jp-Collapse-header:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-Collapse-contents{padding:0 12px;background-color:var(--jp-layout-color1);color:var(--jp-ui-font-color1);overflow:auto}.jupyter-wrapper :root{--jp-private-commandpalette-search-height: 28px}.jupyter-wrapper .lm-CommandPalette{padding-bottom:0;color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .jp-ModalCommandPalette{position:absolute;z-index:10000;top:38px;left:30%;margin:0;padding:4px;width:40%;box-shadow:var(--jp-elevation-z4);border-radius:4px;background:var(--jp-layout-color0)}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette{max-height:40vh}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-close-icon:after{display:none}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-header{display:none}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item{margin-left:4px;margin-right:4px}.jupyter-wrapper .jp-ModalCommandPalette .lm-CommandPalette .lm-CommandPalette-item.lm-mod-disabled{display:none}.jupyter-wrapper .lm-CommandPalette-search{padding:4px;background-color:var(--jp-layout-color1);z-index:2}.jupyter-wrapper .lm-CommandPalette-wrapper{overflow:overlay;padding:0 9px;background-color:var(--jp-input-active-background);height:30px;box-shadow:inset 0 0 0 var(--jp-border-width) var(--jp-input-border-color)}.jupyter-wrapper .lm-CommandPalette.lm-mod-focused .lm-CommandPalette-wrapper{box-shadow:inset 0 0 0 1px var(--jp-input-active-box-shadow-color),inset 0 0 0 3px var(--jp-input-active-box-shadow-color)}.jupyter-wrapper .jp-SearchIconGroup{color:#fff;background-color:var(--jp-brand-color1);position:absolute;top:4px;right:4px;padding:5px 5px 1px}.jupyter-wrapper .jp-SearchIconGroup svg{height:20px;width:20px}.jupyter-wrapper .jp-SearchIconGroup .jp-icon3[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .lm-CommandPalette-input{background:transparent;width:calc(100% - 18px);float:left;border:none;outline:none;font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);line-height:var(--jp-private-commandpalette-search-height)}.jupyter-wrapper .lm-CommandPalette-input::-webkit-input-placeholder,.jupyter-wrapper .lm-CommandPalette-input::-moz-placeholder,.jupyter-wrapper .lm-CommandPalette-input:-ms-input-placeholder{color:var(--jp-ui-font-color2);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .lm-CommandPalette-header:first-child{margin-top:0}.jupyter-wrapper .lm-CommandPalette-header{border-bottom:solid var(--jp-border-width) var(--jp-border-color2);color:var(--jp-ui-font-color1);cursor:pointer;display:flex;font-size:var(--jp-ui-font-size0);font-weight:600;letter-spacing:1px;margin-top:8px;padding:8px 0 8px 12px;text-transform:uppercase}.jupyter-wrapper .lm-CommandPalette-header.lm-mod-active{background:var(--jp-layout-color2)}.jupyter-wrapper .lm-CommandPalette-header>mark{background-color:transparent;font-weight:700;color:var(--jp-ui-font-color1)}.jupyter-wrapper .lm-CommandPalette-item{padding:4px 12px 4px 4px;color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);font-weight:400;display:flex}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled{color:var(--jp-ui-font-color2)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active{color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active .jp-icon-selectable[fill]{fill:var(--jp-layout-color0)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active .lm-CommandPalette-itemLabel>mark{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-active:hover:not(.lm-mod-disabled){color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .lm-CommandPalette-item:hover:not(.lm-mod-active):not(.lm-mod-disabled){background:var(--jp-layout-color2)}.jupyter-wrapper .lm-CommandPalette-itemContent{overflow:hidden}.jupyter-wrapper .lm-CommandPalette-itemLabel>mark{color:var(--jp-ui-font-color0);background-color:transparent;font-weight:700}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled mark{color:var(--jp-ui-font-color2)}.jupyter-wrapper .lm-CommandPalette-item .lm-CommandPalette-itemIcon{margin:0 4px 0 0;position:relative;width:16px;top:2px;flex:0 0 auto}.jupyter-wrapper .lm-CommandPalette-item.lm-mod-disabled .lm-CommandPalette-itemIcon{opacity:.6}.jupyter-wrapper .lm-CommandPalette-item .lm-CommandPalette-itemShortcut{flex:0 0 auto}.jupyter-wrapper .lm-CommandPalette-itemCaption{display:none}.jupyter-wrapper .lm-CommandPalette-content{background-color:var(--jp-layout-color1)}.jupyter-wrapper .lm-CommandPalette-content:empty:after{content:\"No results\";margin:20px auto auto;width:100px;display:block;font-size:var(--jp-ui-font-size2);font-family:var(--jp-ui-font-family);font-weight:lighter}.jupyter-wrapper .lm-CommandPalette-emptyMessage{text-align:center;margin-top:24px;line-height:1.32;padding:0 8px;color:var(--jp-content-font-color3)}.jupyter-wrapper .jp-Dialog{position:absolute;z-index:10000;display:flex;flex-direction:column;align-items:center;justify-content:center;top:0;left:0;margin:0;padding:0;width:100%;height:100%;background:var(--jp-dialog-background)}.jupyter-wrapper .jp-Dialog-content{display:flex;flex-direction:column;margin-left:auto;margin-right:auto;background:var(--jp-layout-color1);padding:24px 24px 12px;min-width:300px;min-height:150px;max-width:1000px;max-height:500px;box-sizing:border-box;box-shadow:var(--jp-elevation-z20);word-wrap:break-word;border-radius:var(--jp-border-radius);font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color1);resize:both}.jupyter-wrapper .jp-Dialog-content.jp-Dialog-content-small{max-width:500px}.jupyter-wrapper .jp-Dialog-button{overflow:visible}.jupyter-wrapper button.jp-Dialog-button:focus{outline:1px solid var(--jp-brand-color1);outline-offset:4px;-moz-outline-radius:0px}.jupyter-wrapper button.jp-Dialog-button:focus::-moz-focus-inner{border:0}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus,.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus,.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus{outline-offset:4px;-moz-outline-radius:0px}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-accept:focus{outline:1px solid var(--md-blue-700)}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-warn:focus{outline:1px solid var(--md-red-600)}.jupyter-wrapper button.jp-Dialog-button.jp-mod-styled.jp-mod-reject:focus{outline:1px solid var(--md-grey-700)}.jupyter-wrapper button.jp-Dialog-close-button{padding:0;height:100%;min-width:unset;min-height:unset}.jupyter-wrapper .jp-Dialog-header{display:flex;justify-content:space-between;flex:0 0 auto;padding-bottom:12px;font-size:var(--jp-ui-font-size3);font-weight:400;color:var(--jp-ui-font-color0)}.jupyter-wrapper .jp-Dialog-body{display:flex;flex-direction:column;flex:1 1 auto;font-size:var(--jp-ui-font-size1);background:var(--jp-layout-color1);overflow:auto}.jupyter-wrapper .jp-Dialog-footer{display:flex;flex-direction:row;justify-content:flex-end;align-items:center;flex:0 0 auto;margin-left:-12px;margin-right:-12px;padding:12px}.jupyter-wrapper .jp-Dialog-checkbox{padding-right:5px}.jupyter-wrapper .jp-Dialog-checkbox>input:focus-visible{outline:1px solid var(--jp-input-active-border-color);outline-offset:1px}.jupyter-wrapper .jp-Dialog-spacer{flex:1 1 auto}.jupyter-wrapper .jp-Dialog-title{overflow:hidden;white-space:nowrap;text-overflow:ellipsis}.jupyter-wrapper .jp-Dialog-body>.jp-select-wrapper{width:100%}.jupyter-wrapper .jp-Dialog-body>button{padding:0 16px}.jupyter-wrapper .jp-Dialog-body>label{line-height:1.4;color:var(--jp-ui-font-color0)}.jupyter-wrapper .jp-Dialog-button.jp-mod-styled:not(:last-child){margin-right:12px}.jupyter-wrapper .jp-HoverBox{position:fixed}.jupyter-wrapper .jp-HoverBox.jp-mod-outofview{display:none}.jupyter-wrapper .jp-IFrame{width:100%;height:100%}.jupyter-wrapper .jp-IFrame>iframe{border:none}.jupyter-wrapper body.lm-mod-override-cursor .jp-IFrame{position:relative}.jupyter-wrapper body.lm-mod-override-cursor .jp-IFrame:before{content:\"\";position:absolute;top:0;left:0;right:0;bottom:0;background:transparent}.jupyter-wrapper .jp-Input-Boolean-Dialog{flex-direction:row-reverse;align-items:end;width:100%}.jupyter-wrapper .jp-Input-Boolean-Dialog>label{flex:1 1 auto}.jupyter-wrapper .jp-MainAreaWidget>:focus{outline:none}.jupyter-wrapper .jp-MainAreaWidget .jp-MainAreaWidget-error{padding:6px}.jupyter-wrapper .jp-MainAreaWidget .jp-MainAreaWidget-error>pre{width:auto;padding:10px;background:var(--jp-error-color3);border:var(--jp-border-width) solid var(--jp-error-color1);border-radius:var(--jp-border-radius);color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);white-space:pre-wrap;word-wrap:break-word}.jupyter-wrapper .jp-MainAreaWidget{contain:strict}.jupyter-wrapper :root{--md-red-50: #ffebee;--md-red-100: #ffcdd2;--md-red-200: #ef9a9a;--md-red-300: #e57373;--md-red-400: #ef5350;--md-red-500: #f44336;--md-red-600: #e53935;--md-red-700: #d32f2f;--md-red-800: #c62828;--md-red-900: #b71c1c;--md-red-A100: #ff8a80;--md-red-A200: #ff5252;--md-red-A400: #ff1744;--md-red-A700: #d50000;--md-pink-50: #fce4ec;--md-pink-100: #f8bbd0;--md-pink-200: #f48fb1;--md-pink-300: #f06292;--md-pink-400: #ec407a;--md-pink-500: #e91e63;--md-pink-600: #d81b60;--md-pink-700: #c2185b;--md-pink-800: #ad1457;--md-pink-900: #880e4f;--md-pink-A100: #ff80ab;--md-pink-A200: #ff4081;--md-pink-A400: #f50057;--md-pink-A700: #c51162;--md-purple-50: #f3e5f5;--md-purple-100: #e1bee7;--md-purple-200: #ce93d8;--md-purple-300: #ba68c8;--md-purple-400: #ab47bc;--md-purple-500: #9c27b0;--md-purple-600: #8e24aa;--md-purple-700: #7b1fa2;--md-purple-800: #6a1b9a;--md-purple-900: #4a148c;--md-purple-A100: #ea80fc;--md-purple-A200: #e040fb;--md-purple-A400: #d500f9;--md-purple-A700: #aa00ff;--md-deep-purple-50: #ede7f6;--md-deep-purple-100: #d1c4e9;--md-deep-purple-200: #b39ddb;--md-deep-purple-300: #9575cd;--md-deep-purple-400: #7e57c2;--md-deep-purple-500: #673ab7;--md-deep-purple-600: #5e35b1;--md-deep-purple-700: #512da8;--md-deep-purple-800: #4527a0;--md-deep-purple-900: #311b92;--md-deep-purple-A100: #b388ff;--md-deep-purple-A200: #7c4dff;--md-deep-purple-A400: #651fff;--md-deep-purple-A700: #6200ea;--md-indigo-50: #e8eaf6;--md-indigo-100: #c5cae9;--md-indigo-200: #9fa8da;--md-indigo-300: #7986cb;--md-indigo-400: #5c6bc0;--md-indigo-500: #3f51b5;--md-indigo-600: #3949ab;--md-indigo-700: #303f9f;--md-indigo-800: #283593;--md-indigo-900: #1a237e;--md-indigo-A100: #8c9eff;--md-indigo-A200: #536dfe;--md-indigo-A400: #3d5afe;--md-indigo-A700: #304ffe;--md-blue-50: #e3f2fd;--md-blue-100: #bbdefb;--md-blue-200: #90caf9;--md-blue-300: #64b5f6;--md-blue-400: #42a5f5;--md-blue-500: #2196f3;--md-blue-600: #1e88e5;--md-blue-700: #1976d2;--md-blue-800: #1565c0;--md-blue-900: #0d47a1;--md-blue-A100: #82b1ff;--md-blue-A200: #448aff;--md-blue-A400: #2979ff;--md-blue-A700: #2962ff;--md-light-blue-50: #e1f5fe;--md-light-blue-100: #b3e5fc;--md-light-blue-200: #81d4fa;--md-light-blue-300: #4fc3f7;--md-light-blue-400: #29b6f6;--md-light-blue-500: #03a9f4;--md-light-blue-600: #039be5;--md-light-blue-700: #0288d1;--md-light-blue-800: #0277bd;--md-light-blue-900: #01579b;--md-light-blue-A100: #80d8ff;--md-light-blue-A200: #40c4ff;--md-light-blue-A400: #00b0ff;--md-light-blue-A700: #0091ea;--md-cyan-50: #e0f7fa;--md-cyan-100: #b2ebf2;--md-cyan-200: #80deea;--md-cyan-300: #4dd0e1;--md-cyan-400: #26c6da;--md-cyan-500: #00bcd4;--md-cyan-600: #00acc1;--md-cyan-700: #0097a7;--md-cyan-800: #00838f;--md-cyan-900: #006064;--md-cyan-A100: #84ffff;--md-cyan-A200: #18ffff;--md-cyan-A400: #00e5ff;--md-cyan-A700: #00b8d4;--md-teal-50: #e0f2f1;--md-teal-100: #b2dfdb;--md-teal-200: #80cbc4;--md-teal-300: #4db6ac;--md-teal-400: #26a69a;--md-teal-500: #009688;--md-teal-600: #00897b;--md-teal-700: #00796b;--md-teal-800: #00695c;--md-teal-900: #004d40;--md-teal-A100: #a7ffeb;--md-teal-A200: #64ffda;--md-teal-A400: #1de9b6;--md-teal-A700: #00bfa5;--md-green-50: #e8f5e9;--md-green-100: #c8e6c9;--md-green-200: #a5d6a7;--md-green-300: #81c784;--md-green-400: #66bb6a;--md-green-500: #4caf50;--md-green-600: #43a047;--md-green-700: #388e3c;--md-green-800: #2e7d32;--md-green-900: #1b5e20;--md-green-A100: #b9f6ca;--md-green-A200: #69f0ae;--md-green-A400: #00e676;--md-green-A700: #00c853;--md-light-green-50: #f1f8e9;--md-light-green-100: #dcedc8;--md-light-green-200: #c5e1a5;--md-light-green-300: #aed581;--md-light-green-400: #9ccc65;--md-light-green-500: #8bc34a;--md-light-green-600: #7cb342;--md-light-green-700: #689f38;--md-light-green-800: #558b2f;--md-light-green-900: #33691e;--md-light-green-A100: #ccff90;--md-light-green-A200: #b2ff59;--md-light-green-A400: #76ff03;--md-light-green-A700: #64dd17;--md-lime-50: #f9fbe7;--md-lime-100: #f0f4c3;--md-lime-200: #e6ee9c;--md-lime-300: #dce775;--md-lime-400: #d4e157;--md-lime-500: #cddc39;--md-lime-600: #c0ca33;--md-lime-700: #afb42b;--md-lime-800: #9e9d24;--md-lime-900: #827717;--md-lime-A100: #f4ff81;--md-lime-A200: #eeff41;--md-lime-A400: #c6ff00;--md-lime-A700: #aeea00;--md-yellow-50: #fffde7;--md-yellow-100: #fff9c4;--md-yellow-200: #fff59d;--md-yellow-300: #fff176;--md-yellow-400: #ffee58;--md-yellow-500: #ffeb3b;--md-yellow-600: #fdd835;--md-yellow-700: #fbc02d;--md-yellow-800: #f9a825;--md-yellow-900: #f57f17;--md-yellow-A100: #ffff8d;--md-yellow-A200: #ffff00;--md-yellow-A400: #ffea00;--md-yellow-A700: #ffd600;--md-amber-50: #fff8e1;--md-amber-100: #ffecb3;--md-amber-200: #ffe082;--md-amber-300: #ffd54f;--md-amber-400: #ffca28;--md-amber-500: #ffc107;--md-amber-600: #ffb300;--md-amber-700: #ffa000;--md-amber-800: #ff8f00;--md-amber-900: #ff6f00;--md-amber-A100: #ffe57f;--md-amber-A200: #ffd740;--md-amber-A400: #ffc400;--md-amber-A700: #ffab00;--md-orange-50: #fff3e0;--md-orange-100: #ffe0b2;--md-orange-200: #ffcc80;--md-orange-300: #ffb74d;--md-orange-400: #ffa726;--md-orange-500: #ff9800;--md-orange-600: #fb8c00;--md-orange-700: #f57c00;--md-orange-800: #ef6c00;--md-orange-900: #e65100;--md-orange-A100: #ffd180;--md-orange-A200: #ffab40;--md-orange-A400: #ff9100;--md-orange-A700: #ff6d00;--md-deep-orange-50: #fbe9e7;--md-deep-orange-100: #ffccbc;--md-deep-orange-200: #ffab91;--md-deep-orange-300: #ff8a65;--md-deep-orange-400: #ff7043;--md-deep-orange-500: #ff5722;--md-deep-orange-600: #f4511e;--md-deep-orange-700: #e64a19;--md-deep-orange-800: #d84315;--md-deep-orange-900: #bf360c;--md-deep-orange-A100: #ff9e80;--md-deep-orange-A200: #ff6e40;--md-deep-orange-A400: #ff3d00;--md-deep-orange-A700: #dd2c00;--md-brown-50: #efebe9;--md-brown-100: #d7ccc8;--md-brown-200: #bcaaa4;--md-brown-300: #a1887f;--md-brown-400: #8d6e63;--md-brown-500: #795548;--md-brown-600: #6d4c41;--md-brown-700: #5d4037;--md-brown-800: #4e342e;--md-brown-900: #3e2723;--md-grey-50: #fafafa;--md-grey-100: #f5f5f5;--md-grey-200: #eeeeee;--md-grey-300: #e0e0e0;--md-grey-400: #bdbdbd;--md-grey-500: #9e9e9e;--md-grey-600: #757575;--md-grey-700: #616161;--md-grey-800: #424242;--md-grey-900: #212121;--md-blue-grey-50: #eceff1;--md-blue-grey-100: #cfd8dc;--md-blue-grey-200: #b0bec5;--md-blue-grey-300: #90a4ae;--md-blue-grey-400: #78909c;--md-blue-grey-500: #607d8b;--md-blue-grey-600: #546e7a;--md-blue-grey-700: #455a64;--md-blue-grey-800: #37474f;--md-blue-grey-900: #263238}.jupyter-wrapper .jp-Spinner{position:absolute;display:flex;justify-content:center;align-items:center;z-index:10;left:0;top:0;width:100%;height:100%;background:var(--jp-layout-color0);outline:none}.jupyter-wrapper .jp-SpinnerContent{font-size:10px;margin:50px auto;text-indent:-9999em;width:3em;height:3em;border-radius:50%;background:var(--jp-brand-color3);background:linear-gradient(to right,#f37626 10%,rgba(255,255,255,0) 42%);position:relative;animation:load3 1s infinite linear,fadeIn 1s}.jupyter-wrapper .jp-SpinnerContent:before{width:50%;height:50%;background:#f37626;border-radius:100% 0 0;position:absolute;top:0;left:0;content:\"\"}.jupyter-wrapper .jp-SpinnerContent:after{background:var(--jp-layout-color0);width:75%;height:75%;border-radius:50%;content:\"\";margin:auto;position:absolute;top:0;left:0;bottom:0;right:0}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes load3{0%{transform:rotate(0)}to{transform:rotate(360deg)}}.jupyter-wrapper button.jp-mod-styled{font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);border:none;box-sizing:border-box;text-align:center;line-height:32px;height:32px;padding:0 12px;letter-spacing:.8px;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper input.jp-mod-styled{background:var(--jp-input-background);height:28px;box-sizing:border-box;border:var(--jp-border-width) solid var(--jp-border-color1);padding-left:7px;padding-right:7px;font-size:var(--jp-ui-font-size2);color:var(--jp-ui-font-color0);outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper input[type=checkbox].jp-mod-styled{appearance:checkbox;-webkit-appearance:checkbox;-moz-appearance:checkbox;height:auto}.jupyter-wrapper input.jp-mod-styled:focus{border:var(--jp-border-width) solid var(--md-blue-500);box-shadow:inset 0 0 4px var(--md-blue-300)}.jupyter-wrapper .jp-FileDialog-Checkbox{margin-top:35px;display:flex;flex-direction:row;align-items:end;width:100%}.jupyter-wrapper .jp-FileDialog-Checkbox>label{flex:1 1 auto}.jupyter-wrapper .jp-select-wrapper{display:flex;position:relative;flex-direction:column;padding:1px;background-color:var(--jp-layout-color1);height:28px;box-sizing:border-box;margin-bottom:12px}.jupyter-wrapper .jp-select-wrapper.jp-mod-focused select.jp-mod-styled{border:var(--jp-border-width) solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow);background-color:var(--jp-input-active-background)}.jupyter-wrapper select.jp-mod-styled:hover{background-color:var(--jp-layout-color1);cursor:pointer;color:var(--jp-ui-font-color0);background-color:var(--jp-input-hover-background);box-shadow:inset 0 0 1px #00000080}.jupyter-wrapper select.jp-mod-styled{flex:1 1 auto;height:32px;width:100%;font-size:var(--jp-ui-font-size2);background:var(--jp-input-background);color:var(--jp-ui-font-color0);padding:0 25px 0 8px;border:var(--jp-border-width) solid var(--jp-input-border-color);border-radius:0;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none}.jupyter-wrapper :root{--jp-private-toolbar-height: calc( 28px + var(--jp-border-width) )}.jupyter-wrapper .jp-Toolbar{color:var(--jp-ui-font-color1);flex:0 0 auto;display:flex;flex-direction:row;border-bottom:var(--jp-border-width) solid var(--jp-toolbar-border-color);box-shadow:var(--jp-toolbar-box-shadow);background:var(--jp-toolbar-background);min-height:var(--jp-toolbar-micro-height);padding:2px;z-index:8;overflow-x:hidden}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-item.jp-Toolbar-spacer{flex-grow:1;flex-shrink:1}.jupyter-wrapper .jp-Toolbar-item.jp-Toolbar-kernelStatus{display:inline-block;width:32px;background-repeat:no-repeat;background-position:center;background-size:16px}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-item{flex:0 0 auto;display:flex;padding-left:1px;padding-right:1px;font-size:var(--jp-ui-font-size1);line-height:var(--jp-private-toolbar-height);height:100%}.jupyter-wrapper div.jp-ToolbarButton{color:transparent;border:none;box-sizing:border-box;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none;padding:0;margin:0}.jupyter-wrapper button.jp-ToolbarButtonComponent{background:var(--jp-layout-color1);border:none;box-sizing:border-box;outline:none;appearance:none;-webkit-appearance:none;-moz-appearance:none;padding:0 6px;margin:0;height:24px;border-radius:var(--jp-border-radius);display:flex;align-items:center;text-align:center;font-size:14px;min-width:unset;min-height:unset}.jupyter-wrapper button.jp-ToolbarButtonComponent:disabled{opacity:.4}.jupyter-wrapper button.jp-ToolbarButtonComponent span{padding:0;flex:0 0 auto}.jupyter-wrapper button.jp-ToolbarButtonComponent .jp-ToolbarButtonComponent-label{font-size:var(--jp-ui-font-size1);line-height:100%;padding-left:2px;color:var(--jp-ui-font-color1)}.jupyter-wrapper #jp-main-dock-panel[data-mode=single-document] .jp-MainAreaWidget>.jp-Toolbar.jp-Toolbar-micro{padding:0;min-height:0}.jupyter-wrapper #jp-main-dock-panel[data-mode=single-document] .jp-MainAreaWidget>.jp-Toolbar{border:none;box-shadow:none}.jupyter-wrapper body.p-mod-override-cursor *,.jupyter-wrapper body.lm-mod-override-cursor *{cursor:inherit!important}.jupyter-wrapper .jp-JSONEditor{display:flex;flex-direction:column;width:100%}.jupyter-wrapper .jp-JSONEditor-host{flex:1 1 auto;border:var(--jp-border-width) solid var(--jp-input-border-color);border-radius:0;background:var(--jp-layout-color0);min-height:50px;padding:1px}.jupyter-wrapper .jp-JSONEditor.jp-mod-error .jp-JSONEditor-host{border-color:red;outline-color:red}.jupyter-wrapper .jp-JSONEditor-header{display:flex;flex:1 0 auto;padding:0 0 0 12px}.jupyter-wrapper .jp-JSONEditor-header label{flex:0 0 auto}.jupyter-wrapper .jp-JSONEditor-commitButton{height:16px;width:16px;background-size:18px;background-repeat:no-repeat;background-position:center}.jupyter-wrapper .jp-JSONEditor-host.jp-mod-focused{background-color:var(--jp-input-active-background);border:1px solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow)}.jupyter-wrapper .jp-Editor.jp-mod-dropTarget{border:var(--jp-border-width) solid var(--jp-input-active-border-color);box-shadow:var(--jp-input-box-shadow)}.jupyter-wrapper .jp-Statusbar-ProgressCircle svg{display:block;margin:0 auto;width:16px;height:24px;align-self:normal}.jupyter-wrapper .jp-Statusbar-ProgressCircle path{fill:var(--jp-inverse-layout-color3)}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar{height:10px;width:100px;border:solid .25px var(--jp-brand-color2);border-radius:3px;overflow:hidden;align-self:center}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar>div{background-color:var(--jp-brand-color2);background-image:linear-gradient(-45deg,rgba(255,255,255,.2) 25%,transparent 25%,transparent 50%,rgba(255,255,255,.2) 50%,rgba(255,255,255,.2) 75%,transparent 75%,transparent);background-size:40px 40px;float:left;width:0%;height:100%;font-size:12px;line-height:14px;color:#fff;text-align:center;animation:jp-Statusbar-ExecutionTime-progress-bar 2s linear infinite}.jupyter-wrapper .jp-Statusbar-ProgressBar-progress-bar p{color:var(--jp-ui-font-color1);font-family:var(--jp-ui-font-family);font-size:var(--jp-ui-font-size1);line-height:10px;width:100px}@keyframes jp-Statusbar-ExecutionTime-progress-bar{0%{background-position:0 0}to{background-position:40px 40px}}.jupyter-wrapper .CodeMirror{font-family:monospace;height:300px;color:#000;direction:ltr}.jupyter-wrapper .CodeMirror-lines{padding:4px 0}.jupyter-wrapper .CodeMirror pre.CodeMirror-line,.jupyter-wrapper .CodeMirror pre.CodeMirror-line-like{padding:0 4px}.jupyter-wrapper .CodeMirror-scrollbar-filler,.jupyter-wrapper .CodeMirror-gutter-filler{background-color:#fff}.jupyter-wrapper .CodeMirror-gutters{border-right:1px solid #ddd;background-color:#f7f7f7;white-space:nowrap}.jupyter-wrapper .CodeMirror-linenumber{padding:0 3px 0 5px;min-width:20px;text-align:right;color:#999;white-space:nowrap}.jupyter-wrapper .CodeMirror-guttermarker{color:#000}.jupyter-wrapper .CodeMirror-guttermarker-subtle{color:#999}.jupyter-wrapper .CodeMirror-cursor{border-left:1px solid black;border-right:none;width:0}.jupyter-wrapper .CodeMirror div.CodeMirror-secondarycursor{border-left:1px solid silver}.jupyter-wrapper .cm-fat-cursor .CodeMirror-cursor{width:auto;border:0!important;background:#7e7}.jupyter-wrapper .cm-fat-cursor div.CodeMirror-cursors{z-index:1}.jupyter-wrapper .cm-fat-cursor-mark{background-color:#14ff1480;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite}.jupyter-wrapper .cm-animate-fat-cursor{width:auto;border:0;-webkit-animation:blink 1.06s steps(1) infinite;-moz-animation:blink 1.06s steps(1) infinite;animation:blink 1.06s steps(1) infinite;background-color:#7e7}@-moz-keyframes blink{50%{background-color:transparent}}@-webkit-keyframes blink{50%{background-color:transparent}}@keyframes blink{50%{background-color:transparent}}.jupyter-wrapper .cm-tab{display:inline-block;text-decoration:inherit}.jupyter-wrapper .CodeMirror-rulers{position:absolute;left:0;right:0;top:-50px;bottom:0;overflow:hidden}.jupyter-wrapper .CodeMirror-ruler{border-left:1px solid #ccc;top:0;bottom:0;position:absolute}.jupyter-wrapper .cm-s-default .cm-header{color:#00f}.jupyter-wrapper .cm-s-default .cm-quote{color:#090}.jupyter-wrapper .cm-negative{color:#d44}.jupyter-wrapper .cm-positive{color:#292}.jupyter-wrapper .cm-header,.jupyter-wrapper .cm-strong{font-weight:700}.jupyter-wrapper .cm-em{font-style:italic}.jupyter-wrapper .cm-link{text-decoration:underline}.jupyter-wrapper .cm-strikethrough{text-decoration:line-through}.jupyter-wrapper .cm-s-default .cm-keyword{color:#708}.jupyter-wrapper .cm-s-default .cm-atom{color:#219}.jupyter-wrapper .cm-s-default .cm-number{color:#164}.jupyter-wrapper .cm-s-default .cm-def{color:#00f}.jupyter-wrapper .cm-s-default .cm-variable-2{color:#05a}.jupyter-wrapper .cm-s-default .cm-variable-3,.jupyter-wrapper .cm-s-default .cm-type{color:#085}.jupyter-wrapper .cm-s-default .cm-comment{color:#a50}.jupyter-wrapper .cm-s-default .cm-string{color:#a11}.jupyter-wrapper .cm-s-default .cm-string-2{color:#f50}.jupyter-wrapper .cm-s-default .cm-meta,.jupyter-wrapper .cm-s-default .cm-qualifier{color:#555}.jupyter-wrapper .cm-s-default .cm-builtin{color:#30a}.jupyter-wrapper .cm-s-default .cm-bracket{color:#997}.jupyter-wrapper .cm-s-default .cm-tag{color:#170}.jupyter-wrapper .cm-s-default .cm-attribute{color:#00c}.jupyter-wrapper .cm-s-default .cm-hr{color:#999}.jupyter-wrapper .cm-s-default .cm-link{color:#00c}.jupyter-wrapper .cm-s-default .cm-error,.jupyter-wrapper .cm-invalidchar{color:red}.jupyter-wrapper .CodeMirror-composing{border-bottom:2px solid}.jupyter-wrapper div.CodeMirror span.CodeMirror-matchingbracket{color:#0b0}.jupyter-wrapper div.CodeMirror span.CodeMirror-nonmatchingbracket{color:#a22}.jupyter-wrapper .CodeMirror-matchingtag{background:rgba(255,150,0,.3)}.jupyter-wrapper .CodeMirror-activeline-background{background:#e8f2ff}.jupyter-wrapper .CodeMirror{position:relative;overflow:hidden;background:white}.jupyter-wrapper .CodeMirror-scroll{overflow:scroll!important;margin-bottom:-50px;margin-right:-50px;padding-bottom:50px;height:100%;outline:none;position:relative}.jupyter-wrapper .CodeMirror-sizer{position:relative;border-right:50px solid transparent}.jupyter-wrapper .CodeMirror-vscrollbar,.jupyter-wrapper .CodeMirror-hscrollbar,.jupyter-wrapper .CodeMirror-scrollbar-filler,.jupyter-wrapper .CodeMirror-gutter-filler{position:absolute;z-index:6;display:none;outline:none}.jupyter-wrapper .CodeMirror-vscrollbar{right:0;top:0;overflow-x:hidden;overflow-y:scroll}.jupyter-wrapper .CodeMirror-hscrollbar{bottom:0;left:0;overflow-y:hidden;overflow-x:scroll}.jupyter-wrapper .CodeMirror-scrollbar-filler{right:0;bottom:0}.jupyter-wrapper .CodeMirror-gutter-filler{left:0;bottom:0}.jupyter-wrapper .CodeMirror-gutters{position:absolute;left:0;top:0;min-height:100%;z-index:3}.jupyter-wrapper .CodeMirror-gutter{white-space:normal;height:100%;display:inline-block;vertical-align:top;margin-bottom:-50px}.jupyter-wrapper .CodeMirror-gutter-wrapper{position:absolute;z-index:4;background:none!important;border:none!important}.jupyter-wrapper .CodeMirror-gutter-background{position:absolute;top:0;bottom:0;z-index:4}.jupyter-wrapper .CodeMirror-gutter-elt{position:absolute;cursor:default;z-index:4}.jupyter-wrapper .CodeMirror-gutter-wrapper ::selection{background-color:transparent}.jupyter-wrapper .CodeMirror-gutter-wrapper ::-moz-selection{background-color:transparent}.jupyter-wrapper .CodeMirror-lines{cursor:text;min-height:1px}.jupyter-wrapper .CodeMirror pre.CodeMirror-line,.jupyter-wrapper .CodeMirror pre.CodeMirror-line-like{-moz-border-radius:0;-webkit-border-radius:0;border-radius:0;border-width:0;background:transparent;font-family:inherit;font-size:inherit;margin:0;white-space:pre;word-wrap:normal;line-height:inherit;color:inherit;z-index:2;position:relative;overflow:visible;-webkit-tap-highlight-color:transparent;-webkit-font-variant-ligatures:contextual;font-variant-ligatures:contextual}.jupyter-wrapper .CodeMirror-wrap pre.CodeMirror-line,.jupyter-wrapper .CodeMirror-wrap pre.CodeMirror-line-like{word-wrap:break-word;white-space:pre-wrap;word-break:normal}.jupyter-wrapper .CodeMirror-linebackground{position:absolute;left:0;right:0;top:0;bottom:0;z-index:0}.jupyter-wrapper .CodeMirror-linewidget{position:relative;z-index:2;padding:.1px}.jupyter-wrapper .CodeMirror-rtl pre{direction:rtl}.jupyter-wrapper .CodeMirror-code{outline:none}.jupyter-wrapper .CodeMirror-scroll,.jupyter-wrapper .CodeMirror-sizer,.jupyter-wrapper .CodeMirror-gutter,.jupyter-wrapper .CodeMirror-gutters,.jupyter-wrapper .CodeMirror-linenumber{-moz-box-sizing:content-box;box-sizing:content-box}.jupyter-wrapper .CodeMirror-measure{position:absolute;width:100%;height:0;overflow:hidden;visibility:hidden}.jupyter-wrapper .CodeMirror-cursor{position:absolute;pointer-events:none}.jupyter-wrapper .CodeMirror-measure pre{position:static}.jupyter-wrapper div.CodeMirror-cursors{visibility:hidden;position:relative;z-index:3}.jupyter-wrapper div.CodeMirror-dragcursors,.jupyter-wrapper .CodeMirror-focused div.CodeMirror-cursors{visibility:visible}.jupyter-wrapper .CodeMirror-selected{background:#d9d9d9}.jupyter-wrapper .CodeMirror-focused .CodeMirror-selected{background:#d7d4f0}.jupyter-wrapper .CodeMirror-crosshair{cursor:crosshair}.jupyter-wrapper .CodeMirror-line::selection,.jupyter-wrapper .CodeMirror-line>span::selection,.jupyter-wrapper .CodeMirror-line>span>span::selection{background:#d7d4f0}.jupyter-wrapper .CodeMirror-line::-moz-selection,.jupyter-wrapper .CodeMirror-line>span::-moz-selection,.jupyter-wrapper .CodeMirror-line>span>span::-moz-selection{background:#d7d4f0}.jupyter-wrapper .cm-searching{background-color:#ffa;background-color:#ff06}.jupyter-wrapper .cm-force-border{padding-right:.1px}@media print{.jupyter-wrapper .CodeMirror div.CodeMirror-cursors{visibility:hidden}}.jupyter-wrapper .cm-tab-wrap-hack:after{content:\"\"}.jupyter-wrapper span.CodeMirror-selectedtext{background:none}.jupyter-wrapper .CodeMirror-dialog{position:absolute;left:0;right:0;background:inherit;z-index:15;padding:.1em .8em;overflow:hidden;color:inherit}.jupyter-wrapper .CodeMirror-dialog-top{border-bottom:1px solid #eee;top:0}.jupyter-wrapper .CodeMirror-dialog-bottom{border-top:1px solid #eee;bottom:0}.jupyter-wrapper .CodeMirror-dialog input{border:none;outline:none;background:transparent;width:20em;color:inherit;font-family:monospace}.jupyter-wrapper .CodeMirror-dialog button{font-size:70%}.jupyter-wrapper .CodeMirror-foldmarker{color:#00f;text-shadow:#b9f 1px 1px 2px,#b9f -1px -1px 2px,#b9f 1px -1px 2px,#b9f -1px 1px 2px;font-family:arial;line-height:.3;cursor:pointer}.jupyter-wrapper .CodeMirror-foldgutter{width:.7em}.jupyter-wrapper .CodeMirror-foldgutter-open,.jupyter-wrapper .CodeMirror-foldgutter-folded{cursor:pointer}.jupyter-wrapper .CodeMirror-foldgutter-open:after{content:\"\u25be\"}.jupyter-wrapper .CodeMirror-foldgutter-folded:after{content:\"\u25b8\"}.jupyter-wrapper .CodeMirror{line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);font-family:var(--jp-code-font-family);border:0;border-radius:0;height:auto}.jupyter-wrapper .CodeMirror pre{padding:0 var(--jp-code-padding)}.jupyter-wrapper .CodeMirror.cm-fat-cursor .cm-overlay.cm-searching{opacity:.5}.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-dialog{background-color:var(--jp-layout-color0);color:var(--jp-content-font-color1)}.jupyter-wrapper .CodeMirror-lines{padding:var(--jp-code-padding) 0}.jupyter-wrapper .CodeMirror-linenumber{padding:0 8px}.jupyter-wrapper .jp-CodeMirrorEditor{cursor:text}.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)}@media screen and (min-width: 2138px) and (max-width: 4319px){.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width1) solid var(--jp-editor-cursor-color)}}@media screen and (min-width: 4320px){.jupyter-wrapper .jp-CodeMirrorEditor[data-type=inline] .CodeMirror-cursor{border-left:var(--jp-code-cursor-width2) solid var(--jp-editor-cursor-color)}}.jupyter-wrapper .CodeMirror.jp-mod-readOnly .CodeMirror-cursor{display:none}.jupyter-wrapper .CodeMirror-gutters{border-right:1px solid var(--jp-border-color2);background-color:var(--jp-layout-color0)}.jupyter-wrapper .jp-CollaboratorCursor{border-left:5px solid transparent;border-right:5px solid transparent;border-top:none;border-bottom:3px solid;background-clip:content-box;margin-left:-5px;margin-right:-5px}.jupyter-wrapper .CodeMirror-selectedtext.cm-searching{background-color:var(--jp-search-selected-match-background-color)!important;color:var(--jp-search-selected-match-color)!important}.jupyter-wrapper .cm-searching{background-color:var(--jp-search-unselected-match-background-color)!important;color:var(--jp-search-unselected-match-color)!important}.jupyter-wrapper .cm-trailingspace{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAFCAYAAAB4ka1VAAAAsElEQVQIHQGlAFr/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA7+r3zKmT0/+pk9P/7+r3zAAAAAAAAAAABAAAAAAAAAAA6OPzM+/q9wAAAAAA6OPzMwAAAAAAAAAAAgAAAAAAAAAAGR8NiRQaCgAZIA0AGR8NiQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQyoYJ/SY80UAAAAASUVORK5CYII=);background-position:center left;background-repeat:repeat-x}.jupyter-wrapper .CodeMirror-focused .CodeMirror-selected{background-color:var(--jp-editor-selected-focused-background)}.jupyter-wrapper .CodeMirror-selected{background-color:var(--jp-editor-selected-background)}.jupyter-wrapper .jp-CollaboratorCursor-hover{position:absolute;z-index:1;transform:translate(-50%);color:#fff;border-radius:3px;padding:1px 4px;text-align:center;font-size:var(--jp-ui-font-size1);white-space:nowrap}.jupyter-wrapper .jp-CodeMirror-ruler{border-left:1px dashed var(--jp-border-color2)}.jupyter-wrapper .CodeMirror.cm-s-jupyter{background:var(--jp-layout-color0);color:var(--jp-content-font-color1)}.jupyter-wrapper .jp-CodeConsole .CodeMirror.cm-s-jupyter,.jupyter-wrapper .jp-Notebook .CodeMirror.cm-s-jupyter{background:transparent}.jupyter-wrapper .cm-s-jupyter .CodeMirror-cursor{border-left:var(--jp-code-cursor-width0) solid var(--jp-editor-cursor-color)}.jupyter-wrapper .cm-s-jupyter span.cm-keyword{color:var(--jp-mirror-editor-keyword-color);font-weight:700}.jupyter-wrapper .cm-s-jupyter span.cm-atom{color:var(--jp-mirror-editor-atom-color)}.jupyter-wrapper .cm-s-jupyter span.cm-number{color:var(--jp-mirror-editor-number-color)}.jupyter-wrapper .cm-s-jupyter span.cm-def{color:var(--jp-mirror-editor-def-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable{color:var(--jp-mirror-editor-variable-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable-2{color:var(--jp-mirror-editor-variable-2-color)}.jupyter-wrapper .cm-s-jupyter span.cm-variable-3{color:var(--jp-mirror-editor-variable-3-color)}.jupyter-wrapper .cm-s-jupyter span.cm-punctuation{color:var(--jp-mirror-editor-punctuation-color)}.jupyter-wrapper .cm-s-jupyter span.cm-property{color:var(--jp-mirror-editor-property-color)}.jupyter-wrapper .cm-s-jupyter span.cm-operator{color:var(--jp-mirror-editor-operator-color);font-weight:700}.jupyter-wrapper .cm-s-jupyter span.cm-comment{color:var(--jp-mirror-editor-comment-color);font-style:italic}.jupyter-wrapper .cm-s-jupyter span.cm-string{color:var(--jp-mirror-editor-string-color)}.jupyter-wrapper .cm-s-jupyter span.cm-string-2{color:var(--jp-mirror-editor-string-2-color)}.jupyter-wrapper .cm-s-jupyter span.cm-meta{color:var(--jp-mirror-editor-meta-color)}.jupyter-wrapper .cm-s-jupyter span.cm-qualifier{color:var(--jp-mirror-editor-qualifier-color)}.jupyter-wrapper .cm-s-jupyter span.cm-builtin{color:var(--jp-mirror-editor-builtin-color)}.jupyter-wrapper .cm-s-jupyter span.cm-bracket{color:var(--jp-mirror-editor-bracket-color)}.jupyter-wrapper .cm-s-jupyter span.cm-tag{color:var(--jp-mirror-editor-tag-color)}.jupyter-wrapper .cm-s-jupyter span.cm-attribute{color:var(--jp-mirror-editor-attribute-color)}.jupyter-wrapper .cm-s-jupyter span.cm-header{color:var(--jp-mirror-editor-header-color)}.jupyter-wrapper .cm-s-jupyter span.cm-quote{color:var(--jp-mirror-editor-quote-color)}.jupyter-wrapper .cm-s-jupyter span.cm-link{color:var(--jp-mirror-editor-link-color)}.jupyter-wrapper .cm-s-jupyter span.cm-error{color:var(--jp-mirror-editor-error-color)}.jupyter-wrapper .cm-s-jupyter span.cm-hr{color:#999}.jupyter-wrapper .cm-s-jupyter span.cm-tab{background:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAMCAYAAAAkuj5RAAAAAXNSR0IArs4c6QAAAGFJREFUSMft1LsRQFAQheHPowAKoACx3IgEKtaEHujDjORSgWTH/ZOdnZOcM/sgk/kFFWY0qV8foQwS4MKBCS3qR6ixBJvElOobYAtivseIE120FaowJPN75GMu8j/LfMwNjh4HUpwg4LUAAAAASUVORK5CYII=);background-position:right;background-repeat:no-repeat}.jupyter-wrapper .cm-s-jupyter .CodeMirror-activeline-background,.jupyter-wrapper .cm-s-jupyter .CodeMirror-gutter{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret{position:relative;border-left:2px solid black;margin-left:-1px;margin-right:-1px;box-sizing:border-box}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret>div{white-space:nowrap;position:absolute;top:-1.15em;padding-bottom:.05em;left:-2px;font-size:.95em;background-color:#fa8100;font-family:var(--jp-ui-font-family);font-weight:700;line-height:normal;-webkit-user-select:none;user-select:none;color:#fff;padding-left:2px;padding-right:2px;z-index:3;transition:opacity .3s ease-in-out}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret.hide-name>div{transition-delay:.7s;opacity:0}.jupyter-wrapper .jp-CodeMirrorEditor .remote-caret:hover>div[style]{opacity:1;transition-delay:0s}.jupyter-wrapper :root{--jp-private-code-span-padding: calc( (var(--jp-code-line-height) - 1) * var(--jp-code-font-size) / 2 )}.jupyter-wrapper .jp-RenderedText{text-align:left;padding-left:var(--jp-code-padding);line-height:var(--jp-code-line-height);font-family:var(--jp-code-font-family)}.jupyter-wrapper .jp-RenderedText pre,.jupyter-wrapper .jp-RenderedJavaScript pre,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore pre{color:var(--jp-content-font-color1);font-size:var(--jp-code-font-size);border:none;margin:0;padding:0}.jupyter-wrapper .jp-RenderedText pre a:link{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre a:hover{text-decoration:underline;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre a:visited{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedText pre .ansi-black-fg{color:#3e424d}.jupyter-wrapper .jp-RenderedText pre .ansi-red-fg{color:#e75c58}.jupyter-wrapper .jp-RenderedText pre .ansi-green-fg{color:#00a250}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-fg{color:#ddb62b}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-fg{color:#208ffb}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-fg{color:#d160c4}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-fg{color:#60c6c8}.jupyter-wrapper .jp-RenderedText pre .ansi-white-fg{color:#c5c1b4}.jupyter-wrapper .jp-RenderedText pre .ansi-black-bg{background-color:#3e424d;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-red-bg{background-color:#e75c58;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-green-bg{background-color:#00a250;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-bg{background-color:#ddb62b;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-bg{background-color:#208ffb;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-bg{background-color:#d160c4;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-bg{background-color:#60c6c8;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-white-bg{background-color:#c5c1b4;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-black-intense-fg{color:#282c36}.jupyter-wrapper .jp-RenderedText pre .ansi-red-intense-fg{color:#b22b31}.jupyter-wrapper .jp-RenderedText pre .ansi-green-intense-fg{color:#007427}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-intense-fg{color:#b27d12}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-intense-fg{color:#0065ca}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-intense-fg{color:#a03196}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-intense-fg{color:#258f8f}.jupyter-wrapper .jp-RenderedText pre .ansi-white-intense-fg{color:#a1a6b2}.jupyter-wrapper .jp-RenderedText pre .ansi-black-intense-bg{background-color:#282c36;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-red-intense-bg{background-color:#b22b31;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-green-intense-bg{background-color:#007427;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-yellow-intense-bg{background-color:#b27d12;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-blue-intense-bg{background-color:#0065ca;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-magenta-intense-bg{background-color:#a03196;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-cyan-intense-bg{background-color:#258f8f;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-white-intense-bg{background-color:#a1a6b2;padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-default-inverse-fg{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .jp-RenderedText pre .ansi-default-inverse-bg{background-color:var(--jp-inverse-layout-color0);padding:var(--jp-private-code-span-padding) 0}.jupyter-wrapper .jp-RenderedText pre .ansi-bold{font-weight:700}.jupyter-wrapper .jp-RenderedText pre .ansi-underline{text-decoration:underline}.jupyter-wrapper .jp-RenderedText[data-mime-type=\"application/vnd.jupyter.stderr\"]{background:var(--jp-rendermime-error-background);padding-top:var(--jp-code-padding)}.jupyter-wrapper .jp-RenderedLatex{color:var(--jp-content-font-color1);font-size:var(--jp-content-font-size1);line-height:var(--jp-content-line-height)}.jupyter-wrapper .jp-OutputArea-output.jp-RenderedLatex{padding:var(--jp-code-padding);text-align:left}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore{color:var(--jp-content-font-color1);font-family:var(--jp-content-font-family);font-size:var(--jp-content-font-size1);line-height:var(--jp-content-line-height);padding-right:20px}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore em{font-style:italic}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore strong{font-weight:700}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore u{text-decoration:underline}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:link{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:hover{text-decoration:underline;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore a:visited{text-decoration:none;color:var(--jp-content-link-color)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6{line-height:var(--jp-content-heading-line-height);font-weight:var(--jp-content-heading-font-weight);font-style:normal;margin:var(--jp-content-heading-margin-top) 0 var(--jp-content-heading-margin-bottom) 0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5:first-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6:first-child{margin-top:calc(.5 * var(--jp-content-heading-margin-top))}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6:last-child{margin-bottom:calc(.5 * var(--jp-content-heading-margin-bottom))}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h1{font-size:var(--jp-content-font-size5)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h2{font-size:var(--jp-content-font-size4)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h3{font-size:var(--jp-content-font-size3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h4{font-size:var(--jp-content-font-size2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h5{font-size:var(--jp-content-font-size1)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore h6{font-size:var(--jp-content-font-size0)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul:not(.list-inline),.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol:not(.list-inline){padding-left:2em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul{list-style:disc}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul{list-style:square}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul ul{list-style:circle}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol{list-style:decimal}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol{list-style:upper-alpha}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol{list-style:lower-alpha}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol ol{list-style:lower-roman}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol ol ol ol{list-style:decimal}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ul,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ul ol,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ul,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore ol ol{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore hr{color:var(--jp-border-color2);background-color:var(--jp-border-color1);margin-top:1em;margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>pre{margin:1.5em 2em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore pre,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore code{border:0;background-color:var(--jp-layout-color0);color:var(--jp-content-font-color1);font-family:var(--jp-code-font-family);font-size:inherit;line-height:var(--jp-code-line-height);padding:0;white-space:pre-wrap}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore :not(pre)>code{background-color:var(--jp-layout-color2);padding:1px 5px}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore table{border-collapse:collapse;border-spacing:0;border:none;color:var(--jp-ui-font-color1);font-size:var(--jp-ui-font-size1);table-layout:fixed;margin-left:auto;margin-right:auto}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore thead{border-bottom:var(--jp-border-width) solid var(--jp-border-color1);vertical-align:bottom}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore th,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tr{vertical-align:middle;padding:.5em;line-height:normal;white-space:normal;max-width:none;border:none}.jupyter-wrapper .jp-RenderedMarkdown.jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper .jp-RenderedMarkdown.jp-RenderedHTMLCommon-ignore th{max-width:none}.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore td,.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore th,.jupyter-wrapper :not(.jp-RenderedMarkdown).jp-RenderedHTMLCommon-ignore tr{text-align:right}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore th{font-weight:700}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:nth-child(odd){background:var(--jp-layout-color0)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:nth-child(2n){background:var(--jp-rendermime-table-row-background)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore tbody tr:hover{background:var(--jp-rendermime-table-row-hover-background)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore table{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore p{text-align:left;margin:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore p{margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img{-moz-force-broken-image-icon:1}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>img{display:block;margin-left:0;margin-right:0;margin-bottom:1em}.jupyter-wrapper [data-jp-theme-light=false] .jp-RenderedImage img.jp-needs-light-background,.jupyter-wrapper [data-jp-theme-light=true] .jp-RenderedImage img.jp-needs-dark-background{background-color:var(--jp-inverse-layout-color1)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img,.jupyter-wrapper .jp-RenderedImage img,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore svg,.jupyter-wrapper .jp-RenderedSVG svg{max-width:100%;height:auto}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore img.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedImage img.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore svg.jp-mod-unconfined,.jupyter-wrapper .jp-RenderedSVG svg.jp-mod-unconfined{max-width:none}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert{padding:var(--jp-notebook-padding);border:var(--jp-border-width) solid transparent;border-radius:var(--jp-border-radius);margin-bottom:1em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info{color:var(--jp-info-color0);background-color:var(--jp-info-color3);border-color:var(--jp-info-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info hr{border-color:var(--jp-info-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-info>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning{color:var(--jp-warn-color0);background-color:var(--jp-warn-color3);border-color:var(--jp-warn-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning hr{border-color:var(--jp-warn-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-warning>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success{color:var(--jp-success-color0);background-color:var(--jp-success-color3);border-color:var(--jp-success-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success hr{border-color:var(--jp-success-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-success>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger{color:var(--jp-error-color0);background-color:var(--jp-error-color3);border-color:var(--jp-error-color2)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger hr{border-color:var(--jp-error-color3)}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger>p:last-child,.jupyter-wrapper .jp-RenderedHTMLCommon-ignore .alert-danger>ul:last-child{margin-bottom:0}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore blockquote{margin:1em 2em;padding:0 1em;border-left:5px solid var(--jp-border-color2)}.jupyter-wrapper a.jp-InternalAnchorLink{visibility:hidden;margin-left:8px;color:var(--md-blue-800)}.jupyter-wrapper h1:hover .jp-InternalAnchorLink,.jupyter-wrapper h2:hover .jp-InternalAnchorLink,.jupyter-wrapper h3:hover .jp-InternalAnchorLink,.jupyter-wrapper h4:hover .jp-InternalAnchorLink,.jupyter-wrapper h5:hover .jp-InternalAnchorLink,.jupyter-wrapper h6:hover .jp-InternalAnchorLink{visibility:visible}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore kbd{background-color:var(--jp-rendermime-table-row-background);border:1px solid var(--jp-border-color0);border-bottom-color:var(--jp-border-color2);border-radius:3px;box-shadow:inset 0 -1px #00000040;display:inline-block;font-size:var(--jp-ui-font-size0);line-height:1em;padding:.2em .5em}.jupyter-wrapper .jp-RenderedHTMLCommon-ignore>*:last-child{margin-bottom:.5em}.jupyter-wrapper .jp-MimeDocument{outline:none}.jupyter-wrapper :root{--jp-private-filebrowser-button-height: 28px;--jp-private-filebrowser-button-width: 48px}.jupyter-wrapper .jp-FileBrowser{display:flex;flex-direction:column;color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1)}.jupyter-wrapper .jp-FileBrowser-toolbar.jp-Toolbar{border-bottom:none;height:auto;margin:8px 12px 0;padding:0;box-shadow:none;justify-content:flex-start}.jupyter-wrapper .jp-BreadCrumbs{flex:0 0 auto;margin:8px 12px}.jupyter-wrapper .jp-BreadCrumbs-item{margin:0 2px;padding:0 2px;border-radius:var(--jp-border-radius);cursor:pointer}.jupyter-wrapper .jp-BreadCrumbs-item:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-BreadCrumbs-item:first-child{margin-left:0}.jupyter-wrapper .jp-BreadCrumbs-item.jp-mod-dropTarget{background-color:var(--jp-brand-color2);opacity:.7}.jupyter-wrapper .jp-FileBrowser-toolbar>.jp-Toolbar-item{flex:0 0 auto;padding-left:0;padding-right:2px}.jupyter-wrapper .jp-FileBrowser-toolbar>.jp-Toolbar-item .jp-ToolbarButtonComponent{width:40px}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]{width:72px;background:var(--jp-brand-color1)}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]:hover,.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"]:focus-visible{background-color:var(--jp-brand-color0)!important}.jupyter-wrapper .jp-FileBrowser-toolbar .jp-ToolbarButtonComponent[data-command=\"filebrowser:create-main-launcher\"] .jp-icon3{fill:var(--jp-layout-color1)}.jupyter-wrapper .jp-FileDialog.jp-mod-conflict input{color:var(--jp-error-color1)}.jupyter-wrapper .jp-FileDialog .jp-new-name-title{margin-top:12px}.jupyter-wrapper .jp-LastModified-hidden{display:none}.jupyter-wrapper .jp-FileBrowser-filterBox{padding:0;flex:0 0 auto;margin:8px 12px 0}.jupyter-wrapper .jp-DirListing{flex:1 1 auto;display:flex;flex-direction:column;outline:0}.jupyter-wrapper .jp-DirListing:focus-visible{outline:1px solid var(--jp-brand-color1);outline-offset:-2px}.jupyter-wrapper .jp-DirListing-header{flex:0 0 auto;display:flex;flex-direction:row;overflow:hidden;border-top:var(--jp-border-width) solid var(--jp-border-color2);border-bottom:var(--jp-border-width) solid var(--jp-border-color1);box-shadow:var(--jp-toolbar-box-shadow);z-index:2}.jupyter-wrapper .jp-DirListing-headerItem{padding:4px 12px 2px;font-weight:500}.jupyter-wrapper .jp-DirListing-headerItem:hover{background:var(--jp-layout-color2)}.jupyter-wrapper .jp-DirListing-headerItem.jp-id-name{flex:1 0 84px}.jupyter-wrapper .jp-DirListing-headerItem.jp-id-modified{flex:0 0 112px;border-left:var(--jp-border-width) solid var(--jp-border-color2);text-align:right}.jupyter-wrapper .jp-id-narrow{display:none;flex:0 0 5px;padding:4px;border-left:var(--jp-border-width) solid var(--jp-border-color2);text-align:right;color:var(--jp-border-color2)}.jupyter-wrapper .jp-DirListing-narrow .jp-id-narrow{display:block}.jupyter-wrapper .jp-DirListing-narrow .jp-id-modified,.jupyter-wrapper .jp-DirListing-narrow .jp-DirListing-itemModified{display:none}.jupyter-wrapper .jp-DirListing-headerItem.jp-mod-selected{font-weight:600}.jupyter-wrapper .jp-DirListing-content{flex:1 1 auto;margin:0;padding:0;list-style-type:none;overflow:auto;background-color:var(--jp-layout-color1)}.jupyter-wrapper .jp-DirListing-content mark{color:var(--jp-ui-font-color0);background-color:transparent;font-weight:700}.jupyter-wrapper .jp-DirListing-content .jp-DirListing-item.jp-mod-selected mark{color:var(--jp-ui-inverse-font-color0)}.jupyter-wrapper .jp-DirListing.jp-mod-native-drop .jp-DirListing-content{outline:5px dashed rgba(128,128,128,.5);outline-offset:-10px;cursor:copy}.jupyter-wrapper .jp-DirListing-item{display:flex;flex-direction:row;padding:4px 12px;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper .jp-DirListing-item[data-is-dot]{opacity:75%}.jupyter-wrapper .jp-DirListing-item.jp-mod-selected{color:var(--jp-ui-inverse-font-color1);background:var(--jp-brand-color1)}.jupyter-wrapper .jp-DirListing-item.jp-mod-dropTarget{background:var(--jp-brand-color3)}.jupyter-wrapper .jp-DirListing-item:hover:not(.jp-mod-selected){background:var(--jp-layout-color2)}.jupyter-wrapper .jp-DirListing-itemIcon{flex:0 0 20px;margin-right:4px}.jupyter-wrapper .jp-DirListing-itemText{flex:1 0 64px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;user-select:none}.jupyter-wrapper .jp-DirListing-itemModified{flex:0 0 125px;text-align:right}.jupyter-wrapper .jp-DirListing-editor{flex:1 0 64px;outline:none;border:none;color:var(--jp-ui-font-color1);background-color:var(--jp-layout-color1)}.jupyter-wrapper .jp-DirListing-item.jp-mod-running .jp-DirListing-itemIcon:before{color:var(--jp-success-color1);content:\"\u25cf\";font-size:8px;position:absolute;left:-8px}.jupyter-wrapper .jp-DirListing-item.jp-mod-running.jp-mod-selected .jp-DirListing-itemIcon:before{color:var(--jp-ui-inverse-font-color1)}.jupyter-wrapper .jp-DirListing-item.lm-mod-drag-image,.jupyter-wrapper .jp-DirListing-item.jp-mod-selected.lm-mod-drag-image{font-size:var(--jp-ui-font-size1);padding-left:4px;margin-left:4px;width:160px;background-color:var(--jp-ui-inverse-font-color2);box-shadow:var(--jp-elevation-z2);border-radius:0;color:var(--jp-ui-font-color1);transform:translate(-40%) translateY(-58%)}.jupyter-wrapper .jp-Document{min-width:120px;min-height:120px;outline:none}.jupyter-wrapper .jp-OutputArea{overflow-y:auto}.jupyter-wrapper .jp-OutputArea-child{display:flex;flex-direction:row}.jupyter-wrapper body[data-format=mobile] .jp-OutputArea-child{flex-direction:column}.jupyter-wrapper .jp-OutputPrompt{flex:0 0 var(--jp-cell-prompt-width);color:var(--jp-cell-outprompt-font-color);font-family:var(--jp-cell-prompt-font-family);padding:var(--jp-code-padding);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent;opacity:var(--jp-cell-prompt-opacity);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper body[data-format=mobile] .jp-OutputPrompt{flex:0 0 auto;text-align:left}.jupyter-wrapper .jp-OutputArea-output{height:auto;overflow:auto;user-select:text;-moz-user-select:text;-webkit-user-select:text;-ms-user-select:text}.jupyter-wrapper .jp-OutputArea-child .jp-OutputArea-output{flex-grow:1;flex-shrink:1}.jupyter-wrapper body[data-format=mobile] .jp-OutputArea-child .jp-OutputArea-output{margin-left:var(--jp-notebook-padding)}.jupyter-wrapper .jp-OutputArea-output.jp-mod-isolated{width:100%;display:block}.jupyter-wrapper body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated{position:relative}.jupyter-wrapper body.lm-mod-override-cursor .jp-OutputArea-output.jp-mod-isolated:before{content:\"\";position:absolute;top:0;left:0;right:0;bottom:0;background:transparent}.jupyter-wrapper .jp-OutputArea-output pre{border:none;margin:0;padding:0;overflow-x:auto;overflow-y:auto;word-break:break-all;word-wrap:break-word;white-space:pre-wrap}.jupyter-wrapper .jp-OutputArea-output.jp-RenderedHTMLCommon-ignore table{margin-left:0;margin-right:0}.jupyter-wrapper .jp-OutputArea-output dl,.jupyter-wrapper .jp-OutputArea-output dt,.jupyter-wrapper .jp-OutputArea-output dd{display:block}.jupyter-wrapper .jp-OutputArea-output dl{width:100%;overflow:hidden;padding:0;margin:0}.jupyter-wrapper .jp-OutputArea-output dt{font-weight:700;float:left;width:20%;padding:0;margin:0}.jupyter-wrapper .jp-OutputArea-output dd{float:left;width:80%;padding:0;margin:0}.jupyter-wrapper .jp-TrimmedOutputs a{margin:10px;text-decoration:none;cursor:pointer}.jupyter-wrapper .jp-OutputArea .jp-OutputArea .jp-OutputArea-prompt{display:none}.jupyter-wrapper .jp-OutputArea-prompt:empty{padding:0;border:0}.jupyter-wrapper .jp-OutputArea-output.jp-OutputArea-executeResult{margin-left:0;flex:1 1 auto}.jupyter-wrapper .jp-OutputArea-executeResult .jp-RenderedText.jp-OutputArea-output{padding-top:var(--jp-code-padding);border-top:var(--jp-border-width) solid transparent}.jupyter-wrapper .jp-Stdin-prompt{color:var(--jp-content-font-color0);padding-right:var(--jp-code-padding);vertical-align:baseline;flex:0 0 auto}.jupyter-wrapper .jp-Stdin-input{font-family:var(--jp-code-font-family);font-size:inherit;color:inherit;background-color:inherit;width:42%;min-width:200px;vertical-align:baseline;padding:0 .25em;margin:0 .25em;flex:0 0 70%}.jupyter-wrapper .jp-Stdin-input::placeholder{opacity:0}.jupyter-wrapper .jp-Stdin-input:focus{box-shadow:none}.jupyter-wrapper .jp-Stdin-input:focus::placeholder{opacity:1}.jupyter-wrapper .jp-LinkedOutputView .jp-OutputArea{height:100%;display:block}.jupyter-wrapper .jp-LinkedOutputView .jp-OutputArea-output:only-child{height:100%}.jupyter-wrapper .jp-Collapser{flex:0 0 var(--jp-cell-collapser-width);padding:0;margin:0;border:none;outline:none;background:transparent;border-radius:var(--jp-border-radius);opacity:1}.jupyter-wrapper .jp-Collapser-child{display:block;width:100%;box-sizing:border-box;position:absolute;top:0;bottom:0}.jupyter-wrapper .jp-CellHeader,.jupyter-wrapper .jp-CellFooter{height:0px;width:100%;padding:0;margin:0;border:none;outline:none;background:transparent}.jupyter-wrapper .jp-InputArea{display:flex;flex-direction:row;overflow:hidden}.jupyter-wrapper body[data-format=mobile] .jp-InputArea{flex-direction:column}.jupyter-wrapper .jp-InputArea-editor{flex:1 1 auto;overflow:hidden}.jupyter-wrapper .jp-InputArea-editor{border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);border-radius:0;background:var(--jp-cell-editor-background)}.jupyter-wrapper body[data-format=mobile] .jp-InputArea-editor{margin-left:var(--jp-notebook-padding)}.jupyter-wrapper .jp-InputPrompt{flex:0 0 var(--jp-cell-prompt-width);color:var(--jp-cell-inprompt-font-color);font-family:var(--jp-cell-prompt-font-family);padding:var(--jp-code-padding);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:var(--jp-code-line-height);font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent;opacity:var(--jp-cell-prompt-opacity);text-align:right;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.jupyter-wrapper body[data-format=mobile] .jp-InputPrompt{flex:0 0 auto;text-align:left}.jupyter-wrapper .jp-Placeholder{display:flex;flex-direction:row;flex:1 1 auto}.jupyter-wrapper .jp-Placeholder-prompt{box-sizing:border-box}.jupyter-wrapper .jp-Placeholder-content{flex:1 1 auto;border:none;background:transparent;height:20px;box-sizing:border-box}.jupyter-wrapper .jp-Placeholder-content .jp-MoreHorizIcon{width:32px;height:16px;border:1px solid transparent;border-radius:var(--jp-border-radius)}.jupyter-wrapper .jp-Placeholder-content .jp-MoreHorizIcon:hover{border:1px solid var(--jp-border-color1);box-shadow:0 0 2px #00000040;background-color:var(--jp-layout-color0)}.jupyter-wrapper :root{--jp-private-cell-scrolling-output-offset: 5px}.jupyter-wrapper .jp-Cell{padding:var(--jp-cell-padding);margin:0;border:none;outline:none;background:transparent}.jupyter-wrapper .jp-Cell-inputWrapper,.jupyter-wrapper .jp-Cell-outputWrapper{display:flex;flex-direction:row;padding:0;margin:0;overflow:visible}.jupyter-wrapper .jp-Cell-inputArea,.jupyter-wrapper .jp-Cell-outputArea{flex:1 1 auto}.jupyter-wrapper .jp-Cell.jp-mod-noOutputs .jp-Cell-outputCollapser{border:none!important;background:transparent!important}.jupyter-wrapper .jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputCollapser{min-height:var(--jp-cell-collapser-min-height)}.jupyter-wrapper .jp-Cell:not(.jp-mod-noOutputs) .jp-Cell-outputWrapper{margin-top:5px}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea{overflow-y:auto;max-height:24em;margin-left:var(--jp-private-cell-scrolling-output-offset)}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-Cell-outputArea:after{content:\" \";box-shadow:inset 0 0 6px 2px #0000004d;width:100%;height:100%;position:sticky;bottom:0;top:0;margin-top:-50%;float:left;display:block;pointer-events:none}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-child{padding-top:6px}.jupyter-wrapper .jp-CodeCell.jp-mod-outputsScrolled .jp-OutputArea-prompt{flex:0 0 calc(var(--jp-cell-prompt-width) - var(--jp-private-cell-scrolling-output-offset))}.jupyter-wrapper .jp-MarkdownOutput{flex:1 1 auto;margin-top:0;margin-bottom:0;padding-left:var(--jp-code-padding)}.jupyter-wrapper .jp-MarkdownOutput.jp-RenderedHTMLCommon-ignore{overflow:auto}.jupyter-wrapper .jp-collapseHeadingButton{display:none;min-height:var(--jp-cell-collapser-min-height);font-size:var(--jp-code-font-size);position:absolute;right:0;top:0;bottom:0;background-color:transparent;background-size:25px;background-repeat:no-repeat;background-position-x:center;background-position-y:top;background-image:var(--jp-icon-caret-down);border:none;cursor:pointer}.jupyter-wrapper .jp-collapseHeadingButton:hover{background-color:var(--jp-layout-color2)}.jupyter-wrapper .jp-collapseHeadingButton.jp-mod-collapsed{background-image:var(--jp-icon-caret-right)}.jupyter-wrapper :is(.jp-MarkdownCell:hover,.jp-mod-active) .jp-collapseHeadingButton{display:flex}.jupyter-wrapper .jp-MarkdownCell .jp-InputPrompt{font-size:var(--jp-content-font-size1)}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"1\"]{font-size:var(--jp-content-font-size5);background-position-y:calc(.3 * var(--jp-content-font-size5))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"2\"]{font-size:var(--jp-content-font-size4);background-position-y:calc(.3 * var(--jp-content-font-size4))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"3\"]{font-size:var(--jp-content-font-size3);background-position-y:calc(.3 * var(--jp-content-font-size3))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"4\"]{font-size:var(--jp-content-font-size2);background-position-y:calc(.3 * var(--jp-content-font-size2))}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"5\"]{font-size:var(--jp-content-font-size1);background-position-y:top}.jupyter-wrapper .jp-mod-rendered .jp-collapseHeadingButton[data-heading-level=\"6\"]{font-size:var(--jp-content-font-size0);background-position-y:top}.jupyter-wrapper .jp-showHiddenCellsButton{margin-left:calc(var(--jp-cell-prompt-width) + 2 * var(--jp-code-padding));margin-top:var(--jp-code-padding);border:1px solid var(--jp-border-color2);background-color:var(--jp-border-color3)!important;color:var(--jp-content-font-color0)!important}.jupyter-wrapper .jp-showHiddenCellsButton:hover{background-color:var(--jp-border-color2)!important}.jupyter-wrapper :root{--jp-notebook-toolbar-padding: 2px 5px 2px 2px}.jupyter-wrapper .jp-NotebookPanel-toolbar{padding:var(--jp-notebook-toolbar-padding)}.jupyter-wrapper .jp-Toolbar-item.jp-Notebook-toolbarCellType .jp-select-wrapper.jp-mod-focused{border:none;box-shadow:none}.jupyter-wrapper .jp-Notebook-toolbarCellTypeDropdown select{height:24px;font-size:var(--jp-ui-font-size1);line-height:14px;border-radius:0;display:block}.jupyter-wrapper .jp-Notebook-toolbarCellTypeDropdown span{top:5px!important}.jupyter-wrapper .jp-Toolbar-responsive-popup{position:absolute;height:fit-content;display:flex;flex-direction:row;flex-wrap:wrap;justify-content:flex-end;border-bottom:var(--jp-border-width) solid var(--jp-toolbar-border-color);box-shadow:var(--jp-toolbar-box-shadow);background:var(--jp-toolbar-background);min-height:var(--jp-toolbar-micro-height);padding:var(--jp-notebook-toolbar-padding);z-index:1;right:0;top:0}.jupyter-wrapper .jp-Toolbar>.jp-Toolbar-responsive-opener{margin-left:auto}.jupyter-wrapper .jp-Notebook-ExecutionIndicator{position:relative;display:inline-block;height:100%;z-index:9997}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip{visibility:hidden;height:auto;width:max-content;width:-moz-max-content;background-color:var(--jp-layout-color2);color:var(--jp-ui-font-color1);text-align:justify;border-radius:6px;padding:0 5px;position:fixed;display:table}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.up{transform:translate(-50%) translateY(-100%) translateY(-32px)}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.down{transform:translate(calc(-100% + 16px)) translateY(5px)}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-tooltip.hidden{display:none}.jupyter-wrapper .jp-Notebook-ExecutionIndicator:hover .jp-Notebook-ExecutionIndicator-tooltip{visibility:visible}.jupyter-wrapper .jp-Notebook-ExecutionIndicator span{font-size:var(--jp-ui-font-size1);font-family:var(--jp-ui-font-family);color:var(--jp-ui-font-color1);line-height:24px;display:block}.jupyter-wrapper .jp-Notebook-ExecutionIndicator-progress-bar{display:flex;justify-content:center;height:100%}.jupyter-wrapper :root{--jp-private-notebook-dragImage-width: 304px;--jp-private-notebook-dragImage-height: 36px;--jp-private-notebook-selected-color: var(--md-blue-400);--jp-private-notebook-active-color: var(--md-green-400)}.jupyter-wrapper .jp-NotebookPanel{display:block;height:100%}.jupyter-wrapper .jp-NotebookPanel.jp-Document{min-width:240px;min-height:120px}.jupyter-wrapper .jp-Notebook{padding:var(--jp-notebook-padding);outline:none;overflow:auto}.jupyter-wrapper .jp-Notebook.jp-mod-scrollPastEnd:after{display:block;content:\"\";min-height:var(--jp-notebook-scroll-padding)}.jupyter-wrapper .jp-MainAreaWidget-ContainStrict .jp-Notebook *{contain:strict}.jupyter-wrapper .jp-Notebook .jp-Cell{overflow:visible}.jupyter-wrapper .jp-Notebook .jp-Cell .jp-InputPrompt{cursor:move;float:left}.jupyter-wrapper .jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-InputPrompt{opacity:var(--jp-cell-prompt-not-active-opacity);color:var(--jp-cell-prompt-not-active-font-color)}.jupyter-wrapper .jp-Notebook .jp-Cell:not(.jp-mod-active) .jp-OutputPrompt{opacity:var(--jp-cell-prompt-not-active-opacity);color:var(--jp-cell-prompt-not-active-font-color)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser{background:var(--jp-brand-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt{color:var(--jp-warn-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-dirty .jp-InputPrompt:before{color:var(--jp-warn-color1);content:\"\u2022\"}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active.jp-mod-dirty .jp-Collapser{background:var(--jp-warn-color1)}.jupyter-wrapper .jp-Notebook .jp-Cell .jp-Collapser:hover{box-shadow:var(--jp-elevation-z2);background:var(--jp-brand-color1);opacity:var(--jp-cell-collapser-not-active-hover-opacity)}.jupyter-wrapper .jp-Notebook .jp-Cell.jp-mod-active .jp-Collapser:hover{background:var(--jp-brand-color0);opacity:1}.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-selected{background:var(--jp-notebook-multiselected-color)}.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Cell.jp-mod-active.jp-mod-selected:not(.jp-mod-multiSelected){background:transparent}.jupyter-wrapper .jp-Notebook.jp-mod-editMode .jp-Cell.jp-mod-active .jp-InputArea-editor{border:var(--jp-border-width) solid var(--jp-cell-editor-active-border-color);box-shadow:var(--jp-input-box-shadow);background-color:var(--jp-cell-editor-active-background)}.jupyter-wrapper .jp-Notebook-cell.jp-mod-dropSource{opacity:.5}.jupyter-wrapper .jp-Notebook-cell.jp-mod-dropTarget,.jupyter-wrapper .jp-Notebook.jp-mod-commandMode .jp-Notebook-cell.jp-mod-active.jp-mod-selected.jp-mod-dropTarget{border-top-color:var(--jp-private-notebook-selected-color);border-top-style:solid;border-top-width:2px}.jupyter-wrapper .jp-dragImage{display:block;flex-direction:row;width:var(--jp-private-notebook-dragImage-width);height:var(--jp-private-notebook-dragImage-height);border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);background:var(--jp-cell-editor-background);overflow:visible}.jupyter-wrapper .jp-dragImage-singlePrompt{box-shadow:2px 2px 4px #0000001f}.jupyter-wrapper .jp-dragImage .jp-dragImage-content{flex:1 1 auto;z-index:2;font-size:var(--jp-code-font-size);font-family:var(--jp-code-font-family);line-height:var(--jp-code-line-height);padding:var(--jp-code-padding);border:var(--jp-border-width) solid var(--jp-cell-editor-border-color);background:var(--jp-cell-editor-background-color);color:var(--jp-content-font-color3);text-align:left;margin:4px 4px 4px 0}.jupyter-wrapper .jp-dragImage .jp-dragImage-prompt{flex:0 0 auto;min-width:36px;color:var(--jp-cell-inprompt-font-color);padding:var(--jp-code-padding);padding-left:12px;font-family:var(--jp-cell-prompt-font-family);letter-spacing:var(--jp-cell-prompt-letter-spacing);line-height:1.9;font-size:var(--jp-code-font-size);border:var(--jp-border-width) solid transparent}.jupyter-wrapper .jp-dragImage-multipleBack{z-index:-1;position:absolute;height:32px;width:300px;top:8px;left:8px;background:var(--jp-layout-color2);border:var(--jp-border-width) solid var(--jp-input-border-color);box-shadow:2px 2px 4px #0000001f}.jupyter-wrapper .jp-NotebookTools{display:block;min-width:var(--jp-sidebar-min-width);color:var(--jp-ui-font-color1);background:var(--jp-layout-color1);font-size:var(--jp-ui-font-size1);overflow:auto}.jupyter-wrapper .jp-NotebookTools-tool{padding:0 12px}.jupyter-wrapper .jp-ActiveCellTool{padding:12px;background-color:var(--jp-layout-color1);border-top:none!important}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-prompt{flex:0 0 auto;padding-left:0}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-editor{flex:1 1 auto;background:var(--jp-cell-editor-background);border-color:var(--jp-cell-editor-border-color)}.jupyter-wrapper .jp-ActiveCellTool .jp-InputArea-editor .CodeMirror{background:transparent}.jupyter-wrapper .jp-MetadataEditorTool{flex-direction:column;padding:12px 0}.jupyter-wrapper .jp-RankedPanel>:not(:first-child){margin-top:12px}.jupyter-wrapper .jp-KeySelector select.jp-mod-styled{font-size:var(--jp-ui-font-size1);color:var(--jp-ui-font-color0);border:var(--jp-border-width) solid var(--jp-border-color1)}.jupyter-wrapper .jp-KeySelector label,.jupyter-wrapper .jp-MetadataEditorTool label{line-height:1.4}.jupyter-wrapper .jp-NotebookTools .jp-select-wrapper{margin-top:4px;margin-bottom:0}.jupyter-wrapper .jp-NotebookTools .jp-Collapse{margin-top:16px}.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook{--jp-content-font-size1: var(--jp-content-presentation-font-size1);--jp-code-font-size: var(--jp-code-presentation-font-size)}.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-InputPrompt,.jupyter-wrapper .jp-mod-presentationMode .jp-Notebook .jp-Cell .jp-OutputPrompt{flex:0 0 110px}.jupyter-wrapper :root{--jp-side-by-side-output-size: 1fr;--jp-side-by-side-resized-cell: var(--jp-side-by-side-output-size)}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-Notebook-cell{margin:3em 5%}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell{display:grid;grid-template-columns:minmax(0,1fr) min-content minmax(0,var(--jp-side-by-side-output-size));grid-template-rows:auto minmax(0,1fr) auto;grid-template-areas:\"header header header\" \"input handle output\" \"footer footer footer\"}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell{grid-template-columns:minmax(0,1fr) min-content minmax(0,var(--jp-side-by-side-resized-cell))}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellHeader{grid-area:header}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-inputWrapper{grid-area:input}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-Cell-outputWrapper{margin-top:0;grid-area:output}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellFooter{grid-area:footer}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle{grid-area:handle;-webkit-user-select:none;user-select:none;display:block;height:100%;cursor:ew-resize;padding:0 var(--jp-cell-padding)}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell .jp-CellResizeHandle:after{content:\"\";display:block;background:var(--jp-border-color2);height:100%;width:5px}.jupyter-wrapper .jp-mod-sideBySide.jp-Notebook .jp-CodeCell.jp-mod-resizedCell .jp-CellResizeHandle:after{background:var(--jp-border-color0)}.jupyter-wrapper .jp-CellResizeHandle{display:none}.jupyter-wrapper .jp-Cell-Placeholder{padding-left:55px}.jupyter-wrapper .jp-Cell-Placeholder-wrapper{background:#fff;border:1px solid;border-color:#e5e6e9 #dfe0e4 #d0d1d5;border-radius:4px;-webkit-border-radius:4px;margin:10px 15px}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-inner{padding:15px;position:relative}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body{background-repeat:repeat;background-size:50% auto}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body div{background:#f6f7f8;background-image:-webkit-linear-gradient(left,#f6f7f8 0%,#edeef1 20%,#f6f7f8 40%,#f6f7f8 100%);background-repeat:no-repeat;background-size:800px 104px;height:104px;position:relative}.jupyter-wrapper .jp-Cell-Placeholder-wrapper-body div{position:absolute;right:15px;left:15px;top:15px}.jupyter-wrapper div.jp-Cell-Placeholder-h1{top:20px;height:20px;left:15px;width:150px}.jupyter-wrapper div.jp-Cell-Placeholder-h2{left:15px;top:50px;height:10px;width:100px}.jupyter-wrapper div.jp-Cell-Placeholder-content-1,.jupyter-wrapper div.jp-Cell-Placeholder-content-2,.jupyter-wrapper div.jp-Cell-Placeholder-content-3{left:15px;right:15px;height:10px}.jupyter-wrapper div.jp-Cell-Placeholder-content-1{top:100px}.jupyter-wrapper div.jp-Cell-Placeholder-content-2{top:120px}.jupyter-wrapper div.jp-Cell-Placeholder-content-3{top:140px}.jupyter-wrapper table.dataframe{table-layout:auto!important}.jupyter-wrapper .md-typeset__scrollwrap{margin:0}.jupyter-wrapper .jp-MarkdownOutput{padding:0}.jupyter-wrapper h1 .anchor-link,.jupyter-wrapper h2 .anchor-link,.jupyter-wrapper h3 .anchor-link,.jupyter-wrapper h4 .anchor-link,.jupyter-wrapper h5 .anchor-link,.jupyter-wrapper h6 .anchor-link{display:none;margin-left:.5rem;color:var(--md-default-fg-color--lighter)}.jupyter-wrapper h1 .anchor-link:hover,.jupyter-wrapper h2 .anchor-link:hover,.jupyter-wrapper h3 .anchor-link:hover,.jupyter-wrapper h4 .anchor-link:hover,.jupyter-wrapper h5 .anchor-link:hover,.jupyter-wrapper h6 .anchor-link:hover{text-decoration:none;color:var(--md-accent-fg-color)}.jupyter-wrapper h1:hover .anchor-link,.jupyter-wrapper h2:hover .anchor-link,.jupyter-wrapper h3:hover .anchor-link,.jupyter-wrapper h4:hover .anchor-link,.jupyter-wrapper h5:hover .anchor-link,.jupyter-wrapper h6:hover .anchor-link{display:inline-block}.jupyter-wrapper .jp-InputArea,.jupyter-wrapper .jp-Cell-inputArea,.jupyter-wrapper .jp-RenderedHTMLCommon{width:100%}.jupyter-wrapper .jp-Cell-inputWrapper .jp-InputPrompt{display:none}.jupyter-wrapper .jp-CodeCell .jp-Cell-inputWrapper .jp-InputPrompt{display:block}.jupyter-wrapper .jp-Cell .jp-InputPrompt{cursor:normal}.jupyter-wrapper .highlight pre{background-color:#f5f5f5;padding:10px;overflow:auto}.jupyter-wrapper .celltoolbar{border:none;background:#eee;border-radius:2px 2px 0 0;width:100%;height:29px;padding-right:4px;box-orient:horizontal;box-align:stretch;display:flex;flex-direction:row;align-items:stretch;box-pack:end;justify-content:flex-start;display:-webkit-flex}.jupyter-wrapper .celltoolbar .tags_button_container{display:flex}.jupyter-wrapper .celltoolbar .tags_button_container .tag-container{display:flex;flex-direction:row;flex-grow:1;overflow:hidden;position:relative}.jupyter-wrapper .celltoolbar .tags_button_container .tag-container .cell-tag{display:inline-flex;align-items:center;background-color:#fff;white-space:nowrap;margin:3px 4px;padding:0 4px;border-radius:1px;border:1px solid #ccc;box-shadow:none;width:inherit;font-size:11px;font-family:Roboto Mono,SFMono-Regular,Consolas,Menlo,monospace;height:17px}.jupyter-wrapper .jp-InputArea-editor{width:1px}.jupyter-wrapper .jp-InputPrompt,.jupyter-wrapper .jp-OutputPrompt{overflow:unset}.jupyter-wrapper .jp-RenderedText{font-size:var(--jp-code-font-size)}.jupyter-wrapper .highlight-ipynb{overflow:auto}.jupyter-wrapper .highlight-ipynb pre{margin:0;padding:5px 10px}.jupyter-wrapper table{width:max-content}.jupyter-wrapper table.dataframe{margin-left:auto;margin-right:auto;border:none;border-collapse:collapse;border-spacing:0;color:#000;font-size:12px;table-layout:fixed}.jupyter-wrapper table.dataframe thead{border-bottom:1px solid black;vertical-align:bottom}.jupyter-wrapper table.dataframe tr,.jupyter-wrapper table.dataframe th,.jupyter-wrapper table.dataframe td{text-align:right;vertical-align:middle;padding:.5em;line-height:normal;white-space:normal;max-width:none;border:none}.jupyter-wrapper table.dataframe th{font-weight:700}.jupyter-wrapper table.dataframe tbody tr:nth-child(odd){background:#f5f5f5}.jupyter-wrapper table.dataframe tbody tr:hover{background:rgba(66,165,245,.2)}.jupyter-wrapper *+table{margin-top:1em}.jupyter-wrapper .jp-InputArea-editor{position:relative}.jupyter-wrapper .zeroclipboard-container{position:absolute;top:-3px;right:0;z-index:1}.jupyter-wrapper .zeroclipboard-container clipboard-copy{-webkit-appearance:button;-moz-appearance:button;padding:7px 5px;font:11px system-ui,sans-serif;display:inline-block;cursor:default}.jupyter-wrapper .zeroclipboard-container clipboard-copy:hover{cursor:pointer}.jupyter-wrapper .zeroclipboard-container .clipboard-copy-icon{width:15px;padding:2px 0;color:#57606a;vertical-align:text-bottom}.jupyter-wrapper .clipboard-copy-txt{display:none}[data-md-color-scheme=slate] .highlight pre{background-color:#21222c;padding:10px;overflow:auto}[data-md-color-scheme=slate] .clipboard-copy-icon{color:#555!important}[data-md-color-scheme=slate] .celltoolbar{background:#333!important}[data-md-color-scheme=slate] .celltoolbar .tags_button_container .tag-container .cell-tag{background-color:transparent!important;border:1px solid #666!important}[data-md-color-scheme=slate] table.dataframe{color:#e9ebfc}[data-md-color-scheme=slate] table.dataframe thead{border-bottom:1px solid rgba(233,235,252,.12)}[data-md-color-scheme=slate] table.dataframe tbody tr:nth-child(odd){background:#222}[data-md-color-scheme=slate] table.dataframe tbody tr:hover{background:rgba(66,165,245,.2)}table{width:max-content} .jupyter-wrapper{--jp-shadow-base-lightness: 0;--jp-shadow-umbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .2 );--jp-shadow-penumbra-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .14 );--jp-shadow-ambient-color: rgba( var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), var(--jp-shadow-base-lightness), .12 );--jp-elevation-z0: none;--jp-elevation-z1: 0px 2px 1px -1px var(--jp-shadow-umbra-color), 0px 1px 1px 0px var(--jp-shadow-penumbra-color), 0px 1px 3px 0px var(--jp-shadow-ambient-color);--jp-elevation-z2: 0px 3px 1px -2px var(--jp-shadow-umbra-color), 0px 2px 2px 0px var(--jp-shadow-penumbra-color), 0px 1px 5px 0px var(--jp-shadow-ambient-color);--jp-elevation-z4: 0px 2px 4px -1px var(--jp-shadow-umbra-color), 0px 4px 5px 0px var(--jp-shadow-penumbra-color), 0px 1px 10px 0px var(--jp-shadow-ambient-color);--jp-elevation-z6: 0px 3px 5px -1px var(--jp-shadow-umbra-color), 0px 6px 10px 0px var(--jp-shadow-penumbra-color), 0px 1px 18px 0px var(--jp-shadow-ambient-color);--jp-elevation-z8: 0px 5px 5px -3px var(--jp-shadow-umbra-color), 0px 8px 10px 1px var(--jp-shadow-penumbra-color), 0px 3px 14px 2px var(--jp-shadow-ambient-color);--jp-elevation-z12: 0px 7px 8px -4px var(--jp-shadow-umbra-color), 0px 12px 17px 2px var(--jp-shadow-penumbra-color), 0px 5px 22px 4px var(--jp-shadow-ambient-color);--jp-elevation-z16: 0px 8px 10px -5px var(--jp-shadow-umbra-color), 0px 16px 24px 2px var(--jp-shadow-penumbra-color), 0px 6px 30px 5px var(--jp-shadow-ambient-color);--jp-elevation-z20: 0px 10px 13px -6px var(--jp-shadow-umbra-color), 0px 20px 31px 3px var(--jp-shadow-penumbra-color), 0px 8px 38px 7px var(--jp-shadow-ambient-color);--jp-elevation-z24: 0px 11px 15px -7px var(--jp-shadow-umbra-color), 0px 24px 38px 3px var(--jp-shadow-penumbra-color), 0px 9px 46px 8px var(--jp-shadow-ambient-color);--jp-border-width: 1px;--jp-border-color0: var(--md-grey-400);--jp-border-color1: var(--md-grey-400);--jp-border-color2: var(--md-grey-300);--jp-border-color3: var(--md-grey-200);--jp-inverse-border-color: var(--md-grey-600);--jp-border-radius: 2px;--jp-ui-font-scale-factor: 1.2;--jp-ui-font-size0: .83333em;--jp-ui-font-size1: 13px;--jp-ui-font-size2: 1.2em;--jp-ui-font-size3: 1.44em;--jp-ui-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-ui-font-color0: rgba(0, 0, 0, 1);--jp-ui-font-color1: rgba(0, 0, 0, .87);--jp-ui-font-color2: rgba(0, 0, 0, .54);--jp-ui-font-color3: rgba(0, 0, 0, .38);--jp-ui-inverse-font-color0: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color1: rgba(255, 255, 255, 1);--jp-ui-inverse-font-color2: rgba(255, 255, 255, .7);--jp-ui-inverse-font-color3: rgba(255, 255, 255, .5);--jp-content-line-height: 1.6;--jp-content-font-scale-factor: 1.2;--jp-content-font-size0: .83333em;--jp-content-font-size1: 14px;--jp-content-font-size2: 1.2em;--jp-content-font-size3: 1.44em;--jp-content-font-size4: 1.728em;--jp-content-font-size5: 2.0736em;--jp-content-presentation-font-size1: 17px;--jp-content-heading-line-height: 1;--jp-content-heading-margin-top: 1.2em;--jp-content-heading-margin-bottom: .8em;--jp-content-heading-font-weight: 500;--jp-content-font-color0: rgba(0, 0, 0, 1);--jp-content-font-color1: rgba(0, 0, 0, .87);--jp-content-font-color2: rgba(0, 0, 0, .54);--jp-content-font-color3: rgba(0, 0, 0, .38);--jp-content-link-color: var(--md-blue-700);--jp-content-font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Helvetica, Arial, sans-serif, \"Apple Color Emoji\", \"Segoe UI Emoji\", \"Segoe UI Symbol\";--jp-code-font-size: 13px;--jp-code-line-height: 1.3077;--jp-code-padding: 5px;--jp-code-font-family-default: Menlo, Consolas, \"DejaVu Sans Mono\", monospace;--jp-code-font-family: var(--jp-code-font-family-default);--jp-code-presentation-font-size: 16px;--jp-code-cursor-width0: 1.4px;--jp-code-cursor-width1: 2px;--jp-code-cursor-width2: 4px;--jp-layout-color0: white;--jp-layout-color1: white;--jp-layout-color2: var(--md-grey-200);--jp-layout-color3: var(--md-grey-400);--jp-layout-color4: var(--md-grey-600);--jp-inverse-layout-color0: #111111;--jp-inverse-layout-color1: var(--md-grey-900);--jp-inverse-layout-color2: var(--md-grey-800);--jp-inverse-layout-color3: var(--md-grey-700);--jp-inverse-layout-color4: var(--md-grey-600);--jp-brand-color0: var(--md-blue-900);--jp-brand-color1: var(--md-blue-700);--jp-brand-color2: var(--md-blue-300);--jp-brand-color3: var(--md-blue-100);--jp-brand-color4: var(--md-blue-50);--jp-accent-color0: var(--md-green-900);--jp-accent-color1: var(--md-green-700);--jp-accent-color2: var(--md-green-300);--jp-accent-color3: var(--md-green-100);--jp-warn-color0: var(--md-orange-900);--jp-warn-color1: var(--md-orange-700);--jp-warn-color2: var(--md-orange-300);--jp-warn-color3: var(--md-orange-100);--jp-error-color0: var(--md-red-900);--jp-error-color1: var(--md-red-700);--jp-error-color2: var(--md-red-300);--jp-error-color3: var(--md-red-100);--jp-success-color0: var(--md-green-900);--jp-success-color1: var(--md-green-700);--jp-success-color2: var(--md-green-300);--jp-success-color3: var(--md-green-100);--jp-info-color0: var(--md-cyan-900);--jp-info-color1: var(--md-cyan-700);--jp-info-color2: var(--md-cyan-300);--jp-info-color3: var(--md-cyan-100);--jp-cell-padding: 5px;--jp-cell-collapser-width: 8px;--jp-cell-collapser-min-height: 20px;--jp-cell-collapser-not-active-hover-opacity: .6;--jp-cell-editor-background: var(--md-grey-100);--jp-cell-editor-border-color: var(--md-grey-300);--jp-cell-editor-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-cell-editor-active-background: var(--jp-layout-color0);--jp-cell-editor-active-border-color: var(--jp-brand-color1);--jp-cell-prompt-width: 64px;--jp-cell-prompt-font-family: var(--jp-code-font-family-default);--jp-cell-prompt-letter-spacing: 0px;--jp-cell-prompt-opacity: 1;--jp-cell-prompt-not-active-opacity: .5;--jp-cell-prompt-not-active-font-color: var(--md-grey-700);--jp-cell-inprompt-font-color: #307fc1;--jp-cell-outprompt-font-color: #bf5b3d;--jp-notebook-padding: 10px;--jp-notebook-select-background: var(--jp-layout-color1);--jp-notebook-multiselected-color: var(--md-blue-50);--jp-notebook-scroll-padding: calc( 100% - var(--jp-code-font-size) * var(--jp-code-line-height) - var(--jp-code-padding) - var(--jp-cell-padding) - 1px );--jp-rendermime-error-background: #fdd;--jp-rendermime-table-row-background: var(--md-grey-100);--jp-rendermime-table-row-hover-background: var(--md-light-blue-50);--jp-dialog-background: rgba(0, 0, 0, .25);--jp-console-padding: 10px;--jp-toolbar-border-color: var(--jp-border-color1);--jp-toolbar-micro-height: 8px;--jp-toolbar-background: var(--jp-layout-color1);--jp-toolbar-box-shadow: 0px 0px 2px 0px rgba(0, 0, 0, .24);--jp-toolbar-header-margin: 4px 4px 0px 4px;--jp-toolbar-active-background: var(--md-grey-300);--jp-statusbar-height: 24px;--jp-input-box-shadow: inset 0 0 2px var(--md-blue-300);--jp-input-active-background: var(--jp-layout-color1);--jp-input-hover-background: var(--jp-layout-color1);--jp-input-background: var(--md-grey-100);--jp-input-border-color: var(--jp-inverse-border-color);--jp-input-active-border-color: var(--jp-brand-color1);--jp-input-active-box-shadow-color: rgba(19, 124, 189, .3);--jp-editor-selected-background: #d9d9d9;--jp-editor-selected-focused-background: #d7d4f0;--jp-editor-cursor-color: var(--jp-ui-font-color0);--jp-mirror-editor-keyword-color: #008000;--jp-mirror-editor-atom-color: #88f;--jp-mirror-editor-number-color: #080;--jp-mirror-editor-def-color: #00f;--jp-mirror-editor-variable-color: var(--md-grey-900);--jp-mirror-editor-variable-2-color: #05a;--jp-mirror-editor-variable-3-color: #085;--jp-mirror-editor-punctuation-color: #05a;--jp-mirror-editor-property-color: #05a;--jp-mirror-editor-operator-color: #aa22ff;--jp-mirror-editor-comment-color: #408080;--jp-mirror-editor-string-color: #ba2121;--jp-mirror-editor-string-2-color: #708;--jp-mirror-editor-meta-color: #aa22ff;--jp-mirror-editor-qualifier-color: #555;--jp-mirror-editor-builtin-color: #008000;--jp-mirror-editor-bracket-color: #997;--jp-mirror-editor-tag-color: #170;--jp-mirror-editor-attribute-color: #00c;--jp-mirror-editor-header-color: blue;--jp-mirror-editor-quote-color: #090;--jp-mirror-editor-link-color: #00c;--jp-mirror-editor-error-color: #f00;--jp-mirror-editor-hr-color: #999;--jp-collaborator-color1: #ffad8e;--jp-collaborator-color2: #dac83d;--jp-collaborator-color3: #72dd76;--jp-collaborator-color4: #00e4d0;--jp-collaborator-color5: #45d4ff;--jp-collaborator-color6: #e2b1ff;--jp-collaborator-color7: #ff9de6;--jp-vega-background: white;--jp-sidebar-min-width: 250px;--jp-search-toggle-off-opacity: .5;--jp-search-toggle-hover-opacity: .8;--jp-search-toggle-on-opacity: 1;--jp-search-selected-match-background-color: rgb(245, 200, 0);--jp-search-selected-match-color: black;--jp-search-unselected-match-background-color: var( --jp-inverse-layout-color0 );--jp-search-unselected-match-color: var(--jp-ui-inverse-font-color0);--jp-icon-contrast-color0: var(--md-purple-600);--jp-icon-contrast-color1: var(--md-green-600);--jp-icon-contrast-color2: var(--md-pink-600);--jp-icon-contrast-color3: var(--md-blue-600);--jp-jupyter-icon-color: #f37626;--jp-notebook-icon-color: #f37626;--jp-json-icon-color: var(--md-orange-700);--jp-console-icon-background-color: var(--md-blue-700);--jp-console-icon-color: white;--jp-terminal-icon-background-color: var(--md-grey-800);--jp-terminal-icon-color: var(--md-grey-200);--jp-text-editor-icon-color: var(--md-grey-700);--jp-inspector-icon-color: var(--md-grey-700);--jp-switch-color: var(--md-grey-400);--jp-switch-true-position-color: var(--md-orange-900)} init_mathjax = function() { if (window.MathJax) { // MathJax loaded MathJax.Hub.Config({ TeX: { equationNumbers: { autoNumber: \"AMS\", useLabelIds: true } }, tex2jax: { inlineMath: [ ['$','$'], [\"\\\\(\",\"\\\\)\"] ], displayMath: [ ['$$','$$'], [\"\\\\[\",\"\\\\]\"] ], processEscapes: true, processEnvironments: true }, displayAlign: 'center', CommonHTML: { linebreaks: { automatic: true } } }); MathJax.Hub.Queue([\"Typeset\", MathJax.Hub]); } } init_mathjax(); document.addEventListener(\"DOMContentLoaded\", async () => { const diagrams = document.querySelectorAll(\".jp-Mermaid > pre.mermaid\"); // do not load mermaidjs if not needed if (!diagrams.length) { return; } const mermaid = (await import(\"https://cdnjs.cloudflare.com/ajax/libs/mermaid/10.7.0/mermaid.esm.min.mjs\")).default; const parser = new DOMParser(); mermaid.initialize({ maxTextSize: 100000, maxEdges: 100000, startOnLoad: false, fontFamily: window .getComputedStyle(document.body) .getPropertyValue(\"--jp-ui-font-family\"), theme: document.querySelector(\"body[data-jp-theme-light='true']\") ? \"default\" : \"dark\", }); let _nextMermaidId = 0; function makeMermaidImage(svg) { const img = document.createElement(\"img\"); const doc = parser.parseFromString(svg, \"image/svg+xml\"); const svgEl = doc.querySelector(\"svg\"); const { maxWidth } = svgEl?.style || {}; const firstTitle = doc.querySelector(\"title\"); const firstDesc = doc.querySelector(\"desc\"); img.setAttribute(\"src\", `data:image/svg+xml,${encodeURIComponent(svg)}`); if (maxWidth) { img.width = parseInt(maxWidth); } if (firstTitle) { img.setAttribute(\"alt\", firstTitle.textContent); } if (firstDesc) { const caption = document.createElement(\"figcaption\"); caption.className = \"sr-only\"; caption.textContent = firstDesc.textContent; return [img, caption]; } return [img]; } async function makeMermaidError(text) { let errorMessage = \"\"; try { await mermaid.parse(text); } catch (err) { errorMessage = `${err}`; } const result = document.createElement(\"details\"); result.className = 'jp-RenderedMermaid-Details'; const summary = document.createElement(\"summary\"); summary.className = 'jp-RenderedMermaid-Summary'; const pre = document.createElement(\"pre\"); const code = document.createElement(\"code\"); code.innerText = text; pre.appendChild(code); summary.appendChild(pre); result.appendChild(summary); const warning = document.createElement(\"pre\"); warning.innerText = errorMessage; result.appendChild(warning); return [result]; } async function renderOneMarmaid(src) { const id = `jp-mermaid-${_nextMermaidId++}`; const parent = src.parentNode; let raw = src.textContent.trim(); const el = document.createElement(\"div\"); el.style.visibility = \"hidden\"; document.body.appendChild(el); let results = null; let output = null; try { let { svg } = await mermaid.render(id, raw, el); svg = cleanMermaidSvg(svg); results = makeMermaidImage(svg); output = document.createElement(\"figure\"); results.map(output.appendChild, output); } catch (err) { parent.classList.add(\"jp-mod-warning\"); results = await makeMermaidError(raw); output = results[0]; } finally { el.remove(); } parent.classList.add(\"jp-RenderedMermaid\"); parent.appendChild(output); } /** * Post-process to ensure mermaid diagrams contain only valid SVG and XHTML. */ function cleanMermaidSvg(svg) { return svg.replace(RE_VOID_ELEMENT, replaceVoidElement); } /** * A regular expression for all void elements, which may include attributes and * a slash. * * @see https://developer.mozilla.org/en-US/docs/Glossary/Void_element * * Of these, only `
    ` is generated by Mermaid in place of `\\n`, * but _any_ \"malformed\" tag will break the SVG rendering entirely. */ const RE_VOID_ELEMENT = /<\\s*(area|base|br|col|embed|hr|img|input|link|meta|param|source|track|wbr)\\s*([^>]*?)\\s*>/gi; /** * Ensure a void element is closed with a slash, preserving any attributes. */ function replaceVoidElement(match, tag, rest) { rest = rest.trim(); if (!rest.endsWith('/')) { rest = `${rest} /`; } return `<${tag} ${rest}>`; } void Promise.all([...diagrams].map(renderOneMarmaid)); }); .jp-Mermaid:not(.jp-RenderedMermaid) { display: none; } .jp-RenderedMermaid { overflow: auto; display: flex; } .jp-RenderedMermaid.jp-mod-warning { width: auto; padding: 0.5em; margin-top: 0.5em; border: var(--jp-border-width) solid var(--jp-warn-color2); border-radius: var(--jp-border-radius); color: var(--jp-ui-font-color1); font-size: var(--jp-ui-font-size1); white-space: pre-wrap; word-wrap: break-word; } .jp-RenderedMermaid figure { margin: 0; overflow: auto; max-width: 100%; } .jp-RenderedMermaid img { max-width: 100%; } .jp-RenderedMermaid-Details > pre { margin-top: 1em; } .jp-RenderedMermaid-Summary { color: var(--jp-warn-color2); } .jp-RenderedMermaid:not(.jp-mod-warning) pre { display: none; } .jp-RenderedMermaid-Summary > pre { display: inline-block; white-space: normal; } scPRINT use case on BPH (part 2, GN analysis) \u00b6 In this use-case, which some of the results are presented in Figure 5 of our manuscript , we perform an extensive analysis of gene networks generated by scPRINT in our previous notebook for fibroblasts of the prostate in both normal and benign prostatic hyperplasia states. We can look at many patterns from the gene networks such as hub genes, gene modules, and gene-gene interactions. Some of them are related to highly variable and differentially expressed genes while others can only be infered by using the gene networks. Table of content: Hub genes Network similarity Network communities Cancer version Normal version Differential Gene - Gene connections Using classification In [1]: Copied! from bengrn import BenGRN import scanpy as sc from bengrn.base import train_classifier from anndata.utils import make_index_unique from grnndata import utils as grnutils from grnndata import read_h5ad from matplotlib import pyplot as plt from scdataloader import utils as data_utils import numpy as np from pyvis import network as pnx import networkx as nx import scipy.sparse import pandas as pd import gseapy as gp from gseapy import dotplot % load_ext autoreload % autoreload 2 from bengrn import BenGRN import scanpy as sc from bengrn.base import train_classifier from anndata.utils import make_index_unique from grnndata import utils as grnutils from grnndata import read_h5ad from matplotlib import pyplot as plt from scdataloader import utils as data_utils import numpy as np from pyvis import network as pnx import networkx as nx import scipy.sparse import pandas as pd import gseapy as gp from gseapy import dotplot %load_ext autoreload %autoreload 2 \ud83d\udca1 connected lamindb: jkobject/scprint In [ ]: Copied! prostate_combined = sc . read_h5ad ( \"../data/prostate_combined_o2uniqsx.h5ad\" ) prostate_combined = sc.read_h5ad(\"../data/prostate_combined_o2uniqsx.h5ad\") In [2]: Copied! # load the generated gene networks from the previous notebook grn = read_h5ad ( \"../../data/prostate_fibro_grn.h5ad\" ) grn_c = read_h5ad ( \"../../data/prostate_cancer_fibro_grn.h5ad\" ) #remove duplicates grn . var . symbol = make_index_unique ( grn . var . symbol . astype ( str )) grn_c . var . symbol = make_index_unique ( grn_c . var . symbol . astype ( str )) # convert gene ids to symbols grn . var [ 'ensembl_id' ] = grn . var . index grn . var . index = grn . var . symbol grn_c . var [ 'ensembl_id' ] = grn_c . var . index grn_c . var . index = grn_c . var . symbol grn . obs . cleaned_pred_disease_ontology_term_id . value_counts (), grn_c . obs . cleaned_pred_disease_ontology_term_id . value_counts () # load the generated gene networks from the previous notebook grn = read_h5ad(\"../../data/prostate_fibro_grn.h5ad\") grn_c = read_h5ad(\"../../data/prostate_cancer_fibro_grn.h5ad\") #remove duplicates grn.var.symbol = make_index_unique(grn.var.symbol.astype(str)) grn_c.var.symbol = make_index_unique(grn_c.var.symbol.astype(str)) # convert gene ids to symbols grn.var['ensembl_id'] = grn.var.index grn.var.index = grn.var.symbol grn_c.var['ensembl_id'] = grn_c.var.index grn_c.var.index = grn_c.var.symbol grn.obs.cleaned_pred_disease_ontology_term_id.value_counts(),grn_c.obs.cleaned_pred_disease_ontology_term_id.value_counts() Out[2]: (cleaned_pred_disease_ontology_term_id normal 300 Name: count, dtype: int64, cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 300 Name: count, dtype: int64) 1. Hub genes \u00b6 We will use 2 different definition of centrality to compare the hubs of the networks in both states. The first one is the degree centrality, which is the number of connections of a node. The second one is the eigenvector centrality, which is the sum of the centrality of the neighbors of a node. For each gene we mostly interogate their meaning with genecards, e.g. https://www.genecards.org/cgi-bin/carddisp.pl?gene=CD99 In [7]: Copied! # between the two networks we have ~3000 genes in common over their 4000 genes common = set ( grn_c . var . symbol ) & set ( grn . var . symbol ) len ( common ) # between the two networks we have ~3000 genes in common over their 4000 genes common = set(grn_c.var.symbol) & set(grn.var.symbol) len(common) Out[7]: 2881 In [8]: Copied! # hub genes based on edge centrality (number of connections / strength of connections) grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 20 ) # hub genes based on edge centrality (number of connections / strength of connections) grn.grn.sum(0).sort_values(ascending=False).head(20) Out[8]: symbol S100A6 58.131020 TGIF2-RAB5IF 51.177635 MIF 44.534096 DNAJB9 40.953262 IGFBP7 38.629910 APOD 38.003906 BRME1 37.598698 SPARCL1 37.160854 TIMP1 36.671650 DCN 34.621376 C1S 32.746254 MGP 30.496748 nan-270 29.884596 SLC25A6 29.308729 BLOC1S5-TXNDC5 28.986681 CETN1 28.746281 FTL 28.266533 AKR1C1 27.641245 FBLN1 26.828733 MT2A 25.590197 dtype: float32 In [7]: Copied! # without taking in account genes that are not present in the cancer network grn . grn . sum ( 0 ) . loc [ list ( common )] . sort_values ( ascending = False ) . head ( 20 ) # without taking in account genes that are not present in the cancer network grn.grn.sum(0).loc[list(common)].sort_values(ascending=False).head(20) Out[7]: symbol TGIF2-RAB5IF 51.177635 IGFBP7 38.629910 APOD 38.003906 BRME1 37.598698 SPARCL1 37.160854 TIMP1 36.671650 DCN 34.621376 C1S 32.746254 MGP 30.496748 BLOC1S5-TXNDC5 28.986681 AKR1C1 27.641245 FBLN1 26.828733 MT2A 25.590197 MYOC 25.428144 FAM205A 25.296257 YBX3 24.937267 CST3 24.676405 C11orf96 18.731924 TFPI 18.429214 ATP6V0C 17.695705 dtype: float32 In [11]: Copied! # cancer hub genes grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 20 ) # cancer hub genes grn_c.grn.sum(0).sort_values(ascending=False).head(20) Out[11]: symbol HSPA1A 75.300415 MT2A 57.938267 CREM 42.478115 TGIF2-RAB5IF 39.980556 HSPE1 38.607624 CALD1 36.512047 SPOCK3 35.564945 HLA-A 33.446110 SPARCL1 33.403152 RBP1 32.482758 C1S 32.037743 BRME1-1 31.879770 FABP4 31.604069 nan-99 31.555256 LUM 30.523245 EIF4A1 29.690474 ATP6V0C 29.475002 PDZD2 27.333025 DEFA1 26.979454 CTSG 25.070097 dtype: float32 In [10]: Copied! # without taking in account genes not present in the normal network grn_c . grn . sum ( 0 ) . loc [ list ( common )] . sort_values ( ascending = False ) . head ( 20 ) # without taking in account genes not present in the normal network grn_c.grn.sum(0).loc[list(common)].sort_values(ascending=False).head(20) Out[10]: symbol HSPA1A 75.300415 MT2A 57.938267 TGIF2-RAB5IF 39.980556 SPOCK3 35.564945 HLA-A 33.446110 SPARCL1 33.403152 C1S 32.037743 nan-99 31.555256 LUM 30.523245 EIF4A1 29.690474 ATP6V0C 29.475002 DEFA1 26.979454 IGFBP7 23.982243 DCN 23.304916 MGP 22.596451 CD99 21.624668 BLOC1S5-TXNDC5 20.914230 SERPING1 20.824636 COL6A2 18.076559 THBS1 17.826540 dtype: float32 In [12]: Copied! # top differential hubs TOP = 10 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) # top differential hubs TOP = 10 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[12]: {'HLA-A', 'HSPA1A', 'MT2A', 'SPOCK3'} In [13]: Copied! TOP = 20 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 20 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[13]: {'ATP6V0C', 'DEFA1', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LUM', 'SPOCK3', 'nan-99'} In [14]: Copied! TOP = 50 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 50 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[14]: {'CD99', 'CPE', 'DEFA1', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LGALS1', 'LUM', 'PYDC2', 'SERPING1', 'SPOCK3', 'THBS1', 'nan-191', 'nan-99'} overall we see that both are somewhat similar in the way the networks classifies main nodes but at least around half of the top 200 nodes are different between the two datasets and half of those are not due to diffent gene being used by the networks (50) genes preferentially given as top elements in the tumor version only: CD99 CPE DEFA1 EIF4A1 HLA-A HSPA1A LGALS1 LUM PYDC2 SERPING1 SPOCK3 THBS1 In [3]: Copied! # we now compute eigen centrality creating a sparse network by only keeping the top 20 neighbors for each gene in the network TOP = 20 grnutils . get_centrality ( grn , TOP , top_k_to_disp = 0 ) grnutils . get_centrality ( grn_c , TOP , top_k_to_disp = 0 ) # we now compute eigen centrality creating a sparse network by only keeping the top 20 neighbors for each gene in the network TOP = 20 grnutils.get_centrality(grn, TOP, top_k_to_disp=0) grnutils.get_centrality(grn_c, TOP, top_k_to_disp=0) Top central genes: [] Top central genes: [] Out[3]: [] In [12]: Copied! grn_c . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn_c.var.centrality.sort_values(ascending=False).head(10) Out[12]: symbol HSPA1A 0.271584 MT2A 0.271584 CREM 0.271574 CD99 0.271517 NR4A3 0.271385 RBP1 0.271130 SOX4 0.264214 ATP6V0C 0.263235 HLA-A 0.232913 LUM 0.202007 Name: centrality, dtype: float64 In [9]: Copied! grn_c . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn_c.var.centrality.sort_values(ascending=False).head(10) Out[9]: symbol HSPA1A 0.271584 MT2A 0.271584 CREM 0.271574 CD99 0.271517 NR4A3 0.271385 RBP1 0.271130 SOX4 0.264214 ATP6V0C 0.263235 HLA-A 0.232913 LUM 0.202007 Name: centrality, dtype: float64 In [10]: Copied! grn . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn.var.centrality.sort_values(ascending=False).head(10) Out[10]: symbol MT2A 0.276470 SLC25A6 0.276183 CXCL8 0.275859 FTH1 0.275757 MIF 0.267968 DNAJB9 0.265635 SOX4 0.241950 RELB 0.234482 YBX3 0.216567 CST3 0.213585 Name: centrality, dtype: float64 In [13]: Copied! TOP = 10 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 10 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[13]: {'ATP6V0C', 'CD99', 'HLA-A', 'HSPA1A', 'LUM'} In [12]: Copied! TOP = 20 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 20 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[12]: {'ATP6V0C', 'CD99', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LUM', 'PAGE4', 'RYR2', 'SERPINF1'} In [11]: Copied! TOP = 50 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 50 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[11]: {'C1R', 'CD99', 'COL6A2', 'HLA-A', 'HNRNPA0', 'HSPA1A', 'LUM', 'PAGE4', 'SERPINA3', 'SERPING1', 'SPOCK3', 'THBS1'} it seems the networks are even more similar when comparing them at the level of the centrality of their nodes. this means that some are highly central while maybe not 2. Network similarity \u00b6 We now look at the similarity of the two networks based on general overlap of their top K edges across their common nodes In [41]: Copied! grn . var . index = grn . var . ensembl_id grn_c . var . index = grn_c . var . ensembl_id overlap = list ( set ( grn . var . index ) & set ( grn_c . var . index )) grn.var.index = grn.var.ensembl_id grn_c.var.index = grn_c.var.ensembl_id overlap = list(set(grn.var.index) & set(grn_c.var.index)) In [43]: Copied! K = 20 subgrn_c = grn_c . get ( overlap ) . grn subgrn_c = subgrn_c . apply ( lambda row : row >= row . nlargest ( K ) . min (), axis = 1 ) subgrn = grn . get ( overlap ) . grn subgrn = subgrn . apply ( lambda row : row >= row . nlargest ( K ) . min (), axis = 1 ) ( subgrn & subgrn_c ) . sum ( 1 ) . mean () / K K = 20 subgrn_c = grn_c.get(overlap).grn subgrn_c = subgrn_c.apply(lambda row: row >= row.nlargest(K).min(), axis=1) subgrn = grn.get(overlap).grn subgrn = subgrn.apply(lambda row: row >= row.nlargest(K).min(), axis=1) (subgrn & subgrn_c).sum(1).mean() / K Out[43]: 0.5055735930735931 when looking at the top 20 connection for each genes in the network we see that on average only 50% of them agree between the two networks 3. Network communities \u00b6 Again looking at the top 20 connections for each gene in the network we use the leiden (or louvain) algorithm to find communities in both networks. We then study the hub of these communities as well as their enrichment using enrichr and ontology databases. We will only look at communities between 20 and 200 genes In [33]: Copied! TOP = 20 grnutils . get_centrality ( grn , TOP , top_k_to_disp = 0 ) grnutils . get_centrality ( grn_c , TOP , top_k_to_disp = 0 ) TOP = 20 grnutils.get_centrality(grn, TOP, top_k_to_disp=0) grnutils.get_centrality(grn_c, TOP, top_k_to_disp=0) Top central genes: [] Top central genes: [] Out[33]: [] In [17]: Copied! grn_c = grnutils . compute_cluster ( grn_c , 1.5 , use = \"leiden\" , n_iterations = 10 , max_comm_size = 100 ) grn_c = grnutils.compute_cluster(grn_c, 1.5, use=\"leiden\", n_iterations=10, max_comm_size=100) In [4]: Copied! grn = grnutils . compute_cluster ( grn , 1.5 ) grn_c = grnutils . compute_cluster ( grn_c , 1.5 ) grn = grnutils.compute_cluster(grn, 1.5) grn_c = grnutils.compute_cluster(grn_c, 1.5) 3.1 Cancer version \u00b6 In [30]: Copied! # our communities grn . var [ 'cluster_1.5' ] . value_counts () . head ( 10 ) # our communities grn.var['cluster_1.5'].value_counts().head(10) Out[30]: cluster_1.5 0 1620 1 1483 2 732 3 111 4 23 5 9 6 4 16 1 23 1 22 1 Name: count, dtype: int64 In [31]: Copied! G = grn_c . plot_subgraph ( grn_c . var [ grn_c . var [ 'cluster_1.5' ] == '4' ] . index . tolist (), only = 200 , interactive = False ) # G = grn_c.plot_subgraph(grn_c.var[grn_c.var['cluster_1.5']=='4'].index.tolist(), only=200, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['PRDM6', 'MSANTD3', 'STAG3', 'TRHDE', 'TBX5', 'HEPH', 'GALNT16', 'NFATC4', 'SYNDIG1', 'HSF4', 'ZNF423', 'PLA2G4C', 'PLPPR2', 'SCN1B', 'ASPA', 'SNX15', 'BAG2', 'PTK7', 'HRH2', 'PLCL1', 'PTCH2', 'TGFB3', 'RASL11A', 'TOX2', 'CPNE5', 'GLIS2', 'HIVEP3', 'FGF13', 'ACAP3', 'DUSP26', 'CTIF', 'CAMK1', 'SLC9A5', 'FBN2', 'LRIG1', 'LIMD1', 'TRPC1', 'SLC2A13', 'ADAMTS12', 'FZD7', 'AFF2', 'CACNA1D', 'MRAS', 'ST6GALNAC6', 'FGFR4', 'PTGER1', 'PKDCC', 'SLC9B2', 'NPY1R', 'ANKRD33B', 'DCLK2', 'PURG', 'GXYLT2', 'LRRN4CL', 'CA8', 'EXOC3L1', 'BHLHE22', 'AATK', 'CMC4', 'BOLA2', 'CCR10', 'TCEAL2', 'SLC24A3', 'ROR1', 'SLC51B', 'EMID1', 'AGMO', 'CENPP', 'OPTC', 'SPOCK3', 'COL27A1', 'DACT3', 'STMN3', 'DLL1', 'SMOC1', 'COLGALT2', 'ZDBF2', 'DOK6', 'HNRNPUL2-BSCL2', 'C3orf84', 'C2orf74', 'ARHGEF25', 'NPIPB5', 'TNFSF12-TNFSF13', 'ZFP91-CNTF', 'nan-41', 'nan-81', 'nan-96', 'nan-98', 'HERC3', 'nan-116', 'nan-117'], dtype='object', name='symbol_2') In [26]: Copied! # if you want to draw better looking networks pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_4.html\" ) # if you want to draw better looking networks pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_4.html\") In [32]: Copied! # Assuming 'node_names' contains the list of gene names. # Note: it seems with enrichr, one can only use one gene set at a time, choose accordingly enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn_c . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names. # Note: it seems with enrichr, one can only use one gene set at a time, choose accordingly enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn_c.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:31:53,534 [WARNING] Input library not found: Reactome. Skip Out[32]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Solute:Potassium Antiporter Activity (GO:0022821) 0.000523 0.050652 0 0 inf inf SLC24A3;SLC9A5 1 GO_Molecular_Function_2023 Coreceptor Activity Involved In Wnt Signaling ... 0.001547 0.050652 0 0 86.822222 561.890021 PTK7;ROR1 2 GO_Molecular_Function_2023 Sodium Ion Transmembrane Transporter Activity ... 0.001547 0.050652 0 0 86.822222 561.890021 SLC9A5;SLC9B2 3 GO_Molecular_Function_2023 Calcium Ion Transmembrane Transporter Activity... 0.001700 0.050652 0 0 16.432584 104.795452 SLC24A3;TRPC1;CACNA1D 4 GO_Molecular_Function_2023 Calcium-Dependent Phospholipid Binding (GO:000... 0.003047 0.050652 0 0 43.400000 251.445478 CPNE5;PLA2G4C 5 GO_Molecular_Function_2023 Coreceptor Activity Involved In Wnt Signaling ... 0.003047 0.050652 0 0 43.400000 251.445478 PTK7;ROR1 6 GO_Molecular_Function_2023 Metal Cation:Proton Antiporter Activity (GO:00... 0.003047 0.050652 0 0 43.400000 251.445478 SLC9A5;SLC9B2 7 GO_Molecular_Function_2023 Sodium:Proton Antiporter Activity (GO:0015385) 0.003047 0.050652 0 0 43.400000 251.445478 SLC9A5;SLC9B2 8 GO_Molecular_Function_2023 Iron Ion Binding (GO:0005506) 0.005002 0.070586 0 0 28.925926 153.247105 HEPH;AGMO 9 GO_Molecular_Function_2023 Calcium Channel Activity (GO:0005262) 0.005307 0.070586 0 0 10.099395 52.907606 SLC24A3;TRPC1;CACNA1D 10 GO_Molecular_Function_2023 Wnt Receptor Activity (GO:0042813) 0.007391 0.089364 0 0 21.688889 106.438022 FZD7;ROR1 11 GO_Molecular_Function_2023 RNA Polymerase II-specific DNA-binding Transcr... 0.010110 0.104284 0 0 7.715135 35.445265 TBX5;DUSP26;DLL1 12 GO_Molecular_Function_2023 Phospholipase Activity (GO:0004620) 0.010193 0.104284 0 0 17.346667 79.552387 PLCL1;PLA2G4C 13 GO_Molecular_Function_2023 Monoatomic Cation Channel Activity (GO:0005261) 0.011601 0.110210 0 0 7.284644 32.465172 SLC24A3;TRPC1;CACNA1D 14 GO_Molecular_Function_2023 Sodium Channel Regulator Activity (GO:0017080) 0.013389 0.118714 0 0 14.451852 62.335739 FGF13;SCN1B 15 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.022992 0.139045 0 0 2.668376 10.066740 HSF4;HIVEP3;BHLHE22;TBX5;ZNF423;NFATC4;GLIS2 16 GO_Molecular_Function_2023 Calcium:Sodium Antiporter Activity (GO:0005432) 0.023000 0.139045 0 0 inf inf SLC24A3 17 GO_Molecular_Function_2023 Potassium:Proton Antiporter Activity (GO:0015386) 0.023000 0.139045 0 0 inf inf SLC9A5 18 GO_Molecular_Function_2023 Xylosyltransferase Activity (GO:0042285) 0.023000 0.139045 0 0 inf inf GXYLT2 19 GO_Molecular_Function_2023 Tat Protein Binding (GO:0030957) 0.023000 0.139045 0 0 inf inf DLL1 In [33]: Copied! # we make a plot of the enrichment enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) # we make a plot of the enrichment enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [34]: Copied! G = grn_c . plot_subgraph ( grn_c . var [ grn_c . var [ 'cluster_1.5' ] == '5' ] . index . tolist (), only = 80 , interactive = False ) # G = grn_c.plot_subgraph(grn_c.var[grn_c.var['cluster_1.5']=='5'].index.tolist(), only=80, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['ABCF2', 'ITIH4', 'OLFM2', 'ICAM4', 'RIGI', 'KAZALD1', 'BST1', 'PANX1', 'C9', 'FBXO2', 'ZNF410', 'ACVR1C', 'VAMP7', 'TOP2A', 'TAF4B', 'KIAA1755', 'EDA', 'YPEL4', 'ENTPD3', 'GP9', 'NLGN2', 'CLCF1', 'RPRM', 'ODF3B', 'MSC', 'NTF3', 'COL13A1', 'GP1BB', 'HSPA1A', 'TMEM158', 'nan-82', 'NBPF19', 'SCO2', 'SMIM41'], dtype='object', name='symbol_2') In [87]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_5.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_5.html\") In [44]: Copied! grn_c . var . loc [ 'nan-82' ] # par of the Glycoside Hydrolase Family grn_c.var.loc['nan-82'] # par of the Glycoside Hydrolase Family Out[44]: uid 4giyQrh7tkXI symbol nan-82 ncbi_gene_ids biotype protein_coding description novel protein synonyms organism_id 2 public_source_id 9.0 created_by_id 1 mt False ribo False hb False organism NCBITaxon:9606 TFs False ensembl_id ENSG00000269590 centrality 0.0 cluster_1.5 5 Name: nan-82, dtype: object In [35]: Copied! enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn_c . var . symbol . tolist (), ) enr . res2d . head ( 20 ) enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn_c.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:33:16,565 [WARNING] Input library not found: Reactome. Skip Out[35]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Death Receptor Binding (GO:0005123) 0.000416 0.028729 0 0 123.875000 964.236668 EDA;NTF3 1 GO_Molecular_Function_2023 Purine Ribonucleoside Triphosphate Binding (GO... 0.007050 0.073312 0 0 8.626100 42.739637 ABCF2;RIGI;HSPA1A 2 GO_Molecular_Function_2023 Receptor Ligand Activity (GO:0048018) 0.007732 0.073312 0 0 5.742222 27.920829 EDA;CLCF1;NTF3;HSPA1A 3 GO_Molecular_Function_2023 Activin Receptor Activity (GO:0017002) 0.008500 0.073312 0 0 inf inf ACVR1C 4 GO_Molecular_Function_2023 Gap Junction Hemi-Channel Activity (GO:0055077) 0.008500 0.073312 0 0 inf inf PANX1 5 GO_Molecular_Function_2023 NF-kappaB Binding (GO:0051059) 0.008500 0.073312 0 0 inf inf TAF4B 6 GO_Molecular_Function_2023 Hydrolase Activity, Hydrolyzing N-glycosyl Com... 0.008500 0.073312 0 0 inf inf BST1 7 GO_Molecular_Function_2023 Ubiquitin-Protein Transferase Activator Activi... 0.008500 0.073312 0 0 inf inf RIGI 8 GO_Molecular_Function_2023 DNA Binding, Bending (GO:0008301) 0.016930 0.083096 0 0 120.151515 490.060134 TOP2A 9 GO_Molecular_Function_2023 Disordered Domain Specific Binding (GO:0097718) 0.016930 0.083096 0 0 120.151515 490.060134 HSPA1A 10 GO_Molecular_Function_2023 UDP Phosphatase Activity (GO:0045134) 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 11 GO_Molecular_Function_2023 GDP Phosphatase Activity (GO:0004382) 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 12 GO_Molecular_Function_2023 Nucleoside Diphosphate Phosphatase Activity (G... 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 13 GO_Molecular_Function_2023 ATP Binding (GO:0005524) 0.017220 0.083096 0 0 11.204545 45.509349 ABCF2;HSPA1A 14 GO_Molecular_Function_2023 Ubiquitin Protein Ligase Binding (GO:0031625) 0.020064 0.083096 0 0 10.265625 40.126707 RIGI;HSPA1A 15 GO_Molecular_Function_2023 Ubiquitin-Like Protein Ligase Binding (GO:0044... 0.021555 0.083096 0 0 9.852500 37.805688 RIGI;HSPA1A 16 GO_Molecular_Function_2023 Growth Factor Activity (GO:0008083) 0.023090 0.083096 0 0 9.471154 35.690549 CLCF1;NTF3 17 GO_Molecular_Function_2023 Adenyl Ribonucleotide Binding (GO:0032559) 0.024670 0.083096 0 0 9.118056 33.756535 ABCF2;HSPA1A 18 GO_Molecular_Function_2023 C3HC4-type RING Finger Domain Binding (GO:0055... 0.025290 0.083096 0 0 60.060606 220.863728 HSPA1A 19 GO_Molecular_Function_2023 Ubiquitin Binding (GO:0043130) 0.025290 0.083096 0 0 60.060606 220.863728 TOP2A In [36]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( similar story to cluster above. this time with PTN often found in the litterature with 6 other m Studies on the role of STEAP1, OR51E2, PTN, ABCC4, NDRG2 have been relatively in-depth. For instance, STEAP1 is all-called six-transmembrane epithelial antigen of the prostate 1, which belongs to a family of metalloproteinases involved in iron and copper homeostasis and other cellular processes has been listed with 8 other members as predictors of CAF-related gene prognostic index (CRGPI) in prostate cancer. https://www.nature.com/articles/s41598-023-36125-0#Sec11 (NDRG2, TSPAN1, PTN, APOE, OR51E2, P4HB, STEAP1 and ABCC4 were used to construct molecular subtypes and) https://www.genecards.org/cgi-bin/carddisp.pl?gene=GSN 3.2 Normal version \u00b6 In [9]: Copied! grn . var [ 'cluster_1.5' ] . value_counts () . head ( 10 ) grn.var['cluster_1.5'].value_counts().head(10) Out[9]: cluster_1.5 0 1620 1 1483 2 732 3 111 4 23 5 9 6 4 16 1 23 1 22 1 Name: count, dtype: int64 https://www.genecards.org/cgi-bin/carddisp.pl?gene=MYOC In [37]: Copied! G = grn . plot_subgraph ( grn . var [ grn . var [ 'cluster_1.5' ] == '3' ] . index . tolist (), only = 200 , interactive = False ) G = grn.plot_subgraph(grn.var[grn.var['cluster_1.5']=='3'].index.tolist(), only=200, interactive=False) ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['TMEM132A', 'ADGRA2', 'AGPAT4', 'THAP3', 'DNAJC25', 'TRAM2', 'NTN1', 'STAG3', 'COL4A4', 'HSD17B14', ... 'nan-75', 'TRABD2B', 'nan-77', 'PCGF2', 'nan-107', 'nan-182', 'nan-192', 'nan-195', 'nan-239', 'nan-259'], dtype='object', name='symbol_2', length=111) In [26]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_3.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_3.html\") In [27]: Copied! grn . var . loc [ 'nan-259' ] # par of the Glycoside Hydrolase Family grn.var.loc['nan-259'] # par of the Glycoside Hydrolase Family Out[27]: uid 62JAXxQNqtOd symbol nan-259 ncbi_gene_ids 83737 biotype protein_coding description novel protein synonyms organism_id 2 public_source_id 9.0 created_by_id 1 mt False ribo False hb False organism NCBITaxon:9606 TFs False ensembl_id ENSG00000289720 centrality 0.0 cluster_1.5 3 Name: nan-259, dtype: object In [12]: Copied! grn . get ( grn . var [ grn . var [ 'cluster_1.5' ] == '3' ] . index . tolist ()) . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 3 ) ##.grn # selenom grn.get(grn.var[grn.var['cluster_1.5']=='3'].index.tolist()).grn.sum(0).sort_values(ascending=False).head(3)##.grn # selenom Out[12]: symbol RNASEK 0.942102 SELENOM 0.292933 nan-259 0.256140 dtype: float32 RNASEK acidifying the internal vesicle important in endocytosis# https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10547866/ RNA phosphodiester bond hydrolysis --> hydrolisis pathway in the model and RNA transcription regulation In [38]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:33:49,291 [WARNING] Input library not found: Reactome. Skip /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/enrichr.py:643: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation. self.results = pd.concat(self.results, ignore_index=True) Out[38]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Sulfotransferase Activity (GO:0008146) 0.007252 0.123369 0 0 20.138462 99.212171 CHST7;SULT1C4 1 GO_Molecular_Function_2023 RNA Polymerase II Transcription Regulatory Reg... 0.007713 0.123369 0 0 3.386005 16.472449 ZNF483;HAND2;NTN1;NFATC4;GLIS2;PURG;ZNF286A 2 GO_Molecular_Function_2023 ATPase Binding (GO:0051117) 0.013790 0.123369 0 0 13.415385 57.468682 SLC2A13;NKD2 3 GO_Molecular_Function_2023 Chondroitin Sulfotransferase Activity (GO:0034... 0.016750 0.123369 0 0 inf inf CHST7 4 GO_Molecular_Function_2023 Peptidyl-Proline 4-Dioxygenase Activity (GO:00... 0.016750 0.123369 0 0 inf inf P4HA3 5 GO_Molecular_Function_2023 Aryl Sulfotransferase Activity (GO:0004062) 0.016750 0.123369 0 0 inf inf SULT1C4 6 GO_Molecular_Function_2023 Histone Reader Activity (GO:0140566) 0.016750 0.123369 0 0 inf inf TONSL 7 GO_Molecular_Function_2023 Hydrolase Activity, Hydrolyzing N-glycosyl Com... 0.016750 0.123369 0 0 inf inf BST1 8 GO_Molecular_Function_2023 Tat Protein Binding (GO:0030957) 0.016750 0.123369 0 0 inf inf DLL1 9 GO_Molecular_Function_2023 WW Domain Binding (GO:0050699) 0.016750 0.123369 0 0 inf inf ENTREP3 10 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.016754 0.123369 0 0 3.180050 13.003634 ZNF483;HAND2;NTN1;NFATC4;GLIS2;ZNF286A 11 GO_Molecular_Function_2023 DNA-binding Transcription Activator Activity, ... 0.026719 0.134555 0 0 5.074219 18.380719 HAND2;INSL3;GLIS2 12 GO_Molecular_Function_2023 Procollagen-Proline Dioxygenase Activity (GO:0... 0.033223 0.134555 0 0 59.575758 202.825781 P4HA3 13 GO_Molecular_Function_2023 N-acetylglucosamine 6-O-sulfotransferase Activ... 0.033223 0.134555 0 0 59.575758 202.825781 CHST7 14 GO_Molecular_Function_2023 ABC-type Xenobiotic Transporter Activity (GO:0... 0.033223 0.134555 0 0 59.575758 202.825781 ABCC1 15 GO_Molecular_Function_2023 alpha-N-acetylgalactosaminide Alpha-2,6-Sialyl... 0.033223 0.134555 0 0 59.575758 202.825781 ST6GALNAC6 16 GO_Molecular_Function_2023 miRNA Binding (GO:0035198) 0.033223 0.134555 0 0 59.575758 202.825781 DND1 17 GO_Molecular_Function_2023 Myosin Heavy Chain Binding (GO:0032036) 0.033223 0.134555 0 0 59.575758 202.825781 NKD2 18 GO_Molecular_Function_2023 Estradiol 17-Beta-Dehydrogenase [NAD(P)] Activ... 0.033223 0.134555 0 0 59.575758 202.825781 HSD17B14 19 GO_Molecular_Function_2023 Solute:Proton Symporter Activity (GO:0015295) 0.033223 0.134555 0 0 59.575758 202.825781 SLC2A13 In [39]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( https://www.genecards.org/cgi-bin/carddisp.pl?gene=PTN In [40]: Copied! G = grn . plot_subgraph ( grn . var [ grn . var [ 'cluster_1.5' ] == '4' ] . index . tolist (), only = 80 , interactive = False ) # G = grn.plot_subgraph(grn.var[grn.var['cluster_1.5']=='4'].index.tolist(), only=80, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['TRHDE', 'PGR', 'ESR1', 'RASD2', 'SYNDIG1', 'OLFM2', 'FZD10', 'BHMT2', 'DUSP26', 'FOXF2', 'ADAM33', 'ADAMTS12', 'HS3ST3A1', 'CHODL', 'FTCD', 'FNDC1', 'HSPB3', 'FOXL1', 'AGMO', 'ADAMTSL2', 'S100A6', 'AKR1B10', 'SCGB1C2'], dtype='object', name='symbol_2') In [29]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_4.html\") In [41]: Copied! enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'GO_Molecular_Function_2023' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['GO_Molecular_Function_2023', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:34:27,578 [WARNING] Input library not found: Reactome. Skip Out[41]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 RNA Polymerase II General Transcription Initia... 0.000032 0.000933 0 0 inf inf FOXF2;ESR1 1 GO_Molecular_Function_2023 Estrogen Response Element Binding (GO:0034056) 0.000032 0.000933 0 0 inf inf PGR;ESR1 2 GO_Molecular_Function_2023 General Transcription Initiation Factor Bindin... 0.000095 0.001860 0 0 378.666667 3508.819727 FOXF2;ESR1 3 GO_Molecular_Function_2023 Transcription Coactivator Binding (GO:0001223) 0.000188 0.002780 0 0 189.285714 1623.428489 PGR;ESR1 4 GO_Molecular_Function_2023 Transition Metal Ion Binding (GO:0046914) 0.000446 0.005263 0 0 13.515099 104.272240 BHMT2;AGMO;ADAM33;TRHDE 5 GO_Molecular_Function_2023 Metalloendopeptidase Activity (GO:0004222) 0.000551 0.005414 0 0 22.794231 171.058857 ADAMTSL2;ADAM33;ADAMTS12 6 GO_Molecular_Function_2023 Metallopeptidase Activity (GO:0008237) 0.000672 0.005666 0 0 21.155357 154.536591 ADAMTSL2;ADAM33;ADAMTS12 7 GO_Molecular_Function_2023 Transcription Coregulator Binding (GO:0001221) 0.001111 0.008195 0 0 54.013605 367.419603 PGR;ESR1 8 GO_Molecular_Function_2023 DNA-binding Transcription Activator Activity, ... 0.001429 0.009365 0 0 15.972973 104.640056 FOXF2;PGR;ESR1 9 GO_Molecular_Function_2023 ATPase Binding (GO:0051117) 0.002016 0.011893 0 0 37.780952 234.495632 PGR;ESR1 10 GO_Molecular_Function_2023 Zinc Ion Binding (GO:0008270) 0.002284 0.012250 0 0 13.407955 81.545835 BHMT2;ADAM33;TRHDE 11 GO_Molecular_Function_2023 Cis-Regulatory Region Sequence-Specific DNA Bi... 0.004517 0.021203 0 0 6.945569 37.504924 FOXF2;PGR;FOXL1;ESR1 12 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.005523 0.021203 0 0 6.541596 34.009122 FOXF2;PGR;FOXL1;ESR1 13 GO_Molecular_Function_2023 DNA Binding, Bending (GO:0008301) 0.005750 0.021203 0 0 inf inf FOXL1 14 GO_Molecular_Function_2023 TBP-class Protein Binding (GO:0017025) 0.005750 0.021203 0 0 inf inf ESR1 15 GO_Molecular_Function_2023 [Heparan Sulfate]-Glucosamine 3-Sulfotransfera... 0.005750 0.021203 0 0 inf inf HS3ST3A1 16 GO_Molecular_Function_2023 RNA Polymerase II Transcription Regulatory Reg... 0.008164 0.028333 0 0 5.812950 27.949028 FOXF2;PGR;FOXL1;ESR1 17 GO_Molecular_Function_2023 Endopeptidase Activity (GO:0004175) 0.008882 0.028593 0 0 8.021918 37.893119 ADAMTSL2;ADAM33;ADAMTS12 18 GO_Molecular_Function_2023 DNA Binding (GO:0003677) 0.009208 0.028593 0 0 7.911486 37.086673 FOXF2;PGR;FOXL1 19 GO_Molecular_Function_2023 Heparan Sulfate Sulfotransferase Activity (GO:... 0.011468 0.030756 0 0 180.727273 807.520606 HS3ST3A1 In [42]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( 4. Differential Gene - Gene connections \u00b6 look at the connections of some key TFs in here do GSEA over these connections compare the connections of these same TFs for both conditions In [5]: Copied! G = grn_c . plot_subgraph ( \"PAGE4\" , only = 100 , max_genes = 40 , interactive = False ) # G = grn_c.plot_subgraph(\"PAGE4\", only=100, max_genes=40, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#ff7f0e'] Index(['MT2A', 'HSPA1A', 'CREM', 'PTN', 'HLA-A', 'SPARCL1', 'SPOCK3', 'NR4A3', 'APOD', 'CALD1', 'MGP', 'HSPE1', 'EIF4A1', 'CD99', 'EMP1', 'FABP4', 'NAMPT', 'NNMT', 'RBP1', 'LUM', 'IGFBP7', 'THBS1', 'YBX3', 'NAF1', 'DCN', 'A2M', 'CPE', 'C1R', 'ATP6V0C', 'MATN2', 'COL6A2', 'UBE2S', 'CST3', 'RHOQ', 'UBE2C', 'C1S', 'H2AZ1', 'GPRC5A', 'HLA-C', 'LGALS1', 'PAGE4'], dtype='object', name='symbol_2') In [96]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) first_node = list ( G . nodes )[ - 1 ] pnet . get_node ( first_node )[ 'color' ] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_PAGE4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) first_node = list(G.nodes)[-1] pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_PAGE4.html\") In [22]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ #'KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', 'WikiPathway_2023_Human' , #'TF_Perturbations_Followed_by_Expression', #'PPI_Hub_Proteins', #'OMIM_Disease', #'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 10 ) enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( 'R-HSA' ) . str [ 0 ] . str . split ( ' WP' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=[ #'KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', 'WikiPathway_2023_Human', #'TF_Perturbations_Followed_by_Expression', #'PPI_Hub_Proteins', #'OMIM_Disease', #'GO_Molecular_Function_2023' ], organism='Human', # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(10) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split('R-HSA').str[0].str.split(' WP').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [139]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size figsize = ( 4 , 5 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size figsize=(4,5), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [17]: Copied! G = grn . plot_subgraph ( \"PAGE4\" , only = 100 , max_genes = 40 , interactive = False ) G = grn.plot_subgraph(\"PAGE4\", only=100, max_genes=40, interactive=False) ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#ff7f0e'] Index(['nan-270', 'S100A6', 'MT2A', 'SPARCL1', 'MIF', 'SLC25A6', 'IGFBP7', 'APOD', 'MGP', 'DCN', 'A2M', 'PTN', 'RELB', 'DNAJB9', 'AKR1C1', 'C1S', 'CST3', 'CXCL8', 'FTH1', 'BRME1', 'FAM205A', 'TIMP1', 'YBX3', 'NPPB', 'TGIF2-RAB5IF', 'FBLN1', 'MTDH', 'IGFBP5', 'TFPI', 'MAP1B', 'COL6A2', 'HNRNPA0', 'EIF4A1', 'CCL21', 'FTL', 'CETN1', 'NME2', 'LSAMP', 'ACR', 'ATP6V0C', 'PAGE4'], dtype='object', name='symbol_2') In [98]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) first_node = list ( G . nodes )[ - 1 ] pnet . get_node ( first_node )[ 'color' ] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_PAGE4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) first_node = list(G.nodes)[-1] pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_PAGE4.html\") In [24]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', #'WikiPathway_2023_Human', # 'TF_Perturbations_Followed_by_Expression', # 'Reactome', #'PPI_Hub_Proteins', #'OMIM_Disease', 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', #'WikiPathway_2023_Human', # 'TF_Perturbations_Followed_by_Expression', # 'Reactome', #'PPI_Hub_Proteins', #'OMIM_Disease', 'GO_Molecular_Function_2023' ], organism='Human', # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) Out[24]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Peptidase Inhibitor Activity (GO:0030414) 0.000020 0.001566 0 0 104.105263 1128.623016 CST3;TIMP1;TFPI 1 GO_Molecular_Function_2023 Transition Metal Ion Binding (GO:0046914) 0.000463 0.016191 0 0 9.025463 69.301557 ACR;MT2A;FTH1;TIMP1;FTL 2 GO_Molecular_Function_2023 Double-Stranded RNA Binding (GO:0003725) 0.000607 0.016191 0 0 101.461538 751.496153 EIF4A1;MTDH 3 GO_Molecular_Function_2023 Endopeptidase Inhibitor Activity (GO:0004866) 0.001010 0.019977 0 0 18.306502 126.278211 CST3;TIMP1;TFPI 4 GO_Molecular_Function_2023 Endopeptidase Regulator Activity (GO:0061135) 0.001498 0.019977 0 0 50.705128 329.757829 CST3;TFPI 5 GO_Molecular_Function_2023 Ferrous Iron Binding (GO:0008198) 0.001498 0.019977 0 0 50.705128 329.757829 FTH1;FTL 6 GO_Molecular_Function_2023 Protease Binding (GO:0002020) 0.002465 0.027606 0 0 12.944079 77.736001 CST3;ACR;TIMP1 7 GO_Molecular_Function_2023 Iron Ion Binding (GO:0005506) 0.002761 0.027606 0 0 33.786325 199.079000 FTH1;FTL 8 GO_Molecular_Function_2023 Calcium Ion Binding (GO:0005509) 0.003252 0.028910 0 0 7.400664 42.393777 CETN1;S100A6;SPARCL1;FBLN1 9 GO_Molecular_Function_2023 Kinase Binding (GO:0019900) 0.005211 0.038377 0 0 9.688322 50.930509 PTN;RELB;HNRNPA0 10 GO_Molecular_Function_2023 RNA Binding (GO:0003723) 0.005277 0.038377 0 0 5.000000 26.222182 EIF4A1;YBX3;DCN;MTDH;HNRNPA0 11 GO_Molecular_Function_2023 Chemokine Activity (GO:0008009) 0.007445 0.039047 0 0 18.405594 90.191859 CXCL8;CCL21 12 GO_Molecular_Function_2023 Chemokine Receptor Binding (GO:0042379) 0.007445 0.039047 0 0 18.405594 90.191859 CXCL8;CCL21 13 GO_Molecular_Function_2023 Metal Ion Binding (GO:0046872) 0.008569 0.039047 0 0 5.523471 26.289761 CETN1;S100A6;SPARCL1;FBLN1 14 GO_Molecular_Function_2023 Protein Kinase Binding (GO:0019901) 0.009285 0.039047 0 0 7.734868 36.193807 PTN;RELB;HNRNPA0 15 GO_Molecular_Function_2023 mRNA 3'-UTR Binding (GO:0003730) 0.009893 0.039047 0 0 15.566075 71.852090 YBX3;HNRNPA0 16 GO_Molecular_Function_2023 NF-kappaB Binding (GO:0051059) 0.010250 0.039047 0 0 inf inf MTDH 17 GO_Molecular_Function_2023 Phosphatase Inhibitor Activity (GO:0019212) 0.010250 0.039047 0 0 inf inf PTN 18 GO_Molecular_Function_2023 Phosphotransferase Activity, Phosphate Group A... 0.010250 0.039047 0 0 inf inf NME2 19 GO_Molecular_Function_2023 Nucleobase-Containing Compound Kinase Activity... 0.010250 0.039047 0 0 inf inf NME2 In [30]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size figsize = ( 4 , 5 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size figsize=(4,5), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( 5. Using classification \u00b6 Here we used the network given by the mean of all heads in our scPRINT model. We could also use other scPRINT versions to see if the results are consistent. but we could also use the classification mechanism presented in our manuscript and other notebooks to get to possibly more specialized networks. In [ ]: Copied! grn_normal = grn_inferer ( layer = list ( range ( model . nlayers ))[:], cell_type = \"naive B cell\" ) grn_normal , m , omni_cls = train_classifier ( grn_normal , C = 0.5 , train_size = 0.9 , class_weight = { 1 : 200 , 0 : 1 }, shuffle = True ) grn_normal = grn_inferer(layer=list(range(model.nlayers))[:], cell_type=\"naive B cell\") grn_normal, m, omni_cls = train_classifier(grn_normal, C=0.5, train_size=0.9, class_weight={ 1: 200, 0: 1}, shuffle=True) number of expressed genes in this cell type: 16801 LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0] Predicting: 0it [00:00, ?it/s] true elem 2115 ... doing regression.... metrics {'used_heads': 25, 'precision': 0.0, 'random_precision': 0.0006433550820644942, 'recall': 0.0, 'predicted_true': 177.0, 'number_of_true': 219.0, 'epr': 0.0} In [ ]: Copied! # highlight differential links on genes that are expressed in both grn_normal . varp [ 'all' ] = grn_normal . varp [ 'GRN' ] . copy () grn_normal . varp [ 'GRN' ] = grn_normal . varp [ 'classified' ] # highlight differential links on genes that are expressed in both grn_normal.varp['all'] = grn_normal.varp['GRN'].copy() grn_normal.varp['GRN'] = grn_normal.varp['classified'] Notes on findings and their relation to the literature \u00b6 CAV1-expressing CAFs contribute to invasion and metastasis in breast cancer24 loss of caveolin1 (CAV1) is found in metabolically reprogrammed CAFs that promote tumorigenesis discoidin domain-containing receptor 2 (DDR2)21 and integrin \u03b111\u03b2122, have emerged to identify CAFs in the context of a specific TME https://www.nature.com/articles/s12276-023-01013-0 normal fibroblast populations marked by the expression of Gli1 and Hoxb6 CAFs, remain perpetually activated with a high capacity for ECM synthesis and microenvironmental remodeling, leading to stromal desmoplasia, a phenomenon characterized by increased deposition of ECM components in tumors. In this regard, CAFs share many basic characteristics, such as a secretory phenotype and capacity to synthesize ECM components, with fibroblasts found in nonmalignant tissue fibrosis. Therefore, the classic markers found to be expressed in fibroblasts, including \u03b1-SMA, vimentin, desmin, fibroblast-specific protein 1 (FSP1; also known as S100A4) Fibrogenesis is part of a normal protective response to tissue injury that can become irreversible and progressive, leading to fatal diseases. Senescent cells are a main driver of fibrotic diseases through their secretome, known as senescence-associated secretory phenotype (SASP) CAFs (vCAFs), cycling CAFs (cCAFs), and developmental CAFs (dCAFs) The stem-like \u2018universal\u2019 type of fibroblast cell, marked by expression of peptidase inhibitor 16 (Pi16) and Col15a, found in the steady state across tissues, activated fibroblasts, as observed by the development of LRRC15+ CAFs in PDAC. . SOCS1: Suppressor of cytokine signaling; STAT3: Signal transducer and activator of transcription 3; LDH: Lactate dehydrogenase; PYCR1: pyrroline-5-carboxylate reductase senescence, and multiple types of fibrotic diseases in mice and humans are characterized by the accumulation of iron. https://www.nature.com/articles/s42255-023-00928-2 Current evidence indicate that cancer-associated fibroblasts (CAFs) play an important role in prostate cancer (PCa) development and progression. playing a role in invasion. NDRG2, TSPAN1, PTN, APOE, OR51E2, P4HB, STEAP1 and ABCC4 were used to construct molecular subtypes and CAF-related gene prognostic index (CRGPI) Studies on the role of STEAP1, OR51E2, PTN, ABCC4, NDRG2 have been relatively in-depth. For instance, STEAP1 is all-called six-transmembrane epithelial antigen of the prostate 1, which belongs to a family of metalloproteinases involved in iron and copper homeostasis and other cellular processes37. STEAP1 is overexpressed on the plasma membrane of PCa cells and is associated with PCa invasiveness and metastasis50. The possible mechanism of STEAP1 promoting tumor proliferation and metastasis is by acting as a channel for small molecules that are involved in intercellular communication OR51E2 perhaps could be used as one of the biomarkers for PCa53,54,55,56 https://www.nature.com/articles/s41598-023-36125-0#Sec11 The protein encoded by ABCC4 is a member of the superfamily of ATP-binding cassette (ABC) transporters, which is also called multidrug resistance protein 4 (MRP4)64. MRP4 was reported to be associated with drug resistance of PCa in many studies65,66,67 PRRX1, OSR1, FOXD1, HOXC4,LHX9, TBX3 and TWIST2, targeted five or more TFs inthe fibroblast TRN. This influential-set explained 62.5% ofthe total number of regulatory edges and they collectivelytargeted 15 out of 18 TFs represented in the network. Upona closer examination of the fibroblastic network, the inter-actions among OSR1\u2013PRRX1\u2013TWIST2 were notably co-ordinated, regulating one another in both directions https://www.researchgate.net/publication/264633205_A_transient_disruption_of_fibroblastic_transcriptional_regulatory_network_facilitates_trans-differentiation FGF receptors are important in PCa initiation and progression. These endocrine FGFs require alpha-Klotho (KL) and/or beta-Klotho (KLB), two related single-pass transmembrane proteins restricted in their tissue distribution. FGF19 is expressed in primary and metastatic PCa tissues where it functions as an autocrine growth factor. https://www.e-cancer.fr/Professionnels-de-sante/Veille-bibliographique/Nota-Bene-Cancer/NBC-174/The-endocrine-fibroblast-growth-factor-FGF19-promotes-prostate-cancer-progression \u2022 Prostate cancer stroma contains diverse populations of fibroblasts. \u2022 Carcinoma associated fibroblasts can promote prostate carcinogenesis. \u2022 Interaction among fibroblast subsets modulate stromal-epithelial paracrine signaling. The stroma in the normal prostate is predominantly composed of smooth muscle cells while in cancer this is partially replaced by fibroblasts and myofibroblasts6. These fibroblastic cells are responsible for collagen and extracellular matrix (ECM) deposition, changing local organ stiffness iCAF, myCAF, apCAF It has been shown that SDF-1/CXCL12, secreted by CAF, acts via TGF\u03b2\u2013mediated upregulation of CXCR4 in epithelial cells to activate Akt signaling associated with tumorigenesis. Overexpression of SDF-1/CXCL12 and TGF\u03b21 in benign human prostate fibroblasts has been shown to induce malignant transformation of benign prostate epithelial cells and formation of highly invasive tumors in vivo increased cadherin 2 (CDH2) mRNA expression in LNCaP cells Upregulation of DNA methyltransferases (DNMT) consistent with aberrant promoter hypermethylation of tumor-suppressor genes in multiple cancer types including PCa has been reported https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8788937/#:~:text=The%20stroma%20in%20the%20normal,deposition%2C%20changing%20local%20organ%20stiffness . CD10 and GPR77 can define a human CAF subset that sustains cancer stemness Fibroblasts are also fundamental for inducing angiogenesis by secreting angiogenic factors such as vascular endothelial growth factor (VEGF) and matrix proteins Epithelial cells release TGF\u03b2 ligands, Kallikrein-related peptidase-4 (KLK4), CAFs are characterized by molecular markers that are upregulated compared to normal fibroblasts, such as fibroblast activation protein (FAP), PDGFR-\u03b2, fibroblast-specific protein-1 (FSP-1) (also known as S100A4) ACTA2 \u03b1-smooth actin (\u03b1-SMA) Upregulated RT-qPCR, IHC on tissue microarrays [42,43] ASPN Asporin Upregulated Tag-based RNA profiling, microarray profiling, IHC, RT-qPCR [38,44,45] CAV1 Caveolin-1 Downregulated Tag profiling, IHC, RT-qPCR [38] COL1A1 Collagen Type-I Upregulated RT-qPCR, IHC [42,43] CXCL12 Stromal cell-derived factor 1 (SDF1)/ (C-X-C motif chemokine ligand 12 (CXCL12) Upregulated Tag-profiling, RT-qPCR, ELISA [38,46] FAP Fibroblast activation protein Upregulated IHC [42] FGF2, FGF7, FGF10 Fibroblast growth factor-2/-7/-10 Upregulated RT-qPCR, Western Blot, IHC [43,47,48] FN1 Fibronectin Upregulated Tag profiling, IHC, RT-qPCR [38] ITGA1 Integrin-\u03b11 (CD49a) Upregulated IHC [49] OGN Osteoglycin Upregulated Tag-profiling, IHC, RT-qPCR [38] PDGFRB Platelet-derived growth factor receptor \u03b2 Upregulated Microarray profiling [44,50] POSTN Periostin Upregulated Microarray profiling, IHC [44] S100A4 Fibroblast-specific protein 1 (FSP1)/S100 Calcium Binding Protein A4 (S100A4) Upregulated Immunofluorescence, RT-qPCR, Western Blot [51,52,53] S100A6 S100 Calcium Binding Protein A6 Downregulated Tag profiling, IHC, RT-qPCR [38] SPARC Secreted Protein Acidic and Cysteine Rich Up/downregulated Microarray profiling, Tag-profiling [38,44] STC1 Stanniocalcin 1 Downregulated Tag profiling, IHC, RT-qPCR [38] THY1 Cluster of differentiation 90 (CD90) antigen Upregulated IHC [54] TNC Tenascin C Upregulated RT-qPCR, IHC [42,43] VIM Vimentin Upregulated IHC Benign prostatic hyperplasia (BPH) is a non-malignant growth of the prostate, typically occurring in older men with an occurrence of 80\u201390% of men in their 70s BPH develops in the transition zone differently from PCa foci, which usually develop in the peripheral zone ESR1= . Here we studied the role of CAF estrogen receptor alpha (ER\u03b1) and found that it could protect against PCa invasion. ER\u03b1 could function through a CAF\u2013epithelial interaction via selectively upregulating thrombospondin 2 (Thbs2) and downregulating matrix metalloproteinase 3 (MMP3) at the protein and messenger RNA levels https://academic.oup.com/carcin/article/35/6/1301/449417 ACTA2: we found that \u201creactive CAFs\u201d induce shear resistance to prostate tumor cells via intercellular contact and soluble derived factors. The reactive CAFs showed higher expression of \u03b1-smooth muscle actin (\u03b1-SMA) and fibroblast activation protein (FAP) compared to differentiated CAFs https://www.oncotarget.com/article/27510/ Proteins that exhibited a significant increase in CAF versus NPF were enriched for the functional categories \u201ccell adhesion\u201d and the \u201cextracellular matrix.\u201d The CAF phosphoproteome exhibited enhanced phosphorylation of proteins associated with the \u201cspliceosome\u201d and \u201cactin binding.\u201d COL1A1/2 and COL5A1; the receptor tyrosine kinase discoidin domain-containing receptor 2 (DDR2), a receptor for fibrillar collagens; and lysyl oxidase-like 2 (LOXL2) https://www.mcponline.org/article/S1535-9476(20)31548-6/fulltext \u2022Cancer-associated fibroblasts (CAFs) exhibit a highly aligned cytoskeleton and extracellular matrix. \u2022CAFs are stiffer than normal fibroblasts from the prostate. \u2022Benign prostate epithelial cells are more compliant after co-culture with CAFs. \u2022Benign epithelial cells are more invasive and proliferative in presence of CAFs. https://www.sciencedirect.com/science/article/pii/S2590006420300338 These findings suggest that CAFs exosomes drive PCa metastasis via the miR-500a-3p/FBXW7/HSF1 axis in a hypoxic microenvironmen https://www.nature.com/articles/s41417-024-00742-2 https://www.genecards.org/cgi-bin/carddisp.pl?gene=CCT8L2 CCT8L2 (Chaperonin Containing TCP1 Subunit 8 Like 2) is a Protein Coding gene. Gene Ontology (GO) annotations related to this gene include calcium-activated potassium channel activity and monoatomic anion channel activity. An important paralog of this gene is CCT8. related to the meta transmembrane activity via Possible molecular chaperone; assists the folding of proteins upon ATP hydrolysis. The TRiC complex mediates the folding of WRAP53/TCAB1, thereby regulating telomere maintenance (PubMed:25467444). As part of the TRiC complex may play a role in the assembly of BBSome, a complex involved in ciliogenesis regulating transports vesicles to the cilia https://www.genecards.org/cgi-bin/carddisp.pl?gene=TIMP1 TIMP Metallopeptidase Inhibitor 1 inhibitors of the matrix metalloproteinases (MMPs), a group of peptidases involved in degradation of the extracellular matrix. In addition to its inhibitory role against most of the known MMPs, the encoded protein is able to promote cell proliferation connected to TLL2: zinc-dependent metalloprotease part of the metzincin protein complex which also is Among its related pathways are Collagen chain trimerization and Extracellular matrix organization. PDXP, SEPTIN5 cytoskeletal organization and regulation PRAME inhibits the signaling of retinoic acid and mediates the regulation of selenoproteins many genes involved in cancer. indeed, it is known that 80% adult male above 70 years old will have such hyperplastic prostate. This is due to scenesence. and that Iron accumulation drives fibrosis, senescence and the senescence-associated secretory phenotype. (of which we have some proteins present here.) A mechanism that this clustered is one of genes that strongly regulates each other in this fibroblasts from pre-cancerous lesions via fibrotic iron accumulation and a secretory mechanism GJC1 (exchange of things between cells (here likely metals?)) Unknown genes like SMIM40. integral membrane protein could be linked to this phenotype ['pre { line-height: 125%; }\\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n.highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) }\\n.highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\\n.highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\\n.highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */\\n.highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\\n.highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\\n.highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\\n.highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\\n.highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\\n.highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\\n.highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\\n.highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\\n.highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\\n.highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\\n.highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\\n.highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\\n.highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\\n.highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\\n.highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\\n.highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\\n.highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\\n.highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\\n.highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\\n.highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\\n.highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\\n.highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\\n.highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\\n.highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\\n.highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\\n.highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\\n.highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\\n.highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\\n.highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\\n.highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\\n.highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\\n.highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\\n.highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\\n.highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\\n.highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\\n.highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\\n.highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\\n.highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\\n.highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */']","title":"scPRINT use case on BPH (part 2, GN analysis)"},{"location":"notebooks/cancer_usecase_part2/#scprint-use-case-on-bph-part-2-gn-analysis","text":"In this use-case, which some of the results are presented in Figure 5 of our manuscript , we perform an extensive analysis of gene networks generated by scPRINT in our previous notebook for fibroblasts of the prostate in both normal and benign prostatic hyperplasia states. We can look at many patterns from the gene networks such as hub genes, gene modules, and gene-gene interactions. Some of them are related to highly variable and differentially expressed genes while others can only be infered by using the gene networks. Table of content: Hub genes Network similarity Network communities Cancer version Normal version Differential Gene - Gene connections Using classification In [1]: Copied! from bengrn import BenGRN import scanpy as sc from bengrn.base import train_classifier from anndata.utils import make_index_unique from grnndata import utils as grnutils from grnndata import read_h5ad from matplotlib import pyplot as plt from scdataloader import utils as data_utils import numpy as np from pyvis import network as pnx import networkx as nx import scipy.sparse import pandas as pd import gseapy as gp from gseapy import dotplot % load_ext autoreload % autoreload 2 from bengrn import BenGRN import scanpy as sc from bengrn.base import train_classifier from anndata.utils import make_index_unique from grnndata import utils as grnutils from grnndata import read_h5ad from matplotlib import pyplot as plt from scdataloader import utils as data_utils import numpy as np from pyvis import network as pnx import networkx as nx import scipy.sparse import pandas as pd import gseapy as gp from gseapy import dotplot %load_ext autoreload %autoreload 2 \ud83d\udca1 connected lamindb: jkobject/scprint In [ ]: Copied! prostate_combined = sc . read_h5ad ( \"../data/prostate_combined_o2uniqsx.h5ad\" ) prostate_combined = sc.read_h5ad(\"../data/prostate_combined_o2uniqsx.h5ad\") In [2]: Copied! # load the generated gene networks from the previous notebook grn = read_h5ad ( \"../../data/prostate_fibro_grn.h5ad\" ) grn_c = read_h5ad ( \"../../data/prostate_cancer_fibro_grn.h5ad\" ) #remove duplicates grn . var . symbol = make_index_unique ( grn . var . symbol . astype ( str )) grn_c . var . symbol = make_index_unique ( grn_c . var . symbol . astype ( str )) # convert gene ids to symbols grn . var [ 'ensembl_id' ] = grn . var . index grn . var . index = grn . var . symbol grn_c . var [ 'ensembl_id' ] = grn_c . var . index grn_c . var . index = grn_c . var . symbol grn . obs . cleaned_pred_disease_ontology_term_id . value_counts (), grn_c . obs . cleaned_pred_disease_ontology_term_id . value_counts () # load the generated gene networks from the previous notebook grn = read_h5ad(\"../../data/prostate_fibro_grn.h5ad\") grn_c = read_h5ad(\"../../data/prostate_cancer_fibro_grn.h5ad\") #remove duplicates grn.var.symbol = make_index_unique(grn.var.symbol.astype(str)) grn_c.var.symbol = make_index_unique(grn_c.var.symbol.astype(str)) # convert gene ids to symbols grn.var['ensembl_id'] = grn.var.index grn.var.index = grn.var.symbol grn_c.var['ensembl_id'] = grn_c.var.index grn_c.var.index = grn_c.var.symbol grn.obs.cleaned_pred_disease_ontology_term_id.value_counts(),grn_c.obs.cleaned_pred_disease_ontology_term_id.value_counts() Out[2]: (cleaned_pred_disease_ontology_term_id normal 300 Name: count, dtype: int64, cleaned_pred_disease_ontology_term_id benign prostatic hyperplasia 300 Name: count, dtype: int64)","title":"scPRINT use case on BPH (part 2, GN analysis)"},{"location":"notebooks/cancer_usecase_part2/#1-hub-genes","text":"We will use 2 different definition of centrality to compare the hubs of the networks in both states. The first one is the degree centrality, which is the number of connections of a node. The second one is the eigenvector centrality, which is the sum of the centrality of the neighbors of a node. For each gene we mostly interogate their meaning with genecards, e.g. https://www.genecards.org/cgi-bin/carddisp.pl?gene=CD99 In [7]: Copied! # between the two networks we have ~3000 genes in common over their 4000 genes common = set ( grn_c . var . symbol ) & set ( grn . var . symbol ) len ( common ) # between the two networks we have ~3000 genes in common over their 4000 genes common = set(grn_c.var.symbol) & set(grn.var.symbol) len(common) Out[7]: 2881 In [8]: Copied! # hub genes based on edge centrality (number of connections / strength of connections) grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 20 ) # hub genes based on edge centrality (number of connections / strength of connections) grn.grn.sum(0).sort_values(ascending=False).head(20) Out[8]: symbol S100A6 58.131020 TGIF2-RAB5IF 51.177635 MIF 44.534096 DNAJB9 40.953262 IGFBP7 38.629910 APOD 38.003906 BRME1 37.598698 SPARCL1 37.160854 TIMP1 36.671650 DCN 34.621376 C1S 32.746254 MGP 30.496748 nan-270 29.884596 SLC25A6 29.308729 BLOC1S5-TXNDC5 28.986681 CETN1 28.746281 FTL 28.266533 AKR1C1 27.641245 FBLN1 26.828733 MT2A 25.590197 dtype: float32 In [7]: Copied! # without taking in account genes that are not present in the cancer network grn . grn . sum ( 0 ) . loc [ list ( common )] . sort_values ( ascending = False ) . head ( 20 ) # without taking in account genes that are not present in the cancer network grn.grn.sum(0).loc[list(common)].sort_values(ascending=False).head(20) Out[7]: symbol TGIF2-RAB5IF 51.177635 IGFBP7 38.629910 APOD 38.003906 BRME1 37.598698 SPARCL1 37.160854 TIMP1 36.671650 DCN 34.621376 C1S 32.746254 MGP 30.496748 BLOC1S5-TXNDC5 28.986681 AKR1C1 27.641245 FBLN1 26.828733 MT2A 25.590197 MYOC 25.428144 FAM205A 25.296257 YBX3 24.937267 CST3 24.676405 C11orf96 18.731924 TFPI 18.429214 ATP6V0C 17.695705 dtype: float32 In [11]: Copied! # cancer hub genes grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 20 ) # cancer hub genes grn_c.grn.sum(0).sort_values(ascending=False).head(20) Out[11]: symbol HSPA1A 75.300415 MT2A 57.938267 CREM 42.478115 TGIF2-RAB5IF 39.980556 HSPE1 38.607624 CALD1 36.512047 SPOCK3 35.564945 HLA-A 33.446110 SPARCL1 33.403152 RBP1 32.482758 C1S 32.037743 BRME1-1 31.879770 FABP4 31.604069 nan-99 31.555256 LUM 30.523245 EIF4A1 29.690474 ATP6V0C 29.475002 PDZD2 27.333025 DEFA1 26.979454 CTSG 25.070097 dtype: float32 In [10]: Copied! # without taking in account genes not present in the normal network grn_c . grn . sum ( 0 ) . loc [ list ( common )] . sort_values ( ascending = False ) . head ( 20 ) # without taking in account genes not present in the normal network grn_c.grn.sum(0).loc[list(common)].sort_values(ascending=False).head(20) Out[10]: symbol HSPA1A 75.300415 MT2A 57.938267 TGIF2-RAB5IF 39.980556 SPOCK3 35.564945 HLA-A 33.446110 SPARCL1 33.403152 C1S 32.037743 nan-99 31.555256 LUM 30.523245 EIF4A1 29.690474 ATP6V0C 29.475002 DEFA1 26.979454 IGFBP7 23.982243 DCN 23.304916 MGP 22.596451 CD99 21.624668 BLOC1S5-TXNDC5 20.914230 SERPING1 20.824636 COL6A2 18.076559 THBS1 17.826540 dtype: float32 In [12]: Copied! # top differential hubs TOP = 10 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) # top differential hubs TOP = 10 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[12]: {'HLA-A', 'HSPA1A', 'MT2A', 'SPOCK3'} In [13]: Copied! TOP = 20 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 20 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[13]: {'ATP6V0C', 'DEFA1', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LUM', 'SPOCK3', 'nan-99'} In [14]: Copied! TOP = 50 ( set ( grn_c . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 50 (set(grn_c.grn.sum(0).sort_values(ascending=False).head(TOP).index) - set(grn.grn.sum(0).sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[14]: {'CD99', 'CPE', 'DEFA1', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LGALS1', 'LUM', 'PYDC2', 'SERPING1', 'SPOCK3', 'THBS1', 'nan-191', 'nan-99'} overall we see that both are somewhat similar in the way the networks classifies main nodes but at least around half of the top 200 nodes are different between the two datasets and half of those are not due to diffent gene being used by the networks (50) genes preferentially given as top elements in the tumor version only: CD99 CPE DEFA1 EIF4A1 HLA-A HSPA1A LGALS1 LUM PYDC2 SERPING1 SPOCK3 THBS1 In [3]: Copied! # we now compute eigen centrality creating a sparse network by only keeping the top 20 neighbors for each gene in the network TOP = 20 grnutils . get_centrality ( grn , TOP , top_k_to_disp = 0 ) grnutils . get_centrality ( grn_c , TOP , top_k_to_disp = 0 ) # we now compute eigen centrality creating a sparse network by only keeping the top 20 neighbors for each gene in the network TOP = 20 grnutils.get_centrality(grn, TOP, top_k_to_disp=0) grnutils.get_centrality(grn_c, TOP, top_k_to_disp=0) Top central genes: [] Top central genes: [] Out[3]: [] In [12]: Copied! grn_c . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn_c.var.centrality.sort_values(ascending=False).head(10) Out[12]: symbol HSPA1A 0.271584 MT2A 0.271584 CREM 0.271574 CD99 0.271517 NR4A3 0.271385 RBP1 0.271130 SOX4 0.264214 ATP6V0C 0.263235 HLA-A 0.232913 LUM 0.202007 Name: centrality, dtype: float64 In [9]: Copied! grn_c . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn_c.var.centrality.sort_values(ascending=False).head(10) Out[9]: symbol HSPA1A 0.271584 MT2A 0.271584 CREM 0.271574 CD99 0.271517 NR4A3 0.271385 RBP1 0.271130 SOX4 0.264214 ATP6V0C 0.263235 HLA-A 0.232913 LUM 0.202007 Name: centrality, dtype: float64 In [10]: Copied! grn . var . centrality . sort_values ( ascending = False ) . head ( 10 ) grn.var.centrality.sort_values(ascending=False).head(10) Out[10]: symbol MT2A 0.276470 SLC25A6 0.276183 CXCL8 0.275859 FTH1 0.275757 MIF 0.267968 DNAJB9 0.265635 SOX4 0.241950 RELB 0.234482 YBX3 0.216567 CST3 0.213585 Name: centrality, dtype: float64 In [13]: Copied! TOP = 10 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 10 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[13]: {'ATP6V0C', 'CD99', 'HLA-A', 'HSPA1A', 'LUM'} In [12]: Copied! TOP = 20 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 20 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[12]: {'ATP6V0C', 'CD99', 'EIF4A1', 'HLA-A', 'HSPA1A', 'LUM', 'PAGE4', 'RYR2', 'SERPINF1'} In [11]: Copied! TOP = 50 ( set ( grn_c . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index ) - set ( grn . var . centrality . sort_values ( ascending = False ) . head ( TOP ) . index )) & ( set ( grn_c . var . symbol ) & set ( grn . var . symbol )) TOP = 50 (set(grn_c.var.centrality.sort_values(ascending=False).head(TOP).index) - set(grn.var.centrality.sort_values(ascending=False).head(TOP).index)) & (set(grn_c.var.symbol) & set(grn.var.symbol)) Out[11]: {'C1R', 'CD99', 'COL6A2', 'HLA-A', 'HNRNPA0', 'HSPA1A', 'LUM', 'PAGE4', 'SERPINA3', 'SERPING1', 'SPOCK3', 'THBS1'} it seems the networks are even more similar when comparing them at the level of the centrality of their nodes. this means that some are highly central while maybe not","title":"1. Hub genes"},{"location":"notebooks/cancer_usecase_part2/#2-network-similarity","text":"We now look at the similarity of the two networks based on general overlap of their top K edges across their common nodes In [41]: Copied! grn . var . index = grn . var . ensembl_id grn_c . var . index = grn_c . var . ensembl_id overlap = list ( set ( grn . var . index ) & set ( grn_c . var . index )) grn.var.index = grn.var.ensembl_id grn_c.var.index = grn_c.var.ensembl_id overlap = list(set(grn.var.index) & set(grn_c.var.index)) In [43]: Copied! K = 20 subgrn_c = grn_c . get ( overlap ) . grn subgrn_c = subgrn_c . apply ( lambda row : row >= row . nlargest ( K ) . min (), axis = 1 ) subgrn = grn . get ( overlap ) . grn subgrn = subgrn . apply ( lambda row : row >= row . nlargest ( K ) . min (), axis = 1 ) ( subgrn & subgrn_c ) . sum ( 1 ) . mean () / K K = 20 subgrn_c = grn_c.get(overlap).grn subgrn_c = subgrn_c.apply(lambda row: row >= row.nlargest(K).min(), axis=1) subgrn = grn.get(overlap).grn subgrn = subgrn.apply(lambda row: row >= row.nlargest(K).min(), axis=1) (subgrn & subgrn_c).sum(1).mean() / K Out[43]: 0.5055735930735931 when looking at the top 20 connection for each genes in the network we see that on average only 50% of them agree between the two networks","title":"2. Network similarity"},{"location":"notebooks/cancer_usecase_part2/#3-network-communities","text":"Again looking at the top 20 connections for each gene in the network we use the leiden (or louvain) algorithm to find communities in both networks. We then study the hub of these communities as well as their enrichment using enrichr and ontology databases. We will only look at communities between 20 and 200 genes In [33]: Copied! TOP = 20 grnutils . get_centrality ( grn , TOP , top_k_to_disp = 0 ) grnutils . get_centrality ( grn_c , TOP , top_k_to_disp = 0 ) TOP = 20 grnutils.get_centrality(grn, TOP, top_k_to_disp=0) grnutils.get_centrality(grn_c, TOP, top_k_to_disp=0) Top central genes: [] Top central genes: [] Out[33]: [] In [17]: Copied! grn_c = grnutils . compute_cluster ( grn_c , 1.5 , use = \"leiden\" , n_iterations = 10 , max_comm_size = 100 ) grn_c = grnutils.compute_cluster(grn_c, 1.5, use=\"leiden\", n_iterations=10, max_comm_size=100) In [4]: Copied! grn = grnutils . compute_cluster ( grn , 1.5 ) grn_c = grnutils . compute_cluster ( grn_c , 1.5 ) grn = grnutils.compute_cluster(grn, 1.5) grn_c = grnutils.compute_cluster(grn_c, 1.5)","title":"3. Network communities"},{"location":"notebooks/cancer_usecase_part2/#31-cancer-version","text":"In [30]: Copied! # our communities grn . var [ 'cluster_1.5' ] . value_counts () . head ( 10 ) # our communities grn.var['cluster_1.5'].value_counts().head(10) Out[30]: cluster_1.5 0 1620 1 1483 2 732 3 111 4 23 5 9 6 4 16 1 23 1 22 1 Name: count, dtype: int64 In [31]: Copied! G = grn_c . plot_subgraph ( grn_c . var [ grn_c . var [ 'cluster_1.5' ] == '4' ] . index . tolist (), only = 200 , interactive = False ) # G = grn_c.plot_subgraph(grn_c.var[grn_c.var['cluster_1.5']=='4'].index.tolist(), only=200, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['PRDM6', 'MSANTD3', 'STAG3', 'TRHDE', 'TBX5', 'HEPH', 'GALNT16', 'NFATC4', 'SYNDIG1', 'HSF4', 'ZNF423', 'PLA2G4C', 'PLPPR2', 'SCN1B', 'ASPA', 'SNX15', 'BAG2', 'PTK7', 'HRH2', 'PLCL1', 'PTCH2', 'TGFB3', 'RASL11A', 'TOX2', 'CPNE5', 'GLIS2', 'HIVEP3', 'FGF13', 'ACAP3', 'DUSP26', 'CTIF', 'CAMK1', 'SLC9A5', 'FBN2', 'LRIG1', 'LIMD1', 'TRPC1', 'SLC2A13', 'ADAMTS12', 'FZD7', 'AFF2', 'CACNA1D', 'MRAS', 'ST6GALNAC6', 'FGFR4', 'PTGER1', 'PKDCC', 'SLC9B2', 'NPY1R', 'ANKRD33B', 'DCLK2', 'PURG', 'GXYLT2', 'LRRN4CL', 'CA8', 'EXOC3L1', 'BHLHE22', 'AATK', 'CMC4', 'BOLA2', 'CCR10', 'TCEAL2', 'SLC24A3', 'ROR1', 'SLC51B', 'EMID1', 'AGMO', 'CENPP', 'OPTC', 'SPOCK3', 'COL27A1', 'DACT3', 'STMN3', 'DLL1', 'SMOC1', 'COLGALT2', 'ZDBF2', 'DOK6', 'HNRNPUL2-BSCL2', 'C3orf84', 'C2orf74', 'ARHGEF25', 'NPIPB5', 'TNFSF12-TNFSF13', 'ZFP91-CNTF', 'nan-41', 'nan-81', 'nan-96', 'nan-98', 'HERC3', 'nan-116', 'nan-117'], dtype='object', name='symbol_2') In [26]: Copied! # if you want to draw better looking networks pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_4.html\" ) # if you want to draw better looking networks pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_4.html\") In [32]: Copied! # Assuming 'node_names' contains the list of gene names. # Note: it seems with enrichr, one can only use one gene set at a time, choose accordingly enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn_c . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names. # Note: it seems with enrichr, one can only use one gene set at a time, choose accordingly enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn_c.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:31:53,534 [WARNING] Input library not found: Reactome. Skip Out[32]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Solute:Potassium Antiporter Activity (GO:0022821) 0.000523 0.050652 0 0 inf inf SLC24A3;SLC9A5 1 GO_Molecular_Function_2023 Coreceptor Activity Involved In Wnt Signaling ... 0.001547 0.050652 0 0 86.822222 561.890021 PTK7;ROR1 2 GO_Molecular_Function_2023 Sodium Ion Transmembrane Transporter Activity ... 0.001547 0.050652 0 0 86.822222 561.890021 SLC9A5;SLC9B2 3 GO_Molecular_Function_2023 Calcium Ion Transmembrane Transporter Activity... 0.001700 0.050652 0 0 16.432584 104.795452 SLC24A3;TRPC1;CACNA1D 4 GO_Molecular_Function_2023 Calcium-Dependent Phospholipid Binding (GO:000... 0.003047 0.050652 0 0 43.400000 251.445478 CPNE5;PLA2G4C 5 GO_Molecular_Function_2023 Coreceptor Activity Involved In Wnt Signaling ... 0.003047 0.050652 0 0 43.400000 251.445478 PTK7;ROR1 6 GO_Molecular_Function_2023 Metal Cation:Proton Antiporter Activity (GO:00... 0.003047 0.050652 0 0 43.400000 251.445478 SLC9A5;SLC9B2 7 GO_Molecular_Function_2023 Sodium:Proton Antiporter Activity (GO:0015385) 0.003047 0.050652 0 0 43.400000 251.445478 SLC9A5;SLC9B2 8 GO_Molecular_Function_2023 Iron Ion Binding (GO:0005506) 0.005002 0.070586 0 0 28.925926 153.247105 HEPH;AGMO 9 GO_Molecular_Function_2023 Calcium Channel Activity (GO:0005262) 0.005307 0.070586 0 0 10.099395 52.907606 SLC24A3;TRPC1;CACNA1D 10 GO_Molecular_Function_2023 Wnt Receptor Activity (GO:0042813) 0.007391 0.089364 0 0 21.688889 106.438022 FZD7;ROR1 11 GO_Molecular_Function_2023 RNA Polymerase II-specific DNA-binding Transcr... 0.010110 0.104284 0 0 7.715135 35.445265 TBX5;DUSP26;DLL1 12 GO_Molecular_Function_2023 Phospholipase Activity (GO:0004620) 0.010193 0.104284 0 0 17.346667 79.552387 PLCL1;PLA2G4C 13 GO_Molecular_Function_2023 Monoatomic Cation Channel Activity (GO:0005261) 0.011601 0.110210 0 0 7.284644 32.465172 SLC24A3;TRPC1;CACNA1D 14 GO_Molecular_Function_2023 Sodium Channel Regulator Activity (GO:0017080) 0.013389 0.118714 0 0 14.451852 62.335739 FGF13;SCN1B 15 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.022992 0.139045 0 0 2.668376 10.066740 HSF4;HIVEP3;BHLHE22;TBX5;ZNF423;NFATC4;GLIS2 16 GO_Molecular_Function_2023 Calcium:Sodium Antiporter Activity (GO:0005432) 0.023000 0.139045 0 0 inf inf SLC24A3 17 GO_Molecular_Function_2023 Potassium:Proton Antiporter Activity (GO:0015386) 0.023000 0.139045 0 0 inf inf SLC9A5 18 GO_Molecular_Function_2023 Xylosyltransferase Activity (GO:0042285) 0.023000 0.139045 0 0 inf inf GXYLT2 19 GO_Molecular_Function_2023 Tat Protein Binding (GO:0030957) 0.023000 0.139045 0 0 inf inf DLL1 In [33]: Copied! # we make a plot of the enrichment enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) # we make a plot of the enrichment enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [34]: Copied! G = grn_c . plot_subgraph ( grn_c . var [ grn_c . var [ 'cluster_1.5' ] == '5' ] . index . tolist (), only = 80 , interactive = False ) # G = grn_c.plot_subgraph(grn_c.var[grn_c.var['cluster_1.5']=='5'].index.tolist(), only=80, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['ABCF2', 'ITIH4', 'OLFM2', 'ICAM4', 'RIGI', 'KAZALD1', 'BST1', 'PANX1', 'C9', 'FBXO2', 'ZNF410', 'ACVR1C', 'VAMP7', 'TOP2A', 'TAF4B', 'KIAA1755', 'EDA', 'YPEL4', 'ENTPD3', 'GP9', 'NLGN2', 'CLCF1', 'RPRM', 'ODF3B', 'MSC', 'NTF3', 'COL13A1', 'GP1BB', 'HSPA1A', 'TMEM158', 'nan-82', 'NBPF19', 'SCO2', 'SMIM41'], dtype='object', name='symbol_2') In [87]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_5.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_5.html\") In [44]: Copied! grn_c . var . loc [ 'nan-82' ] # par of the Glycoside Hydrolase Family grn_c.var.loc['nan-82'] # par of the Glycoside Hydrolase Family Out[44]: uid 4giyQrh7tkXI symbol nan-82 ncbi_gene_ids biotype protein_coding description novel protein synonyms organism_id 2 public_source_id 9.0 created_by_id 1 mt False ribo False hb False organism NCBITaxon:9606 TFs False ensembl_id ENSG00000269590 centrality 0.0 cluster_1.5 5 Name: nan-82, dtype: object In [35]: Copied! enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn_c . var . symbol . tolist (), ) enr . res2d . head ( 20 ) enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn_c.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:33:16,565 [WARNING] Input library not found: Reactome. Skip Out[35]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Death Receptor Binding (GO:0005123) 0.000416 0.028729 0 0 123.875000 964.236668 EDA;NTF3 1 GO_Molecular_Function_2023 Purine Ribonucleoside Triphosphate Binding (GO... 0.007050 0.073312 0 0 8.626100 42.739637 ABCF2;RIGI;HSPA1A 2 GO_Molecular_Function_2023 Receptor Ligand Activity (GO:0048018) 0.007732 0.073312 0 0 5.742222 27.920829 EDA;CLCF1;NTF3;HSPA1A 3 GO_Molecular_Function_2023 Activin Receptor Activity (GO:0017002) 0.008500 0.073312 0 0 inf inf ACVR1C 4 GO_Molecular_Function_2023 Gap Junction Hemi-Channel Activity (GO:0055077) 0.008500 0.073312 0 0 inf inf PANX1 5 GO_Molecular_Function_2023 NF-kappaB Binding (GO:0051059) 0.008500 0.073312 0 0 inf inf TAF4B 6 GO_Molecular_Function_2023 Hydrolase Activity, Hydrolyzing N-glycosyl Com... 0.008500 0.073312 0 0 inf inf BST1 7 GO_Molecular_Function_2023 Ubiquitin-Protein Transferase Activator Activi... 0.008500 0.073312 0 0 inf inf RIGI 8 GO_Molecular_Function_2023 DNA Binding, Bending (GO:0008301) 0.016930 0.083096 0 0 120.151515 490.060134 TOP2A 9 GO_Molecular_Function_2023 Disordered Domain Specific Binding (GO:0097718) 0.016930 0.083096 0 0 120.151515 490.060134 HSPA1A 10 GO_Molecular_Function_2023 UDP Phosphatase Activity (GO:0045134) 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 11 GO_Molecular_Function_2023 GDP Phosphatase Activity (GO:0004382) 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 12 GO_Molecular_Function_2023 Nucleoside Diphosphate Phosphatase Activity (G... 0.016930 0.083096 0 0 120.151515 490.060134 ENTPD3 13 GO_Molecular_Function_2023 ATP Binding (GO:0005524) 0.017220 0.083096 0 0 11.204545 45.509349 ABCF2;HSPA1A 14 GO_Molecular_Function_2023 Ubiquitin Protein Ligase Binding (GO:0031625) 0.020064 0.083096 0 0 10.265625 40.126707 RIGI;HSPA1A 15 GO_Molecular_Function_2023 Ubiquitin-Like Protein Ligase Binding (GO:0044... 0.021555 0.083096 0 0 9.852500 37.805688 RIGI;HSPA1A 16 GO_Molecular_Function_2023 Growth Factor Activity (GO:0008083) 0.023090 0.083096 0 0 9.471154 35.690549 CLCF1;NTF3 17 GO_Molecular_Function_2023 Adenyl Ribonucleotide Binding (GO:0032559) 0.024670 0.083096 0 0 9.118056 33.756535 ABCF2;HSPA1A 18 GO_Molecular_Function_2023 C3HC4-type RING Finger Domain Binding (GO:0055... 0.025290 0.083096 0 0 60.060606 220.863728 HSPA1A 19 GO_Molecular_Function_2023 Ubiquitin Binding (GO:0043130) 0.025290 0.083096 0 0 60.060606 220.863728 TOP2A In [36]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( similar story to cluster above. this time with PTN often found in the litterature with 6 other m Studies on the role of STEAP1, OR51E2, PTN, ABCC4, NDRG2 have been relatively in-depth. For instance, STEAP1 is all-called six-transmembrane epithelial antigen of the prostate 1, which belongs to a family of metalloproteinases involved in iron and copper homeostasis and other cellular processes has been listed with 8 other members as predictors of CAF-related gene prognostic index (CRGPI) in prostate cancer. https://www.nature.com/articles/s41598-023-36125-0#Sec11 (NDRG2, TSPAN1, PTN, APOE, OR51E2, P4HB, STEAP1 and ABCC4 were used to construct molecular subtypes and) https://www.genecards.org/cgi-bin/carddisp.pl?gene=GSN","title":"3.1 Cancer version"},{"location":"notebooks/cancer_usecase_part2/#32-normal-version","text":"In [9]: Copied! grn . var [ 'cluster_1.5' ] . value_counts () . head ( 10 ) grn.var['cluster_1.5'].value_counts().head(10) Out[9]: cluster_1.5 0 1620 1 1483 2 732 3 111 4 23 5 9 6 4 16 1 23 1 22 1 Name: count, dtype: int64 https://www.genecards.org/cgi-bin/carddisp.pl?gene=MYOC In [37]: Copied! G = grn . plot_subgraph ( grn . var [ grn . var [ 'cluster_1.5' ] == '3' ] . index . tolist (), only = 200 , interactive = False ) G = grn.plot_subgraph(grn.var[grn.var['cluster_1.5']=='3'].index.tolist(), only=200, interactive=False) ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['TMEM132A', 'ADGRA2', 'AGPAT4', 'THAP3', 'DNAJC25', 'TRAM2', 'NTN1', 'STAG3', 'COL4A4', 'HSD17B14', ... 'nan-75', 'TRABD2B', 'nan-77', 'PCGF2', 'nan-107', 'nan-182', 'nan-192', 'nan-195', 'nan-239', 'nan-259'], dtype='object', name='symbol_2', length=111) In [26]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_3.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_3.html\") In [27]: Copied! grn . var . loc [ 'nan-259' ] # par of the Glycoside Hydrolase Family grn.var.loc['nan-259'] # par of the Glycoside Hydrolase Family Out[27]: uid 62JAXxQNqtOd symbol nan-259 ncbi_gene_ids 83737 biotype protein_coding description novel protein synonyms organism_id 2 public_source_id 9.0 created_by_id 1 mt False ribo False hb False organism NCBITaxon:9606 TFs False ensembl_id ENSG00000289720 centrality 0.0 cluster_1.5 3 Name: nan-259, dtype: object In [12]: Copied! grn . get ( grn . var [ grn . var [ 'cluster_1.5' ] == '3' ] . index . tolist ()) . grn . sum ( 0 ) . sort_values ( ascending = False ) . head ( 3 ) ##.grn # selenom grn.get(grn.var[grn.var['cluster_1.5']=='3'].index.tolist()).grn.sum(0).sort_values(ascending=False).head(3)##.grn # selenom Out[12]: symbol RNASEK 0.942102 SELENOM 0.292933 nan-259 0.256140 dtype: float32 RNASEK acidifying the internal vesicle important in endocytosis# https://www.ncbi.nlm.nih.gov/pmc/articles/PMC10547866/ RNA phosphodiester bond hydrolysis --> hydrolisis pathway in the model and RNA transcription regulation In [38]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:33:49,291 [WARNING] Input library not found: Reactome. Skip /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/enrichr.py:643: FutureWarning: The behavior of DataFrame concatenation with empty or all-NA entries is deprecated. In a future version, this will no longer exclude empty or all-NA columns when determining the result dtypes. To retain the old behavior, exclude the relevant entries before the concat operation. self.results = pd.concat(self.results, ignore_index=True) Out[38]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Sulfotransferase Activity (GO:0008146) 0.007252 0.123369 0 0 20.138462 99.212171 CHST7;SULT1C4 1 GO_Molecular_Function_2023 RNA Polymerase II Transcription Regulatory Reg... 0.007713 0.123369 0 0 3.386005 16.472449 ZNF483;HAND2;NTN1;NFATC4;GLIS2;PURG;ZNF286A 2 GO_Molecular_Function_2023 ATPase Binding (GO:0051117) 0.013790 0.123369 0 0 13.415385 57.468682 SLC2A13;NKD2 3 GO_Molecular_Function_2023 Chondroitin Sulfotransferase Activity (GO:0034... 0.016750 0.123369 0 0 inf inf CHST7 4 GO_Molecular_Function_2023 Peptidyl-Proline 4-Dioxygenase Activity (GO:00... 0.016750 0.123369 0 0 inf inf P4HA3 5 GO_Molecular_Function_2023 Aryl Sulfotransferase Activity (GO:0004062) 0.016750 0.123369 0 0 inf inf SULT1C4 6 GO_Molecular_Function_2023 Histone Reader Activity (GO:0140566) 0.016750 0.123369 0 0 inf inf TONSL 7 GO_Molecular_Function_2023 Hydrolase Activity, Hydrolyzing N-glycosyl Com... 0.016750 0.123369 0 0 inf inf BST1 8 GO_Molecular_Function_2023 Tat Protein Binding (GO:0030957) 0.016750 0.123369 0 0 inf inf DLL1 9 GO_Molecular_Function_2023 WW Domain Binding (GO:0050699) 0.016750 0.123369 0 0 inf inf ENTREP3 10 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.016754 0.123369 0 0 3.180050 13.003634 ZNF483;HAND2;NTN1;NFATC4;GLIS2;ZNF286A 11 GO_Molecular_Function_2023 DNA-binding Transcription Activator Activity, ... 0.026719 0.134555 0 0 5.074219 18.380719 HAND2;INSL3;GLIS2 12 GO_Molecular_Function_2023 Procollagen-Proline Dioxygenase Activity (GO:0... 0.033223 0.134555 0 0 59.575758 202.825781 P4HA3 13 GO_Molecular_Function_2023 N-acetylglucosamine 6-O-sulfotransferase Activ... 0.033223 0.134555 0 0 59.575758 202.825781 CHST7 14 GO_Molecular_Function_2023 ABC-type Xenobiotic Transporter Activity (GO:0... 0.033223 0.134555 0 0 59.575758 202.825781 ABCC1 15 GO_Molecular_Function_2023 alpha-N-acetylgalactosaminide Alpha-2,6-Sialyl... 0.033223 0.134555 0 0 59.575758 202.825781 ST6GALNAC6 16 GO_Molecular_Function_2023 miRNA Binding (GO:0035198) 0.033223 0.134555 0 0 59.575758 202.825781 DND1 17 GO_Molecular_Function_2023 Myosin Heavy Chain Binding (GO:0032036) 0.033223 0.134555 0 0 59.575758 202.825781 NKD2 18 GO_Molecular_Function_2023 Estradiol 17-Beta-Dehydrogenase [NAD(P)] Activ... 0.033223 0.134555 0 0 59.575758 202.825781 HSD17B14 19 GO_Molecular_Function_2023 Solute:Proton Symporter Activity (GO:0015295) 0.033223 0.134555 0 0 59.575758 202.825781 SLC2A13 In [39]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( https://www.genecards.org/cgi-bin/carddisp.pl?gene=PTN In [40]: Copied! G = grn . plot_subgraph ( grn . var [ grn . var [ 'cluster_1.5' ] == '4' ] . index . tolist (), only = 80 , interactive = False ) # G = grn.plot_subgraph(grn.var[grn.var['cluster_1.5']=='4'].index.tolist(), only=80, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4'] Index(['TRHDE', 'PGR', 'ESR1', 'RASD2', 'SYNDIG1', 'OLFM2', 'FZD10', 'BHMT2', 'DUSP26', 'FOXF2', 'ADAM33', 'ADAMTS12', 'HS3ST3A1', 'CHODL', 'FTCD', 'FNDC1', 'HSPB3', 'FOXL1', 'AGMO', 'ADAMTSL2', 'S100A6', 'AKR1B10', 'SCGB1C2'], dtype='object', name='symbol_2') In [29]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) #first_node = list(G.nodes)[-1] #pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_4.html\") In [41]: Copied! enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'GO_Molecular_Function_2023' , 'MSigDB_Hallmark_2020' , 'Reactome_2022' , 'Tabula_Sapiens' , 'WikiPathway_2023_Human' , 'TF_Perturbations_Followed_by_Expression' , 'Reactome' , 'PPI_Hub_Proteins' , 'OMIM_Disease' , 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['GO_Molecular_Function_2023', 'MSigDB_Hallmark_2020', 'Reactome_2022', 'Tabula_Sapiens', 'WikiPathway_2023_Human', 'TF_Perturbations_Followed_by_Expression', 'Reactome', 'PPI_Hub_Proteins', 'OMIM_Disease', 'GO_Molecular_Function_2023'], organism='Human', # change accordingly #description='pathway', #cutoff=0.08, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) 2024-07-25 18:34:27,578 [WARNING] Input library not found: Reactome. Skip Out[41]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 RNA Polymerase II General Transcription Initia... 0.000032 0.000933 0 0 inf inf FOXF2;ESR1 1 GO_Molecular_Function_2023 Estrogen Response Element Binding (GO:0034056) 0.000032 0.000933 0 0 inf inf PGR;ESR1 2 GO_Molecular_Function_2023 General Transcription Initiation Factor Bindin... 0.000095 0.001860 0 0 378.666667 3508.819727 FOXF2;ESR1 3 GO_Molecular_Function_2023 Transcription Coactivator Binding (GO:0001223) 0.000188 0.002780 0 0 189.285714 1623.428489 PGR;ESR1 4 GO_Molecular_Function_2023 Transition Metal Ion Binding (GO:0046914) 0.000446 0.005263 0 0 13.515099 104.272240 BHMT2;AGMO;ADAM33;TRHDE 5 GO_Molecular_Function_2023 Metalloendopeptidase Activity (GO:0004222) 0.000551 0.005414 0 0 22.794231 171.058857 ADAMTSL2;ADAM33;ADAMTS12 6 GO_Molecular_Function_2023 Metallopeptidase Activity (GO:0008237) 0.000672 0.005666 0 0 21.155357 154.536591 ADAMTSL2;ADAM33;ADAMTS12 7 GO_Molecular_Function_2023 Transcription Coregulator Binding (GO:0001221) 0.001111 0.008195 0 0 54.013605 367.419603 PGR;ESR1 8 GO_Molecular_Function_2023 DNA-binding Transcription Activator Activity, ... 0.001429 0.009365 0 0 15.972973 104.640056 FOXF2;PGR;ESR1 9 GO_Molecular_Function_2023 ATPase Binding (GO:0051117) 0.002016 0.011893 0 0 37.780952 234.495632 PGR;ESR1 10 GO_Molecular_Function_2023 Zinc Ion Binding (GO:0008270) 0.002284 0.012250 0 0 13.407955 81.545835 BHMT2;ADAM33;TRHDE 11 GO_Molecular_Function_2023 Cis-Regulatory Region Sequence-Specific DNA Bi... 0.004517 0.021203 0 0 6.945569 37.504924 FOXF2;PGR;FOXL1;ESR1 12 GO_Molecular_Function_2023 RNA Polymerase II Cis-Regulatory Region Sequen... 0.005523 0.021203 0 0 6.541596 34.009122 FOXF2;PGR;FOXL1;ESR1 13 GO_Molecular_Function_2023 DNA Binding, Bending (GO:0008301) 0.005750 0.021203 0 0 inf inf FOXL1 14 GO_Molecular_Function_2023 TBP-class Protein Binding (GO:0017025) 0.005750 0.021203 0 0 inf inf ESR1 15 GO_Molecular_Function_2023 [Heparan Sulfate]-Glucosamine 3-Sulfotransfera... 0.005750 0.021203 0 0 inf inf HS3ST3A1 16 GO_Molecular_Function_2023 RNA Polymerase II Transcription Regulatory Reg... 0.008164 0.028333 0 0 5.812950 27.949028 FOXF2;PGR;FOXL1;ESR1 17 GO_Molecular_Function_2023 Endopeptidase Activity (GO:0004175) 0.008882 0.028593 0 0 8.021918 37.893119 ADAMTSL2;ADAM33;ADAMTS12 18 GO_Molecular_Function_2023 DNA Binding (GO:0003677) 0.009208 0.028593 0 0 7.911486 37.086673 FOXF2;PGR;FOXL1 19 GO_Molecular_Function_2023 Heparan Sulfate Sulfotransferase Activity (GO:... 0.011468 0.030756 0 0 180.727273 807.520606 HS3ST3A1 In [42]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( ',' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , #title='normal fibro PAGE4', cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split(',').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", #title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace(","title":"3.2 Normal version"},{"location":"notebooks/cancer_usecase_part2/#4-differential-gene-gene-connections","text":"look at the connections of some key TFs in here do GSEA over these connections compare the connections of these same TFs for both conditions In [5]: Copied! G = grn_c . plot_subgraph ( \"PAGE4\" , only = 100 , max_genes = 40 , interactive = False ) # G = grn_c.plot_subgraph(\"PAGE4\", only=100, max_genes=40, interactive=False)# ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#ff7f0e'] Index(['MT2A', 'HSPA1A', 'CREM', 'PTN', 'HLA-A', 'SPARCL1', 'SPOCK3', 'NR4A3', 'APOD', 'CALD1', 'MGP', 'HSPE1', 'EIF4A1', 'CD99', 'EMP1', 'FABP4', 'NAMPT', 'NNMT', 'RBP1', 'LUM', 'IGFBP7', 'THBS1', 'YBX3', 'NAF1', 'DCN', 'A2M', 'CPE', 'C1R', 'ATP6V0C', 'MATN2', 'COL6A2', 'UBE2S', 'CST3', 'RHOQ', 'UBE2C', 'C1S', 'H2AZ1', 'GPRC5A', 'HLA-C', 'LGALS1', 'PAGE4'], dtype='object', name='symbol_2') In [96]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) first_node = list ( G . nodes )[ - 1 ] pnet . get_node ( first_node )[ 'color' ] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_c_PAGE4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) first_node = list(G.nodes)[-1] pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_c_PAGE4.html\") In [22]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ #'KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', 'WikiPathway_2023_Human' , #'TF_Perturbations_Followed_by_Expression', #'PPI_Hub_Proteins', #'OMIM_Disease', #'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 10 ) enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] . str . split ( 'R-HSA' ) . str [ 0 ] . str . split ( ' WP' ) . str [ 0 ] . str [: 50 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size top_term = 20 , figsize = ( 4 , 10 ), cutoff = 0.25 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=[ #'KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', 'WikiPathway_2023_Human', #'TF_Perturbations_Followed_by_Expression', #'PPI_Hub_Proteins', #'OMIM_Disease', #'GO_Molecular_Function_2023' ], organism='Human', # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(10) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0].str.split('R-HSA').str[0].str.split(' WP').str[0].str[:50] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size top_term=20, figsize=(4,10), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [139]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size figsize = ( 4 , 5 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size figsize=(4,5), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace( In [17]: Copied! G = grn . plot_subgraph ( \"PAGE4\" , only = 100 , max_genes = 40 , interactive = False ) G = grn.plot_subgraph(\"PAGE4\", only=100, max_genes=40, interactive=False) ['#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#1f77b4', '#ff7f0e'] Index(['nan-270', 'S100A6', 'MT2A', 'SPARCL1', 'MIF', 'SLC25A6', 'IGFBP7', 'APOD', 'MGP', 'DCN', 'A2M', 'PTN', 'RELB', 'DNAJB9', 'AKR1C1', 'C1S', 'CST3', 'CXCL8', 'FTH1', 'BRME1', 'FAM205A', 'TIMP1', 'YBX3', 'NPPB', 'TGIF2-RAB5IF', 'FBLN1', 'MTDH', 'IGFBP5', 'TFPI', 'MAP1B', 'COL6A2', 'HNRNPA0', 'EIF4A1', 'CCL21', 'FTL', 'CETN1', 'NME2', 'LSAMP', 'ACR', 'ATP6V0C', 'PAGE4'], dtype='object', name='symbol_2') In [98]: Copied! pnet = pnx . Network ( notebook = True , cdn_resources = \"remote\" , directed = True ) pnet . from_nx ( G ) first_node = list ( G . nodes )[ - 1 ] pnet . get_node ( first_node )[ 'color' ] = \"red\" pnet . save_graph ( \"../figures/pyvis/grn_PAGE4.html\" ) pnet = pnx.Network(notebook=True, cdn_resources=\"remote\", directed=True) pnet.from_nx(G) first_node = list(G.nodes)[-1] pnet.get_node(first_node)['color'] = \"red\" pnet.save_graph(\"../figures/pyvis/grn_PAGE4.html\") In [24]: Copied! # Assuming 'node_names' contains the list of gene names enr = gp . enrichr ( gene_list = list ( G . nodes ), gene_sets = [ 'KEGG_2021_Human' , #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', #'WikiPathway_2023_Human', # 'TF_Perturbations_Followed_by_Expression', # 'Reactome', #'PPI_Hub_Proteins', #'OMIM_Disease', 'GO_Molecular_Function_2023' ], organism = 'Human' , # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background = grn . var . symbol . tolist (), ) enr . res2d . head ( 20 ) # Assuming 'node_names' contains the list of gene names enr = gp.enrichr(gene_list=list(G.nodes), gene_sets=['KEGG_2021_Human', #'MSigDB_Hallmark_2020', #'Reactome_2022', #'Tabula_Sapiens', #'WikiPathway_2023_Human', # 'TF_Perturbations_Followed_by_Expression', # 'Reactome', #'PPI_Hub_Proteins', #'OMIM_Disease', 'GO_Molecular_Function_2023' ], organism='Human', # change accordingly #description='pathway', # cutoff=0.02, # test dataset, use lower value for real case background=grn.var.symbol.tolist(), ) enr.res2d.head(20) Out[24]: .dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; } Gene_set Term P-value Adjusted P-value Old P-value Old adjusted P-value Odds Ratio Combined Score Genes 0 GO_Molecular_Function_2023 Peptidase Inhibitor Activity (GO:0030414) 0.000020 0.001566 0 0 104.105263 1128.623016 CST3;TIMP1;TFPI 1 GO_Molecular_Function_2023 Transition Metal Ion Binding (GO:0046914) 0.000463 0.016191 0 0 9.025463 69.301557 ACR;MT2A;FTH1;TIMP1;FTL 2 GO_Molecular_Function_2023 Double-Stranded RNA Binding (GO:0003725) 0.000607 0.016191 0 0 101.461538 751.496153 EIF4A1;MTDH 3 GO_Molecular_Function_2023 Endopeptidase Inhibitor Activity (GO:0004866) 0.001010 0.019977 0 0 18.306502 126.278211 CST3;TIMP1;TFPI 4 GO_Molecular_Function_2023 Endopeptidase Regulator Activity (GO:0061135) 0.001498 0.019977 0 0 50.705128 329.757829 CST3;TFPI 5 GO_Molecular_Function_2023 Ferrous Iron Binding (GO:0008198) 0.001498 0.019977 0 0 50.705128 329.757829 FTH1;FTL 6 GO_Molecular_Function_2023 Protease Binding (GO:0002020) 0.002465 0.027606 0 0 12.944079 77.736001 CST3;ACR;TIMP1 7 GO_Molecular_Function_2023 Iron Ion Binding (GO:0005506) 0.002761 0.027606 0 0 33.786325 199.079000 FTH1;FTL 8 GO_Molecular_Function_2023 Calcium Ion Binding (GO:0005509) 0.003252 0.028910 0 0 7.400664 42.393777 CETN1;S100A6;SPARCL1;FBLN1 9 GO_Molecular_Function_2023 Kinase Binding (GO:0019900) 0.005211 0.038377 0 0 9.688322 50.930509 PTN;RELB;HNRNPA0 10 GO_Molecular_Function_2023 RNA Binding (GO:0003723) 0.005277 0.038377 0 0 5.000000 26.222182 EIF4A1;YBX3;DCN;MTDH;HNRNPA0 11 GO_Molecular_Function_2023 Chemokine Activity (GO:0008009) 0.007445 0.039047 0 0 18.405594 90.191859 CXCL8;CCL21 12 GO_Molecular_Function_2023 Chemokine Receptor Binding (GO:0042379) 0.007445 0.039047 0 0 18.405594 90.191859 CXCL8;CCL21 13 GO_Molecular_Function_2023 Metal Ion Binding (GO:0046872) 0.008569 0.039047 0 0 5.523471 26.289761 CETN1;S100A6;SPARCL1;FBLN1 14 GO_Molecular_Function_2023 Protein Kinase Binding (GO:0019901) 0.009285 0.039047 0 0 7.734868 36.193807 PTN;RELB;HNRNPA0 15 GO_Molecular_Function_2023 mRNA 3'-UTR Binding (GO:0003730) 0.009893 0.039047 0 0 15.566075 71.852090 YBX3;HNRNPA0 16 GO_Molecular_Function_2023 NF-kappaB Binding (GO:0051059) 0.010250 0.039047 0 0 inf inf MTDH 17 GO_Molecular_Function_2023 Phosphatase Inhibitor Activity (GO:0019212) 0.010250 0.039047 0 0 inf inf PTN 18 GO_Molecular_Function_2023 Phosphotransferase Activity, Phosphate Group A... 0.010250 0.039047 0 0 inf inf NME2 19 GO_Molecular_Function_2023 Nucleobase-Containing Compound Kinase Activity... 0.010250 0.039047 0 0 inf inf NME2 In [30]: Copied! enr . res2d . Term = enr . res2d . Term . str . split ( \"(\" ) . str [ 0 ] ax = dotplot ( enr . res2d . replace ([ np . inf , - np . inf ], 0 ) . dropna (), column = \"Adjusted P-value\" , title = 'normal fibro PAGE4' , cmap = plt . cm . viridis , size = 4 , # adjust dot size figsize = ( 4 , 5 ), cutoff = 0.25 ) enr.res2d.Term = enr.res2d.Term.str.split(\"(\").str[0] ax = dotplot(enr.res2d.replace([np.inf, -np.inf], 0).dropna(), column=\"Adjusted P-value\", title='normal fibro PAGE4', cmap=plt.cm.viridis, size=4, # adjust dot size figsize=(4,5), cutoff=0.25) /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: The 'method' keyword in Series.replace is deprecated and will be removed in a future version. df[self.colname].replace( /home/ml4ig1/miniconda3/envs/scprint/lib/python3.10/site-packages/gseapy/plot.py:689: FutureWarning: A value is trying to be set on a copy of a DataFrame or Series through chained assignment using an inplace method. The behavior will change in pandas 3.0. This inplace method will never work because the intermediate object on which we are setting values always behaves as a copy. For example, when doing 'df[col].method(value, inplace=True)', try using 'df.method({col: value}, inplace=True)' or df[col] = df[col].method(value) instead, to perform the operation inplace on the original object. df[self.colname].replace(","title":"4. Differential Gene - Gene connections"},{"location":"notebooks/cancer_usecase_part2/#5-using-classification","text":"Here we used the network given by the mean of all heads in our scPRINT model. We could also use other scPRINT versions to see if the results are consistent. but we could also use the classification mechanism presented in our manuscript and other notebooks to get to possibly more specialized networks. In [ ]: Copied! grn_normal = grn_inferer ( layer = list ( range ( model . nlayers ))[:], cell_type = \"naive B cell\" ) grn_normal , m , omni_cls = train_classifier ( grn_normal , C = 0.5 , train_size = 0.9 , class_weight = { 1 : 200 , 0 : 1 }, shuffle = True ) grn_normal = grn_inferer(layer=list(range(model.nlayers))[:], cell_type=\"naive B cell\") grn_normal, m, omni_cls = train_classifier(grn_normal, C=0.5, train_size=0.9, class_weight={ 1: 200, 0: 1}, shuffle=True) number of expressed genes in this cell type: 16801 LOCAL_RANK: 0 - CUDA_VISIBLE_DEVICES: [0] Predicting: 0it [00:00, ?it/s] true elem 2115 ... doing regression.... metrics {'used_heads': 25, 'precision': 0.0, 'random_precision': 0.0006433550820644942, 'recall': 0.0, 'predicted_true': 177.0, 'number_of_true': 219.0, 'epr': 0.0} In [ ]: Copied! # highlight differential links on genes that are expressed in both grn_normal . varp [ 'all' ] = grn_normal . varp [ 'GRN' ] . copy () grn_normal . varp [ 'GRN' ] = grn_normal . varp [ 'classified' ] # highlight differential links on genes that are expressed in both grn_normal.varp['all'] = grn_normal.varp['GRN'].copy() grn_normal.varp['GRN'] = grn_normal.varp['classified']","title":"5. Using classification"},{"location":"notebooks/cancer_usecase_part2/#notes-on-findings-and-their-relation-to-the-literature","text":"CAV1-expressing CAFs contribute to invasion and metastasis in breast cancer24 loss of caveolin1 (CAV1) is found in metabolically reprogrammed CAFs that promote tumorigenesis discoidin domain-containing receptor 2 (DDR2)21 and integrin \u03b111\u03b2122, have emerged to identify CAFs in the context of a specific TME https://www.nature.com/articles/s12276-023-01013-0 normal fibroblast populations marked by the expression of Gli1 and Hoxb6 CAFs, remain perpetually activated with a high capacity for ECM synthesis and microenvironmental remodeling, leading to stromal desmoplasia, a phenomenon characterized by increased deposition of ECM components in tumors. In this regard, CAFs share many basic characteristics, such as a secretory phenotype and capacity to synthesize ECM components, with fibroblasts found in nonmalignant tissue fibrosis. Therefore, the classic markers found to be expressed in fibroblasts, including \u03b1-SMA, vimentin, desmin, fibroblast-specific protein 1 (FSP1; also known as S100A4) Fibrogenesis is part of a normal protective response to tissue injury that can become irreversible and progressive, leading to fatal diseases. Senescent cells are a main driver of fibrotic diseases through their secretome, known as senescence-associated secretory phenotype (SASP) CAFs (vCAFs), cycling CAFs (cCAFs), and developmental CAFs (dCAFs) The stem-like \u2018universal\u2019 type of fibroblast cell, marked by expression of peptidase inhibitor 16 (Pi16) and Col15a, found in the steady state across tissues, activated fibroblasts, as observed by the development of LRRC15+ CAFs in PDAC. . SOCS1: Suppressor of cytokine signaling; STAT3: Signal transducer and activator of transcription 3; LDH: Lactate dehydrogenase; PYCR1: pyrroline-5-carboxylate reductase senescence, and multiple types of fibrotic diseases in mice and humans are characterized by the accumulation of iron. https://www.nature.com/articles/s42255-023-00928-2 Current evidence indicate that cancer-associated fibroblasts (CAFs) play an important role in prostate cancer (PCa) development and progression. playing a role in invasion. NDRG2, TSPAN1, PTN, APOE, OR51E2, P4HB, STEAP1 and ABCC4 were used to construct molecular subtypes and CAF-related gene prognostic index (CRGPI) Studies on the role of STEAP1, OR51E2, PTN, ABCC4, NDRG2 have been relatively in-depth. For instance, STEAP1 is all-called six-transmembrane epithelial antigen of the prostate 1, which belongs to a family of metalloproteinases involved in iron and copper homeostasis and other cellular processes37. STEAP1 is overexpressed on the plasma membrane of PCa cells and is associated with PCa invasiveness and metastasis50. The possible mechanism of STEAP1 promoting tumor proliferation and metastasis is by acting as a channel for small molecules that are involved in intercellular communication OR51E2 perhaps could be used as one of the biomarkers for PCa53,54,55,56 https://www.nature.com/articles/s41598-023-36125-0#Sec11 The protein encoded by ABCC4 is a member of the superfamily of ATP-binding cassette (ABC) transporters, which is also called multidrug resistance protein 4 (MRP4)64. MRP4 was reported to be associated with drug resistance of PCa in many studies65,66,67 PRRX1, OSR1, FOXD1, HOXC4,LHX9, TBX3 and TWIST2, targeted five or more TFs inthe fibroblast TRN. This influential-set explained 62.5% ofthe total number of regulatory edges and they collectivelytargeted 15 out of 18 TFs represented in the network. Upona closer examination of the fibroblastic network, the inter-actions among OSR1\u2013PRRX1\u2013TWIST2 were notably co-ordinated, regulating one another in both directions https://www.researchgate.net/publication/264633205_A_transient_disruption_of_fibroblastic_transcriptional_regulatory_network_facilitates_trans-differentiation FGF receptors are important in PCa initiation and progression. These endocrine FGFs require alpha-Klotho (KL) and/or beta-Klotho (KLB), two related single-pass transmembrane proteins restricted in their tissue distribution. FGF19 is expressed in primary and metastatic PCa tissues where it functions as an autocrine growth factor. https://www.e-cancer.fr/Professionnels-de-sante/Veille-bibliographique/Nota-Bene-Cancer/NBC-174/The-endocrine-fibroblast-growth-factor-FGF19-promotes-prostate-cancer-progression \u2022 Prostate cancer stroma contains diverse populations of fibroblasts. \u2022 Carcinoma associated fibroblasts can promote prostate carcinogenesis. \u2022 Interaction among fibroblast subsets modulate stromal-epithelial paracrine signaling. The stroma in the normal prostate is predominantly composed of smooth muscle cells while in cancer this is partially replaced by fibroblasts and myofibroblasts6. These fibroblastic cells are responsible for collagen and extracellular matrix (ECM) deposition, changing local organ stiffness iCAF, myCAF, apCAF It has been shown that SDF-1/CXCL12, secreted by CAF, acts via TGF\u03b2\u2013mediated upregulation of CXCR4 in epithelial cells to activate Akt signaling associated with tumorigenesis. Overexpression of SDF-1/CXCL12 and TGF\u03b21 in benign human prostate fibroblasts has been shown to induce malignant transformation of benign prostate epithelial cells and formation of highly invasive tumors in vivo increased cadherin 2 (CDH2) mRNA expression in LNCaP cells Upregulation of DNA methyltransferases (DNMT) consistent with aberrant promoter hypermethylation of tumor-suppressor genes in multiple cancer types including PCa has been reported https://www.ncbi.nlm.nih.gov/pmc/articles/PMC8788937/#:~:text=The%20stroma%20in%20the%20normal,deposition%2C%20changing%20local%20organ%20stiffness . CD10 and GPR77 can define a human CAF subset that sustains cancer stemness Fibroblasts are also fundamental for inducing angiogenesis by secreting angiogenic factors such as vascular endothelial growth factor (VEGF) and matrix proteins Epithelial cells release TGF\u03b2 ligands, Kallikrein-related peptidase-4 (KLK4), CAFs are characterized by molecular markers that are upregulated compared to normal fibroblasts, such as fibroblast activation protein (FAP), PDGFR-\u03b2, fibroblast-specific protein-1 (FSP-1) (also known as S100A4) ACTA2 \u03b1-smooth actin (\u03b1-SMA) Upregulated RT-qPCR, IHC on tissue microarrays [42,43] ASPN Asporin Upregulated Tag-based RNA profiling, microarray profiling, IHC, RT-qPCR [38,44,45] CAV1 Caveolin-1 Downregulated Tag profiling, IHC, RT-qPCR [38] COL1A1 Collagen Type-I Upregulated RT-qPCR, IHC [42,43] CXCL12 Stromal cell-derived factor 1 (SDF1)/ (C-X-C motif chemokine ligand 12 (CXCL12) Upregulated Tag-profiling, RT-qPCR, ELISA [38,46] FAP Fibroblast activation protein Upregulated IHC [42] FGF2, FGF7, FGF10 Fibroblast growth factor-2/-7/-10 Upregulated RT-qPCR, Western Blot, IHC [43,47,48] FN1 Fibronectin Upregulated Tag profiling, IHC, RT-qPCR [38] ITGA1 Integrin-\u03b11 (CD49a) Upregulated IHC [49] OGN Osteoglycin Upregulated Tag-profiling, IHC, RT-qPCR [38] PDGFRB Platelet-derived growth factor receptor \u03b2 Upregulated Microarray profiling [44,50] POSTN Periostin Upregulated Microarray profiling, IHC [44] S100A4 Fibroblast-specific protein 1 (FSP1)/S100 Calcium Binding Protein A4 (S100A4) Upregulated Immunofluorescence, RT-qPCR, Western Blot [51,52,53] S100A6 S100 Calcium Binding Protein A6 Downregulated Tag profiling, IHC, RT-qPCR [38] SPARC Secreted Protein Acidic and Cysteine Rich Up/downregulated Microarray profiling, Tag-profiling [38,44] STC1 Stanniocalcin 1 Downregulated Tag profiling, IHC, RT-qPCR [38] THY1 Cluster of differentiation 90 (CD90) antigen Upregulated IHC [54] TNC Tenascin C Upregulated RT-qPCR, IHC [42,43] VIM Vimentin Upregulated IHC Benign prostatic hyperplasia (BPH) is a non-malignant growth of the prostate, typically occurring in older men with an occurrence of 80\u201390% of men in their 70s BPH develops in the transition zone differently from PCa foci, which usually develop in the peripheral zone ESR1= . Here we studied the role of CAF estrogen receptor alpha (ER\u03b1) and found that it could protect against PCa invasion. ER\u03b1 could function through a CAF\u2013epithelial interaction via selectively upregulating thrombospondin 2 (Thbs2) and downregulating matrix metalloproteinase 3 (MMP3) at the protein and messenger RNA levels https://academic.oup.com/carcin/article/35/6/1301/449417 ACTA2: we found that \u201creactive CAFs\u201d induce shear resistance to prostate tumor cells via intercellular contact and soluble derived factors. The reactive CAFs showed higher expression of \u03b1-smooth muscle actin (\u03b1-SMA) and fibroblast activation protein (FAP) compared to differentiated CAFs https://www.oncotarget.com/article/27510/ Proteins that exhibited a significant increase in CAF versus NPF were enriched for the functional categories \u201ccell adhesion\u201d and the \u201cextracellular matrix.\u201d The CAF phosphoproteome exhibited enhanced phosphorylation of proteins associated with the \u201cspliceosome\u201d and \u201cactin binding.\u201d COL1A1/2 and COL5A1; the receptor tyrosine kinase discoidin domain-containing receptor 2 (DDR2), a receptor for fibrillar collagens; and lysyl oxidase-like 2 (LOXL2) https://www.mcponline.org/article/S1535-9476(20)31548-6/fulltext \u2022Cancer-associated fibroblasts (CAFs) exhibit a highly aligned cytoskeleton and extracellular matrix. \u2022CAFs are stiffer than normal fibroblasts from the prostate. \u2022Benign prostate epithelial cells are more compliant after co-culture with CAFs. \u2022Benign epithelial cells are more invasive and proliferative in presence of CAFs. https://www.sciencedirect.com/science/article/pii/S2590006420300338 These findings suggest that CAFs exosomes drive PCa metastasis via the miR-500a-3p/FBXW7/HSF1 axis in a hypoxic microenvironmen https://www.nature.com/articles/s41417-024-00742-2 https://www.genecards.org/cgi-bin/carddisp.pl?gene=CCT8L2 CCT8L2 (Chaperonin Containing TCP1 Subunit 8 Like 2) is a Protein Coding gene. Gene Ontology (GO) annotations related to this gene include calcium-activated potassium channel activity and monoatomic anion channel activity. An important paralog of this gene is CCT8. related to the meta transmembrane activity via Possible molecular chaperone; assists the folding of proteins upon ATP hydrolysis. The TRiC complex mediates the folding of WRAP53/TCAB1, thereby regulating telomere maintenance (PubMed:25467444). As part of the TRiC complex may play a role in the assembly of BBSome, a complex involved in ciliogenesis regulating transports vesicles to the cilia https://www.genecards.org/cgi-bin/carddisp.pl?gene=TIMP1 TIMP Metallopeptidase Inhibitor 1 inhibitors of the matrix metalloproteinases (MMPs), a group of peptidases involved in degradation of the extracellular matrix. In addition to its inhibitory role against most of the known MMPs, the encoded protein is able to promote cell proliferation connected to TLL2: zinc-dependent metalloprotease part of the metzincin protein complex which also is Among its related pathways are Collagen chain trimerization and Extracellular matrix organization. PDXP, SEPTIN5 cytoskeletal organization and regulation PRAME inhibits the signaling of retinoic acid and mediates the regulation of selenoproteins many genes involved in cancer. indeed, it is known that 80% adult male above 70 years old will have such hyperplastic prostate. This is due to scenesence. and that Iron accumulation drives fibrosis, senescence and the senescence-associated secretory phenotype. (of which we have some proteins present here.) A mechanism that this clustered is one of genes that strongly regulates each other in this fibroblasts from pre-cancerous lesions via fibrotic iron accumulation and a secretory mechanism GJC1 (exchange of things between cells (here likely metals?)) Unknown genes like SMIM40. integral membrane protein could be linked to this phenotype ['pre { line-height: 125%; }\\ntd.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\nspan.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }\\ntd.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\nspan.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }\\n.highlight-ipynb .hll { background-color: var(--jp-cell-editor-active-background) }\\n.highlight-ipynb { background: var(--jp-cell-editor-background); color: var(--jp-mirror-editor-variable-color) }\\n.highlight-ipynb .c { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment */\\n.highlight-ipynb .err { color: var(--jp-mirror-editor-error-color) } /* Error */\\n.highlight-ipynb .k { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword */\\n.highlight-ipynb .o { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator */\\n.highlight-ipynb .p { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation */\\n.highlight-ipynb .ch { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Hashbang */\\n.highlight-ipynb .cm { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Multiline */\\n.highlight-ipynb .cp { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Preproc */\\n.highlight-ipynb .cpf { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.PreprocFile */\\n.highlight-ipynb .c1 { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Single */\\n.highlight-ipynb .cs { color: var(--jp-mirror-editor-comment-color); font-style: italic } /* Comment.Special */\\n.highlight-ipynb .kc { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Constant */\\n.highlight-ipynb .kd { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Declaration */\\n.highlight-ipynb .kn { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Namespace */\\n.highlight-ipynb .kp { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Pseudo */\\n.highlight-ipynb .kr { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Reserved */\\n.highlight-ipynb .kt { color: var(--jp-mirror-editor-keyword-color); font-weight: bold } /* Keyword.Type */\\n.highlight-ipynb .m { color: var(--jp-mirror-editor-number-color) } /* Literal.Number */\\n.highlight-ipynb .s { color: var(--jp-mirror-editor-string-color) } /* Literal.String */\\n.highlight-ipynb .ow { color: var(--jp-mirror-editor-operator-color); font-weight: bold } /* Operator.Word */\\n.highlight-ipynb .pm { color: var(--jp-mirror-editor-punctuation-color) } /* Punctuation.Marker */\\n.highlight-ipynb .w { color: var(--jp-mirror-editor-variable-color) } /* Text.Whitespace */\\n.highlight-ipynb .mb { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Bin */\\n.highlight-ipynb .mf { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Float */\\n.highlight-ipynb .mh { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Hex */\\n.highlight-ipynb .mi { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer */\\n.highlight-ipynb .mo { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Oct */\\n.highlight-ipynb .sa { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Affix */\\n.highlight-ipynb .sb { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Backtick */\\n.highlight-ipynb .sc { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Char */\\n.highlight-ipynb .dl { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Delimiter */\\n.highlight-ipynb .sd { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Doc */\\n.highlight-ipynb .s2 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Double */\\n.highlight-ipynb .se { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Escape */\\n.highlight-ipynb .sh { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Heredoc */\\n.highlight-ipynb .si { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Interpol */\\n.highlight-ipynb .sx { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Other */\\n.highlight-ipynb .sr { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Regex */\\n.highlight-ipynb .s1 { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Single */\\n.highlight-ipynb .ss { color: var(--jp-mirror-editor-string-color) } /* Literal.String.Symbol */\\n.highlight-ipynb .il { color: var(--jp-mirror-editor-number-color) } /* Literal.Number.Integer.Long */']","title":"Notes on findings and their relation to the literature"}]} \ No newline at end of file diff --git a/sitemap.xml b/sitemap.xml index 6307dfc..944ee9e 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -2,57 +2,57 @@ https://www.jkobject.com/scPRINT/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/cli/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/embedder/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/model/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/pretrain/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/structure/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/tasks/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/usage/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/utils/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/notebooks/cancer_usecase/ - 2024-09-04 + 2024-09-09 daily https://www.jkobject.com/scPRINT/notebooks/cancer_usecase_part2/ - 2024-09-04 + 2024-09-09 daily \ No newline at end of file diff --git a/sitemap.xml.gz b/sitemap.xml.gz index 3d7a39b0a00be27076a55475131e1b0519deb5f5..ab13f00fce84e45dec9e6650cf40b2a91c875aef 100644 GIT binary patch literal 295 zcmV+?0oeW@iwFo{9^PgG|8r?{Wo=<_E_iKh0M(U2PsAV)h41?-8tz+aCXuRiqnx-5z!5~M>o$olRK5mdNA}{hC6Pqm79B^G-sxnTA zIR%%P)7dpAP?Re-#F*!o$EO3Y_-tFBl1PJVMOl=$+hP|-v@F`nrg~{Rc=PZsTB*%f z#aGG|hyU>WicA@uFdYmHv@Q6A5#xnm66PB{keAvfjELleqTnH6Mv{2Og!ux>F6I6O t(kA8pSx3+~7vES(tH2)vf|3aT5cxPtPvzf(U#9q%if_e031)i-0016Ni&Fpq literal 297 zcmV+^0oMK>iwFqdhSz2S|8r?{Wo=<_E_iKh0M(T-Ps1<}h4=o7D0|{G>OfKAZb&Q$ zp)yyFb0lsZJNV87{yk0`q0C4~<`&ye&+k5+2UmyBK_?&JP+3!_+q_5lRFwJL2T zpHpy&IbUpZ21&WJLx_2Pd3-vuip{q5ErB%HmX}4j%Zhzg?1E*{RyNrS)4`jAcisx6 zzbdv;ZaD0R=T~G>tBC1fXrOJuMT{64f{vJPbU;oh6EPx^^OC%Sh#5)X1taG3D7u*E v=Sk_9=VvTIV{Le2DU1Yn@(5BO{6pl^C>)i44}M+3U&_A$22}H%dj|jjD?W`M