def compute(self, fractions_dict, concentration_dict, start_date, end_date): """Compute and return the concentration time series. Parameters: * fractions_list -- dict of fractions timeseries in [0.0, 1.0] * concentration_list -- dict of label keys with concentration values in [mg/l] Computation is based on constant concentration of the fractions """ timeseries = SparseTimeseriesStub() for events in enumerate_dict_events(fractions_dict): date = events['date'] del(events['date']) concentration = 0 for key, value in events.items(): if key in ['intakes', 'defined_input']: for key_intake, value_intake in value.items(): if key_intake == 'intake_wl_control': concentration += value_intake[1] * concentration_dict[key_intake] else: concentration += value_intake[1] * concentration_dict[key_intake.label.program_name] else: concentration += value[1] * concentration_dict[key] timeseries.add_value(date, concentration) return timeseries
def compute(self, start_date, end_date, level_control_timeseries, # pylint: disable=C0301, R0201 measured_timeseries): """Compute and return the sluice error time series. The sluice error on a specific day is defined as the sum of the (calculated) level control intakes and pumps values minus the sum of the measured (non level control) intakes and pumps values. This function returns the sluice error time series as a SparseTimeseriesStub. Parameters: * level_control_timeseries * list of calculated time series of the level control intakes and pumps * measured_timeseries * list of measured time series of the (non level control) intakes and pumps * start_date * first date for which to compute the sluice error * end_date * date after the last date for which to compute the sluice error """ sluice_error_timeseries = SparseTimeseriesStub() timeseries = level_control_timeseries + \ [multiply_timeseries(ts, -1.0) for ts in measured_timeseries] for date, value in add_timeseries(*timeseries).events(): # pylint: disable=C0301, W0142 if date < start_date: continue elif date < end_date: sluice_error_timeseries.add_value(date, value) else: break return sluice_error_timeseries
def transform_evaporation_timeseries_penman_to_makkink(evaporation_timeseries): """Return the adjusted evaporation timeserie. Parameters: * evaporation_timeseries -- timeserie with evaporation [mm/day] """ result = SparseTimeseriesStub() month_factor = [0.400, 0.933, 1.267, 1.300, 1.300, 1.310, 1.267, 1.193, 1.170, 0.900, 0.700, 0.000] for evaporation_event in enumerate_events(evaporation_timeseries): month_number = evaporation_event[0][0].month factor = month_factor[month_number-1] result.add_value(evaporation_event[0][0], evaporation_event[0][1]*factor) return result
def compute(self, open_water, buckets_summary, precipitation, evaporation, seepage, infiltration, minimum_level_timeseries, maximum_level_timeseries, intakes_timeseries, pumps_timeseries, max_intake = None, max_outtake = None): """Compute and return the pair of intake and pump time series. This function returns the pair of SparseTimeseriesStub(s) that consists of the intake time series and pump time series for the given open water. Parameters: * open_water -- OpenWater for which to compute the level control * buckets_summary -- BucketsSummary with the summed buckets outcome * precipitation, * evaporation, * seepage, * infiltration * intakes_timeseries -- dict of intake timeseries in [m3/day] * pumps_timeseries -- dict of pump timeseries in [m3/day] """ storage = SparseTimeseriesStub() result = SparseTimeseriesStub() water_level_timeseries = SparseTimeseriesStub() pump_time_series = SparseTimeseriesStub() intake_time_series = SparseTimeseriesStub() total_incoming = SparseTimeseriesStub() total_outgoing = SparseTimeseriesStub() surface = 1.0 * open_water.surface water_level = open_water.init_water_level ts = {} ts['bucket_total_incoming'] = buckets_summary.total_incoming ts['bucket_total_outgoing'] = buckets_summary.total_outgoing ts['precipitation'] = precipitation ts['evaporation'] = evaporation ts['seepage'] = seepage ts['infiltration'] = infiltration ts['min_level'] = minimum_level_timeseries ts['max_level'] = maximum_level_timeseries ts['intakes'] = {} for intake, timeseries in intakes_timeseries.iteritems(): if not intake.computed_level_control: ts['intakes'][intake] = timeseries ts['pumps'] = {} for pump, timeseries in pumps_timeseries.iteritems(): if not pump.computed_level_control: ts['pumps'][pump] = timeseries for events in enumerate_dict_events(ts): date = events['date'] if self.inside_range(date) < 0: continue elif self.inside_range(date) > 0: break if not events.has_key('intakes'): events['intakes'] = {} incoming_value = [ events['bucket_total_outgoing'][1], events['precipitation'][1], events['seepage'][1]] + \ [event[1] for event in events['intakes'].values()] incoming_value = sum(incoming_value) if not events.has_key('pumps'): events['pumps'] = {} outgoing_value = [ events['bucket_total_incoming'][1], events['infiltration'][1], events['evaporation'][1]] + \ [event[1] for event in events['pumps'].values()] outgoing_value = sum(outgoing_value) water_level += (incoming_value + outgoing_value) / surface level_control = self._compute_level_control(surface, water_level, events['min_level'][1], events['max_level'][1]) if level_control < 0: if max_outtake is not None: pump = max(level_control, -1*max_outtake) else: pump = level_control intake = 0 else: pump = 0 if max_intake is not None: intake = min(level_control, max_intake) else: intake = level_control water_level += (pump + intake) / surface pump_time_series.add_value(date, pump) intake_time_series.add_value(date, intake) water_level_timeseries.add_value(date, water_level) storage_value = (water_level - open_water.bottom_height) * surface storage.add_value(date, storage_value) result.add_value(date, level_control) total_incoming.add_value(date, sum([incoming_value, intake])) total_outgoing.add_value(date, sum([outgoing_value, pump])) date += timedelta(1) return {'intake_wl_control':intake_time_series, 'outtake_wl_control':pump_time_series, 'storage':storage, 'water_level':water_level_timeseries, 'total_incoming':total_incoming, 'total_outgoing':total_outgoing}
def compute(self, inflow_dict, outflow_dict, storage, concentration_dict, start_date, end_date): """Compute and return the concentration time series. Parameters: * fractions_list -- dict of fractions timeseries in [0.0, 1.0] * concentration_list -- dict of label keys with concentration values in [mg/l] Computation is based on constant concentration of the fractions """ total_outflow = SparseTimeseriesStub() for events in enumerate_dict_events(outflow_dict): date = events['date'] del(events['evaporation']) del(events['date']) total= 0.0 for key, event in events.items(): if key in ['outtakes', 'defined_output']: for key_outtake, event_outtake in event.items(): total += event_outtake[1] else: total += event[1] total_outflow.add_value(date, total) start_storage = next(storage.events(start_date, end_date))[1] storage_chloride = start_storage * concentration_dict['initial'] delta = SparseTimeseriesStub() timeseries = SparseTimeseriesStub() for events in enumerate_dict_events(dict(tuple(inflow_dict.items()) + (('total_outflow', total_outflow), ('storage', storage)))): date = events['date'] if date < start_date: continue if date >= end_date: break total_outflow = -events['total_outflow'][1] storage = events['storage'][1] del(events['date']) del(events['total_outflow']) del(events['storage']) out = (storage_chloride/storage) * total_outflow plus = 0.0 for key, value in events.items(): if key in ['intakes', 'defined_input']: for key_intake, value_intake in value.items(): if key_intake == 'intake_wl_control': plus += value_intake[1] * concentration_dict[key_intake] else: plus += value_intake[1] * concentration_dict[key_intake.label.program_name] else: plus += value[1] * concentration_dict[key] storage_chloride = storage_chloride + plus - out timeseries.add_value(date, storage_chloride/storage) delta.add_value(date, plus - out) return timeseries, delta
def get_input_timeseries(self, start_date, end_date): """return (and collect) all input timeseries Args: *start_date* date of the first day for which to compute the time series *end_date* date of the day *after* the last day for which to compute the time series This method returns a tuple that contains 1. a dictionary with all input timeseries. - precipitation - evaporation - seepage - open_water minimum_level/maximum_level - incoming_timeseries[intake] """ if (self.input.has_key('timeseries') and self.input_info['timeseries']['start_date']==start_date and self.input_info['timeseries']['end_date']>=end_date): return self.input['timeseries'] else: logger.debug("get input timeseries (%s - %s)..." % ( start_date.strftime('%Y-%m-%d'), end_date.strftime('%Y-%m-%d'))) input_ts = {} input_ts['precipitation'] = SparseTimeseriesStub() for event in self.configuration.retrieve_precipitation(start_date, end_date).events(): input_ts['precipitation'].add_value(event[0], event[1]) input_ts['evaporation'] = SparseTimeseriesStub() for event in self.configuration.retrieve_evaporation(start_date, end_date).events(): input_ts['evaporation'].add_value(event[0], event[1]) input_ts['seepage'] = SparseTimeseriesStub() for event in self.configuration.retrieve_seepage(start_date, end_date).events(): #for the time_being, officially part of each bucket + openwater input_ts['seepage'].add_value(event[0], event[1]) input_ts['sewer'] = self.configuration.open_water.retrieve_sewer(start_date, end_date) input_ts['open_water'] = {} input_ts['open_water']['minimum_level'] = self.configuration.open_water.retrieve_minimum_level(start_date, end_date) input_ts['open_water']['maximum_level'] = self.configuration.open_water.retrieve_maximum_level(start_date, end_date) input_ts['open_water']['seepage'] = input_ts['seepage'] for bucket in self.configuration.retrieve_buckets(): input_ts[bucket] = {} input_ts[bucket]['seepage'] = bucket.retrieve_seepage(start_date, end_date) input_ts['incoming_timeseries'] = {} for intake, timeseries in self.configuration.open_water.retrieve_incoming_timeseries(only_input=False).iteritems(): sparse_timeseries = SparseTimeseriesStub() for event in timeseries.events(): sparse_timeseries.add_value(event[0], event[1]) input_ts['incoming_timeseries'][intake] = TimeseriesRestrictedStub(timeseries=sparse_timeseries, start_date=start_date, end_date=end_date) input_ts['outgoing_timeseries'] = {} for pump, timeseries in self.configuration.open_water.retrieve_outgoing_timeseries(only_input=False).iteritems(): input_ts['outgoing_timeseries'][pump] = TimeseriesRestrictedStub(timeseries=timeseries, start_date=start_date, end_date=end_date) #store for later use (some kind of cache) self.input['timeseries'] = input_ts self.input_info['timeseries'] = {} self.input_info['timeseries']['start_date'] = start_date self.input_info['timeseries']['end_date'] = end_date self.updated = True return input_ts
def compute(self, open_water, buckets_summary, precipitation_timeseries, seepage_timeseries, storage_timeseries, total_output_timeseries, intakes_timeseries, start_date, end_date): """Compute and return the fraction series. This function returns the pair of SparseTimeseriesStub(s) that consists of the intake time series and pump time series for the given open water. Parameters: * open_water -- OpenWater for which to compute the fractions * buckets_summary -- BucketsSummary with the summed buckets outcome * precipitation, * seepage, * storage_timeseries -- storage time series in [m3/day] * intakes_timeseries -- list of intake timeseries in [m3/day] """ fractions_initial = SparseTimeseriesStub() fractions_precipitation = SparseTimeseriesStub() fractions_seepage = SparseTimeseriesStub() fractions_hardened = SparseTimeseriesStub() fractions_sewer = SparseTimeseriesStub() fractions_drained = SparseTimeseriesStub() fractions_undrained = SparseTimeseriesStub() fractions_flow_off = SparseTimeseriesStub() fractions_intakes = {} for key in intakes_timeseries.keys(): fractions_intakes[key] = SparseTimeseriesStub() previous_initial = 100.0 previous_precipitation = 0.0 previous_seepage = 0.0 previous_hardened = 0.0 previous_sewer = 0.0 previous_drained = 0.0 previous_undrained = 0.0 previous_flow_off = 0.0 previous_intakes = {} for key in intakes_timeseries.keys(): previous_intakes[key] = 0.0 previous_storage = self.initial_storage(open_water) ts = {} ts['hardened'] = buckets_summary.hardened ts['drained'] = buckets_summary.drained ts['undrained'] = buckets_summary.undrained ts['flow_off'] = buckets_summary.flow_off ts['precipitation'] = precipitation_timeseries ts['seepage'] = seepage_timeseries ts['sewer'] = buckets_summary.sewer ts['storage'] = storage_timeseries ts['total_output'] = total_output_timeseries ts['intakes'] = intakes_timeseries first = True for events in enumerate_dict_events(ts): date = events['date'] if date < start_date: continue if date >= end_date: break if first: first = False previous_storage = (open_water.init_water_level - open_water.bottom_height) * open_water.surface total_output = -1 * events['total_output'][1] current_storage = events['storage'][1] initial = self.compute_fraction(0, total_output, current_storage, previous_initial, previous_storage) precipitation = self.compute_fraction(events['precipitation'][1], total_output, current_storage, previous_precipitation, previous_storage) seepage = self.compute_fraction(events['seepage'][1], total_output, current_storage, previous_seepage, previous_storage) hardened = self.compute_fraction(events['hardened'][1], total_output, current_storage, previous_hardened, previous_storage) sewer = self.compute_fraction(events['sewer'][1], total_output, current_storage, previous_sewer, previous_storage) drained = self.compute_fraction(events['drained'][1], total_output, current_storage, previous_drained, previous_storage) undrained = self.compute_fraction(events['undrained'][1], total_output, current_storage, previous_undrained, previous_storage) flow_off = self.compute_fraction(events['flow_off'][1], total_output, current_storage, previous_flow_off, previous_storage) intakes = {} for key, intake_timeserie in events['intakes'].items(): intakes[key] = self.compute_fraction(intake_timeserie[1], total_output, current_storage, previous_intakes[key], previous_storage) # Due to rounding errors, the sum of the fractions is seldom equal # to 1.0. As the fraction of the next day depends on the fraction # of the previous day, this effect gets worse over time. To avoid # this effect, we divide each fraction by the sum of fractions. total_fractions = initial + precipitation + seepage + sewer + hardened + \ drained + undrained + flow_off + sum(intakes.values()) #TO DO: dit is een correctie die niet mogelijk hoeft te zijn. graag een alert als dit niet klopt #initial /= total_fractions #precipitation /= total_fractions #seepage /= total_fractions #hardened /= total_fractions #drained /= total_fractions #undrained /= total_fractions #flow_off /= total_fractions #intakes = [intake / total_fractions for intake in intakes] fractions_initial.add_value(date, initial) previous_initial = initial fractions_precipitation.add_value(date, precipitation) previous_precipitation = precipitation fractions_seepage.add_value(date, seepage) previous_seepage = seepage fractions_hardened.add_value(date, hardened) previous_hardened = hardened fractions_sewer.add_value(date, sewer) previous_sewer = sewer fractions_drained.add_value(date, drained) previous_drained = drained fractions_undrained.add_value(date, undrained) previous_undrained = undrained fractions_flow_off.add_value(date, flow_off) previous_flow_off = flow_off previous_intakes = {} for key in intakes.keys(): fractions_intakes[key].add_value(date, intakes[key]) previous_intakes[key] = intakes[key] previous_storage = current_storage result = {'initial':fractions_initial, 'precipitation':fractions_precipitation, 'seepage':fractions_seepage, 'hardened':fractions_hardened, 'drained':fractions_drained, 'sewer':fractions_sewer, 'undrained':fractions_undrained, 'flow_off':fractions_flow_off, 'intakes': {} } for key in intakes_timeseries.keys(): result['intakes'][key] = fractions_intakes[key] return result