def test_simple_time_range(self): events = [ Time('2020-02-10', step='5m'), Linear(start=0, step=1), Linear(start=0, step=-1), ] history = History() history.start(events_count=len(events)) for _ in range(10): for position, event in enumerate(events): event.position = position history.set_event(event, event.generate()) self.assertEqual([10, 9, 8], list(history.get_range(1, '15m'))) self.assertEqual([-10, -9, -8], list(history.get_range(2, '15m'))) self.assertEqual([10, 9, 8], list(history.get_range(1, '720s')))
class Generator: EMPTY_VALUE = None def __init__(self, sequential: bool = False): self.__events = [] self.__sequential = sequential self.history = History() self.__add_event(Time(shadow=True)) def generate(self, samples: int = 3) -> pd.DataFrame: data = pd.DataFrame() self.history.start(events_count=len(self.__events)) default_sample = { event.label: self.EMPTY_VALUE for event in self.get_events() } events = self.get_events() position = 1 while len(data) < samples: sample = default_sample.copy() if self.__sequential: # Process only one event at a time, but always process time. events = [self.get_events()[0], self.get_events()[position]] position = position % (len(self.__events) - 1) + 1 for event in events: # Allow event to be executed regarding its probability, if not event.draw(): continue value = event.generate() if value is not None: self.history.set_event(event, value) sample[event.label] = value # Only add sample if it is not empty. if not all(value is None for value in list(sample.values())[1:]): data = data.append(sample, ignore_index=True) # Convert columns to specified data type. for event in events: data[event.label] = data[event.label].astype(event.data_type) # Remove shadow causes from generator. columns = [event.label for event in events if event.shadow] data = data.drop(columns, axis=1) # Remove line breaks in column names. data.columns = data.columns.str.replace("\n", " ") return data def get_events(self, include_shadow: bool = True) -> List[EventInterface]: return self.__events if include_shadow else [ event for event in self.__events if not event.shadow ] def __add_event(self, event: EventInterface) -> Generator: event.setup(self.__events) self.__events.append(event) return self def add_function(self, event_function: Callable[[History], float], **kwargs) -> Generator: return self.__add_event( Function(event_function, self.history, **kwargs)) def add_uniform(self, min: int = 0, max: int = 10, **kwargs) -> Generator: return self.__add_event(Uniform(min, max, **kwargs)) def add_gaussian(self, mu: float = 0, sigma: float = 1, **kwargs) -> Generator: return self.__add_event(Gaussian(mu, sigma, **kwargs)) def add_discrete(self, samples: int = 2, weights: tuple = None, data_type=int, **kwargs) -> Generator: return self.__add_event( Discrete(samples, weights, data_type=data_type, **kwargs)) def add_linear(self, start: float = 0, step: float = 1, **kwargs) -> Generator: return self.__add_event(Linear(start, step, **kwargs)) def add_constant(self, value: float = 1, **kwargs) -> Generator: return self.__add_event(Constant(value, **kwargs)) def add_categorical(self, values: tuple = (0, 1), weights: tuple = None, data_type=str, **kwargs) -> Generator: return self.__add_event( Categorical(values, weights, data_type=data_type, **kwargs)) def set_time(self, start_date: str = None, step: str = '1m', precision: str = None, **kwargs) -> Generator: event = Time(start_date, step, precision, **kwargs) event.setup(events=[]) self.__events[0] = event return self def get_time(self) -> Time: return self.__events[0] def build_relations(self, include_shadow=True) -> List[Relation]: return RelationFactory.build_relations(self.get_events(), include_shadow) def plot_relations(self, fig_size=(4, 3), node_size=20, include_shadow=True, dpi=None): RelationPlot.show(self.get_events(), self.build_relations(include_shadow), fig_size, node_size * 100, dpi=dpi)