Source code for pyclm.core.patterns.wave_patterns

import numpy as np

from .pattern import PatternMethod
from .zoo import ZooMeta


class WavePatternBase(PatternMethod):
    """
    Creates a WavePattern or StationaryWavePattern depending on the requested wavespeed
    """

    def __new__(cls, *args, **kwargs):
        if cls is WavePatternBase:  # Check if the base class is being instantiated
            if kwargs.get("wave_speed") != 0:
                return super().__new__(WavePattern)
            else:
                return super().__new__(StationaryWavePattern)
        return super().__new__(cls)

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        print(f"Initializing {self.__class__.__name__}")


[docs] class StationaryWavePattern(WavePatternBase): """ Wave coming out from the center """ name = "wave (stationary)" def __init__(self, duty_cycle=0.2, wave_speed=0, period=30, **kwargs): """ :param duty_cycle: fraction of time spent on (float 0-1), and consequently fraction of vertical axis containing "on" pixels :param wave_speed: speed in um/min :param period: period in um """ super().__init__(**kwargs) self.duty_cycle = duty_cycle self.wave_speed = 0 self.period_space = period # in um self.period_time = 0 # in minutes def generate(self, context): xx, yy = self.get_um_meshgrid() center_x, center_y = self.center_um() distance = np.sqrt((xx - center_x) ** 2 + (yy - center_y) ** 2) is_on = ((distance / self.period_space) % 1.0) < self.duty_cycle return is_on.astype(np.float16)
[docs] class WavePattern(WavePatternBase): """ moves a wave in or out of the center """ name = "wave" zoo_meta = ZooMeta( source="mdck", kwargs={"duty_cycle": 0.2, "wave_speed": 10, "period": 100, "direction": 1}, title="Radial Wave", description="Concentric rings propagating outward from the center.", ) def __init__(self, duty_cycle=0.2, wave_speed=1, period=30, direction=1, **kwargs): """ :param duty_cycle: fraction of time spent on (float 0-1), and consequently fraction of radial axis containing "on" pixels :param wave_speed: speed in um/min :param period: period in um :param direction: movement in/out relative to the center. 1 is out; -1 is in """ super().__init__(**kwargs) self.duty_cycle = duty_cycle self.wave_speed = wave_speed self.period_space = period # in um self.period_time = period / wave_speed # in minutes self.direction = direction def generate(self, context): t = context.time / 60 xx, yy = self.get_um_meshgrid() center_x, center_y = self.center_um() distance = np.sqrt((xx - center_x) ** 2 + (yy - center_y) ** 2) is_on = ( ((t * self.direction) - (distance / self.wave_speed)) % self.period_time ) < self.duty_cycle * self.period_time return is_on.astype(np.float16)