Exemple #1
0
 def get_config(self, **kwargs):
     file_name = self.custom_app_config(
         dataset_datapath=H5AD_FIXTURE, config_file_name=self.config_file_name, **kwargs
     )
     config = AppConfig()
     config.update_from_config_file(file_name)
     return config
Exemple #2
0
    def test_get_dataset_config_returns_dataset_config_for_single_datasets(self):
        datapath = f"{FIXTURES_ROOT}/1e4dfec4-c0b2-46ad-a04e-ff3ffb3c0a8f.h5ad"
        file_name = self.custom_app_config(dataset_datapath=datapath, config_file_name=self.config_file_name)
        config = AppConfig()
        config.update_from_config_file(file_name)

        self.assertEqual(config.get_dataset_config(), config.dataset_config)
Exemple #3
0
    def test_aws_secrets_manager(self, mock_get_secret_key):
        mock_get_secret_key.return_value = {
            "flask_secret_key": "mock_flask_secret_key",
        }
        configfile = self.custom_external_config(
            aws_secrets_manager_region="us-west-2",
            aws_secrets_manager_secrets=[
                dict(
                    name="my_secret",
                    values=[
                        dict(key="flask_secret_key",
                             path=["server", "app", "flask_secret_key"],
                             required=True),
                    ],
                )
            ],
            config_file_name="secret_external_config.yaml",
        )

        app_config = AppConfig()
        app_config.update_from_config_file(configfile)
        app_config.server_config.single_dataset__datapath = f"{FIXTURES_ROOT}/pbmc3k-CSC-gz.h5ad"

        app_config.complete_config()

        self.assertEqual(app_config.server_config.app__flask_secret_key,
                         "mock_flask_secret_key")
Exemple #4
0
    def test_configfile_with_specialization(self):
        # test that per_dataset_config config load the default config, then the specialized config

        with tempfile.TemporaryDirectory() as tempdir:
            configfile = os.path.join(tempdir, "config.yaml")
            with open(configfile, "w") as fconfig:
                config = """
                server:
                    single_dataset:
                        datapath: fake_datapath
                dataset:
                    user_annotations:
                        enable: false
                        type: local_file_csv
                        local_file_csv:
                            file: fake_file
                            directory: fake_dir
                """
                fconfig.write(config)

            app_config = AppConfig()
            app_config.update_from_config_file(configfile)

            test_config = app_config.dataset_config

            # test config from default
            self.assertEqual(test_config.user_annotations__type,
                             "local_file_csv")
            self.assertEqual(
                test_config.user_annotations__local_file_csv__file,
                "fake_file")
Exemple #5
0
 def test_handle_embeddings__checks_data_file_types(self):
     file_name = self.custom_app_config(
         embedding_names=["name1", "name2"],
         enable_reembedding="true",
         dataset_datapath=f"{FIXTURES_ROOT}/pbmc3k-CSC-gz.h5ad",
         anndata_backed="true",
         config_file_name=self.config_file_name,
     )
     config = AppConfig()
     config.update_from_config_file(file_name)
     config.server_config.complete_config(self.context)
     with self.assertRaises(ConfigurationError):
         config.dataset_config.handle_embeddings()
    def test_config_for_single_dataset(self):
        file_name = self.custom_app_config(
            config_file_name="single_dataset.yml",
            dataset_datapath=f"{H5AD_FIXTURE}")
        config = AppConfig()
        config.update_from_config_file(file_name)
        config.server_config.handle_single_dataset(self.context)

        file_name = self.custom_app_config(
            config_file_name="single_dataset_with_about.yml",
            about="www.cziscience.com",
            dataset_datapath=f"{H5AD_FIXTURE}",
        )
        config = AppConfig()
        config.update_from_config_file(file_name)
        with self.assertRaises(ConfigurationError):
            config.server_config.handle_single_dataset(self.context)
Exemple #7
0
    def test_configfile_no_server_section(self):
        # test a config file without a dataset section

        with tempfile.TemporaryDirectory() as tempdir:
            configfile = os.path.join(tempdir, "config.yaml")
            with open(configfile, "w") as fconfig:
                config = """
                dataset:
                    user_annotations:
                        enable: false
                """
                fconfig.write(config)

            app_config = AppConfig()
            app_config.update_from_config_file(configfile)
            server_changes = app_config.server_config.changes_from_default()
            dataset_changes = app_config.dataset_config.changes_from_default()
            self.assertEqual(server_changes, [])
            self.assertEqual(dataset_changes, [("user_annotations__enable", False, True)])
 def test_handle_data_locator_works_for_default_types(
         self, mock_discover_region_name):
     mock_discover_region_name.return_value = None
     # Default config
     self.assertEqual(
         self.config.server_config.data_locator__s3__region_name, None)
     # hard coded
     config = self.get_config()
     self.assertEqual(config.server_config.data_locator__s3__region_name,
                      "us-east-1")
     # incorrectly formatted
     datapath = "s3://shouldnt/work"
     file_name = self.custom_app_config(
         dataset_datapath=datapath,
         config_file_name=self.config_file_name,
         data_locater_region_name="true")
     config = AppConfig()
     config.update_from_config_file(file_name)
     with self.assertRaises(ConfigurationError):
         config.server_config.handle_data_locator()
Exemple #9
0
def launch(
    datapath,
    verbose,
    debug,
    open_browser,
    port,
    host,
    embedding,
    obs_names,
    var_names,
    max_category_items,
    disable_custom_colors,
    diffexp_lfc_cutoff,
    title,
    scripts,
    about,
    disable_annotations,
    annotations_file,
    annotations_dir,
    backed,
    disable_diffexp,
    experimental_annotations_ontology,
    experimental_annotations_ontology_obo,
    experimental_enable_reembedding,
    config_file,
    dump_default_config,
):
    """Launch the cellxgene data viewer.
    This web app lets you explore single-cell expression data.
    Data must be in a format that cellxgene expects.
    Read the "getting started" guide to learn more:
    https://chanzuckerberg.github.io/cellxgene/getting-started.html

    Examples:

    > cellxgene launch example-dataset/pbmc3k.h5ad --title pbmc3k

    > cellxgene launch <your data file> --title <your title>

    > cellxgene launch <url>"""

    if dump_default_config:
        print(default_config)
        sys.exit(0)

    # Startup message
    click.echo("[cellxgene] Starting the CLI...")

    # app config
    app_config = AppConfig()
    server_config = app_config.server_config

    try:
        if config_file:
            app_config.update_from_config_file(config_file)

        # Determine which config options were give on the command line.
        # Those will override the ones provided in the config file (if provided).
        cli_config = AppConfig()
        cli_config.update_server_config(
            app__verbose=verbose,
            app__debug=debug,
            app__host=host,
            app__port=port,
            app__open_browser=open_browser,
            single_dataset__datapath=datapath,
            single_dataset__title=title,
            single_dataset__about=about,
            single_dataset__obs_names=obs_names,
            single_dataset__var_names=var_names,
            adaptor__anndata_adaptor__backed=backed,
        )
        cli_config.update_dataset_config(
            app__scripts=scripts,
            user_annotations__enable=not disable_annotations,
            user_annotations__local_file_csv__file=annotations_file,
            user_annotations__local_file_csv__directory=annotations_dir,
            user_annotations__ontology__enable=
            experimental_annotations_ontology,
            user_annotations__ontology__obo_location=
            experimental_annotations_ontology_obo,
            presentation__max_categories=max_category_items,
            presentation__custom_colors=not disable_custom_colors,
            embeddings__names=embedding,
            embeddings__enable_reembedding=experimental_enable_reembedding,
            diffexp__enable=not disable_diffexp,
            diffexp__lfc_cutoff=diffexp_lfc_cutoff,
        )

        diff = cli_config.server_config.changes_from_default()
        changes = {key: val for key, val, _ in diff}
        app_config.update_server_config(**changes)

        diff = cli_config.dataset_config.changes_from_default()
        changes = {key: val for key, val, _ in diff}
        app_config.update_dataset_config(**changes)

        # process the configuration
        #  any errors will be thrown as an exception.
        #  any info messages will be passed to the messagefn function.

        def messagefn(message):
            click.echo("[cellxgene] " + message)

        # Use a default secret if one is not provided
        if not server_config.app__flask_secret_key:
            app_config.update_server_config(
                app__flask_secret_key="SparkleAndShine")

        app_config.complete_config(messagefn)

    except (ConfigurationError, DatasetAccessError) as e:
        raise click.ClickException(e)

    handle_scripts(scripts)

    # create the server
    server = CliLaunchServer(app_config)

    if not server_config.app__verbose:
        log = logging.getLogger("werkzeug")
        log.setLevel(logging.ERROR)

    cellxgene_url = f"http://{app_config.server_config.app__host}:{app_config.server_config.app__port}"
    if server_config.app__open_browser:
        click.echo(
            f"[cellxgene] Launching! Opening your browser to {cellxgene_url} now."
        )
        webbrowser.open(cellxgene_url)
    else:
        click.echo(
            f"[cellxgene] Launching! Please go to {cellxgene_url} in your browser."
        )

    click.echo("[cellxgene] Type CTRL-C at any time to exit.")

    if not server_config.app__verbose:
        f = open(os.devnull, "w")
        sys.stdout = f

    try:
        server.app.run(
            host=server_config.app__host,
            debug=server_config.app__debug,
            port=server_config.app__port,
            threaded=not server_config.app__debug,
            use_debugger=False,
            use_reloader=False,
        )
    except OSError as e:
        if e.errno == errno.EADDRINUSE:
            raise click.ClickException(
                "Port is in use, please specify an open port using the --port flag."
            ) from e
        raise