dsa-helpers 0.4__tar.gz → 0.4.dev0__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 (43) hide show
  1. {dsa_helpers-0.4/dsa_helpers.egg-info → dsa_helpers-0.4.dev0}/PKG-INFO +2 -8
  2. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/README.md +2 -4
  3. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/__init__.py +1 -1
  4. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/dash/header.py +21 -31
  5. dsa_helpers-0.4.dev0/dsa_helpers/dash/header_callbacks.py +98 -0
  6. dsa_helpers-0.4.dev0/dsa_helpers/ml/__init__.py +2 -0
  7. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/mongo_utils.py +14 -10
  8. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0/dsa_helpers.egg-info}/PKG-INFO +2 -8
  9. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers.egg-info/SOURCES.txt +2 -12
  10. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers.egg-info/requires.txt +0 -4
  11. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/pyproject.toml +2 -6
  12. dsa_helpers-0.4.dev0/readthedocs.yaml +27 -0
  13. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/requirements.txt +1 -5
  14. dsa_helpers-0.4/dsa_helpers/dash/header_callbacks.py +0 -99
  15. dsa_helpers-0.4/dsa_helpers/ml/__init__.py +0 -2
  16. dsa_helpers-0.4/dsa_helpers/ml/datasets/SegFormerSegmentationDataset.py +0 -33
  17. dsa_helpers-0.4/dsa_helpers/ml/datasets/__init__.py +0 -3
  18. dsa_helpers-0.4/dsa_helpers/ml/datasets/utils.py +0 -42
  19. dsa_helpers-0.4/dsa_helpers/ml/metrics/__init__.py +0 -3
  20. dsa_helpers-0.4/dsa_helpers/ml/metrics/binary_dice_coefficient_metric.py +0 -24
  21. dsa_helpers-0.4/dsa_helpers/ml/transforms/__init__.py +0 -1
  22. dsa_helpers-0.4/dsa_helpers/ml/transforms/segformer_transforms.py +0 -23
  23. dsa_helpers-0.4/dsa_helpers/utils.py +0 -28
  24. dsa_helpers-0.4/tests/app/Dockerfile +0 -18
  25. dsa_helpers-0.4/tests/app/app.py +0 -55
  26. dsa_helpers-0.4/tests/docker-compose.yaml +0 -31
  27. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/.gitignore +0 -0
  28. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/LICENSE +0 -0
  29. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/app.py +0 -0
  30. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/dash/__init__.py +0 -0
  31. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/girder_utils.py +0 -0
  32. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/image_utils.py +0 -0
  33. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/imread.py +0 -0
  34. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/imwrite.py +0 -0
  35. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/login.py +0 -0
  36. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/ml/object_detection/__init__.py +0 -0
  37. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/ml/object_detection/get_pearce_roi_images.py +0 -0
  38. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/ml/object_detection/tile_image.py +0 -0
  39. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers/ml/object_detection/utils.py +0 -0
  40. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers.egg-info/dependency_links.txt +0 -0
  41. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/dsa_helpers.egg-info/top_level.txt +0 -0
  42. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/setup.cfg +0 -0
  43. {dsa_helpers-0.4 → dsa_helpers-0.4.dev0}/tests/test.ipynb +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dsa_helpers
3
- Version: 0.4
3
+ Version: 0.4.dev0
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>
@@ -22,10 +22,6 @@ Requires-Dist: dash
22
22
  Requires-Dist: dash_bootstrap_components
23
23
  Requires-Dist: shapely
24
24
  Requires-Dist: geopandas
25
- Requires-Dist: torch
26
- Requires-Dist: datasets
27
- Requires-Dist: transformers
28
- Requires-Dist: torchvision
29
25
 
30
26
  # Digital Slide Archive (DSA) Helpers
31
27
  Digital Slide Archive Python utility library.
@@ -40,11 +36,9 @@ This Python PyPI package is found [here](https://pypi.org/project/dsa-helpers/).
40
36
  1. Install requirements for building and distributing package:
41
37
  ```
42
38
  $ python3 -m pip install --upgrade build # for building package
43
- $ python3 -m pip install --upgrade twine # for uploading to PyPI
39
+ $ python3 -m pip install --upgrade build # for uploading to PyPI
44
40
  ```
45
41
  2. When ready to build:
46
42
  - Modify "pyproject.toml" file, change the "version" key to a different value than a version already pushed.
47
43
  - Run ```$ python3 -m build```. This will create a dist directory and put your new wheel and tar distribution files there.
48
44
  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.
@@ -11,11 +11,9 @@ This Python PyPI package is found [here](https://pypi.org/project/dsa-helpers/).
11
11
  1. Install requirements for building and distributing package:
12
12
  ```
13
13
  $ python3 -m pip install --upgrade build # for building package
14
- $ python3 -m pip install --upgrade twine # for uploading to PyPI
14
+ $ python3 -m pip install --upgrade build # for uploading to PyPI
15
15
  ```
16
16
  2. When ready to build:
17
17
  - Modify "pyproject.toml" file, change the "version" key to a different value than a version already pushed.
18
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.
19
+ 3. To install locally for development: ```$ pip3 install dist/dsa_helpers-*.whl```, choosing the wheel version you want to test.
@@ -5,4 +5,4 @@ from .imwrite import imwrite
5
5
  # Modules that should be available.
6
6
  # from . import girder_utils, image_utils, dash
7
7
 
8
- __all__ = ["girder_utils", "image_utils", "dash", "ml"]
8
+ __all__ = ["girder_utils", "image_utils", "dash"]
@@ -1,37 +1,24 @@
1
1
  from dash import html, dcc
2
2
  import dash_bootstrap_components as dbc
3
- from .header_callbacks import get_callbacks
3
+ from . import header_callbacks
4
4
 
5
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:
6
+ def get_header(title: str = "App", config: dict | None = None) -> html.Div:
12
7
  """Get the Dash html component that contains the header of the application
13
8
  with login capabilities.
14
9
 
15
10
  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
- }
11
+ title (str): The title of the application.
12
+ config (dict): The configuration of the component.
13
+
14
+ backgroundColor
15
+ titleColor
16
+ fontColor
25
17
 
26
18
  Returns:
27
19
  html.Div: The header component.
28
20
 
29
21
  """
30
- if config is None:
31
- config = {}
32
-
33
- get_callbacks(dsa_api_url, store_id)
34
-
35
22
  login_modal = dbc.Modal(
36
23
  [
37
24
  dbc.ModalHeader("Log in"),
@@ -41,7 +28,7 @@ def get_header(
41
28
  "Login or email", style={"margin": 5, "fontWeight": "bold"}
42
29
  ),
43
30
  dbc.Input(
44
- id=f"{store_id}=login",
31
+ id="login",
45
32
  type="text",
46
33
  placeholder="Enter login",
47
34
  style={"margin": 5},
@@ -51,7 +38,7 @@ def get_header(
51
38
  style={"margin": 5, "marginTop": 15, "fontWeight": "bold"},
52
39
  ),
53
40
  dbc.Input(
54
- id=f"{store_id}=password",
41
+ id="password",
55
42
  type="password",
56
43
  placeholder="Enter password",
57
44
  style={"margin": 5},
@@ -59,7 +46,7 @@ def get_header(
59
46
  html.Div(
60
47
  "Login failed.",
61
48
  hidden=True,
62
- id=f"{store_id}=login-failed",
49
+ id="login-failed",
63
50
  style={"color": "red", "fontWeight": "bold", "margin": 10},
64
51
  ),
65
52
  ],
@@ -70,7 +57,7 @@ def get_header(
70
57
  dbc.Col(
71
58
  dbc.Button(
72
59
  "Close",
73
- id=f"{store_id}=close-login-modal",
60
+ id="close-login-modal",
74
61
  className="me-1",
75
62
  color="light",
76
63
  )
@@ -78,7 +65,7 @@ def get_header(
78
65
  dbc.Col(
79
66
  dbc.Button(
80
67
  "Login",
81
- id=f"{store_id}=log-in-btn",
68
+ id="log-in-btn",
82
69
  className="me-1",
83
70
  color="primary",
84
71
  )
@@ -88,7 +75,7 @@ def get_header(
88
75
  ),
89
76
  ],
90
77
  is_open=False,
91
- id=f"{store_id}=login-modal",
78
+ id="login-modal",
92
79
  )
93
80
 
94
81
  logout_modal = dbc.Modal(
@@ -97,7 +84,7 @@ def get_header(
97
84
  [
98
85
  dbc.Button(
99
86
  "Log out",
100
- id=f"{store_id}=logout-btn",
87
+ id="logout-btn",
101
88
  color="danger",
102
89
  className="me-1",
103
90
  ),
@@ -105,9 +92,12 @@ def get_header(
105
92
  )
106
93
  ],
107
94
  is_open=False,
108
- id=f"{store_id}=logout-modal",
95
+ id="logout-modal",
109
96
  )
110
97
 
98
+ if config is None:
99
+ config = {}
100
+
111
101
  return html.Div(
112
102
  [
113
103
  dbc.Row(
@@ -126,7 +116,7 @@ def get_header(
126
116
  dbc.Col(
127
117
  dbc.Button(
128
118
  "Log in",
129
- id=f"{store_id}=login-btn",
119
+ id="login-btn",
130
120
  color=config.get("backgroundColor", "#012169"),
131
121
  style={
132
122
  "color": config.get("fontColor", "#f2a900"),
@@ -142,7 +132,7 @@ def get_header(
142
132
  ),
143
133
  login_modal,
144
134
  logout_modal,
145
- dcc.Store(id=store_id, storage_type="local", data={}),
135
+ dcc.Store(id="user-store", storage_type="local", data={}),
146
136
  ],
147
137
  style={
148
138
  "backgroundColor": config.get("backgroundColor", "#012169"),
@@ -0,0 +1,98 @@
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
@@ -0,0 +1,2 @@
1
+ # Modules that can be imported.
2
+ __all__ = ["object_detection"]
@@ -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
- ):
16
+ ) -> pymongo.MongoClient:
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
- The mongo client.
39
+ pymongo.MongoClient: 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,
70
+ mongo_collection: pymongo.collection.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: The mongo collection to add to.
78
+ mongo_collection (pymongo.collection.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
 
@@ -89,8 +89,10 @@ def add_many_to_collection(
89
89
 
90
90
  operations = []
91
91
 
92
- for _id, item in items.items():
93
- operations.append(pymongo.UpdateOne({"_id": _id}, {"$set": item}, upsert=True))
92
+ for item in items:
93
+ operations.append(
94
+ pymongo.UpdateOne({"_id": item[key]}, {"$set": item}, upsert=True)
95
+ )
94
96
 
95
97
  for chunk in chunks(operations):
96
98
  _ = mongo_collection.bulk_write(chunk)
@@ -98,11 +100,13 @@ def add_many_to_collection(
98
100
  return items
99
101
 
100
102
 
101
- def get_img_from_db(mongo_db, img_id: str) -> Union[np.ndarray, None]:
103
+ def get_img_from_db(
104
+ mongo_db: pymongo.database.Database, img_id: str
105
+ ) -> Union[np.ndarray, None]:
102
106
  """Get an image from the database by its location id.
103
107
 
104
108
  Args:
105
- mongo_db: The mongo database.
109
+ mongo_db (pymongo.database.Database): The mongo database.
106
110
  img_loc (str): The image id in mongo.
107
111
 
108
112
  Returns:
@@ -127,13 +131,13 @@ def get_img_from_db(mongo_db, img_id: str) -> Union[np.ndarray, None]:
127
131
 
128
132
 
129
133
  def add_img_to_db(
130
- mongo_db,
134
+ mongo_db: pymongo.database.Database,
131
135
  img: Image.Image | np.ndarray,
132
136
  ) -> str:
133
137
  """Add an image to the database.
134
138
 
135
139
  Args:
136
- mongo_db: The mongo database.
140
+ mongo_db (pymongo.database.Database): The mongo database.
137
141
  img (np.ndarray or PIL.Image.Image): The image.
138
142
 
139
143
  Returns:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dsa_helpers
3
- Version: 0.4
3
+ Version: 0.4.dev0
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>
@@ -22,10 +22,6 @@ Requires-Dist: dash
22
22
  Requires-Dist: dash_bootstrap_components
23
23
  Requires-Dist: shapely
24
24
  Requires-Dist: geopandas
25
- Requires-Dist: torch
26
- Requires-Dist: datasets
27
- Requires-Dist: transformers
28
- Requires-Dist: torchvision
29
25
 
30
26
  # Digital Slide Archive (DSA) Helpers
31
27
  Digital Slide Archive Python utility library.
@@ -40,11 +36,9 @@ This Python PyPI package is found [here](https://pypi.org/project/dsa-helpers/).
40
36
  1. Install requirements for building and distributing package:
41
37
  ```
42
38
  $ python3 -m pip install --upgrade build # for building package
43
- $ python3 -m pip install --upgrade twine # for uploading to PyPI
39
+ $ python3 -m pip install --upgrade build # for uploading to PyPI
44
40
  ```
45
41
  2. When ready to build:
46
42
  - Modify "pyproject.toml" file, change the "version" key to a different value than a version already pushed.
47
43
  - Run ```$ python3 -m build```. This will create a dist directory and put your new wheel and tar distribution files there.
48
44
  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.
@@ -3,6 +3,7 @@ LICENSE
3
3
  README.md
4
4
  app.py
5
5
  pyproject.toml
6
+ readthedocs.yaml
6
7
  requirements.txt
7
8
  dsa_helpers/__init__.py
8
9
  dsa_helpers/girder_utils.py
@@ -11,7 +12,6 @@ dsa_helpers/imread.py
11
12
  dsa_helpers/imwrite.py
12
13
  dsa_helpers/login.py
13
14
  dsa_helpers/mongo_utils.py
14
- dsa_helpers/utils.py
15
15
  dsa_helpers.egg-info/PKG-INFO
16
16
  dsa_helpers.egg-info/SOURCES.txt
17
17
  dsa_helpers.egg-info/dependency_links.txt
@@ -21,18 +21,8 @@ dsa_helpers/dash/__init__.py
21
21
  dsa_helpers/dash/header.py
22
22
  dsa_helpers/dash/header_callbacks.py
23
23
  dsa_helpers/ml/__init__.py
24
- dsa_helpers/ml/datasets/SegFormerSegmentationDataset.py
25
- dsa_helpers/ml/datasets/__init__.py
26
- dsa_helpers/ml/datasets/utils.py
27
- dsa_helpers/ml/metrics/__init__.py
28
- dsa_helpers/ml/metrics/binary_dice_coefficient_metric.py
29
24
  dsa_helpers/ml/object_detection/__init__.py
30
25
  dsa_helpers/ml/object_detection/get_pearce_roi_images.py
31
26
  dsa_helpers/ml/object_detection/tile_image.py
32
27
  dsa_helpers/ml/object_detection/utils.py
33
- dsa_helpers/ml/transforms/__init__.py
34
- dsa_helpers/ml/transforms/segformer_transforms.py
35
- tests/docker-compose.yaml
36
- tests/test.ipynb
37
- tests/app/Dockerfile
38
- tests/app/app.py
28
+ tests/test.ipynb
@@ -9,7 +9,3 @@ dash
9
9
  dash_bootstrap_components
10
10
  shapely
11
11
  geopandas
12
- torch
13
- datasets
14
- transformers
15
- torchvision
@@ -14,11 +14,7 @@ dependencies = [
14
14
  'dash',
15
15
  'dash_bootstrap_components',
16
16
  'shapely',
17
- 'geopandas',
18
- "torch",
19
- "datasets",
20
- "transformers",
21
- "torchvision"
17
+ 'geopandas'
22
18
  ]
23
19
  name = "dsa_helpers"
24
20
  authors = [
@@ -35,7 +31,7 @@ classifiers = [
35
31
  "License :: OSI Approved :: MIT License",
36
32
  ]
37
33
  keywords = ["dsa", "girder", "girder_client"]
38
- version = "v0.4"
34
+ version = "v0.4dev0"
39
35
 
40
36
  [project.urls]
41
37
  Repository = "https://github.com/Gutman-Lab/dsa-python-utils"
@@ -0,0 +1,27 @@
1
+ # .readthedocs.yaml
2
+ # Read the Docs configuration file
3
+ # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
4
+
5
+ # Required
6
+ version: 2
7
+
8
+ # Set the OS, Python version and other tools you might need
9
+ build:
10
+ tools:
11
+ python: "3.9"
12
+
13
+ # Build documentation in the "docs/" directory with Sphinx
14
+ sphinx:
15
+ configuration: docs/conf.py
16
+
17
+ # Optionally build your docs in additional formats such as PDF and ePub
18
+ # formats:
19
+ # - pdf
20
+ # - epub
21
+
22
+ # Optional but recommended, declare the Python requirements required
23
+ # to build your documentation
24
+ # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
25
+ # python:
26
+ # install:
27
+ # - requirements: docs/requirements.txt
@@ -8,8 +8,4 @@ jupyter
8
8
  pillow
9
9
  dash
10
10
  dash_bootstrap_components
11
- python-dotenv
12
- torch
13
- datasets
14
- transformers
15
- torchvision
11
+ python-dotenv
@@ -1,99 +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
-
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
@@ -1,2 +0,0 @@
1
- # Modules that can be imported.
2
- __all__ = ["object_detection", "datasets", "metrics", "transforms"]
@@ -1,33 +0,0 @@
1
- from torch.utils.data import Dataset
2
- import pandas as pd
3
- from PIL import Image
4
- import numpy as np
5
-
6
-
7
- class SegFormerSegmentationDataset(Dataset):
8
- """PyTorch dataset class for semantic segmentation using HuggingFaces SegFormer
9
- model.
10
-
11
- """
12
-
13
- def __init__(self, df: pd.DataFrame):
14
- """Initiate an instance of the segmentation dataset.
15
-
16
- Args:
17
- df (pandas.DataFrame): A pandas DataFrame with columns "fp" and "mask_fp".
18
-
19
- """
20
- self.image_files = df["fp"].tolist()
21
- self.mask_files = df["mask_fp"].tolist()
22
- self.df = df # store potential metadata
23
-
24
- def __len__(self):
25
- return len(self.image_files)
26
-
27
- def __getitem__(self, idx):
28
- # Get the filepath to the image and its mask.
29
- image_path = self.image_files[idx]
30
- mask_path = self.mask_files[idx]
31
-
32
- # Return image & mask as PIL images in a dictionary.
33
- return {"pixel_values": Image.open(image_path), "label": Image.open(mask_path)}
@@ -1,3 +0,0 @@
1
- from .SegFormerSegmentationDataset import SegFormerSegmentationDataset
2
-
3
- __all__ = ["SegFormerSegmentationDataset", "utils"]
@@ -1,42 +0,0 @@
1
- # Utility functions, usualy for creating Datasets in specific formats.
2
- import pandas as pd
3
- from .SegFormerSegmentationDataset import SegFormerSegmentationDataset
4
- from datasets import Dataset, Features, Image
5
-
6
-
7
- def dataset_generator(dataset):
8
- """Yield a dataset."""
9
- for item in dataset:
10
- yield item
11
-
12
-
13
- def create_segformer_segmentation_dataset(
14
- df: pd.DataFrame | str, low_memory: bool = True, transforms=None
15
- ):
16
- """Create a SegFormer segmentation dataset from a DataFrame.
17
-
18
- Args:
19
- df (pd.DataFrame | str): A pandas DataFrame with columns "fp" and "mask_fp" or a
20
- path to a CSV file.
21
- low_memory (bool): Whether to read the CSV file in low memory mode.
22
- transforms: A function that takes in a batch of samples (dictionary with
23
- pixel_values and label keys) and returns a transformed batch.
24
-
25
- Returns:
26
- A Dataset object to be used for HuggingFaces SegFormer model training.
27
-
28
- """
29
- if isinstance(df, str):
30
- df = pd.read_csv(df, low_memory=low_memory)
31
-
32
- dataset = SegFormerSegmentationDataset(df)
33
-
34
- dataset = Dataset.from_generator(
35
- generator=lambda: dataset_generator(dataset),
36
- features=Features({"pixel_values": Image(), "label": Image()}), # Example shape
37
- )
38
-
39
- if transforms is not None:
40
- dataset.set_transform(transforms)
41
-
42
- return dataset
@@ -1,3 +0,0 @@
1
- from .binary_dice_coefficient_metric import binary_dice_coefficient_metric
2
-
3
- __all__ = ["binary_dice_coefficient_metric"]
@@ -1,24 +0,0 @@
1
- import torch
2
- from torch import nn
3
- from ...utils import binary_dice_coefficient
4
-
5
-
6
- def binary_dice_coefficient_metric(eval_pred):
7
- with torch.no_grad():
8
- logits, labels = eval_pred # assumed both are numpy
9
-
10
- logits_tensor = torch.from_numpy(logits).cpu()
11
- labels_tensor = torch.from_numpy(labels).cpu()
12
-
13
- # Scale the logits to the size of the label.
14
- logits_tensor = nn.functional.interpolate(
15
- logits_tensor,
16
- size=labels.shape[-2:],
17
- mode="bilinear",
18
- align_corners=False,
19
- ).argmax(dim=1)
20
-
21
- pred_labels = logits_tensor.detach().numpy()
22
- labels = labels_tensor.numpy()
23
-
24
- return {"dice_coefficient": binary_dice_coefficient(pred_labels, labels)}
@@ -1 +0,0 @@
1
- __all__ = ["segformer_transforms"]
@@ -1,23 +0,0 @@
1
- from transformers import SegformerImageProcessor
2
- from torchvision.transforms import ColorJitter
3
-
4
-
5
- def train_transforms(example_batch):
6
- """Default transforms for training images."""
7
- processor = SegformerImageProcessor() # required for using SegFormer model.
8
- jitter = ColorJitter(brightness=0.25, contrast=0.25, saturation=0.25, hue=0.1)
9
-
10
- images = [jitter(x) for x in example_batch["pixel_values"]]
11
- labels = [x for x in example_batch["label"]]
12
- inputs = processor(images, labels)
13
- return inputs
14
-
15
-
16
- def val_transforms(example_batch):
17
- """Default transforms for validation images."""
18
- processor = SegformerImageProcessor() # required for using SegFormer model.
19
-
20
- images = [x for x in example_batch["pixel_values"]]
21
- labels = [x for x in example_batch["label"]]
22
- inputs = processor(images, labels)
23
- return inputs
@@ -1,28 +0,0 @@
1
- # Basic utility functions.
2
- import numpy as np
3
-
4
-
5
- def binary_dice_coefficient(mask1: np.ndarray, mask2: np.ndarray) -> float:
6
- """Calculate the dice coefficient between two binary masks.
7
-
8
- Args:
9
- mask1 (np.ndarray): A binary mask.
10
- mask2 (np.ndarray): A binary mask.
11
-
12
- Returns:
13
- float: The dice coefficient between the two masks.
14
-
15
- """
16
- # Convert the masks to binary.
17
- mask1 = mask1 > 0
18
- mask2 = mask2 > 0
19
-
20
- # Calculate dice.
21
- intersection = np.sum(mask1 * mask2)
22
-
23
- sum_masks = np.sum(mask1) + np.sum(mask2)
24
-
25
- if sum_masks == 0:
26
- return 1.0 # Both masks are empty
27
-
28
- return 2.0 * intersection / sum_masks
@@ -1,18 +0,0 @@
1
- FROM python:3.11-slim-buster
2
-
3
- ENV PYTHONUNBUFFERED True
4
-
5
- RUN apt-get update && apt-get install ffmpeg libsm6 libxext6 -y
6
-
7
- WORKDIR /app
8
-
9
- COPY requirements.txt /app
10
-
11
- RUN pip install --upgrade pip
12
-
13
- RUN python -m pip install pymongo==4.9.1
14
-
15
- RUN pip install --no-cache-dir -r requirements.txt
16
-
17
- COPY dsa_helpers-0.4.dev1-py3-none-any.whl /app
18
- RUN pip install dsa_helpers-0.4.dev1-py3-none-any.whl
@@ -1,55 +0,0 @@
1
- from dash import html, Dash, callback, Output, Input, State, no_update
2
- import dash_bootstrap_components as dbc
3
- from dsa_helpers.dash.header import get_header
4
- from os import getenv
5
- from dash_ag_grid import AgGrid
6
-
7
- table = AgGrid(
8
- id="table",
9
- columnDefs=[],
10
- rowData=[],
11
- )
12
-
13
- app = Dash(
14
- __name__,
15
- external_stylesheets=[
16
- dbc.themes.BOOTSTRAP,
17
- ],
18
- title="Test Application",
19
- )
20
-
21
- app.layout = html.Div(
22
- [
23
- get_header(
24
- getenv("DSA_API_URL"),
25
- title="Test Application",
26
- store_id="user-store",
27
- ),
28
- dbc.Row(
29
- [dbc.Col(dbc.Button("Get items", id="get-item-btn"), width="auto")],
30
- justify="start",
31
- ),
32
- table
33
- ]
34
- )
35
-
36
-
37
- @callback(
38
- [
39
- Output("table", "columnDefs"),
40
- Output("table", "rowData"),
41
- ],
42
- Input("get-item-btn", "n_clicks"),
43
- prevent_initial_call=True,
44
- )
45
- def get_items(n_clicks):
46
- """Get the items."""
47
-
48
-
49
-
50
- if __name__ == "__main__":
51
- app.run(
52
- host="0.0.0.0",
53
- port=8060,
54
- debug=True,
55
- )
@@ -1,31 +0,0 @@
1
- volumes:
2
- mongodb-data-volume:
3
-
4
- services:
5
- mongodb:
6
- image: mongo:7.0.6-jammy
7
- restart: always
8
- platform: linux/amd64
9
- container_name: mongodb
10
- volumes:
11
- - mongodb-data-volume:/data/db
12
- ports:
13
- - 27017:27017
14
- env_file: .env
15
- command: [ "--quiet", "--maxConns", "1000" ]
16
- logging:
17
- options:
18
- max-size: "10M"
19
- max-file: "5"
20
-
21
- dash:
22
- build: app/
23
- platform: linux/amd64
24
- volumes:
25
- - ./app:/app
26
- ports:
27
- - 8060:8060
28
- env_file: .env
29
- command: python app.py
30
- depends_on:
31
- - mongodb
File without changes
File without changes
File without changes
File without changes