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, 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 compute(self,
                flow_dict, concentration_dict,
                start_date, end_date, nutricalc_timeseries=None):
        """Compute and return the concentration time series.

        Parameters:
          *flow_list*
            dictionary of incoming waterflows
          *concentration_list*
            dict of label keys with concentration values in [mg/l]

        This method returns a dictionary of flow to time series. The flow can
        be (specified by) a string such as 'precipitation', 'seepage' or
        'drained', or can be (specified by) a PumpingStation.

        In an earlier version of this method the keys of the returned
        dictionary where always a string but that has been changed to solve the
        problem reported in ticket:2542.

        Remarks:
          * flows_dict['defined_input'] is a dictionary from intake to time
            series
          * this method would benefit from additional documentation and a
            review

        """

        loads = {}

        if nutricalc_timeseries:
            flow_dict['nutricalc'] = nutricalc_timeseries

        first_ts = True
        for events in enumerate_dict_events(flow_dict):
            date = events['date']
            if date < start_date:
                continue
            if date >= end_date:
                break

            del(events['date'])

            if nutricalc_timeseries:
                del(events['drained'])
                del(events['undrained'])

            for key, value in events.items():
                # key never seems to be equal to 'intakes'
                if key in ['intakes', 'defined_input']:
                    for key_intake, value_intake in value.items():
                        if key_intake == 'intake_wl_control':
                            # if key is indeed never equal to 'intakes',
                            # key_intake will never be equal to
                            # 'intake_wl_control'
                            load = value_intake[1] * \
                                   concentration_dict[key_intake]
                            label = 'intake_wl_control'
                        else:
                            load = value_intake[1] * \
                                   concentration_dict[key_intake.label.program_name]
                            label = key_intake
                elif key == 'nutricalc':
                    label = key
                    load = value[1]
                else:
                    label = key
                    load = value[1] * concentration_dict[key]

                if first_ts:
                    loads[label] = TimeseriesStub()

                loads[label].add_value(date, load)
            first_ts = False

        return loads
def export_excel_small(request, area_slug, scenario_slug):
    """ export van een configuratie naar Excel """

    t1 = time.time()

    bucket_export = False

    configuration = WaterbalanceConf.objects.get(
        waterbalance_area__slug=area_slug,
        waterbalance_scenario__slug=scenario_slug)

    waterbalance_computer = \
        CachedWaterbalanceComputer(CacheKeyName(configuration), configuration)

    logger.debug("%s seconds - got waterbalance computer", time.time() - t1)

    start_date = configuration.calculation_start_date
    end_date = datetime.now()
    end_date = datetime(end_date.year, end_date.month, end_date.day)

    excel_template = pkg_resources.resource_filename("lizard_waterbalance",
                                                     "/templates/lizard_waterbalance/excel_export_template.xls")

    rb = xlrd.open_workbook(excel_template, on_demand=True)
    wb = copy(rb)

    logger.debug("%s seconds - opened excel template", time.time() - t1)

    input_ts = waterbalance_computer.get_input_timeseries(start_date, end_date)
    buckets_summary = waterbalance_computer.get_bucketflow_summary(start_date, end_date)

    #bakjes export
    if bucket_export:

        if u'bakjes' in rb.sheet_names():
            sheet = wb.sheet_by_name(u'bakjes')
        else:
            sheet = wb.add_sheet('bakje')

        buckets = waterbalance_computer.get_buckets_timeseries(start_date, end_date)

        #TO DO: afmaken


    sheet = wb.get_sheet(0)
    #tests
    buckets_summary = waterbalance_computer.get_bucketflow_summary(start_date, end_date)
    vertical_openwater = waterbalance_computer.get_vertical_open_water_timeseries(start_date, end_date)
    level_control = waterbalance_computer.get_level_control_timeseries(start_date, end_date)
    fractions = waterbalance_computer.get_fraction_timeseries(start_date, end_date)
    sluice_error = waterbalance_computer.calc_sluice_error_timeseries(start_date, end_date)
    chloride_concentration, delta_concentration = waterbalance_computer.get_concentration_timeseries(start_date, end_date)
    impact_minimum, impact_incremental = waterbalance_computer.get_impact_timeseries(start_date, end_date)

    logger.debug("%s seconds - got all values", time.time() - t1)

    #combine cols of table
    header = ['year', 'month', 'day']
    data_cols = {}
    data_cols[(2, 'neerslag', '[mm/dag]')] = input_ts['precipitation']
    data_cols[(3, 'verdamping', '[mm/dag]')] = input_ts['evaporation']
    data_cols[(5, 'min peil', '[mNAP]')] = configuration.open_water.minimum_level.get_timeseries()
    data_cols[(7, 'neerslag', '[mNAP]')] = configuration.open_water.maximum_level.get_timeseries()
#    try:
#        data_cols[(6, 'streefpeil', '[mNAP]')] = configuration.open_water.target_level.get_timeseries()
#    except:
#        pass

    #in
    data_cols[(9, 'neerslag', '[m3/dag]')] = vertical_openwater['precipitation']
    data_cols[(10, 'verdamping', '[m3/dag]')] = vertical_openwater['seepage']
    data_cols[(11, 'verhard', '[m3/dag]')] = buckets_summary.hardened
    data_cols[(12, 'riolering', '[m3/dag]')] = buckets_summary.sewer
    data_cols[(13, 'gedraineerd', '[m3/dag]')] = buckets_summary.drained
    data_cols[(14, 'uitspoelig', '[m3/dag]')] = buckets_summary.undrained
    data_cols[(15, 'afstroming', '[m3/dag]')] = buckets_summary.flow_off
    col = 16
    for intake, timeserie in input_ts['incoming_timeseries'].items():
        data_cols[(col, str(intake), '[m3/dag]')] = timeserie
        col = col + 1

    data_cols[(20, 'inlaat peilhandhaving', '[m3/dag]')] = level_control["intake_wl_control"]

    #uit
    data_cols[(22, 'verdamping', '[m3/dag]')] = vertical_openwater['evaporation']
    data_cols[(23, 'wegzijiging', '[m3/dag]')] = vertical_openwater['infiltration']
    data_cols[(24, 'intrek', '[m3/dag]')] = buckets_summary.indraft
    data_cols[(29, 'uitlaat', '[m3/dag]')] = level_control["outtake_wl_control"]

    #totaal
    data_cols[(32, 'totaal in', '[m3/dag]')] = level_control['total_incoming']
    data_cols[(33, 'totaal uit', '[m3/dag]')] = level_control['total_outgoing']
    data_cols[(35, 'berekend waterpeil', '[mNAP]')] = level_control['water_level']
    data_cols[(36, 'berekende berging', '[m3]')] = level_control['storage']

    data_cols[(50, 'verschil chloride', '[g]')] = delta_concentration
    data_cols[(51, 'chloride concentratie', '[mg/l]')] = chloride_concentration

    #fracties
    data_cols[(68, 'fractie initieel', '[-]')] = fractions['initial']
    data_cols[(69, 'fractie neerslag', '[-]')] = fractions['precipitation']
    data_cols[(70, 'fractie kwel', '[-]')] = fractions['seepage']
    data_cols[(71, 'fractie verhard', '[-]')] = fractions['hardened']
    data_cols[(72, 'fractie riolering', '[-]')] = fractions['sewer']
    data_cols[(73, 'fractie gedraineerd', '[-]')] = fractions['drained']
    data_cols[(74, 'fractie uitspoeling', '[-]')] = fractions['undrained']
    data_cols[(75, 'fractie uitstroom', '[-]')] = fractions['flow_off']
    colnr = 76
    for key, item in fractions['intakes'].items():
        data_cols[(colnr, 'fractie %s'%str(key), '[-]')] = item
        colnr = colnr + 1

    data_cols[(108, 'sluitfout', '[m3/dag]')] = sluice_error

    colnr = 135
    for key, item in impact_minimum.items():
        data_cols[(colnr, 'min fosfaatb %s'%str(key), '[mg/m2/dag]' )] = item
        colnr = colnr + 1

    colnr = colnr + 1

    for key, item in impact_incremental.items():
        data_cols[(colnr, 'incr fosfaatb %s'%str(key), '[mg/m2/dag]')] = item
        colnr = colnr + 1

    start_row = 13
    row = start_row


    excel_date_fmt = 'D/M/YY'
    style = xlwt.XFStyle()
    style.num_format_str = excel_date_fmt

    logger.debug("%s seconds - referenced all values", time.time() - t1)

    sheet.write(10,0,'datum')
    for key in data_cols.keys():
        sheet.write(10,key[0],key[1])
        sheet.write(11,key[0],key[2])

    for event_dict in enumerate_dict_events(data_cols):
        date = event_dict['date']
        sheet.write(row,0,date, style)
        for key, event in event_dict.items():
            if not key == 'date':
                sheet.write(row,key[0],event[1])

        row = row + 1
        if date > end_date:
            break

    #for max: Formula('MAX(A1:B1)')
    buffer = StringIO()
    wb.save(buffer)
    del wb
    logger.debug("%s seconds - saved excel file to memory", time.time() - t1)

    buffer.seek(0)
    response = HttpResponse(buffer.read(), mimetype='xls')
    today = datetime.now()
    response['Content-Disposition'] = \
                'attachment; filename=wb_export_%s_%s_%i-%i-%i.xls'% \
                    (configuration.waterbalance_area.slug[:25],
                     configuration.waterbalance_scenario.slug[:20],
                     today.day, today.month, today.year)

    return  response
    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