Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up

Implements weather station class in Python that calculates ETo (reference crop's evapotranspiration) based on UN-FAO Irrigation and Drainage Paper 56

License

NotificationsYou must be signed in to change notification settings

sherzodr/penmon

Repository files navigation

penmon - Implementation of weather station class in Python that supportsPenman-Monteith ETo Equation.

INSTALL

$ pip install penmon

USAGE

import penmon as pm### create a station class with known location and elevationstation = pm.Station(latitude=41.42, altitude=109)station.anemometer_height = 10### getting a day instance for August 16thday = station.day_entry(238, temp_min = 19.5, temp_max = 25.6, wind_speed = 2.5,humidity_mean = 65,radiation_s =25.6)print("ETo for this day is", day.eto() )

Importing data from dataframe

import pandas as pdimport penmon as pm# Assuming 'your_data.csv' contains your dataimport_data_frame = pd.read_csv('import_test.csv')# Create an instance of the Station classstation = pm.Station(latitude=41.42, altitude=109)# Import data into the Station instanceday = station.import_data(import_data_frame)print(station.days[1].eto)for day_number, day_entry in station.days.items():eto_value = day_entry.eto()print(f"Day {day_number}: ETo = {eto_value:.2f} mm")

DESCRIPTION

Full implementation ofPenman-MonteithETo equation based onUAN-FAO Irrigation and Drainage Paper 56.

Penman-Monteith equation is used to calculate reference crop evapotranspirationETofor a given location using available climate data. This method provides many ways of estimatingmissing climate data.

Following are the least data required to estimate ETo (But the more data you providethe better the accuracy gets):

* latitude* elevation* date* daily minimum temperature* daily maximum temperature

It can do this by making certain assumptions about the climate. These assumptionscan be fine-tuned.Climate-class is responsible for setting these assumptions.We'll talk more about it later (see Climate class below)

OVERVIEW

To calculateETo, including intermediate atmospheric data you first need todefine an instance of aStation with a knownlatitude andaltitude. Thenyou request the station to create an instance of aDayEntry, which representsa single day with a known date. We then set whatever data we know about that particularday, and ask theday to calculate information that we do not know, includingETo.

BEWARE

This is pre-release version of the library and intended for review only. API ofthe class may change in future releases. Do not assume backwards compatabilityin future releases. ConsultsCHANGES file before upgrading!

Station CLASS

CREATE A STATION instance

import penmon as pmstation = pm.Station(latitude=41.42, altitude=109)

latitude must be a float between -90 and 90.altitudu must be a positiveinteger. These arguments values are of utmost importance. Please make sure thesedata are as accurate as you can get them be.latitude is used to calculatesunset hour angle (Eq. 25) andExtraterrestrial radiation (Eq. 21),which in turn, along with date, is used to calculate solar radiation!

altitude is used to calculateatmospheric pressure, which in turn is used tocalculatepsychrometric constant, which in turn is used to calculatevapour pressure,which is used to calculatenet longwave radiation. As you can see, thesevery innocent looking numbers are pretty much backbone of the whole equation.Show them respect!

ANEMOMETER HEIGHT

Abovestation assumes its anemometer height is 2m above ground surface.If it's not, you can set the height as:

station.anemometer_height = 10

Now all the wind_speed information is assumed to be wind speed at 10mheight. This is important information, since ETo is calculated with speedclose the crop surface, which is 2m. Library uses logarithmic algorithmto convert the data accordingly. Again, important setting! Shoud you wish toaccess calculated wind speed at 2m usewind_speed_2m() method:

day.wind_speed=2.0;u2m = day.wind_speed_2m();

In the above exampleu2m returns2.0 if the anemometer was set to 2 meters.If it was set to 10m, it returns 1.5. If it was set to 50 meters, it reads 1.2 m/s.

STATION CLIMATE

Station also makes certain assumptions about its climate. You can set thisby creating a new climate instance (seeClimate class) and set is as:

humid_climate = pm.Climate().humid().coastal().strong_winds()arid_climate = pm.Climate().arid().interior().moderare_winds()station.climate = humid_climate

By default it assumes we are inarid, interior location, with moderate winds.If it's in arid climate, it makes certain assumption about the dew point temperature.This temperature will be used to calculate relative humidity if humidity datais missing. It deduces dew_point temperature by looking at the temp_min of the record.In particulare, for arid location it substracts 2.0 degrees from temp_min. Inhumid location it treats temp_min as temp_dew. In the following examplewe set dew_point temperature 4.0 below temp_min

climate=pm.Climate() # above is the same as saying:climate=pm.Climate().arid().interior().moderate_winds()climate.dew_point_difference=4.0station.climate=climate;# from now on if humidity data is missing it substtracts 4.0 degreesfrom temp_min to take a guess at temp_dew

REFERENCE CROP

It assumes it will be calculating ETo for a refernce crop. Accordingto the original paper reference crop is assumed to be grass of 0.12m height,aerodynamic resistance of 70 and albedo of 0.23. It you wish to calculate ETofor a different reference crop you may do so as:

different_crop = pm.Crop(resistance_a=208, albedo=0.23, height=0.12)station.ref_crop = different_crop

ITERATE THROUGH INDIVIDUAL ENTRIES

Based on the above example this station has no climate data available at thismoment. But if it were you would've been able to iterate through these recordslike following:

for a_day in station.days:# do stuff with a_day

DayEntry class

Once we have station data available we work with a day at a time. We firstneed to get a single day, identified by a day number:

day = station.day_entry(238)

day is an instance ofDayEntry class.238 above representsAugust 26th - it is 238th day of the year. Day number can only be an integerin 1-366 range. It also supports a date string:

day = station.day_entry("2020-08-26")day.day_number # returns 238

If you have to pass a date string that has a different template than "%Y-%m-%d",you can pass your template string to the method as follows. Above example assumesfollowing defaultdate_template value:

day = station.day_entry("2020-08-26", date_template="%Y-%m-%d")

To learn more about date template placeholders refer tostrptime() manual eitherfromdatetime module, or by refering to your system'sstrptime manual(available in all linux/unix machines).

Based on this day number alone library is able to calculate inverseof the relative Sun-Earth distance (Eq. 23), solar declination (Eq. 24),which is used to calculate possible daylight hours for that particular day forthat particular latitude. It's amazing how much information we can deduce basedon this single number!

Once you haveday instance now all the fun begins!

Everyday has following attributes:

- day_number (whatever we passed to the constructor)- station (set automatically by station)# following are required to be set:- temp_min- temp_max# following are better to be set:- temp_dew- wind_speed- humidity_min- humidity_max- radiation_s- Solar Radiation# following are optional, if above attributes are known- radiation_a- temp_mean- temp_dry     - dry bulb temperature- temp_wet     - wet bulb temperature

INTERMEDIATE CALCULATIONS

Before setting any of the above attributes following information is available forus. These information do not use any recorded data, but only usesmostly astronomical calculations.

day.atmospheric_pressure()

Returns atmostpheric pressure in kPa for station elevation. For the above examplealtitude (109m) returns 100.0kpa. Atmospheric pressure is also available throughstation.atmospheric_pressure() call. In fact,DayEntry.atmospheric_pressure()is just an alias to it.

Value returned is a pressure inkPa. If you wish to convert it to mercuryscale multiply it by7.50 to getmm Hg, or0.295 to getin Hg.

day.latent_heat_of_vaporization()

Returns 2.45

day.specific_heat()

Returns 0.001013

day.psychrometric_constant()

For the elevation in this example returns 0.0665.

day.saturation_vapour_pressure(T)

GivenT - temperature returns saturation vapour pressure. For example for T=25.0returns 3.168

day.slope_of_saturation_vapour_pressure(T)

GivenT - temperature returns slope of saturation vapour pressure curve. For examplefor T=25.0 returns 0.188684

day.relative_sun_distance()

Returns inverse of relative Earth-Sun distance. For this example returns 0.981

day.solar_declination()

For this example returns 0.172. This is angle in radians. To convert this todegrees multiply by 180 and devide tomath.pi(). For example, 0.172 rad is thesame as 9.8 degrees. So Sun's declination was 9.8 degrees north relative to equatorialplane. If the value were negative it would've meant the Sun is declined to thesouth of the equatorial plane.

day.sunset_hour_angle()

For this example, returns 1.725. Seeday.solar_declination to convert thisto degrees.

day.R_a()

Returns extraterrestrial radiation in MJ/m2/day. For this given example returns 40.3.

day.R_a_in_mm()

The same as above but in mm. 16.4 for this example.

day.daylight_hours()

Possible daylight hours for this day.

day.solar_radiation()

Depends on the value ofday.sunshine_hours attribute. Returns solar radiationin MJ/m2/day

day.solar_radiation_in_mm()

Same as above, but returns in mm.

day.R_so()

Calculates Clear-Sky solar radiation.

day.R_ns()

Given hours of direct sunlight (inday.sunshine_hours attribute) calculatesnet solar radiation (or shortwave radiation) Takes into account albedo of the crop.

day.soil_heat_flux()

Returns 0.00 for daily calculations.

RECORDED DATA MANIPULATIONS

At this point we still cannot calculateETo. some vital information are stillmissing. Let's record some data for this day:

day.temp_min = 19.5day.tmep_max = 25.6

Now we can calculateETo for the first time:

day.eto() # returns 3.2mm

To calculate ETo with the current recorded data the library did lots of assumptionsand calculations based on empirical data. Let's help it further by recordingother important information:

day.temp_dew = 15.0day.eto() # returns 3.58mmday.wind_speed=2.50day.eto()# returns 3.82mm

Recording solar radiation gets us the most accurate ETo:

day.radiation_s = 25.0day.eto() # returns 5.04m

TODO AND ISSUES

See:Issues at github.com

SEE ALSO

libpenmon - port of the current module into C++. Seegithub.com/sherzodr/libpenmon

AUTHOR

Sherzod Ruzmetovsherzodr@gmail.com


[8]ページ先頭

©2009-2025 Movatter.jp