tyba-client 0.3.7__py3-none-any.whl → 0.4.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of tyba-client might be problematic. Click here for more details.

tyba_client/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.3.1"
1
+ __version__ = "0.4.0"
tyba_client/forecast.py CHANGED
@@ -12,12 +12,15 @@ class Forecast(object):
12
12
  return response.json()
13
13
 
14
14
  def most_recent(
15
- self,
16
- object_name: str,
17
- product: str,
18
- start_time: datetime,
19
- end_time: datetime,
20
- forecast_type=None,
15
+ self,
16
+ object_name: str,
17
+ product: str,
18
+ start_time: datetime,
19
+ end_time: datetime,
20
+ forecast_type=None,
21
+ predictions_per_hour=None,
22
+ prediction_lead_time_mins=None,
23
+ horizon_mins=None,
21
24
  ):
22
25
  return self.get(
23
26
  "most_recent_forecast",
@@ -27,17 +30,24 @@ class Forecast(object):
27
30
  "start_time": start_time,
28
31
  "end_time": end_time,
29
32
  "forecast_type": forecast_type,
33
+ "predictions_per_hour": predictions_per_hour,
34
+ "prediction_lead_time_mins": prediction_lead_time_mins,
35
+ "horizon_mins": horizon_mins,
30
36
  },
31
37
  )
32
38
 
33
39
  def most_recent_probabilistic(
34
- self,
35
- object_name: str,
36
- product: str,
37
- start_time: datetime,
38
- end_time: datetime,
39
- quantiles: List[float],
40
- forecast_type=None,
40
+ self,
41
+ object_name: str,
42
+ product: str,
43
+ start_time: datetime,
44
+ end_time: datetime,
45
+ quantiles: List[float],
46
+ forecast_type=None,
47
+ predictions_per_hour=None,
48
+ prediction_lead_time_mins=None,
49
+ horizon_mins=None,
50
+
41
51
  ):
42
52
  return self.get(
43
53
  "most_recent_probabilistic_forecast",
@@ -48,19 +58,25 @@ class Forecast(object):
48
58
  "end_time": end_time,
49
59
  "quantiles": quantiles,
50
60
  "forecast_type": forecast_type,
61
+ "predictions_per_hour": predictions_per_hour,
62
+ "prediction_lead_time_mins": prediction_lead_time_mins,
63
+ "horizon_mins": horizon_mins,
51
64
  },
52
65
  )
53
66
 
54
67
  def vintaged(
55
- self,
56
- object_name: str,
57
- product: str,
58
- start_time: datetime,
59
- end_time: datetime,
60
- days_ago: int,
61
- before_time: time,
62
- exact_vintage: bool = False,
63
- forecast_type=None,
68
+ self,
69
+ object_name: str,
70
+ product: str,
71
+ start_time: datetime,
72
+ end_time: datetime,
73
+ days_ago: int,
74
+ before_time: time,
75
+ exact_vintage: bool = False,
76
+ forecast_type=None,
77
+ predictions_per_hour=None,
78
+ prediction_lead_time_mins=None,
79
+ horizon_mins=None,
64
80
  ):
65
81
  return self.get(
66
82
  "vintaged_forecast",
@@ -73,20 +89,26 @@ class Forecast(object):
73
89
  "before_time": before_time,
74
90
  "exact_vintage": exact_vintage,
75
91
  "forecast_type": forecast_type,
92
+ "predictions_per_hour": predictions_per_hour,
93
+ "prediction_lead_time_mins": prediction_lead_time_mins,
94
+ "horizon_mins": horizon_mins,
76
95
  },
77
96
  )
78
97
 
79
98
  def vintaged_probabilistic(
80
- self,
81
- object_name: str,
82
- product: str,
83
- start_time: datetime,
84
- end_time: datetime,
85
- quantiles: List[float],
86
- days_ago: int,
87
- before_time: time,
88
- exact_vintage: bool = False,
89
- forecast_type=None,
99
+ self,
100
+ object_name: str,
101
+ product: str,
102
+ start_time: datetime,
103
+ end_time: datetime,
104
+ quantiles: List[float],
105
+ days_ago: int,
106
+ before_time: time,
107
+ exact_vintage: bool = False,
108
+ forecast_type=None,
109
+ predictions_per_hour=None,
110
+ prediction_lead_time_mins=None,
111
+ horizon_mins=None,
90
112
  ):
91
113
  return self.get(
92
114
  "vintaged_probabilistic_forecast",
@@ -100,16 +122,22 @@ class Forecast(object):
100
122
  "before_time": before_time,
101
123
  "exact_vintage": exact_vintage,
102
124
  "forecast_type": forecast_type,
125
+ "predictions_per_hour": predictions_per_hour,
126
+ "prediction_lead_time_mins": prediction_lead_time_mins,
127
+ "horizon_mins": horizon_mins,
103
128
  },
104
129
  )
105
130
 
106
131
  def by_vintage(
107
- self,
108
- object_name: str,
109
- product: str,
110
- vintage_start_time: datetime,
111
- vintage_end_time: datetime,
112
- forecast_type=None,
132
+ self,
133
+ object_name: str,
134
+ product: str,
135
+ vintage_start_time: datetime,
136
+ vintage_end_time: datetime,
137
+ forecast_type=None,
138
+ predictions_per_hour=None,
139
+ prediction_lead_time_mins=None,
140
+ horizon_mins=None,
113
141
  ):
114
142
  return self.get(
115
143
  "forecasts_by_vintage",
@@ -119,17 +147,23 @@ class Forecast(object):
119
147
  "start_time": vintage_start_time,
120
148
  "end_time": vintage_end_time,
121
149
  "forecast_type": forecast_type,
150
+ "predictions_per_hour": predictions_per_hour,
151
+ "prediction_lead_time_mins": prediction_lead_time_mins,
152
+ "horizon_mins": horizon_mins,
122
153
  },
123
154
  )
124
155
 
125
156
  def by_vintage_probabilistic(
126
- self,
127
- object_name: str,
128
- product: str,
129
- quantiles: List[float],
130
- vintage_start_time: datetime,
131
- vintage_end_time: datetime,
132
- forecast_type=None,
157
+ self,
158
+ object_name: str,
159
+ product: str,
160
+ quantiles: List[float],
161
+ vintage_start_time: datetime,
162
+ vintage_end_time: datetime,
163
+ forecast_type=None,
164
+ predictions_per_hour=None,
165
+ prediction_lead_time_mins=None,
166
+ horizon_mins=None,
133
167
  ):
134
168
  return self.get(
135
169
  "probabilistic_forecasts_by_vintage",
@@ -140,11 +174,14 @@ class Forecast(object):
140
174
  "start_time": vintage_start_time,
141
175
  "end_time": vintage_end_time,
142
176
  "forecast_type": forecast_type,
177
+ "predictions_per_hour": predictions_per_hour,
178
+ "prediction_lead_time_mins": prediction_lead_time_mins,
179
+ "horizon_mins": horizon_mins,
143
180
  },
144
181
  )
145
182
 
146
183
  def actuals(
147
- self, object_name: str, product: str, start_time: datetime, end_time: datetime
184
+ self, object_name: str, product: str, start_time: datetime, end_time: datetime
148
185
  ):
149
186
  return self.get(
150
187
  "actuals",
tyba_client/io.py CHANGED
@@ -4,11 +4,7 @@ from generation_models import (
4
4
  ONDInverter,
5
5
  ONDEfficiencyCurve,
6
6
  ONDTemperatureDerateCurve,
7
- SolarResource,
8
- SolarResourceTimeSeries,
9
7
  )
10
- import pandas as pd
11
- import typing as t
12
8
 
13
9
 
14
10
  def read_pvsyst_file(path: str) -> dict:
@@ -160,48 +156,3 @@ def inverter_from_ond(ond_file: str, includes_xfmr: bool = True) -> ONDInverter:
160
156
  aux_loss_threshold=aux_loss_threshold,
161
157
  includes_xfmr=includes_xfmr,
162
158
  )
163
-
164
-
165
- psm_column_map = {
166
- "Year": "year",
167
- "Month": "month",
168
- "Day": "day",
169
- "Hour": "hour",
170
- "Minute": "minute",
171
- "GHI": "gh",
172
- "DNI": "dn",
173
- "DHI": "df",
174
- "POA": "poa",
175
- "Temperature": "tdry",
176
- # twet
177
- "Dew Point": "tdew",
178
- "Relative Humidity": "rhum",
179
- "Pressure": "pres",
180
- # Snow
181
- "Surface Albedo": "alb",
182
- # aod
183
- "Wind Speed": "wspd",
184
- "Wind Direction": "wdir",
185
- }
186
-
187
-
188
- def solar_resource_from_psm_csv(
189
- filename: str,
190
- typical: bool = True,
191
- monthly_albedo: t.Optional[t.List[float]] = None,
192
- ) -> SolarResource:
193
- """_"""
194
- with open(filename) as f:
195
- _meta = [f.readline().split(",") for _ in range(2)]
196
- _data = pd.read_csv(f)
197
- meta = {k: v for k, v in zip(*_meta)}
198
- data = _data.rename(columns=psm_column_map)
199
- return SolarResource(
200
- latitude=float(meta["Latitude"]),
201
- longitude=float(meta["Longitude"]),
202
- elevation=float(meta["Elevation"]),
203
- time_zone_offset=float(meta["Time Zone"]),
204
- data=SolarResourceTimeSeries(**data.to_dict(orient="list")),
205
- monthly_albedo=monthly_albedo,
206
- typical=typical,
207
- )
tyba_client/models.py CHANGED
@@ -4,7 +4,8 @@ from enum import Enum
4
4
  from dataclasses_json import config, dataclass_json
5
5
  import pandas as pd
6
6
  import typing as t
7
- from .io import read_pvsyst_file, psm_column_map
7
+ from .io import read_pvsyst_file
8
+ from .solar_resource import psm_column_map
8
9
 
9
10
  from tyba_client.utils import string_enum
10
11
 
@@ -0,0 +1,117 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+
5
+ import pandas as pd
6
+ import requests
7
+ from generation_models import SolarResource, SolarResourceTimeSeries
8
+ from requests.exceptions import HTTPError
9
+ import typing as t
10
+ from io import StringIO
11
+
12
+
13
+ @dataclass
14
+ class PSMClient:
15
+ api_key: str
16
+ email: str
17
+
18
+ def _get_solar_resource(
19
+ self,
20
+ source: str,
21
+ latitude: float,
22
+ longitude: float,
23
+ year: t.Union[str, int],
24
+ utc: bool,
25
+ ):
26
+ resp = requests.get(
27
+ url=f"https://developer.nrel.gov/api/nsrdb/v2/solar/{source}.csv",
28
+ params={
29
+ "api_key": self.api_key,
30
+ "email": self.email,
31
+ "wkt": f"POINT({longitude} {latitude})",
32
+ "names": year,
33
+ "utc": "true" if utc else "false",
34
+ },
35
+ )
36
+ if resp.status_code == 400:
37
+ raise HTTPError(resp.json()["errors"])
38
+ resp.raise_for_status()
39
+ return resp.text
40
+
41
+ @staticmethod
42
+ def _process_csv(raw: str) -> SolarResource:
43
+ with StringIO(raw) as f:
44
+ _meta = [f.readline().split(",") for _ in range(2)]
45
+ _data = pd.read_csv(f)
46
+ meta = {k: v for k, v in zip(*_meta)}
47
+ data = _data.rename(columns=psm_column_map)
48
+ return SolarResource(
49
+ latitude=float(meta["Latitude"]),
50
+ longitude=float(meta["Longitude"]),
51
+ elevation=float(meta["Elevation"]),
52
+ time_zone_offset=float(meta["Time Zone"]),
53
+ data=SolarResourceTimeSeries(**data.to_dict(orient="list")),
54
+ )
55
+
56
+ def get_historical(
57
+ self,
58
+ latitude: float,
59
+ longitude: float,
60
+ year: int,
61
+ utc: bool = False,
62
+ ) -> SolarResource:
63
+ raw = self._get_solar_resource(source="psm3-2-2-download", latitude=latitude, longitude=longitude, year=year, utc=utc)
64
+ return self._process_csv(raw)
65
+
66
+ def get_typical(
67
+ self,
68
+ latitude: float,
69
+ longitude: float,
70
+ year: str = "tgy-2022",
71
+ utc: bool = False,
72
+ ) -> SolarResource:
73
+ raw = self._get_solar_resource(source="psm3-2-2-tmy-download", latitude=latitude, longitude=longitude, year=year, utc=utc)
74
+ return self._process_csv(raw)
75
+
76
+
77
+ def solar_resource_from_psm_csv(
78
+ filename: str,
79
+ monthly_albedo: t.Optional[t.List[float]] = None,
80
+ ) -> SolarResource:
81
+ """_"""
82
+ with open(filename) as f:
83
+ _meta = [f.readline().split(",") for _ in range(2)]
84
+ _data = pd.read_csv(f)
85
+ meta = {k: v for k, v in zip(*_meta)}
86
+ data = _data.rename(columns=psm_column_map)
87
+ return SolarResource(
88
+ latitude=float(meta["Latitude"]),
89
+ longitude=float(meta["Longitude"]),
90
+ elevation=float(meta["Elevation"]),
91
+ time_zone_offset=float(meta["Time Zone"]),
92
+ data=SolarResourceTimeSeries(**data.to_dict(orient="list")),
93
+ monthly_albedo=monthly_albedo,
94
+ )
95
+
96
+
97
+ psm_column_map = {
98
+ "Year": "year",
99
+ "Month": "month",
100
+ "Day": "day",
101
+ "Hour": "hour",
102
+ "Minute": "minute",
103
+ "GHI": "gh",
104
+ "DNI": "dn",
105
+ "DHI": "df",
106
+ "POA": "poa",
107
+ "Temperature": "tdry",
108
+ # twet
109
+ "Dew Point": "tdew",
110
+ "Relative Humidity": "rhum",
111
+ "Pressure": "pres",
112
+ # Snow
113
+ "Surface Albedo": "alb",
114
+ # aod
115
+ "Wind Speed": "wspd",
116
+ "Wind Direction": "wdir",
117
+ }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: tyba-client
3
- Version: 0.3.7
3
+ Version: 0.4.1
4
4
  Summary: A Python API client for the Tyba Public API
5
5
  License: MIT
6
6
  Author: Tyler Nisonoff
@@ -13,13 +13,13 @@ Classifier: Programming Language :: Python :: 3.9
13
13
  Classifier: Programming Language :: Python :: 3.10
14
14
  Classifier: Programming Language :: Python :: 3.11
15
15
  Classifier: Programming Language :: Python :: 3.12
16
- Requires-Dist: dataclasses-json (>=0.5.4,<0.6.0)
17
- Requires-Dist: generation-models (>=0.4.1,<0.5.0)
16
+ Requires-Dist: dataclasses-json (>=0.6.4,<0.7.0)
17
+ Requires-Dist: generation-models (>=0,<1)
18
18
  Requires-Dist: marshmallow (>=3.12.1,<4.0.0)
19
19
  Requires-Dist: pandas (>=1.3.2,<2.0.0)
20
20
  Requires-Dist: requests (>=2.25.1,<3.0.0)
21
- Requires-Dist: structlog (>=23.1.0,<24.0.0)
22
- Requires-Dist: tyba-financial-model (>=0.1.0,<0.2.0)
21
+ Requires-Dist: structlog (>=24.1.0,<25.0.0)
22
+ Requires-Dist: tyba-financial-model (>=0,<1)
23
23
  Description-Content-Type: text/markdown
24
24
 
25
25
  # Tyba API Client
@@ -0,0 +1,12 @@
1
+ LICENSE,sha256=LbMfEdjEK-IRzvCfdEBhn9UCANze0Rc7hWrQTEj_xvU,1079
2
+ tyba_client/__init__.py,sha256=42STGor_9nKYXumfeV5tiyD_M8VdcddX7CEexmibPBk,22
3
+ tyba_client/client.py,sha256=zEqlK-w4T02u8VKatIeJuBY8xDcDlTfko_9yJvBT64c,5761
4
+ tyba_client/forecast.py,sha256=lhzTewXZNqxOmuNuBmjw_NnikObqJSSu-yLFt7qSBSM,6377
5
+ tyba_client/io.py,sha256=iyiQrpM1xg9XAoXlU6JvNB1uxRK77keJ8gAG-fefV2U,5783
6
+ tyba_client/models.py,sha256=_ZhMOwbEknOhwyjrpedUT1r7r7J92-AAqkpGbZJaEVQ,17525
7
+ tyba_client/solar_resource.py,sha256=oUD6-qUJhiIjrHbSzSL0X4asGgU4lRBocyy0MkA3keY,3379
8
+ tyba_client/utils.py,sha256=n4tUBGlQIwxbLqJcQRiAIbIJA0DaLSjbAxakhukqaeE,876
9
+ tyba_client-0.4.1.dist-info/LICENSE,sha256=LbMfEdjEK-IRzvCfdEBhn9UCANze0Rc7hWrQTEj_xvU,1079
10
+ tyba_client-0.4.1.dist-info/METADATA,sha256=tARY9izCghh03klzoix8JNoKdSTwDqSllwIuayLZ6Ec,2292
11
+ tyba_client-0.4.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
12
+ tyba_client-0.4.1.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- LICENSE,sha256=LbMfEdjEK-IRzvCfdEBhn9UCANze0Rc7hWrQTEj_xvU,1079
2
- tyba_client/__init__.py,sha256=r4xAFihOf72W9TD-lpMi6ntWSTKTP2SlzKP1ytkjRbI,22
3
- tyba_client/client.py,sha256=zEqlK-w4T02u8VKatIeJuBY8xDcDlTfko_9yJvBT64c,5761
4
- tyba_client/forecast.py,sha256=Cd9HD7ZtwkJf86V_nGMP1dcSr_LEKMWrcAfbL1htJfg,4428
5
- tyba_client/io.py,sha256=jT2V6UaLTFiH4gi0Luo80jO9abV86qsVa_LQfD99LSo,7015
6
- tyba_client/models.py,sha256=J17fQKIMGV1BDBleJutyJkTvk_sqIiqU-9OHd6kV58A,17498
7
- tyba_client/utils.py,sha256=n4tUBGlQIwxbLqJcQRiAIbIJA0DaLSjbAxakhukqaeE,876
8
- tyba_client-0.3.7.dist-info/LICENSE,sha256=LbMfEdjEK-IRzvCfdEBhn9UCANze0Rc7hWrQTEj_xvU,1079
9
- tyba_client-0.3.7.dist-info/METADATA,sha256=U99PYV7_YfY0xWnmu-h64765r5SV-MLjOlAkteG1H10,2308
10
- tyba_client-0.3.7.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
11
- tyba_client-0.3.7.dist-info/RECORD,,