Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

160 clean up abstractspotanalysisimageprocessor #162

Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ecb3054
combine AbstractSpotAnalysisImageProcessor and AbstractSpotAnalysisIm…
bbean23 Aug 14, 2024
2461661
move cacheing functionality from AbstractSpotAnalysisImageProcessor t…
bbean23 Aug 14, 2024
54e132d
add process_images() method to AbstractSpotAnalysisImageProcessor
bbean23 Aug 14, 2024
9de7087
add unit tests for CacheableImage.__init__(), fix __init__()
bbean23 Aug 15, 2024
e8c46e4
fix CacheableImage._register* by making it static instead of a class …
bbean23 Aug 15, 2024
cd44fd4
add test for CacheableImage memory usage
bbean23 Aug 15, 2024
315b5a8
remove unnecessary CacheableImage.cached field, better docstrings
bbean23 Aug 15, 2024
c0e6b4d
small fixes and code cleanup
bbean23 Aug 15, 2024
e04962a
add test_CacheableImage.test_cache() method, fix CacheableImage.cache…
bbean23 Aug 15, 2024
0e7440a
better behavior for CacheableImage properties
bbean23 Aug 19, 2024
a98f401
fix CacheableImage.cache(), test CacheableImage.lru()
bbean23 Aug 19, 2024
6f59509
forgot input data for the CacheableImage tests
bbean23 Aug 20, 2024
8326b32
add most basic test for AbstractSpotAnalysisImageProcessor
bbean23 Aug 20, 2024
4bea2bc
whoops that's not supposed to be here yet
bbean23 Aug 20, 2024
db503b0
add test_AbstractSpotAnalysisImageProcess.test_finished()
bbean23 Aug 20, 2024
af3c34d
add test_CacheableImage.test_save_image()
bbean23 Aug 20, 2024
e49fe33
add test_run(), fix type hint
bbean23 Aug 20, 2024
7cb6771
add test_process_operable() and test_process_images()
bbean23 Aug 20, 2024
0d1cbda
increasing the delta to enable more difference between array sizes on…
bbean23 Sep 6, 2024
e3595aa
Apply suggestions from code review
bbean23 Nov 5, 2024
7ba1981
Apply suggestions from code review
bbean23 Nov 5, 2024
972fd10
Apply suggestions from code review
bbean23 Nov 5, 2024
a8f9e1e
add image_tools.getsizeof_approx() method to get the in-memory size o…
bbean23 Nov 6, 2024
3c217fa
actually include the size of the image in the CacheableImage's memory…
bbean23 Nov 6, 2024
fe3cd68
implement changes suggested in PR #162
bbean23 Nov 6, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
535 changes: 491 additions & 44 deletions opencsp/common/lib/cv/CacheableImage.py

Large diffs are not rendered by default.

11 changes: 1 addition & 10 deletions opencsp/common/lib/cv/SpotAnalysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,15 +190,6 @@ def set_image_processors(self, image_processors: list[asaip.AbstractSpotAnalysis
self.visualization_coordinator.clear()
self.visualization_coordinator.register_visualization_processors(image_processors)

# limit the amount of memory that image processors utilize
from opencsp.common.lib.cv.spot_analysis.image_processor.AbstractSpotAnalysisImageProcessorLeger import (
image_processors_persistant_memory_total,
)

mem_per_image_processor = image_processors_persistant_memory_total / len(self.image_processors)
for image_processor in self.image_processors:
image_processor._allowed_memory_footprint = mem_per_image_processor

# assign the input stream to the first image processor
if self.input_stream != None:
self._assign_inputs(self.input_stream)
Expand Down Expand Up @@ -263,7 +254,7 @@ def process_next(self):

# Release memory from the previous result
if self._prev_result is not None:
self.image_processors[-1].cache_image_to_disk_as_necessary(self._prev_result)
self.image_processors[-1].cache_images_to_disk_as_necessary()
self._prev_result = None

# Attempt to get the next image. Raises StopIteration if there are no
Expand Down
49 changes: 33 additions & 16 deletions opencsp/common/lib/cv/spot_analysis/SpotAnalysisOperable.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,13 @@ def __post_init__(self):
requires_update = True

# record the primary image source, if not available already
if primary_image_source_path == None:
if primary_image.source_path != None:
if primary_image_source_path is None:
if primary_image.source_path is not None:
primary_image_source_path = primary_image.source_path
else:
primary_image_source_path = primary_image.cache_path
requires_update = True

# set the source path on the cacheable instance of the primary image
if primary_image.source_path == None:
if primary_image_source_path != None:
primary_image.source_path = primary_image_source_path
if primary_image_source_path is not None:
requires_update = True

if requires_update:
# use __init__ to update frozen values
Expand All @@ -114,8 +110,21 @@ def __post_init__(self):
self.image_processor_notes,
)

def __sizeof__(self) -> int:
return sys.getsizeof(self.primary_image) + sum([sys.getsizeof(im) for im in self.supporting_images.values()])
def get_all_images(self, primary=True, supporting=True, visualization=True, algorithm=True) -> list[CacheableImage]:
bbean23 marked this conversation as resolved.
Show resolved Hide resolved
"""
Get a list of all images tracked by this operable including all primary
images, supporting images, visualization, and algorithm images.
"""
bbean23 marked this conversation as resolved.
Show resolved Hide resolved
ret: list[CacheableImage] = []

if primary:
ret.append(self.primary_image)

if supporting:
for image_type in self.supporting_images:
ret.append(self.supporting_images[image_type])

return ret

def replace_use_default_values(
self, supporting_images: dict[ImageType, CacheableImage] = None, data: 'SpotAnalysisOperable' = None
Expand All @@ -125,13 +134,13 @@ def replace_use_default_values(
values."""
ret = self

if supporting_images != None:
if supporting_images is not None:
for image_type in supporting_images:
if (image_type in ret.supporting_images) and (ret.supporting_images[image_type] != None):
if (image_type in ret.supporting_images) and (ret.supporting_images[image_type] is not None):
supporting_images[image_type] = ret.supporting_images[image_type]
ret = replace(ret, supporting_images=supporting_images)

if data != None:
if data is not None:
given_fiducials = data.given_fiducials if len(self.given_fiducials) == 0 else self.given_fiducials
found_fiducials = data.found_fiducials if len(self.found_fiducials) == 0 else self.found_fiducials
annotations = data.annotations if len(self.annotations) == 0 else self.annotations
Expand Down Expand Up @@ -180,7 +189,7 @@ def get_primary_path_nameext(self) -> tuple[str, str]:
if image_name is not None and image_name != "":
break

if image_name == None or image_name == "":
if image_name is None or image_name == "":
ret_path, ret_name_ext = "unknown_path", "unknown_image"
else:
ret_path, name, ext = ft.path_components(image_name)
Expand All @@ -202,7 +211,7 @@ def best_primary_pathnameext(self) -> str:
def max_popf(self) -> npt.NDArray[np.float_]:
"""Returns the maximum population float value, if it exists. Otherwise
returns the maximum value for this instance's primary image."""
if self.population_statistics != None:
if self.population_statistics is not None:
return self.population_statistics.maxf
else:
return np.max(self.primary_image.nparray)
Expand All @@ -211,7 +220,7 @@ def max_popf(self) -> npt.NDArray[np.float_]:
def min_popf(self) -> npt.NDArray[np.float_]:
"""Returns the minimum population float value, if it exists. Otherwise
returns the minimum value for this instance's primary image."""
if self.population_statistics != None:
if self.population_statistics is not None:
return self.population_statistics.minf
else:
return np.min(self.primary_image.nparray)
Expand All @@ -233,3 +242,11 @@ def get_fiducials_by_type(
+ f"found 0 fiducials matching type {fiducial_type.__name__} for image {self.best_primary_pathnameext}"
)
return ret

def __sizeof__(self) -> int:
"""
Get the size of this operable in memory including all primary images,
supporting images, and visualization images.
"""
all_images_size = sum([sys.getsizeof(im) for im in self.get_all_images()])
bbean23 marked this conversation as resolved.
Show resolved Hide resolved
return all_images_size
Loading