-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from pooyad359/fixes
Restructured the library
- Loading branch information
Showing
17 changed files
with
1,046 additions
and
154 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
# Byte-compiled / optimized / DLL files | ||
__pycache__/ | ||
*.py[cod] | ||
|
||
# C extensions | ||
*.so | ||
|
||
# Distribution / packaging | ||
.Python | ||
env/ | ||
build/ | ||
develop-eggs/ | ||
dist/ | ||
downloads/ | ||
eggs/ | ||
.eggs/ | ||
lib/ | ||
lib64/ | ||
parts/ | ||
sdist/ | ||
var/ | ||
*.egg-info/ | ||
.installed.cfg | ||
*.egg | ||
|
||
# PyInstaller | ||
# Usually these files are written by a python script from a template | ||
# before PyInstaller builds the exe, so as to inject date/other infos into it. | ||
*.manifest | ||
*.spec | ||
|
||
# Installer logs | ||
pip-log.txt | ||
pip-delete-this-directory.txt | ||
|
||
# Unit test / coverage reports | ||
htmlcov/ | ||
.tox/ | ||
.coverage | ||
.coverage.* | ||
.cache | ||
nosetests.xml | ||
coverage.xml | ||
*.cover | ||
|
||
# Translations | ||
*.mo | ||
*.pot | ||
|
||
# Django stuff: | ||
*.log | ||
|
||
# Sphinx documentation | ||
docs/_build/ | ||
|
||
# PyBuilder | ||
target/ | ||
|
||
# DotEnv configuration | ||
.env | ||
|
||
# Database | ||
*.db | ||
*.rdb | ||
|
||
# Pycharm | ||
.idea | ||
|
||
# VS Code | ||
.vscode/ | ||
|
||
# Spyder | ||
.spyproject/ | ||
|
||
# Jupyter NB Checkpoints | ||
.ipynb_checkpoints/ | ||
|
||
# exclude data from source control by default | ||
/data/ | ||
|
||
# Mac OS-specific storage files | ||
.DS_Store | ||
|
||
# vim | ||
*.swp | ||
*.swo | ||
|
||
# Mypy cache | ||
.mypy_cache/ |
Large diffs are not rendered by default.
Oops, something went wrong.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
MIT License | ||
Copyright (c) 2018 YOUR NAME | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,85 @@ | ||
# SolarLib | ||
# Solarlib | ||
|
||
|
||
```python | ||
from solarlib.location import Location | ||
import datetime | ||
import pytz | ||
``` | ||
|
||
## Define a location | ||
|
||
|
||
```python | ||
latitude = -31.9505 | ||
longitude = 115.8605 | ||
timezone = 'Australia/Perth' | ||
perth = Location(latitude,longitude,timezone) | ||
``` | ||
|
||
## Sunrise | ||
The output is a python datetime object. | ||
|
||
|
||
```python | ||
print(perth.sunrise('2020-06-27')) | ||
``` | ||
|
||
2020-06-27 07:17:33.495057+08:00 | ||
|
||
|
||
## Sunset | ||
The output is a python datetime object. | ||
|
||
|
||
```python | ||
print(perth.sunset('2020-06-27')) | ||
``` | ||
|
||
2020-06-27 17:21:50.791503+08:00 | ||
|
||
|
||
## Day length | ||
The output is a python timedelta object. | ||
|
||
|
||
```python | ||
print(perth.day_length('2020-06-27')) | ||
``` | ||
|
||
10:04:17.296446 | ||
|
||
|
||
## Solar irradiance | ||
The output is irradiance in $kW/m^2$. | ||
|
||
|
||
```python | ||
perth.solar_irradiance('2020-06-27 14:27:00') | ||
``` | ||
|
||
|
||
|
||
|
||
0.7360521598862617 | ||
|
||
|
||
|
||
## Irradiance throughout a day | ||
|
||
|
||
|
||
```python | ||
import matplotlib.pyplot as plt | ||
``` | ||
|
||
|
||
```python | ||
output = perth.daily_irradiance('2020-06-27') | ||
time, irradiance = list(zip(*output)) | ||
plt.plot(time,irradiance) | ||
``` | ||
|
||
![png](Examples_files/Examples_14_1.png) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
pytz |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[metadata] | ||
description-file = README.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
from setuptools import find_packages, setup | ||
|
||
setup( | ||
name='solarlib', | ||
packages=find_packages(), | ||
version='0.1.0', | ||
description='A library for calculating solar irradiance, sunrise, sunset, and more. ', | ||
author='Pooya Darvehei', | ||
url='https://github.com/pooyad359/solarlib', | ||
license='MIT', | ||
install_requires=['pytz'] | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1 @@ | ||
from .solarlib import * | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import datetime | ||
import pytz | ||
|
||
JULIAN_DAYS_INIT = 1721424.5 | ||
CENTURY21 = 2451545 | ||
CENTURY_DAYS = 36525 | ||
|
||
def time2seconds(time): | ||
hour = time.hour | ||
minute = time.minute | ||
seconds = time.second | ||
return hour * 3600 + minute * 60 + seconds | ||
|
||
|
||
def julian_day(time): | ||
utc = pytz.timezone('UTC') | ||
utc_time = time.astimezone(utc) | ||
time_of_day = time2seconds(utc_time)/3600/24 | ||
return JULIAN_DAYS_INIT + utc_time.toordinal() + time_of_day | ||
|
||
def julian_century(time): | ||
return (julian_day(time)-CENTURY21)/CENTURY_DAYS | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
class ValueOutOfRange(Exception): | ||
def __init__(self, name, rng, value): | ||
self.message = f'{name} = {value} ' | ||
self.message += 'but is expected to be in {rng} range.' | ||
super().__init__(self.message) | ||
|
||
|
||
def type_check(variable, types_list): | ||
checks = [isinstance(variable, o) for o in types_list] | ||
return any(checks) | ||
|
||
|
||
def raise_type_error(variable_name, input_type): | ||
raise TypeError(f'Unrecognised type {input_type} for {variable_name}') |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,140 @@ | ||
from solarlib.error_handling import ( | ||
ValueOutOfRange, | ||
raise_type_error, | ||
type_check) | ||
from solarlib.solar import ( | ||
sunrise, | ||
sunset, | ||
estimated_irradiance, | ||
solar_noon | ||
) | ||
import pytz | ||
import datetime | ||
|
||
|
||
class Location: | ||
def __init__(self, latitude, longitude, timezone=None): | ||
self.set_timezone(timezone) | ||
self.set_latitude(latitude) | ||
self.set_longitude(longitude) | ||
|
||
def set_latitude(self, latitude): | ||
if not type_check(latitude, [int, float]): | ||
raise_type_error('latitude', type(latitude)) | ||
elif -90 <= latitude <= 90: | ||
self.__latitude = latitude | ||
else: | ||
raise ValueError( | ||
'latitude must be between -90 and 90 degrees ' + | ||
f'but recieved {latitude}' | ||
) | ||
|
||
def set_longitude(self, longitude): | ||
if not type_check(longitude, [int, float]): | ||
raise_type_error('longitude', type(longitude)) | ||
elif -180 <= longitude <= 180: | ||
self.__longitude = longitude | ||
else: | ||
raise ValueOutOfRange( | ||
'longitude must be between -180 and 180 ' + | ||
f'degrees but recieved {longitude}' | ||
) | ||
|
||
def set_timezone(self, timezone): | ||
if timezone is None: | ||
self.__timezone = pytz.timezone('UTC') | ||
elif isinstance(timezone, str): | ||
self.__timezone = pytz.timezone(timezone) | ||
elif isinstance(timezone, float) or isinstance(timezone, int): | ||
timezone_hours = round(timezone*2)/2 | ||
timedelta = datetime.timedelta(hours=timezone_hours) | ||
self.__timezone = datetime.timezone(timedelta) | ||
else: | ||
raise_type_error('timezone', type(timezone)) | ||
|
||
@property | ||
def latitude(self): | ||
return self.__latitude | ||
|
||
@property | ||
def longitude(self): | ||
return self.__longitude | ||
|
||
@property | ||
def timezone(self): | ||
return self.__timezone | ||
|
||
def __repr__(self): | ||
lat = self.__latitude | ||
lon = self.__longitude | ||
tz = self.__timezone | ||
output = f'''Location(latitude={lat}, | ||
longitude={lon}, | ||
timezone={str(tz)})''' | ||
return output.replace(' '*4, '').replace('\n', '') | ||
|
||
def __str__(self): | ||
return repr(self) | ||
|
||
def sunrise(self, date, fmt='%Y-%m-%d'): | ||
date = self.__parse_date(date, fmt='%Y-%m-%d') | ||
lat = self.latitude | ||
lon = self.longitude | ||
base = sunrise(date, lat, lon) | ||
return sunrise(base, lat, lon) | ||
|
||
def sunset(self, date, fmt='%Y-%m-%d'): | ||
date = self.__parse_date(date, fmt=fmt) | ||
lat = self.latitude | ||
lon = self.longitude | ||
base = sunset(date, lat, lon) | ||
return sunset(base, lat, lon) | ||
|
||
def solar_irradiance(self, time, fmt='%Y-%m-%d %H:%M:%S'): | ||
time = self.__parse_time(time, fmt=fmt) | ||
lat = self.latitude | ||
lon = self.longitude | ||
return estimated_irradiance(time, lat, lon) | ||
|
||
def daily_irradiance(self, date, fmt='%Y-%m-%d', freq_min=30): | ||
date = self.__parse_date(date, fmt=fmt) | ||
delta = datetime.timedelta(minutes=freq_min) | ||
n = 1440//freq_min + 1 | ||
output = [ | ||
( | ||
date+i*delta, | ||
self.solar_irradiance(date+i*delta) | ||
) for i in range(n) | ||
] | ||
return output | ||
|
||
def day_length(self, date, fmt='%Y-%m-%d'): | ||
date = self.__parse_date(date, fmt=fmt) | ||
rise_time = self.sunrise(date, fmt) | ||
set_time = self.sunset(date, fmt) | ||
return set_time-rise_time | ||
|
||
def solar_noon(self, date, fmt='%Y-%m-%d'): | ||
date = self.__parse_date(date, fmt=fmt) | ||
lon = self.longitude | ||
base = solar_noon(date, lon) | ||
return solar_noon(base, lon) | ||
|
||
def __parse_date(self, date, fmt='%Y-%m-%d'): | ||
if isinstance(date, str): | ||
return datetime.datetime.strptime(date, fmt) | ||
elif isinstance(date, datetime.datetime): | ||
return date | ||
elif isinstance(date, datetime.date): | ||
time = datetime.time() | ||
return datetime.datetime.combine(date, time) | ||
else: | ||
raise_type_error('date', datetime.datetime) | ||
|
||
def __parse_time(self, date, fmt='%Y-%m-%d %H:%M:%S'): | ||
if isinstance(date, str): | ||
return datetime.datetime.strptime(date, fmt) | ||
elif isinstance(date, datetime.datetime): | ||
return date | ||
else: | ||
raise_type_error('date', datetime.datetime) |
Oops, something went wrong.