dsa-helpers 0.4.dev0__tar.gz → 0.4.dev1__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.4.dev0/dsa_helpers.egg-info → dsa_helpers-0.4.dev1}/PKG-INFO +1 -1
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/dash/header.py +31 -21
- dsa_helpers-0.4.dev1/dsa_helpers/dash/header_callbacks.py +99 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1/dsa_helpers.egg-info}/PKG-INFO +1 -1
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/pyproject.toml +1 -1
- dsa_helpers-0.4.dev1/tests/test.ipynb +79 -0
- dsa_helpers-0.4.dev0/dsa_helpers/dash/header_callbacks.py +0 -98
- dsa_helpers-0.4.dev0/tests/test.ipynb +0 -268
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/.gitignore +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/LICENSE +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/README.md +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/app.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/__init__.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/dash/__init__.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/girder_utils.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/image_utils.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/imread.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/imwrite.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/login.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/ml/__init__.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/ml/object_detection/__init__.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/ml/object_detection/get_pearce_roi_images.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/ml/object_detection/tile_image.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/ml/object_detection/utils.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers/mongo_utils.py +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers.egg-info/SOURCES.txt +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers.egg-info/dependency_links.txt +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers.egg-info/requires.txt +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/dsa_helpers.egg-info/top_level.txt +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/readthedocs.yaml +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/requirements.txt +0 -0
- {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev1}/setup.cfg +0 -0
|
@@ -1,24 +1,37 @@
|
|
|
1
1
|
from dash import html, dcc
|
|
2
2
|
import dash_bootstrap_components as dbc
|
|
3
|
-
from . import
|
|
3
|
+
from .header_callbacks import get_callbacks
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
def get_header(
|
|
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:
|
|
7
12
|
"""Get the Dash html component that contains the header of the application
|
|
8
13
|
with login capabilities.
|
|
9
14
|
|
|
10
15
|
Args:
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
+
}
|
|
17
25
|
|
|
18
26
|
Returns:
|
|
19
27
|
html.Div: The header component.
|
|
20
28
|
|
|
21
29
|
"""
|
|
30
|
+
if config is None:
|
|
31
|
+
config = {}
|
|
32
|
+
|
|
33
|
+
get_callbacks(dsa_api_url, store_id)
|
|
34
|
+
|
|
22
35
|
login_modal = dbc.Modal(
|
|
23
36
|
[
|
|
24
37
|
dbc.ModalHeader("Log in"),
|
|
@@ -28,7 +41,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
28
41
|
"Login or email", style={"margin": 5, "fontWeight": "bold"}
|
|
29
42
|
),
|
|
30
43
|
dbc.Input(
|
|
31
|
-
id="login",
|
|
44
|
+
id=f"{store_id}=login",
|
|
32
45
|
type="text",
|
|
33
46
|
placeholder="Enter login",
|
|
34
47
|
style={"margin": 5},
|
|
@@ -38,7 +51,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
38
51
|
style={"margin": 5, "marginTop": 15, "fontWeight": "bold"},
|
|
39
52
|
),
|
|
40
53
|
dbc.Input(
|
|
41
|
-
id="password",
|
|
54
|
+
id=f"{store_id}=password",
|
|
42
55
|
type="password",
|
|
43
56
|
placeholder="Enter password",
|
|
44
57
|
style={"margin": 5},
|
|
@@ -46,7 +59,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
46
59
|
html.Div(
|
|
47
60
|
"Login failed.",
|
|
48
61
|
hidden=True,
|
|
49
|
-
id="login-failed",
|
|
62
|
+
id=f"{store_id}=login-failed",
|
|
50
63
|
style={"color": "red", "fontWeight": "bold", "margin": 10},
|
|
51
64
|
),
|
|
52
65
|
],
|
|
@@ -57,7 +70,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
57
70
|
dbc.Col(
|
|
58
71
|
dbc.Button(
|
|
59
72
|
"Close",
|
|
60
|
-
id="close-login-modal",
|
|
73
|
+
id=f"{store_id}=close-login-modal",
|
|
61
74
|
className="me-1",
|
|
62
75
|
color="light",
|
|
63
76
|
)
|
|
@@ -65,7 +78,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
65
78
|
dbc.Col(
|
|
66
79
|
dbc.Button(
|
|
67
80
|
"Login",
|
|
68
|
-
id="log-in-btn",
|
|
81
|
+
id=f"{store_id}=log-in-btn",
|
|
69
82
|
className="me-1",
|
|
70
83
|
color="primary",
|
|
71
84
|
)
|
|
@@ -75,7 +88,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
75
88
|
),
|
|
76
89
|
],
|
|
77
90
|
is_open=False,
|
|
78
|
-
id="login-modal",
|
|
91
|
+
id=f"{store_id}=login-modal",
|
|
79
92
|
)
|
|
80
93
|
|
|
81
94
|
logout_modal = dbc.Modal(
|
|
@@ -84,7 +97,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
84
97
|
[
|
|
85
98
|
dbc.Button(
|
|
86
99
|
"Log out",
|
|
87
|
-
id="logout-btn",
|
|
100
|
+
id=f"{store_id}=logout-btn",
|
|
88
101
|
color="danger",
|
|
89
102
|
className="me-1",
|
|
90
103
|
),
|
|
@@ -92,12 +105,9 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
92
105
|
)
|
|
93
106
|
],
|
|
94
107
|
is_open=False,
|
|
95
|
-
id="logout-modal",
|
|
108
|
+
id=f"{store_id}=logout-modal",
|
|
96
109
|
)
|
|
97
110
|
|
|
98
|
-
if config is None:
|
|
99
|
-
config = {}
|
|
100
|
-
|
|
101
111
|
return html.Div(
|
|
102
112
|
[
|
|
103
113
|
dbc.Row(
|
|
@@ -116,7 +126,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
116
126
|
dbc.Col(
|
|
117
127
|
dbc.Button(
|
|
118
128
|
"Log in",
|
|
119
|
-
id="login-btn",
|
|
129
|
+
id=f"{store_id}=login-btn",
|
|
120
130
|
color=config.get("backgroundColor", "#012169"),
|
|
121
131
|
style={
|
|
122
132
|
"color": config.get("fontColor", "#f2a900"),
|
|
@@ -132,7 +142,7 @@ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
|
|
|
132
142
|
),
|
|
133
143
|
login_modal,
|
|
134
144
|
logout_modal,
|
|
135
|
-
dcc.Store(id=
|
|
145
|
+
dcc.Store(id=store_id, storage_type="local", data={}),
|
|
136
146
|
],
|
|
137
147
|
style={
|
|
138
148
|
"backgroundColor": config.get("backgroundColor", "#012169"),
|
|
@@ -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
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"metadata": {},
|
|
6
|
+
"source": [
|
|
7
|
+
"# Test Python Package Build"
|
|
8
|
+
]
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
"cell_type": "code",
|
|
12
|
+
"execution_count": 1,
|
|
13
|
+
"metadata": {},
|
|
14
|
+
"outputs": [],
|
|
15
|
+
"source": [
|
|
16
|
+
"# Import all modules.\n",
|
|
17
|
+
"from dsa_helpers import *"
|
|
18
|
+
]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"cell_type": "markdown",
|
|
22
|
+
"metadata": {},
|
|
23
|
+
"source": [
|
|
24
|
+
"#### Authenticate girder client."
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"cell_type": "code",
|
|
29
|
+
"execution_count": 3,
|
|
30
|
+
"metadata": {},
|
|
31
|
+
"outputs": [],
|
|
32
|
+
"source": [
|
|
33
|
+
"gc = girder_utils.login(\"\")"
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"cell_type": "markdown",
|
|
38
|
+
"metadata": {},
|
|
39
|
+
"source": [
|
|
40
|
+
"#### Get DSA items recursively"
|
|
41
|
+
]
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
"cell_type": "code",
|
|
45
|
+
"execution_count": null,
|
|
46
|
+
"metadata": {},
|
|
47
|
+
"outputs": [],
|
|
48
|
+
"source": [
|
|
49
|
+
"# Get items from a folder.\n",
|
|
50
|
+
"items = girder_utils.get_items(gc, \"\")\n",
|
|
51
|
+
"print(f\"Got {len(items)} items from folder.\")\n",
|
|
52
|
+
"\n",
|
|
53
|
+
"items = girder_utils.get_items(gc, \"\")\n",
|
|
54
|
+
"print(f\"Got {len(items)} items from collection.\")"
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
],
|
|
58
|
+
"metadata": {
|
|
59
|
+
"kernelspec": {
|
|
60
|
+
"display_name": "env",
|
|
61
|
+
"language": "python",
|
|
62
|
+
"name": "python3"
|
|
63
|
+
},
|
|
64
|
+
"language_info": {
|
|
65
|
+
"codemirror_mode": {
|
|
66
|
+
"name": "ipython",
|
|
67
|
+
"version": 3
|
|
68
|
+
},
|
|
69
|
+
"file_extension": ".py",
|
|
70
|
+
"mimetype": "text/x-python",
|
|
71
|
+
"name": "python",
|
|
72
|
+
"nbconvert_exporter": "python",
|
|
73
|
+
"pygments_lexer": "ipython3",
|
|
74
|
+
"version": "3.12.3"
|
|
75
|
+
}
|
|
76
|
+
},
|
|
77
|
+
"nbformat": 4,
|
|
78
|
+
"nbformat_minor": 2
|
|
79
|
+
}
|
|
@@ -1,98 +0,0 @@
|
|
|
1
|
-
# Callbacks for the header component.
|
|
2
|
-
from dash import callback, Output, Input, State, no_update
|
|
3
|
-
from girder_client import GirderClient
|
|
4
|
-
from os import getenv
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
@callback(Output("login-btn", "children"), Input("user-store", "data"))
|
|
8
|
-
def check_user_store(data):
|
|
9
|
-
# Check if the user store has user info or if no one is logged in.
|
|
10
|
-
return data["user"] if len(data) else "Log in"
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
@callback(
|
|
14
|
-
[
|
|
15
|
-
Output("login-modal", "is_open", allow_duplicate=True),
|
|
16
|
-
Output("logout-modal", "is_open", allow_duplicate=True),
|
|
17
|
-
],
|
|
18
|
-
[Input("login-btn", "n_clicks"), State("login-btn", "children")],
|
|
19
|
-
prevent_initial_call=True,
|
|
20
|
-
)
|
|
21
|
-
def open_login_modal(n_clicks, children):
|
|
22
|
-
# Open login / logout modal.
|
|
23
|
-
if n_clicks:
|
|
24
|
-
if children == "Log in":
|
|
25
|
-
return True, False
|
|
26
|
-
else:
|
|
27
|
-
return False, True
|
|
28
|
-
|
|
29
|
-
return False, False
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
@callback(
|
|
33
|
-
[
|
|
34
|
-
Output("user-store", "data"),
|
|
35
|
-
Output("login-failed", "hidden", allow_duplicate=True),
|
|
36
|
-
Output("login-modal", "is_open", allow_duplicate=True),
|
|
37
|
-
Output("login", "value", allow_duplicate=True),
|
|
38
|
-
Output("password", "value", allow_duplicate=True),
|
|
39
|
-
],
|
|
40
|
-
[
|
|
41
|
-
Input("log-in-btn", "n_clicks"),
|
|
42
|
-
State("login", "value"),
|
|
43
|
-
State("password", "value"),
|
|
44
|
-
],
|
|
45
|
-
prevent_initial_call=True,
|
|
46
|
-
)
|
|
47
|
-
def login(n_clicks, login, password):
|
|
48
|
-
# Try to login.
|
|
49
|
-
gc = GirderClient(apiUrl=getenv("DSA_API_URL"))
|
|
50
|
-
|
|
51
|
-
try:
|
|
52
|
-
_ = gc.authenticate(username=login, password=password)
|
|
53
|
-
|
|
54
|
-
response = gc.get("token/session")
|
|
55
|
-
|
|
56
|
-
user = gc.get("user/me")["login"]
|
|
57
|
-
|
|
58
|
-
return {"user": user, "token": response["token"]}, True, False, "", ""
|
|
59
|
-
except:
|
|
60
|
-
return (
|
|
61
|
-
{},
|
|
62
|
-
False,
|
|
63
|
-
True,
|
|
64
|
-
no_update,
|
|
65
|
-
no_update,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
@callback(
|
|
70
|
-
[
|
|
71
|
-
Output("login-modal", "is_open", allow_duplicate=True),
|
|
72
|
-
Output("login", "value", allow_duplicate=True),
|
|
73
|
-
Output("password", "value", allow_duplicate=True),
|
|
74
|
-
Output("login-failed", "hidden", allow_duplicate=True),
|
|
75
|
-
],
|
|
76
|
-
Input("close-login-modal", "n_clicks"),
|
|
77
|
-
prevent_initial_call=True,
|
|
78
|
-
)
|
|
79
|
-
def close_login_modal(n_clicks):
|
|
80
|
-
if n_clicks:
|
|
81
|
-
return False, "", "", True
|
|
82
|
-
|
|
83
|
-
return False, "", "", True
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
@callback(
|
|
87
|
-
[
|
|
88
|
-
Output("user-store", "data", allow_duplicate=True),
|
|
89
|
-
Output("logout-modal", "is_open", allow_duplicate=True),
|
|
90
|
-
],
|
|
91
|
-
Input("logout-btn", "n_clicks"),
|
|
92
|
-
prevent_initial_call=True,
|
|
93
|
-
)
|
|
94
|
-
def logout(n_clicks):
|
|
95
|
-
if n_clicks:
|
|
96
|
-
return {}, False
|
|
97
|
-
|
|
98
|
-
return no_update, False
|