Open alexzwanenburg opened 2 weeks ago
I have been working on option 1, build the framework, and created an implementation for run length-matrix features. This seems to work quite well.
To do:
_compute_radiomics_features
into generate_features
so that generate_features
also computes feature values. A particular concern is that information required to compute features is cached until all features have been computed, which may be problematic for feature classes which store large sets of information (e.g. statistical features). It would be preferable to clear caches after the required data is no longer required.ibsi_compliant
attributes based on discretisation.
Proposal
MIRP currently uses a functional approach to computing features. Features are computed by sequentially from feature family-based methods. While this works for many applications, it has some drawbacks:
The proposal is to switch the current functional feature computation backend to a generator-based one.
Implementation
Features are computed from an image and a mask. These are pre-processed up to the point where feature computation takes place. Some features (e.g. statistical features) do not require additional processing, but others, e.g. texture features, do. This may involve image discretisation and computation of texture matrices.
The simplest approach is to have each feature as its own object class with methods for additional processing and computation. However, because these additional processing steps generally take the most time, their results should be shared between features to prevent degrading performance. What options do we have to achieve this?
functools.cache
. This would allow for caching processed results based on the input parameters of the function or method decorated using@cache
. This makes it possible generate feature objects directly. For consistency, consider making feature classes inherit from their family object and from an overarching processing object. important reminder: the wrapped method should not use internal (self
) attributes that determine the fingerprint of the method, but should pass them through the method arguments and it should return the processed data, not set it as an attribute internally. Therefore decorate using@staticmethod
and then@cache
. See here for more information. Additionally create a cache clearing method that callsself.wrapped_method.cache_clear()
internally to remove cached data after all features are computed. Since feature objects should persist until the programme ends, the cache would persist if not explicitly cleared.yield from
that produce the actual features. The minor disadvantage is that the logic for computing features from images cannot be contained entirely within their classes.