Metadata-Version: 2.4
Name: fusion-tools
Version: 3.5.7
Summary: Modular visualization and analysis dashboard creation for high-resolution microscopy images
Home-page: https://github.com/spborder/fusion-tools
Author: Sam Border
Author-email: sam.border2256@gmail.com
Classifier: Development Status :: 4 - Beta
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: lxml>=4.9.2
Requires-Dist: geojson>=3.0.1
Requires-Dist: shapely>=2.0.1
Requires-Dist: anndata
Requires-Dist: geopandas>=1.0.1
Requires-Dist: girder-client
Requires-Dist: numpy>=1.20.0
Requires-Dist: large-image[common]
Requires-Dist: requests
Requires-Dist: uuid>=1.30
Requires-Dist: scikit-image
Requires-Dist: umap-learn>=0.5.6
Requires-Dist: statsmodels>=0.14.0
Requires-Dist: typing-extensions>=4.8.0
Requires-Dist: girder-job-sequence>=0.2.7
Provides-Extra: interactive
Requires-Dist: dash-leaflet[all]>=1.0.15; extra == "interactive"
Requires-Dist: dash<3.0.0,>=2.18.1; extra == "interactive"
Requires-Dist: dash-extensions>=1.0.18; extra == "interactive"
Requires-Dist: dash-uploader==0.7.0-a1; extra == "interactive"
Requires-Dist: dash_mantine_components>=0.14.4; extra == "interactive"
Requires-Dist: dash-bootstrap-components>=1.6.0; extra == "interactive"
Requires-Dist: dash_treeview_antd>=0.0.1; extra == "interactive"
Requires-Dist: fastapi>=0.103.2; extra == "interactive"
Requires-Dist: uvicorn>=0.30.6; extra == "interactive"
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: home-page
Dynamic: license-file
Dynamic: provides-extra
Dynamic: requires-dist
Dynamic: requires-python
Dynamic: summary

# *fusion-tools*
Modular visualization and analysis dashboard creation for high-resolution microscopy images.


## Installation

To access interactive dashboard components and functionality use:
```bash
$ pip install fusion-tools[interactive]
```

To just use the `shapes` utility functions and `dataset` classes (`SegmentationDataset` and `ClassificationDataset`) use:
```bash
$ pip install fusion-tools
```

## Usage

`fusion-tools` is intended to bring some of the functionality found in FUSION to developers working with whole slide images (WSIs) stored locally. 

One such example would be the `Visualization` and `SlideMap` class:
<div align="center">
    <img src="docs/images/local-slide-viewer.PNG">
</div>

```python
from fusion_tools.visualization import Visualization
from fusion_tools.components import SlideMap

vis_session = Visualization(
    local_slides = [path_to_slide]
    components = [
        [
            SlideMap()
        ]
    ]
)

vis_session.start()

```

The `Visualization` class lets users construct custom layouts of different tools by passing a list containing rows, columns, and tabs. (e.g. [ [column in row 1], [ [ tab 1 in column 2 in row 1, tab 2 in column 2 in row 1] ], [ [ column 1 in row 2 ] ] ] ).

By passing a list of paths to locally-stored whole slide images (WSIs), `fusion-tools` automatically generates a `LocalTileServer` which is bundled in with the `Visualization` session to allow for high-resolution image viewing.

<div align="center">
    <img src="docs/images/slide-annotations-layout.PNG">
</div>


```python

from fusion_tools.visualization import Visualization
from fusion_tools.components import SlideMap, OverlayOptions, PropertyViewer
from fusion_tools.utils.shapes import load_aperio


path_to_slide = '/path/to/wsi.svs'
path_to_annotations = '/path/to/aperio_annotations.xml'

annotations = load_aperio(path_to_annotations)

vis_session = Visualization(
    local_slides = [path_to_slide],
    local_annotations = [annotations],
    components = [
        [
            SlideMap(),
            [
                OverlayOptions(),
                PropertyViewer()
            ]
        ]
    ]
)

vis_session.start()

```

You can also access remote tile servers (either through `DSATileServer` or `CustomTileServer`) as well as annotations stored on a [Digital Slide Archive](https://digitalslidearchive.github.io/digital_slide_archive/) instance.

<div align="center">
    <img src="docs/images/remote-slide-annotations.PNG">
</div>


```python

from fusion_tools.visualization import Visualization
from fusion_tools.handler.dsa_handler import DSAHandler
from fusion_tools.components import SlideMap

# Grabbing first item from demo DSA instance
base_url = 'https://demo.kitware.com/histomicstk/api/v1'
item_id = '5bbdeed1e629140048d01bcb'

# Starting the DSAHandler to grab information:
dsa_handler = DSAHandler(
    girderApiUrl = base_url
)

# Checking how many annotations this item has:
#print('This item has the following annotations: ')
#print(dsa_handler.query_annotation_count(item=item_id).to_dict('records'))

vis_session = Visualization(
    tileservers = [dsa_handler.get_tile_server(item_id)],
    components = [
        [
            SlideMap()
        ]
    ]
)

vis_session.start()


```

You can also use some of `segmentation` components for adding labels and annotations to structures in the slide.

### Creating annotations on top of structures
<div align="center">
    <img src="docs/images/feature-annotation.PNG">
</div>

### Applying labels to many structures at the same time
<div align="center">
    <img src="docs/images/bulk-labels.PNG">
</div>

```python

from fusion_tools.visualization import Visualization
from fusion_tools.handler.dsa_handler import DSAHandler
from fusion_tools.components import SlideMap, FeatureAnnotation, BulkLabels

# Grabbing first item from demo DSA instance
base_url = 'https://demo.kitware.com/histomicstk/api/v1'
item_id = '5bbdeed1e629140048d01bcb'

# Starting the DSAHandler to grab information:
dsa_handler = DSAHandler(
    girderApiUrl = base_url
)

# Checking how many annotations this item has:
#print('This item has the following annotations: ')
#print(dsa_handler.query_annotation_count(item=item_id).to_dict('records'))

vis_session = Visualization(
    tileservers = [dsa_handler.get_tile_server(item_id)],
    components = [
        [
            SlideMap(),
            [
                FeatureAnnotation(
                    storage_path = os.getcwd()+'\\tests\\Test_Annotations\\',
                    labels_format = 'json',
                    annotations_format = 'rgb'
                ),
                BulkLabels()
            ]
        ]
    ]
)

vis_session.start()


```

### New in *fusion-tools*>2.0.0!
Now you can add multiple slides to a single visualization session and you can even view them side-by-side!
- By default, components in the same *row* are **linked**, or they can interact with each other through callbacks. This can be updated using the "linkage" kwarg when initializing a `Visualization` session.
- If two of the same types of components (e.g., two `SlideMap` components) are placed in the same row and "linkage" is set to "row", callbacks will not work. **Beware!**

```python

from fusion_tools.visualization import Visualization
from fusion_tools.components import SlideMap, OverlayOptions, PropertyViewer, PropertyPlotter
from fusion_tools.handler.dsa_handler import DSAHandler

# Mixed types of slides and annotations
local_slide_list = ['slide1.tif','slide2.ome.tif','slide3.svs']
local_annotations_list = ['slide1_annotations.xml','slide2 annotations.json','annotations for slide3.h5ad']

dsa_handler = DSAHandler(
    girderApiUrl = 'http://example_dsa_address.com/api/v1'
)

dsa_items_list = [
    'item_uuid_1',
    'item_uuid_2'
]

dsa_tileservers = [dsa_handler.get_tile_server(i) for i in dsa_items_list]

# Setting linkage to "col" to enable side-by-side visualization
vis_sess = Visualization(
    local_slides = local_slide_list,
    local_annotations = local_annotations_list,
    tileservers = dsa_tileservers,
    linkage = 'col',
    components = [
        [
            [
                SlideMap(),
                OverlayOptions(),
                PropertyViewer(),
                PropertyPlotter()
            ],            
            [
                SlideMap(),
                OverlayOptions(),
                PropertyViewer(),
                PropertyPlotter()
            ]
        ]
    ],
    app_options={'port': 8050}
)

vis_sess.start()


```
<div align="center">
    <img src="docs/images/side-by-side-view.PNG">
</div>


## Contributing

Open to contributions. Feel free to submit a PR or post feature requests in [Issues](https://github.com/spborder/fusion-tools/issues)

### Open Projects:
- Automated segmentation workflow for locally stored images (active-learning, SAM, etc.)
- Monitoring long-running model training/other external processes
- Import anndata spatial --omics dataset (UPDATE (v2.0.0): see `utils.shapes.load_visium` for example loading *10x Visium* dataset)


## License
`fusion-tools` was created by Samuel Border. It is licensed under the terms of the Apache 2.0 License

