Skip to content

Commit

Permalink
Merge pull request #60 from CAVEconnectome/random_segprop
Browse files Browse the repository at this point in the history
* fix helpers with config and add test

* add random columns to segment properties

* update docs
  • Loading branch information
ceesem authored Dec 11, 2024
2 parents 9478be4 + 0dae61a commit 568be65
Show file tree
Hide file tree
Showing 15 changed files with 262 additions and 60 deletions.
20 changes: 10 additions & 10 deletions docs/usage/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ title: Site Configuration

!!!abstract

TLDR: Use `site_config` to set default configurations for your `StateBuilder` objects.
After your imports, the recommended default code is: `site_config.set_default_config(target_site='spelunker')`
TLDR: Use `site_utils` to set default configurations for your `StateBuilder` objects.
After your imports, the recommended default code is: `site_utils.set_default_config(target_site='spelunker')`

## Using `site_config` to configure your StateBuilder
## Using `site_utils` to configure your StateBuilder

The `site_config` module is intended to access and change the baseline configuration of StateBuilder sites.
The `site_utils` submodule of `statebuilder` is intended to access and change the baseline configuration of StateBuilder sites.
This will let you configure a target site, url, and caveclient to use as defaults throughout your analysis without further specification.

The first thing to note is the options within the default configuration.
You can see this via

```python
from nglui import site_config, statebuilder
from nglui import statebuilder

site_config.get_default_config()
statebuilder.site_config.get_default_config()
```

This will return a dictionary with a number of variables:
Expand Down Expand Up @@ -58,7 +58,7 @@ the result will be a `url` that is based on the value in `target_url` and is con
You can change any of these values through the `set_default_config` method. For example, to change the target site to `spelunker`, you can use

```python
site_config.set_default_config(target_site='spelunker')
statebuilder.site_utils.set_default_config(target_site='spelunker')
```

If you run this and then check the default config again, you will see that the `target_site` has changed to `spelunker` and the `target_url` has changed to `https://spelunker.cave-explorer.org/` the value that was shown in `mainline_fallback_url`.
Expand All @@ -69,7 +69,7 @@ You can also set a `caveclient` object here directly or via a `datastack_name`.
For example, to set the default datastack to `minnie65_public` (the public MICrONs dataset), you can use

```python
site_utils.set_default_config(datastack=CAVEclient('minnie65_public'))
statebuilder.site_utils.set_default_config(datastack_name='minnie65_public')
```

This is particularly useful when working with `spelunker` datasets in particular, as they require a resolution to be specified to work properly and the CAVEclient object can provide this value.
Expand All @@ -79,7 +79,7 @@ You may see a warning if you do not include a caveclient object, but the code wi
If the resulting state does not work, you may need to specify the version of Neuroglancer you are using or add a caveclient.


## Why these different types of Neuroglancer?
## Why are there different types of Neuroglancer?

Neuroglancer is a webapp for viewing large scale 3d image datasets that has been developed over many years.
At one point, there was a major fork by the lab of Sebastian Seung to allow proofreading of connectomics data, which led to the development of the `seunglab` version of Neuroglancer.
Expand All @@ -101,5 +101,5 @@ If you are not sure, you should use the `spelunker` version. This will give you
The simplest way to do this is to set the default configuration to `spelunker` as shown above:

```python
site_config.set_default_config(target_site='spelunker')
statebuilder.site_utils.set_default_config(target_site='spelunker')
```
22 changes: 22 additions & 0 deletions docs/usage/segmentprops.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,28 @@ Any tag without a description will be passed through directly.
If you look at the JSON output above, you see that the `soma_depth` property has a field "data_type" that specifies the type of the numerical property, in this case `int32`.
Data type values are inferred from the column dtype and safe conversions are validated.

### Random number columns

Often, segment properties are used for very large lists of root ids.
If you want to sample just a few percent of these in Neuroglancer, it can be hard to get a small number of random ids without a lot of clicking.
Adding a numerical property that is just a random number between 0 and 1 will give you a way to load small subsets of the data using the filter tools.
You can add random columns when building a SegmentProperty object from a dataframe by setting the `random_columns` argument with the number of extra columns you want to add.
For example, to add a single random column:

```python
seg_prop = SegmentProperties.from_dataframe(
df,
id_col='segment_id',
number_cols='soma_depth',
random_columns=1,
)
```

Will add one random column as a numerical property with the default name `random_sample`.
Using numbers higher than 1 will add multiple random columns with names `random_sample_0`, `random_sample_1`, etc.
The name of the random column can be changed with the `random_column_prefix` argument.
Note that a value error will be raised if you try to add a random column with a name that already exists in the dataframe.

### Building segment properties manually

It is also possible to build segment properties manually with the `SegmentProperties` class.
Expand Down
21 changes: 21 additions & 0 deletions src/nglui/segmentprops/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,8 @@ def from_dataframe(
label_separator: str = "_",
label_format_map: Optional[str] = None,
prepend_col_name: bool = False,
random_columns: Optional[int] = None,
random_column_prefix: str = "random_sample",
):
"""Generate a segment property object from a pandas dataframe based on column
Expand Down Expand Up @@ -461,6 +463,25 @@ def from_dataframe(
SegmentProperties
Segment properties object
"""
if random_columns:
df = df.copy()
random_column_names = []
if random_columns > 1:
random_column_names = [
f"{random_column_prefix}_{i}" for i in range(random_columns)
]
else:
random_column_names = [random_column_prefix]
for col in random_column_names:
if col in df.columns:
raise ValueError(f"Column {col} already exists in dataframe")
df[col] = np.random.rand(len(df))
if number_cols is None:
number_cols = []
elif isinstance(number_cols, str):
number_cols = [number_cols]
number_cols = number_cols + random_column_names

ids = df[id_col].tolist()
properties = {}
if label_col or label_format_map:
Expand Down
10 changes: 10 additions & 0 deletions src/nglui/site_utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import os
from typing import Literal, Optional
from warnings import warn

import attrs
import caveclient
Expand Down Expand Up @@ -107,6 +108,7 @@ def __attrs_post_init__(self):
target_url=DEFAULT_URL,
)
default_key = "default"

NGL_CONFIG = {default_key: default_config} # type: dict[str, NGLUIConfig]


Expand Down Expand Up @@ -251,6 +253,14 @@ def get_target_site(
else:
msg = f"No client provided to check target site from URL. Assuming default value of \"{get_default_config(config_key)['target_site']}\""
logging.warning(msg)
if (
config_key == "default"
and get_default_config(config_key).get("target_site") == "seunglab"
):
msg = """
You are using default settings for target_site. The default target_site will become "spelunker" in the next major version release.
"""
warn(msg, DeprecationWarning)
return get_default_config(config_key)["target_site"]


Expand Down
1 change: 1 addition & 0 deletions src/nglui/statebuilder/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from .. import site_utils
from .helpers import from_client, make_neuron_neuroglancer_link
from .layers import AnnotationLayerConfig, ImageLayerConfig, SegmentationLayerConfig
from .mappers import (
Expand Down
Loading

0 comments on commit 568be65

Please sign in to comment.