Source code for pvlib.location

"""
This module contains the Location class.
"""

# Will Holmgren, University of Arizona, 2014-2016.

import datetime

import pandas as pd
import pytz

from pvlib import solarposition
from pvlib import clearsky
from pvlib import atmosphere


[docs]class Location(object): """ Location objects are convenient containers for latitude, longitude, timezone, and altitude data associated with a particular geographic location. You can also assign a name to a location object. Location objects have two timezone attributes: * ``tz`` is a IANA timezone string. * ``pytz`` is a pytz timezone object. Location objects support the print method. Parameters ---------- latitude : float. Positive is north of the equator. Use decimal degrees notation. longitude : float. Positive is east of the prime meridian. Use decimal degrees notation. tz : str, int, float, or pytz.timezone. See http://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of valid time zones. pytz.timezone objects will be converted to strings. ints and floats must be in hours from UTC. alitude : float. Altitude from sea level in meters. name : None or string. Sets the name attribute of the Location object. **kwargs Arbitrary keyword arguments. Included for compatibility, but not used. See also -------- pvsystem.PVSystem """ def __init__(self, latitude, longitude, tz='UTC', altitude=0, name=None, **kwargs): self.latitude = latitude self.longitude = longitude if isinstance(tz, str): self.tz = tz self.pytz = pytz.timezone(tz) elif isinstance(tz, datetime.tzinfo): self.tz = tz.zone self.pytz = tz elif isinstance(tz, (int, float)): self.tz = tz self.pytz = pytz.FixedOffset(tz*60) else: raise TypeError('Invalid tz specification') self.altitude = altitude self.name = name # needed for tying together Location and PVSystem in LocalizedPVSystem # if LocalizedPVSystem signature is reversed # super(Location, self).__init__(**kwargs) def __str__(self): return ('{}: latitude={}, longitude={}, tz={}, altitude={}' .format(self.name, self.latitude, self.longitude, self.tz, self.altitude)) @classmethod
[docs] def from_tmy(cls, tmy_metadata, tmy_data=None, **kwargs): """ Create an object based on a metadata dictionary from tmy2 or tmy3 data readers. Parameters ---------- tmy_metadata : dict Returned from tmy.readtmy2 or tmy.readtmy3 tmy_data : None or DataFrame Optionally attach the TMY data to this object. Returns ------- Location object (or the child class of Location that you called this method from). """ # not complete, but hopefully you get the idea. # might need code to handle the difference between tmy2 and tmy3 # determine if we're dealing with TMY2 or TMY3 data tmy2 = tmy_metadata.get('City', False) latitude = tmy_metadata['latitude'] longitude = tmy_metadata['longitude'] if tmy2: name = tmy_metadata['City'] else: name = tmy_metadata['Name'] tz = tmy_metadata['TZ'] altitude = tmy_metadata['altitude'] new_object = cls(latitude, longitude, tz=tz, altitude=altitude, name=name, **kwargs) # not sure if this should be assigned regardless of input. if tmy_data is not None: new_object.tmy_data = tmy_data return new_object
[docs] def get_solarposition(self, times, pressure=None, temperature=12, **kwargs): """ Uses the :py:func:`solarposition.get_solarposition` function to calculate the solar zenith, azimuth, etc. at this location. Parameters ---------- times : DatetimeIndex pressure : None, float, or array-like If None, pressure will be calculated using :py:func:`atmosphere.alt2pres` and ``self.altitude``. temperature : None, float, or array-like kwargs passed to :py:func:`solarposition.get_solarposition` Returns ------- solar_position : DataFrame Columns depend on the ``method`` kwarg, but always include ``zenith`` and ``azimuth``. """ if pressure is None: pressure = atmosphere.alt2pres(self.altitude) return solarposition.get_solarposition(times, latitude=self.latitude, longitude=self.longitude, altitude=self.altitude, pressure=pressure, temperature=temperature, **kwargs)
[docs] def get_clearsky(self, times, model='ineichen', **kwargs): """ Calculate the clear sky estimates of GHI, DNI, and/or DHI at this location. Parameters ---------- times : DatetimeIndex model : str The clear sky model to use. kwargs passed to the relevant function(s). Returns ------- clearsky : DataFrame Column names are: ``ghi, dni, dhi``. """ if model == 'ineichen': cs = clearsky.ineichen(times, latitude=self.latitude, longitude=self.longitude, altitude=self.altitude, **kwargs) elif model == 'haurwitz': solpos = self.get_solarposition(times, **kwargs) cs = clearsky.haurwitz(solpos['apparent_zenith']) else: raise ValueError('{} is not a valid clear sky model' .format(model)) return cs
[docs] def get_airmass(self, times=None, solar_position=None, model='kastenyoung1989'): """ Calculate the relative and absolute airmass. Automatically chooses zenith or apparant zenith depending on the selected model. Parameters ---------- times : None or DatetimeIndex Only used if solar_position is not provided. solar_position : None or DataFrame DataFrame with with columns 'apparent_zenith', 'zenith'. model : str Relative airmass model Returns ------- airmass : DataFrame Columns are 'airmass_relative', 'airmass_absolute' """ if solar_position is None: solar_position = self.get_solarposition(times) if model in atmosphere.APPARENT_ZENITH_MODELS: zenith = solar_position['apparent_zenith'] elif model in atmosphere.TRUE_ZENITH_MODELS: zenith = solar_position['zenith'] else: raise ValueError('{} is not a valid airmass model'.format(model)) airmass_relative = atmosphere.relativeairmass(zenith, model) pressure = atmosphere.alt2pres(self.altitude) airmass_absolute = atmosphere.absoluteairmass(airmass_relative, pressure) airmass = pd.DataFrame() airmass['airmass_relative'] = airmass_relative airmass['airmass_absolute'] = airmass_absolute return airmass