Git Product home page Git Product logo

enerdata's Introduction

Enerdata

A set of energy models

https://coveralls.io/repos/github/gisce/enerdata/badge.svg?branch=master

Considerations

Any date instance must be localized. See enerdata.datetime.timezone.localize method!!!

from enerdata.datetime.timezone import TIMEZONE

TIMEZONE.localize(datetime(2018, 2, 5, 1, 0))

Default timezone is set to Europe/Madrid. It can be changed overriding the TIMEZONE definition.

enerdata's People

Contributors

ecarreras avatar francescpuig7 avatar davidmunoznovoa avatar xavitorello avatar tinogis avatar mroig avatar polsala avatar eberloso avatar guillejb avatar sim6 avatar totaler avatar egarciadiaz avatar aivan2022 avatar

Stargazers

 avatar Tobias Augspurger avatar Mahmoud avatar gavioto avatar  avatar  avatar Damien Tavan avatar  avatar  avatar

Watchers

 avatar James Cloos avatar Gisce avatar  avatar  avatar  avatar Dani Estanyol avatar  avatar  avatar Fabio Renda avatar ilyass Jaatit avatar Xavi G. Sunyer avatar  avatar Aleix Soler avatar  avatar  avatar  avatar Kostas Georgiou avatar Adrià Gual avatar  avatar  avatar  avatar

enerdata's Issues

Dragging key assignation to review

There is something to review here, probably I've a misunderstanding about the dragging process but can it be a bug.

It seems like the drag_key is defined based on the period of the previous gap iteration (the last gap period for the first iteration).

Could it be that the correct period key to define is the one of the current iteration?

The affected method [suspect line 375]:

def estimate(self, tariff, balance):
assert isinstance(tariff, Tariff)
logger.debug('Estimating for tariff: {0}'.format(
tariff.code
))
measures = [x for x in self.measures if x.valid]
start = self.start_date
end = self.end_date
cofs = self.profile_class.get_range(start, end)
cofs = Coefficients(cofs)
cofs_per_period = Counter()
for gap in self.gaps:
period = tariff.get_period_by_date(gap)
gap_cof = cofs.get(gap)
cofs_per_period[period.code] += gap_cof.cof[tariff.cof]
logger.debug('Coefficients per period calculated: {0}'.format(
cofs_per_period
))
energy_per_period = self.get_estimable_consumption(tariff, balance)
energy_per_period_rem = energy_per_period.copy()
dragger = Dragger()
for idx, gap in enumerate(self.gaps):
logger.debug('Gap {0}/{1}'.format(
idx + 1, len(self.gaps)
))
drag_key = period.code
period = tariff.get_period_by_date(gap)
gap_cof = cofs.get(gap).cof[tariff.cof]
energy = energy_per_period[period.code]
# If the balance[period] < energy_profile[period] fill with 0
# the gaps
if energy < 0:
energy = 0
gap_energy = (energy * gap_cof) / cofs_per_period[period.code]
aprox = dragger.drag(gap_energy, key=drag_key)
energy_per_period_rem[period.code] -= gap_energy
logger.debug(
'Energy for hour {0} is {1}. {2} Energy {3}/{4}'.format(
gap, aprox, period.code,
energy_per_period_rem[period.code], energy
))
pos = bisect.bisect_left(measures, ProfileHour(gap, 0, True))
profile_hour = ProfileHour(TIMEZONE.normalize(gap), aprox, True)
measures.insert(pos, profile_hour)
profile = Profile(self.start_date, self.end_date, measures)
return profile

Proposal solution:
Assign drag_key before period assignation (to exchange lines 375 and 376)

Add 3.X fake tariff without holidays and weekends

It's needed to provide a fake 3.X tariff that does not take care about periods definition.

The goal is to integrate all available periods into main P1 period to be able to profile metters with an erroneous configuration.

Periods not properly identified

get_period_by_date doesn't properly identify period due wrong condition or timezone used to identify whether datetime is within interval limits specified by TariffPeriod

example:
date_time, 2016-01-01 12:00:00+01:00
date_time.hour, 12
tariffperiod 20DHA, winter, range_h= P1 (12,22), P2 (0,12),(22,24)

interval condition
range_h[0] < hour <= range_h[1]

P1 12 < 12 <= 22 FALSE
P2 0 < 12 <= 12 TRUE
P2 22< 12 <= 24 FALSE

Profile RE with sum coffs is 0

Some coefficients of RE (solar) are 0 because there are no hours of sunshine. If it happens to have use this coefficient, the value of the measure will be 0

Estimable consumption for a specific period of a tariff

If we pretend to estimate a profile that it's described just by an alternative period than master (p.e P2), get_estimable_consumption will raise a key error (trying to lookup 'P1' instead of the desired one for this scenario.

Maybe can be interesting to permit this kind of estimation / fixing for non-fully described profiles.

With it, if the profile just have another key than the first one, the estimation can be done taking care about just this/those periods.

BUG weekend and holidays identification

It seems that holidays and weekends are not identified as expected.

Enerdata measure for hour X describes the consumption between X-1 and X, i.e measure=5 for datetime $DAY 17:00 describe that between the 4:00 and 4:59 the consumption is 5kWh.

Taking care about this, the holidays identification for the hour 0 of $DAY must analyze if $DAY-1 was a holiday, due to this hour describes the consumption between $D-1 23:00 to $D-1 23:59.

An example is this scenario:

# Weekend 15/02/14
datetime.datetime(2014, 2, 15, 0, 0, tzinfo=<DstTzInfo 'Europe/Madrid' CET+1:00:00 STD>

, that describes the consumption between 14/02/14 23:00 and 23:59.

This hour is not inside the weekend time.

The issue becomes here, where it is identified as weekend due to the global current day reviewing:

def get_period_by_date(self, date_time):
station = get_station(date_time)
date = date_time.date()
holidays = get_holidays(date.year)
if (calendar.weekday(date.year, date.month, date.day) in (5, 6) or
date in holidays):
holiday = True
else:
holiday = False

Review it and provide a fix

Pass possible initial accumulated at Profile initi

Will be interesting to integrate a way to pass an initial accumulated value to start Dragging.

This will support the profiling of partial time ranges taking care that the first hour will use the rounded accumulated for the previous hour although this is not in current Profile range.

So far if this previous hour is not inside current range, there are no way to take care about it.

Think about to be able to pass an accumulated initial value and initialize the Dragger for the first hour (also take care about the first period to increase just the first hour)

Python3 support

We need to review compatibility of this lib with Python3 (py3.5)

If not, try to identify which changes are needed to provide it.

BUG testing winter holidays

REE does not consider the epiphany as a holiday.

Here it's used to confirm that the periods assignation is performed as expected based for each tariff:

with description('Correct period for tariff an hour'):
with before.all:
self.winter_holiday_day = TIMEZONE.localize(datetime(2014, 1, 6))
self.summer_holiday_day = TIMEZONE.localize(datetime(2014, 8, 15))
self.winter_weekend_day = TIMEZONE.localize(datetime(2014, 2, 15))
self.summer_weekend_day = TIMEZONE.localize(datetime(2014, 6, 21))
self.winter_laboral_day = TIMEZONE.localize(datetime(2014, 11, 12))
self.summer_laboral_day = TIMEZONE.localize(datetime(2014, 7, 16))

Review it and provide an alternative date, maybe the All Saints (01/11).

Profile class must handle dragging method

ERP profiling improvements must use an isolated class that inherits from the base one.

The goal is to reach the same profiling functionality, but using a hardcoded Dragger key, to ensure that profiling accumulated energy is passed to the next gap (the next hour).

The base usage must be the same than now

get_cof_per_tariff method creation?

Can be interesting to extend enerdata to integrate get_cof_per_tariff(tariff_name) method?

To reach the cof (A,B,C,D) for a specific tariff name.

If it, I will make the related PR.

Translate civil hour to solar hour

In RE profiling, the coefficients are indicated in solar hours, they must be translated at civil hours according to:

Los valores de las horas que aparecen en las tablas siguientes corresponden al tiempo solar. En el horario de invierno la hora civil corresponde a la hora solar más 1 unidad, y en el horario de verano la hora civil corresponde a la hora solar más 2 unidades. Los cambios de horario de invierno a verano o viceversa coincidirán con la fecha de cambio oficial de hora.

Estimate with hourly Dragger

As agreed with @ecarreras and @tinogis, Profile.estimate() will drag decimals based on hourly criteria, I mean, each accumulated decimals will passed to next hour independently of the period of both hours.

Review it and provide a fix

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.