dsa-helpers 0.3.dev0__tar.gz → 0.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/.gitignore +4 -1
- dsa_helpers-0.4/PKG-INFO +50 -0
- dsa_helpers-0.4/README.md +21 -0
- dsa_helpers-0.4/app.py +14 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/dsa_helpers/__init__.py +3 -2
- dsa_helpers-0.4/dsa_helpers/dash/__init__.py +1 -0
- dsa_helpers-0.4/dsa_helpers/dash/header.py +151 -0
- dsa_helpers-0.4/dsa_helpers/dash/header_callbacks.py +99 -0
- dsa_helpers-0.4/dsa_helpers/girder_utils.py +346 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/dsa_helpers/login.py +3 -1
- dsa_helpers-0.4/dsa_helpers/ml/__init__.py +2 -0
- dsa_helpers-0.4/dsa_helpers/ml/datasets/SegFormerSegmentationDataset.py +33 -0
- dsa_helpers-0.4/dsa_helpers/ml/datasets/__init__.py +3 -0
- dsa_helpers-0.4/dsa_helpers/ml/datasets/utils.py +42 -0
- dsa_helpers-0.4/dsa_helpers/ml/metrics/__init__.py +3 -0
- dsa_helpers-0.4/dsa_helpers/ml/metrics/binary_dice_coefficient_metric.py +24 -0
- dsa_helpers-0.4/dsa_helpers/ml/object_detection/__init__.py +5 -0
- dsa_helpers-0.4/dsa_helpers/ml/object_detection/get_pearce_roi_images.py +136 -0
- dsa_helpers-0.4/dsa_helpers/ml/object_detection/tile_image.py +137 -0
- dsa_helpers-0.4/dsa_helpers/ml/object_detection/utils.py +104 -0
- dsa_helpers-0.4/dsa_helpers/ml/transforms/__init__.py +1 -0
- dsa_helpers-0.4/dsa_helpers/ml/transforms/segformer_transforms.py +23 -0
- dsa_helpers-0.4/dsa_helpers/mongo_utils.py +160 -0
- dsa_helpers-0.4/dsa_helpers/utils.py +28 -0
- dsa_helpers-0.4/dsa_helpers.egg-info/PKG-INFO +50 -0
- dsa_helpers-0.4/dsa_helpers.egg-info/SOURCES.txt +38 -0
- dsa_helpers-0.4/dsa_helpers.egg-info/requires.txt +15 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/pyproject.toml +16 -6
- dsa_helpers-0.4/requirements.txt +15 -0
- dsa_helpers-0.4/tests/app/Dockerfile +18 -0
- dsa_helpers-0.4/tests/app/app.py +55 -0
- dsa_helpers-0.4/tests/docker-compose.yaml +31 -0
- dsa_helpers-0.4/tests/test.ipynb +268 -0
- dsa_helpers-0.3.dev0/PKG-INFO +0 -25
- dsa_helpers-0.3.dev0/README.md +0 -6
- dsa_helpers-0.3.dev0/dsa_helpers/girder_utils.py +0 -116
- dsa_helpers-0.3.dev0/dsa_helpers.egg-info/PKG-INFO +0 -25
- dsa_helpers-0.3.dev0/dsa_helpers.egg-info/SOURCES.txt +0 -16
- dsa_helpers-0.3.dev0/dsa_helpers.egg-info/requires.txt +0 -5
- dsa_helpers-0.3.dev0/requirements.txt +0 -5
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/LICENSE +0 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/dsa_helpers/image_utils.py +0 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/dsa_helpers/imread.py +0 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/dsa_helpers/imwrite.py +0 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/dsa_helpers.egg-info/dependency_links.txt +0 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/dsa_helpers.egg-info/top_level.txt +0 -0
- {dsa_helpers-0.3.dev0 → dsa_helpers-0.4}/setup.cfg +0 -0
dsa_helpers-0.4/PKG-INFO
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: dsa_helpers
|
|
3
|
+
Version: 0.4
|
|
4
|
+
Summary: Utility functions for working with the DSA girder client.
|
|
5
|
+
Author-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
|
|
6
|
+
Maintainer-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
|
|
7
|
+
Project-URL: Repository, https://github.com/Gutman-Lab/dsa-python-utils
|
|
8
|
+
Keywords: dsa,girder,girder_client
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: girder-client
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Requires-Dist: setuptools
|
|
17
|
+
Requires-Dist: opencv-python
|
|
18
|
+
Requires-Dist: pandas
|
|
19
|
+
Requires-Dist: pymongo
|
|
20
|
+
Requires-Dist: pillow
|
|
21
|
+
Requires-Dist: dash
|
|
22
|
+
Requires-Dist: dash_bootstrap_components
|
|
23
|
+
Requires-Dist: shapely
|
|
24
|
+
Requires-Dist: geopandas
|
|
25
|
+
Requires-Dist: torch
|
|
26
|
+
Requires-Dist: datasets
|
|
27
|
+
Requires-Dist: transformers
|
|
28
|
+
Requires-Dist: torchvision
|
|
29
|
+
|
|
30
|
+
# Digital Slide Archive (DSA) Helpers
|
|
31
|
+
Digital Slide Archive Python utility library.
|
|
32
|
+
|
|
33
|
+
This library is available for installation through [Python Package Index (PyPI)](https://pypi.org/).
|
|
34
|
+
|
|
35
|
+
This library was tested using Python version 3.11.8 and uses the dependencies described in requirements.txt.
|
|
36
|
+
|
|
37
|
+
This Python PyPI package is found [here](https://pypi.org/project/dsa-helpers/).
|
|
38
|
+
|
|
39
|
+
## Instructions for Development
|
|
40
|
+
1. Install requirements for building and distributing package:
|
|
41
|
+
```
|
|
42
|
+
$ python3 -m pip install --upgrade build # for building package
|
|
43
|
+
$ python3 -m pip install --upgrade twine # for uploading to PyPI
|
|
44
|
+
```
|
|
45
|
+
2. When ready to build:
|
|
46
|
+
- Modify "pyproject.toml" file, change the "version" key to a different value than a version already pushed.
|
|
47
|
+
- Run ```$ python3 -m build```. This will create a dist directory and put your new wheel and tar distribution files there.
|
|
48
|
+
3. To install locally for development: ```$ pip3 install dist/dsa_helpers-*.whl```, choosing the wheel version you want to test.
|
|
49
|
+
4. Upload to PyPI using twine: ```python3 -m twine upload --repository pypi dist/*```
|
|
50
|
+
* You can specify specific files to upload, the line above pushes everything in dist directory.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Digital Slide Archive (DSA) Helpers
|
|
2
|
+
Digital Slide Archive Python utility library.
|
|
3
|
+
|
|
4
|
+
This library is available for installation through [Python Package Index (PyPI)](https://pypi.org/).
|
|
5
|
+
|
|
6
|
+
This library was tested using Python version 3.11.8 and uses the dependencies described in requirements.txt.
|
|
7
|
+
|
|
8
|
+
This Python PyPI package is found [here](https://pypi.org/project/dsa-helpers/).
|
|
9
|
+
|
|
10
|
+
## Instructions for Development
|
|
11
|
+
1. Install requirements for building and distributing package:
|
|
12
|
+
```
|
|
13
|
+
$ python3 -m pip install --upgrade build # for building package
|
|
14
|
+
$ python3 -m pip install --upgrade twine # for uploading to PyPI
|
|
15
|
+
```
|
|
16
|
+
2. When ready to build:
|
|
17
|
+
- Modify "pyproject.toml" file, change the "version" key to a different value than a version already pushed.
|
|
18
|
+
- Run ```$ python3 -m build```. This will create a dist directory and put your new wheel and tar distribution files there.
|
|
19
|
+
3. To install locally for development: ```$ pip3 install dist/dsa_helpers-*.whl```, choosing the wheel version you want to test.
|
|
20
|
+
4. Upload to PyPI using twine: ```python3 -m twine upload --repository pypi dist/*```
|
|
21
|
+
* You can specify specific files to upload, the line above pushes everything in dist directory.
|
dsa_helpers-0.4/app.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# A test application.
|
|
2
|
+
from dash import Dash, html
|
|
3
|
+
import dash_bootstrap_components as dbc
|
|
4
|
+
from dsa_helpers.dash.header import get_header
|
|
5
|
+
import os
|
|
6
|
+
|
|
7
|
+
os.environ["DSA_API_URL"] = "https://megabrain.neurology.emory.edu/api/v1"
|
|
8
|
+
|
|
9
|
+
app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
|
|
10
|
+
|
|
11
|
+
app.layout = html.Div([get_header("Test")])
|
|
12
|
+
|
|
13
|
+
if __name__ == "__main__":
|
|
14
|
+
app.run_server(debug=True)
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Shadow imports.
|
|
2
|
-
from .login import login
|
|
3
2
|
from .imread import imread
|
|
4
3
|
from .imwrite import imwrite
|
|
5
4
|
|
|
6
5
|
# Modules that should be available.
|
|
7
|
-
from . import girder_utils, image_utils
|
|
6
|
+
# from . import girder_utils, image_utils, dash
|
|
7
|
+
|
|
8
|
+
__all__ = ["girder_utils", "image_utils", "dash", "ml"]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
from . import header
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
from dash import html, dcc
|
|
2
|
+
import dash_bootstrap_components as dbc
|
|
3
|
+
from .header_callbacks import get_callbacks
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_header(
|
|
7
|
+
dsa_api_url: str,
|
|
8
|
+
title: str = "App",
|
|
9
|
+
store_id: str = "user-store",
|
|
10
|
+
config: dict | None = None,
|
|
11
|
+
) -> html.Div:
|
|
12
|
+
"""Get the Dash html component that contains the header of the application
|
|
13
|
+
with login capabilities.
|
|
14
|
+
|
|
15
|
+
Args:
|
|
16
|
+
dsa_api_url (str): The URL of the DSA API.
|
|
17
|
+
title (str, optional): The title of the application. Defaults to "App".
|
|
18
|
+
config (dict, optional): The configuration of the component. Defaults to None.
|
|
19
|
+
If None the default configuration is:
|
|
20
|
+
{
|
|
21
|
+
"backgroundColor": "#012169",
|
|
22
|
+
"titleColor": "#d9d9d6",
|
|
23
|
+
"fontColor": "#f2a900",
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
html.Div: The header component.
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
if config is None:
|
|
31
|
+
config = {}
|
|
32
|
+
|
|
33
|
+
get_callbacks(dsa_api_url, store_id)
|
|
34
|
+
|
|
35
|
+
login_modal = dbc.Modal(
|
|
36
|
+
[
|
|
37
|
+
dbc.ModalHeader("Log in"),
|
|
38
|
+
dbc.ModalBody(
|
|
39
|
+
[
|
|
40
|
+
html.Div(
|
|
41
|
+
"Login or email", style={"margin": 5, "fontWeight": "bold"}
|
|
42
|
+
),
|
|
43
|
+
dbc.Input(
|
|
44
|
+
id=f"{store_id}=login",
|
|
45
|
+
type="text",
|
|
46
|
+
placeholder="Enter login",
|
|
47
|
+
style={"margin": 5},
|
|
48
|
+
),
|
|
49
|
+
html.Div(
|
|
50
|
+
"Password",
|
|
51
|
+
style={"margin": 5, "marginTop": 15, "fontWeight": "bold"},
|
|
52
|
+
),
|
|
53
|
+
dbc.Input(
|
|
54
|
+
id=f"{store_id}=password",
|
|
55
|
+
type="password",
|
|
56
|
+
placeholder="Enter password",
|
|
57
|
+
style={"margin": 5},
|
|
58
|
+
),
|
|
59
|
+
html.Div(
|
|
60
|
+
"Login failed.",
|
|
61
|
+
hidden=True,
|
|
62
|
+
id=f"{store_id}=login-failed",
|
|
63
|
+
style={"color": "red", "fontWeight": "bold", "margin": 10},
|
|
64
|
+
),
|
|
65
|
+
],
|
|
66
|
+
),
|
|
67
|
+
dbc.ModalFooter(
|
|
68
|
+
dbc.Row(
|
|
69
|
+
[
|
|
70
|
+
dbc.Col(
|
|
71
|
+
dbc.Button(
|
|
72
|
+
"Close",
|
|
73
|
+
id=f"{store_id}=close-login-modal",
|
|
74
|
+
className="me-1",
|
|
75
|
+
color="light",
|
|
76
|
+
)
|
|
77
|
+
),
|
|
78
|
+
dbc.Col(
|
|
79
|
+
dbc.Button(
|
|
80
|
+
"Login",
|
|
81
|
+
id=f"{store_id}=log-in-btn",
|
|
82
|
+
className="me-1",
|
|
83
|
+
color="primary",
|
|
84
|
+
)
|
|
85
|
+
),
|
|
86
|
+
],
|
|
87
|
+
)
|
|
88
|
+
),
|
|
89
|
+
],
|
|
90
|
+
is_open=False,
|
|
91
|
+
id=f"{store_id}=login-modal",
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
logout_modal = dbc.Modal(
|
|
95
|
+
[
|
|
96
|
+
dbc.ModalFooter(
|
|
97
|
+
[
|
|
98
|
+
dbc.Button(
|
|
99
|
+
"Log out",
|
|
100
|
+
id=f"{store_id}=logout-btn",
|
|
101
|
+
color="danger",
|
|
102
|
+
className="me-1",
|
|
103
|
+
),
|
|
104
|
+
]
|
|
105
|
+
)
|
|
106
|
+
],
|
|
107
|
+
is_open=False,
|
|
108
|
+
id=f"{store_id}=logout-modal",
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
return html.Div(
|
|
112
|
+
[
|
|
113
|
+
dbc.Row(
|
|
114
|
+
[
|
|
115
|
+
dbc.Col(
|
|
116
|
+
html.H1(
|
|
117
|
+
title,
|
|
118
|
+
style={
|
|
119
|
+
"fontWeight": "bold",
|
|
120
|
+
"color": config.get("titleColor", "#d9d9d6"),
|
|
121
|
+
"marginLeft": 5,
|
|
122
|
+
},
|
|
123
|
+
),
|
|
124
|
+
width="auto",
|
|
125
|
+
),
|
|
126
|
+
dbc.Col(
|
|
127
|
+
dbc.Button(
|
|
128
|
+
"Log in",
|
|
129
|
+
id=f"{store_id}=login-btn",
|
|
130
|
+
color=config.get("backgroundColor", "#012169"),
|
|
131
|
+
style={
|
|
132
|
+
"color": config.get("fontColor", "#f2a900"),
|
|
133
|
+
"fontSize": "1.2rem",
|
|
134
|
+
},
|
|
135
|
+
className="me-1",
|
|
136
|
+
),
|
|
137
|
+
width="auto",
|
|
138
|
+
),
|
|
139
|
+
],
|
|
140
|
+
justify="between",
|
|
141
|
+
align="center",
|
|
142
|
+
),
|
|
143
|
+
login_modal,
|
|
144
|
+
logout_modal,
|
|
145
|
+
dcc.Store(id=store_id, storage_type="local", data={}),
|
|
146
|
+
],
|
|
147
|
+
style={
|
|
148
|
+
"backgroundColor": config.get("backgroundColor", "#012169"),
|
|
149
|
+
"padding": 5,
|
|
150
|
+
},
|
|
151
|
+
)
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# Callbacks for the header component.
|
|
2
|
+
from dash import callback, Output, Input, State, no_update
|
|
3
|
+
from girder_client import GirderClient
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def get_callbacks(dsa_api_url: str, store_id: str):
|
|
7
|
+
"""Setup the callbacks to the DSA API url of interest and the proper store id."""
|
|
8
|
+
|
|
9
|
+
@callback(Output(f"{store_id}=login-btn", "children"), Input(store_id, "data"))
|
|
10
|
+
def check_user_store(data):
|
|
11
|
+
# Check if the user store has user info or if no one is logged in.
|
|
12
|
+
return data["user"] if len(data) else "Log in"
|
|
13
|
+
|
|
14
|
+
@callback(
|
|
15
|
+
[
|
|
16
|
+
Output(f"{store_id}=login-modal", "is_open", allow_duplicate=True),
|
|
17
|
+
Output(f"{store_id}=logout-modal", "is_open", allow_duplicate=True),
|
|
18
|
+
],
|
|
19
|
+
[
|
|
20
|
+
Input(f"{store_id}=login-btn", "n_clicks"),
|
|
21
|
+
State(f"{store_id}=login-btn", "children"),
|
|
22
|
+
],
|
|
23
|
+
prevent_initial_call=True,
|
|
24
|
+
)
|
|
25
|
+
def open_login_modal(n_clicks, children):
|
|
26
|
+
# Open login / logout modal.
|
|
27
|
+
if n_clicks:
|
|
28
|
+
if children == "Log in":
|
|
29
|
+
return True, False
|
|
30
|
+
else:
|
|
31
|
+
return False, True
|
|
32
|
+
|
|
33
|
+
return False, False
|
|
34
|
+
|
|
35
|
+
@callback(
|
|
36
|
+
[
|
|
37
|
+
Output(store_id, "data"),
|
|
38
|
+
Output(f"{store_id}=login-failed", "hidden", allow_duplicate=True),
|
|
39
|
+
Output(f"{store_id}=login-modal", "is_open", allow_duplicate=True),
|
|
40
|
+
Output(f"{store_id}=login", "value", allow_duplicate=True),
|
|
41
|
+
Output(f"{store_id}=password", "value", allow_duplicate=True),
|
|
42
|
+
],
|
|
43
|
+
[
|
|
44
|
+
Input(f"{store_id}=log-in-btn", "n_clicks"),
|
|
45
|
+
State(f"{store_id}=login", "value"),
|
|
46
|
+
State(f"{store_id}=password", "value"),
|
|
47
|
+
],
|
|
48
|
+
prevent_initial_call=True,
|
|
49
|
+
)
|
|
50
|
+
def login(n_clicks, login, password):
|
|
51
|
+
# Try to login.
|
|
52
|
+
gc = GirderClient(apiUrl=dsa_api_url)
|
|
53
|
+
|
|
54
|
+
try:
|
|
55
|
+
_ = gc.authenticate(username=login, password=password)
|
|
56
|
+
|
|
57
|
+
response = gc.get("token/session")
|
|
58
|
+
|
|
59
|
+
user = gc.get("user/me")["login"]
|
|
60
|
+
|
|
61
|
+
return {"user": user, "token": response["token"]}, True, False, "", ""
|
|
62
|
+
except:
|
|
63
|
+
return (
|
|
64
|
+
{},
|
|
65
|
+
False,
|
|
66
|
+
True,
|
|
67
|
+
no_update,
|
|
68
|
+
no_update,
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
@callback(
|
|
72
|
+
[
|
|
73
|
+
Output(f"{store_id}=login-modal", "is_open", allow_duplicate=True),
|
|
74
|
+
Output(f"{store_id}=login", "value", allow_duplicate=True),
|
|
75
|
+
Output(f"{store_id}=password", "value", allow_duplicate=True),
|
|
76
|
+
Output(f"{store_id}=login-failed", "hidden", allow_duplicate=True),
|
|
77
|
+
],
|
|
78
|
+
Input(f"{store_id}=close-login-modal", "n_clicks"),
|
|
79
|
+
prevent_initial_call=True,
|
|
80
|
+
)
|
|
81
|
+
def close_login_modal(n_clicks):
|
|
82
|
+
if n_clicks:
|
|
83
|
+
return False, "", "", True
|
|
84
|
+
|
|
85
|
+
return False, "", "", True
|
|
86
|
+
|
|
87
|
+
@callback(
|
|
88
|
+
[
|
|
89
|
+
Output(store_id, "data", allow_duplicate=True),
|
|
90
|
+
Output(f"{store_id}=logout-modal", "is_open", allow_duplicate=True),
|
|
91
|
+
],
|
|
92
|
+
Input(f"{store_id}=logout-btn", "n_clicks"),
|
|
93
|
+
prevent_initial_call=True,
|
|
94
|
+
)
|
|
95
|
+
def logout(n_clicks):
|
|
96
|
+
if n_clicks:
|
|
97
|
+
return {}, False
|
|
98
|
+
|
|
99
|
+
return no_update, False
|