Source code for traveltimes_prediction.interface.prediction_manager

import datetime as dt
import logging
import time
import pytz
import collections
from copy import deepcopy

from ..configs import all_models, sections_settings, prediction_interval_seconds, sections_to_maintain

from . import SectionInterface
from ..data_processing import DBInterface
from ..support_files import ExtrapolatingCache
from ..support_files import MessageCodes

logger = logging.getLogger('traveltimes_prediction')


[docs]class PredictionManager: """ Class managing the prediction routine for all allowed sections. """ def __init__(self): """ Constructor. """ self.db_interface = DBInterface() self.training_manager_process = None # reserved self.maintained_sections = dict() self.buffer = dict() # storage of past traveltime values for individual sections (queue) self.max_traveltime = 7200 # @profile
[docs] def launch_prediction(self, sections=sections_to_maintain, prediction_interval_s=prediction_interval_seconds, test_dtime=None): """ Method for looped prediction of traveltime. :param list sections: list of all sections for which the prediction should be executed. :param number prediction_interval_s: how often should the manager execute prediction. :param datetime test_dtime: For TESTING PURPOSES -- artificial "now" datetime. """ self._initialize_prediction(sections=sections) dt_now = test_dtime if test_dtime is not None else dt.datetime.now() last_day = None while True: tick = time.time() # Prepare interval for data retrieval dt_now = (dt_now + dt.timedelta(seconds=60)) if test_dtime else dt.datetime.now() dt_delta_future = dt.timedelta(seconds=30) dt_delta_past = dt.timedelta(seconds=600) interval_now = {'from': dt_now - dt_delta_past, 'to': dt_now + dt_delta_future} results = [] for section in sections: # For each section execute prediction prediction_result = self.maintained_sections[section].predict(time_interval=interval_now, db_interface=self.db_interface) for model_prediction in prediction_result: pred_val = model_prediction['predicted_value'] if self.max_traveltime > pred_val > -1: # In case of valid prediction tmp_res = model_prediction self.buffer[section][model_prediction['model_type']].put(pred_val) logger.info("[%s] Prediction by model - %s: %s -- %s " % (section, model_prediction['model_type'], pred_val, dt_now.strftime("%Y-%m-%d %H:%M:%S"))) else: # In case of invalid prediction try to use cached values and extrapolate tmp_res = deepcopy(model_prediction) if model_prediction['model_type'] != -1: res = self.buffer[section][model_prediction['model_type']].get() \ if not self.buffer[section][model_prediction['model_type']].empty() else -1 tmp_res['messages'].append(MessageCodes.RESULT_EXTRAPOLATED) else: res = -1 tmp_res['predicted_value'] = res if pred_val > self.max_traveltime: tmp_res['messages'].append(MessageCodes.TOO_HIGH_TRAVELTIME) logger.warning("[%s] Too high traveltime predicted by model -- %s!! ", section, model_prediction['model_type']) logger.info("[%s] Result of prediction by model - %s - invalid, extrapolating and producing %s -- %s", section, model_prediction['model_type'], str(res), dt_now.strftime("%Y-%m-%d %H:%M:%S")) # Localize timezone -> for calculation_time (from calculation_time_local taken from BCK prediction) tzone = pytz.timezone(sections_settings[section]['timezone']) local_dt = tzone.localize(dt_now) utc_dt = local_dt.astimezone(pytz.utc) # Gave the tuple correct structure and order -> will be saved to DB rr = (section, utc_dt.strftime('%Y-%m-%d %H:%M:00'), dt_now.strftime('%Y-%m-%d %H:%M:00'), float(tmp_res['predicted_value'][0]) if isinstance(tmp_res['predicted_value'], collections.Iterable) else float(tmp_res['predicted_value']), tmp_res['model_type'], tmp_res['confidence'], str(tmp_res['messages']), tmp_res['delay']) results.append(rr) # Save prediction for all models and sections to DB. self.db_interface.save_prediction_result(rows=results) tock = time.time() logger.info("Results successfully saved to DB. Prediction loop took %.2f seconds", (tock-tick)) if prediction_interval_s - (tock - tick) > 0: time.sleep(prediction_interval_s - (tock - tick))
def _initialize_prediction(self, sections): """ Method for initializing the SerialManager`s attributes. :param list sections: list of sections for which the SectionInterfaces should be initialized """ for section in sections: models = list(all_models - sections_settings[section]['forbidden_models']) self.maintained_sections[section] = SectionInterface(section=section, models=models) self.buffer[section] = {model.name: ExtrapolatingCache() for model in models}