dsa-helpers 0.4.dev0__tar.gz → 0.4.dev2__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.
Files changed (32) hide show
  1. {dsa_helpers-0.4.dev0/dsa_helpers.egg-info → dsa_helpers-0.4.dev2}/PKG-INFO +1 -1
  2. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/dash/header.py +31 -21
  3. dsa_helpers-0.4.dev2/dsa_helpers/dash/header_callbacks.py +99 -0
  4. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/mongo_utils.py +8 -10
  5. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2/dsa_helpers.egg-info}/PKG-INFO +1 -1
  6. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/pyproject.toml +1 -1
  7. dsa_helpers-0.4.dev2/tests/test.ipynb +79 -0
  8. dsa_helpers-0.4.dev0/dsa_helpers/dash/header_callbacks.py +0 -98
  9. dsa_helpers-0.4.dev0/tests/test.ipynb +0 -268
  10. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/.gitignore +0 -0
  11. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/LICENSE +0 -0
  12. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/README.md +0 -0
  13. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/app.py +0 -0
  14. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/__init__.py +0 -0
  15. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/dash/__init__.py +0 -0
  16. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/girder_utils.py +0 -0
  17. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/image_utils.py +0 -0
  18. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/imread.py +0 -0
  19. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/imwrite.py +0 -0
  20. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/login.py +0 -0
  21. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/ml/__init__.py +0 -0
  22. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/ml/object_detection/__init__.py +0 -0
  23. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/ml/object_detection/get_pearce_roi_images.py +0 -0
  24. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/ml/object_detection/tile_image.py +0 -0
  25. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers/ml/object_detection/utils.py +0 -0
  26. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers.egg-info/SOURCES.txt +0 -0
  27. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers.egg-info/dependency_links.txt +0 -0
  28. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers.egg-info/requires.txt +0 -0
  29. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/dsa_helpers.egg-info/top_level.txt +0 -0
  30. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/readthedocs.yaml +0 -0
  31. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/requirements.txt +0 -0
  32. {dsa_helpers-0.4.dev0 → dsa_helpers-0.4.dev2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dsa_helpers
3
- Version: 0.4.dev0
3
+ Version: 0.4.dev2
4
4
  Summary: Utility functions for working with the DSA girder client.
5
5
  Author-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
6
6
  Maintainer-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
@@ -1,24 +1,37 @@
1
1
  from dash import html, dcc
2
2
  import dash_bootstrap_components as dbc
3
- from . import header_callbacks
3
+ from .header_callbacks import get_callbacks
4
4
 
5
5
 
6
- def get_header(title: str = "App", config: dict | None = None) -> html.Div:
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
- title (str): The title of the application.
12
- config (dict): The configuration of the component.
13
-
14
- backgroundColor
15
- titleColor
16
- fontColor
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="user-store", storage_type="local", data={}),
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
@@ -13,7 +13,7 @@ def get_mongo_client(
13
13
  username: str | None = None,
14
14
  password: str | None = None,
15
15
  port: int | None = None,
16
- ) -> pymongo.MongoClient:
16
+ ):
17
17
  """Get a mongo client by providing the key parts of the URL. By default
18
18
  when the parameters are not passed, it sets them to default values first
19
19
  by looking at key environment variables. If the environment variables are
@@ -36,7 +36,7 @@ def get_mongo_client(
36
36
  missing it will default to 27017.
37
37
 
38
38
  Returns:
39
- pymongo.MongoClient: The mongo client.
39
+ The mongo client.
40
40
 
41
41
  """
42
42
  if username is None:
@@ -67,7 +67,7 @@ def chunks(lst: list, n=500):
67
67
 
68
68
 
69
69
  def add_many_to_collection(
70
- mongo_collection: pymongo.collection.Collection,
70
+ mongo_collection,
71
71
  items: dict | list,
72
72
  key: str = "_id",
73
73
  ) -> dict[str | dict]:
@@ -75,7 +75,7 @@ def add_many_to_collection(
75
75
  user key.
76
76
 
77
77
  Args:
78
- mongo_collection (pymongo.collection.Collection): The mongo collection to add to.
78
+ mongo_collection: The mongo collection to add to.
79
79
  items (dict | list): The items to add to the collection.
80
80
  key (str): The key to use to identify the items.
81
81
 
@@ -100,13 +100,11 @@ def add_many_to_collection(
100
100
  return items
101
101
 
102
102
 
103
- def get_img_from_db(
104
- mongo_db: pymongo.database.Database, img_id: str
105
- ) -> Union[np.ndarray, None]:
103
+ def get_img_from_db(mongo_db, img_id: str) -> Union[np.ndarray, None]:
106
104
  """Get an image from the database by its location id.
107
105
 
108
106
  Args:
109
- mongo_db (pymongo.database.Database): The mongo database.
107
+ mongo_db: The mongo database.
110
108
  img_loc (str): The image id in mongo.
111
109
 
112
110
  Returns:
@@ -131,13 +129,13 @@ def get_img_from_db(
131
129
 
132
130
 
133
131
  def add_img_to_db(
134
- mongo_db: pymongo.database.Database,
132
+ mongo_db,
135
133
  img: Image.Image | np.ndarray,
136
134
  ) -> str:
137
135
  """Add an image to the database.
138
136
 
139
137
  Args:
140
- mongo_db (pymongo.database.Database): The mongo database.
138
+ mongo_db: The mongo database.
141
139
  img (np.ndarray or PIL.Image.Image): The image.
142
140
 
143
141
  Returns:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dsa_helpers
3
- Version: 0.4.dev0
3
+ Version: 0.4.dev2
4
4
  Summary: Utility functions for working with the DSA girder client.
5
5
  Author-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
6
6
  Maintainer-email: "Juan C. Vizcarra" <jvizcar@emory.edu>
@@ -31,7 +31,7 @@ classifiers = [
31
31
  "License :: OSI Approved :: MIT License",
32
32
  ]
33
33
  keywords = ["dsa", "girder", "girder_client"]
34
- version = "v0.4dev0"
34
+ version = "v0.4dev2"
35
35
 
36
36
  [project.urls]
37
37
  Repository = "https://github.com/Gutman-Lab/dsa-python-utils"
@@ -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