I’m looking to implement a pull model Dynamic Parameters for an expensive calculation that can return a large array of values. A series of different manipulations of the final array will be completed but it should never change as long as the dependent parameters within the parent class are not changed. It may never be accessed during the user’s analysis so I don’t want the force this calculation unnecessarily. I’m sure the approach I have working is probably a rather hackish approach to solving this problem but I have failed all other attempts. An Example of what I have working is as follows
import numpy as np
import param
class CachedExpensiveArray(param.Parameterized):
parent = param.Parameter()
cached_value = param.Parameter(default=None, allow_None=True)
def __call__(self):
if self.cached_value is None:
## Do some really expensive calculation and set the array values
print("Original Calc completed")
a = np.array([[self.parent.f1], [self.parent.f2], [self.parent.f3]])
self.cached_value = np.hstack((a, np.random.random((3,5))))
return self.cached_value
else:
print("Cached Result")
return self.cached_value
def clear(self):
self.cached_value = None
class TestClass(param.Parameterized):
p = param.Dynamic()
f1 = param.Number(1)
f2 = param.Number(2)
f3 = param.Number(3)
def __init__(self, **params):
super(TestClass, self).__init__(**params)
self.p = CachedExpensiveArray(parent=self)
@param.depends('f1','f2','f3', watch=True)
def _clear_cached_array(self):
self.p = CachedExpensiveArray(parent=self)
t = TestClass()
for i in range(3):
print(t.p)
this prints the following
Original Calc completed
[[1. 0.81225398 0.18993548 0.67357551 0.96969163 0.86284378]
[2. 0.75041076 0.40631964 0.83326135 0.7365204 0.98758376]
[3. 0.0938844 0.99253526 0.84002868 0.11344561 0.19863643]]
Cached Result
[[1. 0.81225398 0.18993548 0.67357551 0.96969163 0.86284378]
[2. 0.75041076 0.40631964 0.83326135 0.7365204 0.98758376]
[3. 0.0938844 0.99253526 0.84002868 0.11344561 0.19863643]]
Cached Result
[[1. 0.81225398 0.18993548 0.67357551 0.96969163 0.86284378]
[2. 0.75041076 0.40631964 0.83326135 0.7365204 0.98758376]
[3. 0.0938844 0.99253526 0.84002868 0.11344561 0.19863643]]
if I then change a parameter on the TestClass instance like this
t.f1 = 4
for i in range(3):
print(t.p)
I get the following
Original Calc completed
[[4. 0.84168804 0.52191216 0.55006135 0.85956553 0.52409848]
[2. 0.10932542 0.92722704 0.10955687 0.70387541 0.32335225]
[3. 0.83724005 0.82746697 0.17713918 0.94543894 0.69945296]]
Cached Result
[[4. 0.84168804 0.52191216 0.55006135 0.85956553 0.52409848]
[2. 0.10932542 0.92722704 0.10955687 0.70387541 0.32335225]
[3. 0.83724005 0.82746697 0.17713918 0.94543894 0.69945296]]
Cached Result
[[4. 0.84168804 0.52191216 0.55006135 0.85956553 0.52409848]
[2. 0.10932542 0.92722704 0.10955687 0.70387541 0.32335225]
[3. 0.83724005 0.82746697 0.17713918 0.94543894 0.69945296]]
so it appears to work.
I have a few questions
-
I use @param.depends to watch the parameters the calc depends on and then just bulk replace the
CachedExpensiveArray
object. I’m doing this because all attempts to reset the cached_value on the p param.Dynamic parameter toNone
from theTestClass
have failed and I can’t seem to use the param.watch pattern to connect parameter changes on theTestClass
to the clear method on theCachedExpensiveArray
instance. -
I assume I should probably by subclassing the param.Dynamic class to make a new parameter that does all of this but I have failed at successfully doing this as well.
-
Is there a way to access the param.owner parameter from the
CachedExpensiveArray
class rather than passing a parent? It seems to only be available after I instantiate theTestClass
which makes sense but it throws an error if I try to access it from within theCachedExpensiveArray
class.