Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trigger an event in Python traits package when an Array element is changed

I'm using Python's traits package, and I'm trying to figure out the right way to use the traits.trait_numeric.Array class. It's straightforward to write a subclass of traits.api.HasTraits with an Array trait, so that when the Array changes, an on_trait_change is triggered, but I can't figure out how to trigger any sort of event when elements of the array are modified in place. Here is a minimal example:

from traits.api import HasTraits
from traits.trait_numeric import Array
import numpy as np

class C(HasTraits):
    x = Array
    def __init__(self):
        self.on_trait_event(self.do_something, 'x')
    def do_something(self):
        print 'Doing something'

c = C()

# This line calls do_something()
c.x = np.linspace(0,1,10)

# This one doesn't, and I wish it did
c.x[3] = 100

# Same with this one
c.x[:] = np.ones(c.x.shape)

I'm hoping there is some built in feature of traits.trait_numeric.Array that I don't know about, since detecting when part of an array has changed seems like a very standard thing to need.

Barring that, I think the problem might be solvable by making a custom trait class that also inherits numpy.array, then changing the [] operator so that it explicitly triggers the right kind of trait events. But hopefully that is a can of worms I won't have to open.

like image 690
Ben Fogelson Avatar asked Feb 16 '23 09:02

Ben Fogelson


1 Answers

I'm afraid that it's not really possible. numpy arrays view raw memory. Anything can change that memory without going through the numpy array object itself. The pattern we usually use is to reassign the whole array after doing the slice/index assignment.

import numpy as np
from traits.api import Array, HasTraits, NO_COMPARE


class C(HasTraits):
    x = Array(comparison_mode=NO_COMPARE)

    def _x_changed(self):
        print 'Doing something'


c = C()
c.x = np.linspace(0, 1, 10)

# This does not trigger:
c.x[3] = 100
# This does:
c.x = c.x
like image 175
Robert Kern Avatar answered Apr 28 '23 12:04

Robert Kern