dsa-helpers 0.2__tar.gz → 0.3.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dsa_helpers
3
- Version: 0.2
3
+ Version: 0.3.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>
@@ -14,6 +14,8 @@ License-File: LICENSE
14
14
  Requires-Dist: girder-client==3.2.3
15
15
  Requires-Dist: numpy==2.0.0
16
16
  Requires-Dist: setuptools==71.0.3
17
+ Requires-Dist: opencv-python==4.10.0.84
18
+ Requires-Dist: pandas==2.2.2
17
19
 
18
20
  # Digital Slide Archive (DSA) Helpers
19
21
  Digital Slide Archive Python utility library.
@@ -0,0 +1,7 @@
1
+ # Shadow imports.
2
+ from .login import login
3
+ from .imread import imread
4
+ from .imwrite import imwrite
5
+
6
+ # Modules that should be available.
7
+ from . import girder_utils, image_utils
@@ -43,18 +43,14 @@ def get_thumbnail(
43
43
  Returns:
44
44
  np.ndarray: The thumbnail image.
45
45
 
46
- Raises:
47
- ValueError: If neither mag, width, nor height is provided.
48
-
49
46
  """
50
- if all([mag is None, width is None, height is None]):
51
- raise ValueError("Either mag, width, or height must be provided.")
47
+ get_url = f"item/{item_id}/tiles/"
52
48
 
53
49
  if mag is not None:
54
- get_url = f"item/{item_id}/tiles/region?magnification{mag}"
50
+ get_url += f"region?magnification={mag}&encoding=pickle"
55
51
  else:
56
52
  # Instead use width and height.
57
- get_url = f"item/{item_id}/tiles/thumbnail?"
53
+ params = ["encoding=pickle"]
58
54
 
59
55
  if width is not None and height is not None:
60
56
  if isinstance(fill, (tuple, list)):
@@ -63,13 +59,13 @@ def get_thumbnail(
63
59
  elif len(fill) == 4:
64
60
  fill = f"rgba({fill[0]},{fill[1]},{fill[2]},{fill[3]})"
65
61
 
66
- get_url += f"width={width}&height={height}&fill={fill}"
62
+ params.extend([f"width={width}", f"height={height}", f"fill={fill}"])
67
63
  elif width is not None:
68
- get_url += f"width={width}"
69
- else:
70
- get_url += f"height={height}"
64
+ params.append(f"width={width}")
65
+ elif height is not None:
66
+ params.append(f"height={height}")
71
67
 
72
- get_url += "&encoding=pickle"
68
+ get_url += "thumbnail?" + "&".join(params)
73
69
 
74
70
  response = gc.get(get_url, jsonResp=False)
75
71
 
@@ -0,0 +1,65 @@
1
+ # Functions for working images.
2
+ import numpy as np
3
+ import pandas as pd
4
+ from pathlib import Path
5
+ import cv2 as cv
6
+ from . import imwrite
7
+
8
+
9
+ def tile_image(
10
+ img: np.ndarray,
11
+ save_loc: str,
12
+ tile_size: int,
13
+ stride: int | None = None,
14
+ fill: int | tuple = (255, 255, 255),
15
+ prepend_name: str = "",
16
+ ) -> pd.DataFrame:
17
+ """Tile an image into smaller images.
18
+
19
+ Args:
20
+ img (np.ndarray): The image to tile.
21
+ save_loc (str): The location to save the tiles.
22
+ tile_size (int): The size of the tiles.
23
+ stride (int | None, optional): The stride for the tiles. Defaults to None,
24
+ in which case it is set equal to tile_size.
25
+ fill (int | tuple, optional): The fill value for tiles over the edges.
26
+ Defaults to (255, 255, 255).
27
+ prepend_name (str, optional): A string to prepend to the tile names.
28
+
29
+ Returns:
30
+ pandas.DataFrame: A DataFrame with the tile locations.
31
+
32
+ """
33
+ h, w = img.shape[:2]
34
+
35
+ img = cv.copyMakeBorder(
36
+ img, 0, tile_size, 0, tile_size, cv.BORDER_CONSTANT, value=fill
37
+ )
38
+
39
+ # Pad the image to avoid tiles not of the right size.
40
+ save_loc = Path(save_loc)
41
+
42
+ if not save_loc.exists():
43
+ save_loc.mkdir(parents=True)
44
+
45
+ if stride is None:
46
+ stride = tile_size
47
+
48
+ df_data = []
49
+
50
+ xys = [(x, y) for x in range(0, w, stride) for y in range(0, h, stride)]
51
+
52
+ for xy in xys:
53
+ x, y = xy
54
+ # Get the tile from the image.
55
+ tile_img = img[x : x + tile_size, y : y + tile_size]
56
+
57
+ save_fp = str(save_loc.joinpath(f"{prepend_name}x-{x}y-{y}.png"))
58
+
59
+ imwrite(save_fp, tile_img)
60
+
61
+ df_data.append([save_fp, x, y])
62
+
63
+ df = pd.DataFrame(df_data, columns=["fp", "x", "y"])
64
+
65
+ return df
@@ -0,0 +1,32 @@
1
+ # Function to read image from disk.
2
+ import cv2 as cv
3
+ import numpy as np
4
+
5
+
6
+ def imread(fp: str, grayscale: bool = False) -> np.ndarray:
7
+ """Read image from disk. Currently does not support reading RGBA images.
8
+
9
+ Args:
10
+ fp (str): The file path to save the image.
11
+ grayscale (bool, optional): If True, the image will be read as grayscale.
12
+ Defaults to False.
13
+
14
+ Returns:
15
+ np.ndarray: The image read from disk.
16
+
17
+ """
18
+ if grayscale:
19
+ img = cv.imread(fp, cv.IMREAD_GRAYSCALE)
20
+ else:
21
+ img = cv.imread(fp, cv.IMREAD_UNCHANGED)
22
+
23
+ # Convert the image from OpenCV's BGR to RGB.
24
+ shape = img.shape
25
+
26
+ if len(shape) == 3:
27
+ if shape[2] == 3:
28
+ img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
29
+ elif shape[2] == 4:
30
+ img = cv.cvtColor(img, cv.COLOR_RGBA2BGRA)
31
+
32
+ return img
@@ -0,0 +1,37 @@
1
+ # Function to save image to disk.
2
+ import cv2 as cv
3
+ import numpy as np
4
+
5
+
6
+ def imwrite(fp: str, img: np.ndarray, grayscale: bool = False) -> None:
7
+ """Save an image to disk.
8
+
9
+ Args:
10
+ img (np.ndarray): The image to save.
11
+ fp (str): The file path to save the image.
12
+ grayscale (bool, optional): Whether to save the image as grayscale.
13
+ Defaults to False.
14
+
15
+ Raises:
16
+ ValueError: The image must be grayscale, RGB, or RGBA.
17
+
18
+ """
19
+ if grayscale:
20
+ if len(img.shape) == 2:
21
+ _ = cv.imwrite(fp, img)
22
+ else:
23
+ _ = cv.imwrite(fp, cv.cvtColor(img, cv.COLOR_RGB2GRAY))
24
+ else:
25
+ shape = img.shape
26
+
27
+ if len(shape) == 2:
28
+ _ = cv.imwrite(fp)
29
+ elif len(shape) == 3:
30
+ if shape[2] == 3:
31
+ _ = cv.imwrite(fp, cv.cvtColor(img, cv.COLOR_RGB2BGR))
32
+ elif shape[2] == 4:
33
+ _ = cv.imwrite(fp, cv.cvtColor(img, cv.COLOR_RGBA2BGRA))
34
+ else:
35
+ raise ValueError("The image must be grayscale, RGB, or RGBA.")
36
+ else:
37
+ raise ValueError("The image must be grayscale, RGB, or RGBA.")
@@ -20,13 +20,7 @@ def login(
20
20
  Returns:
21
21
  girder_client.GirderClient: The authenticated girder client.
22
22
 
23
- Raises:
24
- ValueError: If neither login_or_email nor api_key is provided.
25
-
26
23
  """
27
- if login_or_email is None and api_key is None:
28
- raise ValueError("Either login_or_email or api_key must be provided.")
29
-
30
24
  gc = GirderClient(apiUrl=api_url)
31
25
 
32
26
  if api_key is None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dsa_helpers
3
- Version: 0.2
3
+ Version: 0.3.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>
@@ -14,6 +14,8 @@ License-File: LICENSE
14
14
  Requires-Dist: girder-client==3.2.3
15
15
  Requires-Dist: numpy==2.0.0
16
16
  Requires-Dist: setuptools==71.0.3
17
+ Requires-Dist: opencv-python==4.10.0.84
18
+ Requires-Dist: pandas==2.2.2
17
19
 
18
20
  # Digital Slide Archive (DSA) Helpers
19
21
  Digital Slide Archive Python utility library.
@@ -5,10 +5,12 @@ pyproject.toml
5
5
  requirements.txt
6
6
  dsa_helpers/__init__.py
7
7
  dsa_helpers/girder_utils.py
8
+ dsa_helpers/image_utils.py
9
+ dsa_helpers/imread.py
10
+ dsa_helpers/imwrite.py
8
11
  dsa_helpers/login.py
9
12
  dsa_helpers.egg-info/PKG-INFO
10
13
  dsa_helpers.egg-info/SOURCES.txt
11
14
  dsa_helpers.egg-info/dependency_links.txt
12
15
  dsa_helpers.egg-info/requires.txt
13
- dsa_helpers.egg-info/top_level.txt
14
- tests/general-tests.py
16
+ dsa_helpers.egg-info/top_level.txt
@@ -0,0 +1,5 @@
1
+ girder-client==3.2.3
2
+ numpy==2.0.0
3
+ setuptools==71.0.3
4
+ opencv-python==4.10.0.84
5
+ pandas==2.2.2
@@ -6,7 +6,9 @@ build-backend = "setuptools.build_meta"
6
6
  dependencies = [
7
7
  'girder-client==3.2.3',
8
8
  'numpy==2.0.0',
9
- 'setuptools==71.0.3'
9
+ 'setuptools==71.0.3',
10
+ 'opencv-python==4.10.0.84',
11
+ 'pandas==2.2.2'
10
12
  ]
11
13
  name = "dsa_helpers"
12
14
  authors = [
@@ -23,7 +25,7 @@ classifiers = [
23
25
  "License :: OSI Approved :: MIT License",
24
26
  ]
25
27
  keywords = ["dsa", "girder", "girder_client"]
26
- version = "v0.2"
28
+ version = "v0.3dev"
27
29
 
28
30
  [project.urls]
29
31
  Repository = "https://github.com/Gutman-Lab/dsa-python-utils"
@@ -1,3 +1,5 @@
1
+ setuptools==71.0.3
1
2
  girder-client==3.2.3
2
3
  numpy==2.0.0
3
- setuptools==71.0.3
4
+ opencv-python==4.10.0.84
5
+ pandas==2.2.2
@@ -1,5 +0,0 @@
1
- # Shadow imports.
2
- from .login import login
3
-
4
- # Modules that should be available.
5
- from . import girder_utils
@@ -1,3 +0,0 @@
1
- setuptools==71.0.3
2
- girder-client==3.2.3
3
- numpy==2.0.0
@@ -1,11 +0,0 @@
1
- # Run various tests on the dash_utils module.
2
- import dsa_utils as du
3
-
4
-
5
- def main():
6
- # Use this script to test out various development functions.
7
- pass
8
-
9
-
10
- if __name__ == "__main__":
11
- main()
File without changes
File without changes
File without changes
File without changes