env-canada 0.7.1__py3-none-any.whl → 0.8.0__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.
- env_canada/__init__.py +9 -0
- env_canada/constants.py +1 -1
- env_canada/ec_aqhi.py +6 -6
- env_canada/ec_cache.py +2 -1
- env_canada/ec_historical.py +44 -34
- env_canada/ec_hydro.py +2 -3
- env_canada/ec_radar.py +7 -7
- env_canada/ec_weather.py +12 -6
- {env_canada-0.7.1.dist-info → env_canada-0.8.0.dist-info}/LICENSE +1 -1
- {env_canada-0.7.1.dist-info → env_canada-0.8.0.dist-info}/METADATA +75 -24
- env_canada-0.8.0.dist-info/RECORD +16 -0
- {env_canada-0.7.1.dist-info → env_canada-0.8.0.dist-info}/WHEEL +1 -1
- env_canada-0.7.1.dist-info/RECORD +0 -16
- {env_canada-0.7.1.dist-info → env_canada-0.8.0.dist-info}/top_level.txt +0 -0
env_canada/__init__.py
CHANGED
env_canada/constants.py
CHANGED
@@ -1 +1 @@
|
|
1
|
-
USER_AGENT = "env_canada/0.
|
1
|
+
USER_AGENT = "env_canada/0.8.0"
|
env_canada/ec_aqhi.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1
|
-
from datetime import datetime, timezone
|
2
1
|
import logging
|
2
|
+
from datetime import datetime, timezone
|
3
3
|
|
4
|
+
import voluptuous as vol
|
4
5
|
from aiohttp import ClientSession
|
5
|
-
import defusedxml.ElementTree as et
|
6
6
|
from geopy import distance
|
7
|
-
import
|
7
|
+
from lxml import etree as et
|
8
8
|
|
9
9
|
from .constants import USER_AGENT
|
10
10
|
|
@@ -43,7 +43,7 @@ async def get_aqhi_regions(language):
|
|
43
43
|
)
|
44
44
|
result = await response.read()
|
45
45
|
|
46
|
-
site_xml = result
|
46
|
+
site_xml = result
|
47
47
|
xml_object = et.fromstring(site_xml)
|
48
48
|
|
49
49
|
for zone in xml_object.findall("./EC_administrativeZone"):
|
@@ -83,7 +83,7 @@ async def find_closest_region(language, lat, lon):
|
|
83
83
|
return min(region_list, key=site_distance)
|
84
84
|
|
85
85
|
|
86
|
-
class ECAirQuality
|
86
|
+
class ECAirQuality:
|
87
87
|
"""Get air quality data from Environment Canada."""
|
88
88
|
|
89
89
|
def __init__(self, **kwargs):
|
@@ -152,7 +152,7 @@ class ECAirQuality(object):
|
|
152
152
|
return None
|
153
153
|
|
154
154
|
result = await response.read()
|
155
|
-
aqhi_xml = result
|
155
|
+
aqhi_xml = result
|
156
156
|
return et.fromstring(aqhi_xml)
|
157
157
|
|
158
158
|
async def update(self):
|
env_canada/ec_cache.py
CHANGED
env_canada/ec_historical.py
CHANGED
@@ -1,26 +1,28 @@
|
|
1
|
+
import asyncio
|
1
2
|
import copy
|
2
3
|
import csv
|
4
|
+
import logging
|
3
5
|
from datetime import datetime
|
4
|
-
from dateutil.relativedelta import relativedelta
|
5
6
|
from io import StringIO
|
6
|
-
import logging
|
7
|
-
import xml.etree.ElementTree as et
|
8
|
-
import pandas as pd
|
9
|
-
import asyncio
|
10
7
|
|
11
|
-
from aiohttp import ClientSession
|
12
|
-
from dateutil import parser, tz
|
13
|
-
import defusedxml.ElementTree as et
|
14
8
|
import lxml.html
|
9
|
+
import pandas as pd
|
15
10
|
import voluptuous as vol
|
11
|
+
from aiohttp import ClientSession
|
12
|
+
from dateutil import parser, tz
|
13
|
+
from dateutil.relativedelta import relativedelta
|
14
|
+
from lxml import etree as et
|
16
15
|
|
17
16
|
from .constants import USER_AGENT
|
18
17
|
|
19
|
-
|
20
18
|
STATIONS_URL = "https://climate.weather.gc.ca/historical_data/search_historic_data_stations_{}.html"
|
21
19
|
|
22
20
|
WEATHER_URL = "https://climate.weather.gc.ca/climate_data/bulk_data_{}.html"
|
23
21
|
|
22
|
+
_TODAY = datetime.today().date()
|
23
|
+
_ONE_YEAR_AGO = _TODAY - relativedelta(years=1, months=1, day=1)
|
24
|
+
_YEAR = datetime.today().year
|
25
|
+
|
24
26
|
LOG = logging.getLogger(__name__)
|
25
27
|
|
26
28
|
__all__ = ["ECHistorical"]
|
@@ -126,7 +128,7 @@ async def get_historical_stations(
|
|
126
128
|
coordinates,
|
127
129
|
radius=25,
|
128
130
|
start_year=1840,
|
129
|
-
end_year=
|
131
|
+
end_year=_YEAR,
|
130
132
|
limit=25,
|
131
133
|
language="english",
|
132
134
|
timeframe=2,
|
@@ -204,8 +206,7 @@ async def get_historical_stations(
|
|
204
206
|
return stations
|
205
207
|
|
206
208
|
|
207
|
-
class ECHistorical
|
208
|
-
|
209
|
+
class ECHistorical:
|
209
210
|
"""Get historical weather data from Environment Canada."""
|
210
211
|
|
211
212
|
def __init__(self, **kwargs):
|
@@ -353,30 +354,30 @@ def flip_daterange(f):
|
|
353
354
|
return wrapper
|
354
355
|
|
355
356
|
|
356
|
-
class ECHistoricalRange
|
357
|
+
class ECHistoricalRange:
|
357
358
|
"""Get historical weather data from Environment Canada in the given range for the given station.
|
358
359
|
|
359
|
-
|
360
|
+
options are daily or hourly data
|
360
361
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
362
|
+
Example:
|
363
|
+
import pandas as pd
|
364
|
+
import asyncio
|
365
|
+
from env_canada import ECHistoricalRange, get_historical_stations
|
366
|
+
from datetime import datetime
|
366
367
|
|
367
|
-
|
368
|
+
coordinates = ['48.508333', '-68.467667']
|
368
369
|
|
369
|
-
|
370
|
-
|
370
|
+
stations = pd.DataFrame(asyncio.run(get_historical_stations(coordinates, start_year=2022,
|
371
|
+
end_year=2022, radius=200, limit=100))).T
|
371
372
|
|
372
|
-
|
373
|
-
|
373
|
+
ec = ECHistoricalRange(station_id=int(stations.iloc[0,2]), timeframe="hourly",
|
374
|
+
daterange=(datetime(2022, 7, 1, 12, 12), datetime(2022, 8, 1, 12, 12)))
|
374
375
|
|
375
|
-
|
376
|
+
ec.get_data()
|
376
377
|
|
377
|
-
|
378
|
-
|
379
|
-
|
378
|
+
ec.xml #yield an XML formatted str. For more options, use ec.to_xml(*arg, **kwargs) with pandas options
|
379
|
+
=
|
380
|
+
ec.csv #yield an CSV formatted str. For more options, use ec.to_csv(*arg, **kwargs) with pandas options
|
380
381
|
"""
|
381
382
|
|
382
383
|
@flip_daterange
|
@@ -384,8 +385,8 @@ class ECHistoricalRange(object):
|
|
384
385
|
self,
|
385
386
|
station_id,
|
386
387
|
daterange=(
|
387
|
-
|
388
|
-
|
388
|
+
_ONE_YEAR_AGO,
|
389
|
+
_TODAY,
|
389
390
|
),
|
390
391
|
language="english",
|
391
392
|
timeframe="daily",
|
@@ -409,7 +410,14 @@ class ECHistoricalRange(object):
|
|
409
410
|
self.months = self.monthlist(daterange=daterange)
|
410
411
|
self.language = language
|
411
412
|
_tf = {"hourly": 1, "daily": 2, "monthly": 3}
|
412
|
-
|
413
|
+
timeframe_int = _tf[timeframe]
|
414
|
+
if timeframe_int == 2:
|
415
|
+
# prune the months list so it only has unique years. if daily is selected.
|
416
|
+
years = set()
|
417
|
+
for year, _ in self.months:
|
418
|
+
years.add(year)
|
419
|
+
self.months = [(year, 1) for year in years]
|
420
|
+
self.timeframe = timeframe_int
|
413
421
|
|
414
422
|
def get_data(self):
|
415
423
|
"""
|
@@ -419,7 +427,6 @@ class ECHistoricalRange(object):
|
|
419
427
|
"""
|
420
428
|
if not self.df.empty:
|
421
429
|
self.df = pd.DataFrame()
|
422
|
-
|
423
430
|
ec = [
|
424
431
|
ECHistorical(
|
425
432
|
station_id=self.station_id,
|
@@ -437,7 +444,7 @@ class ECHistoricalRange(object):
|
|
437
444
|
self.df = pd.concat((self.df, pd.read_csv(data.station_data)))
|
438
445
|
|
439
446
|
self.df = self.df.set_index(
|
440
|
-
self.df.filter(regex="Date/*", axis=1).columns.
|
447
|
+
self.df.filter(regex="Date/*", axis=1).columns.to_numpy()[0]
|
441
448
|
)
|
442
449
|
self.df.index = pd.to_datetime(self.df.index)
|
443
450
|
|
@@ -477,7 +484,10 @@ class ECHistoricalRange(object):
|
|
477
484
|
@flip_daterange
|
478
485
|
def monthlist(self, daterange):
|
479
486
|
startdate, stopdate = daterange
|
480
|
-
|
487
|
+
|
488
|
+
def total_months(dt):
|
489
|
+
return dt.month + 12 * dt.year
|
490
|
+
|
481
491
|
mlist = []
|
482
492
|
for tot_m in range(total_months(startdate) - 1, total_months(stopdate)):
|
483
493
|
y, m = divmod(tot_m, 12)
|
env_canada/ec_hydro.py
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
import csv
|
2
2
|
import io
|
3
3
|
|
4
|
+
import voluptuous as vol
|
4
5
|
from aiohttp import ClientSession
|
5
6
|
from dateutil.parser import isoparse
|
6
7
|
from geopy import distance
|
7
|
-
import voluptuous as vol
|
8
8
|
|
9
9
|
from .constants import USER_AGENT
|
10
10
|
|
@@ -54,8 +54,7 @@ async def closest_site(lat, lon):
|
|
54
54
|
return closest
|
55
55
|
|
56
56
|
|
57
|
-
class ECHydro
|
58
|
-
|
57
|
+
class ECHydro:
|
59
58
|
"""Get hydrometric data from Environment Canada."""
|
60
59
|
|
61
60
|
def __init__(self, **kwargs):
|
env_canada/ec_radar.py
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
import asyncio
|
2
|
-
from datetime import date, timedelta
|
3
2
|
import logging
|
4
3
|
import math
|
5
4
|
import os
|
5
|
+
from datetime import date, timedelta
|
6
6
|
from io import BytesIO
|
7
7
|
from typing import cast
|
8
8
|
|
9
9
|
import dateutil.parser
|
10
|
-
import defusedxml.ElementTree as et
|
11
10
|
import voluptuous as vol
|
12
11
|
from aiohttp import ClientSession
|
13
12
|
from aiohttp.client_exceptions import ClientConnectorError
|
13
|
+
from lxml import etree as et
|
14
14
|
from PIL import Image, ImageDraw, ImageFont
|
15
15
|
|
16
16
|
from .constants import USER_AGENT
|
@@ -114,7 +114,7 @@ async def _get_resource(url, params, bytes=True):
|
|
114
114
|
return await response.text()
|
115
115
|
|
116
116
|
|
117
|
-
class ECRadar
|
117
|
+
class ECRadar:
|
118
118
|
def __init__(self, **kwargs):
|
119
119
|
"""Initialize the radar object."""
|
120
120
|
|
@@ -195,7 +195,7 @@ class ECRadar(object):
|
|
195
195
|
return Cache.add("basemap", base_bytes, timedelta(days=7))
|
196
196
|
|
197
197
|
except ClientConnectorError as e:
|
198
|
-
logging.warning("Map from %s could not be retrieved: %s"
|
198
|
+
logging.warning("Map from %s could not be retrieved: %s", map_url, e)
|
199
199
|
|
200
200
|
async def _get_legend(self):
|
201
201
|
"""Fetch legend image."""
|
@@ -226,7 +226,7 @@ class ECRadar(object):
|
|
226
226
|
if not (capabilities_xml := Cache.get(capabilities_cache_key)):
|
227
227
|
capabilities_params["layer"] = precip_layers[self._precip_type_actual]
|
228
228
|
capabilities_xml = await _get_resource(
|
229
|
-
geomet_url, capabilities_params, bytes=
|
229
|
+
geomet_url, capabilities_params, bytes=True
|
230
230
|
)
|
231
231
|
Cache.add(capabilities_cache_key, capabilities_xml, timedelta(minutes=5))
|
232
232
|
|
@@ -236,9 +236,9 @@ class ECRadar(object):
|
|
236
236
|
)
|
237
237
|
if dimension_string is not None:
|
238
238
|
if dimension_string := dimension_string.text:
|
239
|
-
start, end =
|
239
|
+
start, end = (
|
240
240
|
dateutil.parser.isoparse(t) for t in dimension_string.split("/")[:2]
|
241
|
-
|
241
|
+
)
|
242
242
|
self.timestamp = end.isoformat()
|
243
243
|
return (start, end)
|
244
244
|
return None
|
env_canada/ec_weather.py
CHANGED
@@ -3,11 +3,11 @@ import datetime
|
|
3
3
|
import logging
|
4
4
|
import re
|
5
5
|
|
6
|
+
import voluptuous as vol
|
6
7
|
from aiohttp import ClientSession
|
7
8
|
from dateutil import parser, relativedelta, tz
|
8
|
-
import defusedxml.ElementTree as et
|
9
9
|
from geopy import distance
|
10
|
-
import
|
10
|
+
from lxml import etree as et
|
11
11
|
|
12
12
|
from . import ec_exc
|
13
13
|
from .constants import USER_AGENT
|
@@ -259,7 +259,7 @@ def closest_site(site_list, lat, lon):
|
|
259
259
|
return "{}/{}".format(closest["Province Codes"], closest["Codes"])
|
260
260
|
|
261
261
|
|
262
|
-
class ECWeather
|
262
|
+
class ECWeather:
|
263
263
|
"""Get weather data from Environment Canada."""
|
264
264
|
|
265
265
|
def __init__(self, **kwargs):
|
@@ -342,12 +342,14 @@ class ECWeather(object):
|
|
342
342
|
timeout=10,
|
343
343
|
)
|
344
344
|
result = await response.read()
|
345
|
-
weather_xml = result
|
345
|
+
weather_xml = result
|
346
346
|
|
347
347
|
try:
|
348
348
|
weather_tree = et.fromstring(weather_xml)
|
349
|
-
except et.ParseError:
|
350
|
-
raise ECWeatherUpdateFailed(
|
349
|
+
except et.ParseError as err:
|
350
|
+
raise ECWeatherUpdateFailed(
|
351
|
+
"Weather update failed; could not parse result"
|
352
|
+
) from err
|
351
353
|
|
352
354
|
# Update metadata
|
353
355
|
for m, meta in metadata_meta.items():
|
@@ -451,6 +453,7 @@ class ECWeather(object):
|
|
451
453
|
self.hourly_forecasts = []
|
452
454
|
|
453
455
|
# Update daily forecasts
|
456
|
+
forecast_time = self.forecast_time
|
454
457
|
for f in weather_tree.findall("./forecastGroup/forecast"):
|
455
458
|
self.daily_forecasts.append(
|
456
459
|
{
|
@@ -464,8 +467,11 @@ class ECWeather(object):
|
|
464
467
|
"precip_probability": int(
|
465
468
|
f.findtext("./abbreviatedForecast/pop") or "0"
|
466
469
|
),
|
470
|
+
"timestamp": forecast_time,
|
467
471
|
}
|
468
472
|
)
|
473
|
+
if self.daily_forecasts[-1]["temperature_class"] == "low":
|
474
|
+
forecast_time = forecast_time + datetime.timedelta(days=1)
|
469
475
|
|
470
476
|
# Update hourly forecasts
|
471
477
|
for f in weather_tree.findall("./hourlyForecastGroup/hourlyForecast"):
|
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
16
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
17
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
18
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
-
SOFTWARE
|
19
|
+
SOFTWARE
|
@@ -1,34 +1,73 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: env_canada
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.8.0
|
4
4
|
Summary: A package to access meteorological data from Environment Canada
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
Author-email: Michael Davie <michael.davie@gmail.com>
|
6
|
+
Maintainer-email: Michael Davie <michael.davie@gmail.com>
|
7
|
+
License: Copyright (c) 2018 The Python Packaging Authority
|
8
|
+
|
9
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
10
|
+
of this software and associated documentation files (the "Software"), to deal
|
11
|
+
in the Software without restriction, including without limitation the rights
|
12
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
13
|
+
copies of the Software, and to permit persons to whom the Software is
|
14
|
+
furnished to do so, subject to the following conditions:
|
15
|
+
|
16
|
+
The above copyright notice and this permission notice shall be included in all
|
17
|
+
copies or substantial portions of the Software.
|
18
|
+
|
19
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
20
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
21
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
22
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
23
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
24
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
25
|
+
SOFTWARE
|
26
|
+
|
27
|
+
Project-URL: Homepage, https://github.com/michaeldavie/env_canada
|
28
|
+
Project-URL: Documentation, https://github.com/michaeldavie/env_canada
|
29
|
+
Project-URL: Repository, https://github.com/michaeldavie/env_canada
|
30
|
+
Project-URL: Bug Tracker, https://github.com/michaeldavie/env_canada/issues
|
31
|
+
Project-URL: Changelog, https://github.com/michaeldavie/env_canada/blob/master/CHANGELOG.md
|
9
32
|
Classifier: Programming Language :: Python :: 3
|
10
33
|
Classifier: License :: OSI Approved :: MIT License
|
11
34
|
Classifier: Operating System :: OS Independent
|
35
|
+
Requires-Python: >=3.10
|
12
36
|
Description-Content-Type: text/markdown
|
13
37
|
License-File: LICENSE
|
14
|
-
Requires-Dist: aiohttp
|
15
|
-
Requires-Dist: defusedxml
|
38
|
+
Requires-Dist: aiohttp>=3.9.0
|
16
39
|
Requires-Dist: geopy
|
17
|
-
Requires-Dist: imageio
|
40
|
+
Requires-Dist: imageio>=2.28.0
|
18
41
|
Requires-Dist: lxml
|
19
|
-
Requires-Dist: numpy
|
20
|
-
Requires-Dist: pandas
|
21
|
-
Requires-Dist: Pillow
|
42
|
+
Requires-Dist: numpy>=1.22.2
|
43
|
+
Requires-Dist: pandas>=1.3.0
|
44
|
+
Requires-Dist: Pillow>=10.0.1
|
22
45
|
Requires-Dist: python-dateutil
|
23
46
|
Requires-Dist: voluptuous
|
47
|
+
Provides-Extra: dev
|
48
|
+
Requires-Dist: pytest; extra == "dev"
|
24
49
|
|
25
50
|
# Environment Canada (env_canada)
|
26
51
|
|
27
52
|
[](https://badge.fury.io/py/env-canada)
|
28
|
-
[](https://snyk.io/vuln/pip:env-canada@0.
|
53
|
+
[](https://snyk.io/vuln/pip:env-canada@0.8.0?utm_source=badge)
|
54
|
+
[](../../actions/workflows/python-app.yml)
|
29
55
|
|
30
56
|
This package provides access to various data sources published by [Environment and Climate Change Canada](https://www.canada.ca/en/environment-climate-change.html).
|
31
57
|
|
58
|
+
> [!IMPORTANT]
|
59
|
+
> If you're using the library in a Jupyter notebook, replace `asyncio.run(...)` with `await ...` in the examples below. For example:
|
60
|
+
>
|
61
|
+
> ```python
|
62
|
+
> asyncio.run(ec_en.update())
|
63
|
+
> ```
|
64
|
+
>
|
65
|
+
> becomes
|
66
|
+
>
|
67
|
+
> ```python
|
68
|
+
> await ec_en.update()
|
69
|
+
> ```
|
70
|
+
|
32
71
|
## Weather Observations and Forecasts
|
33
72
|
|
34
73
|
`ECWeather` provides current conditions and forecasts. It automatically determines which weather station to use based on latitude/longitude provided. It is also possible to specify a specific station code of the form `AB/s0000123` based on those listed in [this CSV file](https://dd.weather.gc.ca/citypage_weather/docs/site_list_towns_en.csv). For example:
|
@@ -39,7 +78,7 @@ import asyncio
|
|
39
78
|
from env_canada import ECWeather
|
40
79
|
|
41
80
|
ec_en = ECWeather(coordinates=(50, -100))
|
42
|
-
ec_fr = ECWeather(station_id=
|
81
|
+
ec_fr = ECWeather(station_id="ON/s0000430", language="french")
|
43
82
|
|
44
83
|
asyncio.run(ec_en.update())
|
45
84
|
|
@@ -120,7 +159,7 @@ from env_canada import ECHistorical
|
|
120
159
|
from env_canada.ec_historical import get_historical_stations
|
121
160
|
|
122
161
|
# search for stations, response contains station_ids
|
123
|
-
coordinates = [53.916944, -122.749444]
|
162
|
+
coordinates = [53.916944, -122.749444] # [lat, long]
|
124
163
|
|
125
164
|
# coordinates: [lat, long]
|
126
165
|
# radius: km
|
@@ -136,8 +175,12 @@ ec_fr_csv = ECHistorical(station_id=31688, year=2020, language="french", format=
|
|
136
175
|
# timeframe argument can be passed to change the granularity
|
137
176
|
# timeframe=1 hourly (need to create of for every month in that case, use ECHistoricalRange to handle it automatically)
|
138
177
|
# timeframe=2 daily (default)
|
139
|
-
ec_en_xml = ECHistorical(
|
140
|
-
|
178
|
+
ec_en_xml = ECHistorical(
|
179
|
+
station_id=31688, year=2020, month=1, language="english", format="xml", timeframe=1
|
180
|
+
)
|
181
|
+
ec_en_csv = ECHistorical(
|
182
|
+
station_id=31688, year=2020, month=1, language="english", format="csv", timeframe=1
|
183
|
+
)
|
141
184
|
|
142
185
|
asyncio.run(ec_en_xml.update())
|
143
186
|
asyncio.run(ec_en_csv.update())
|
@@ -150,8 +193,8 @@ ec_en_xml.station_data
|
|
150
193
|
|
151
194
|
# csv-generated responses return csv-like station data
|
152
195
|
import pandas as pd
|
153
|
-
df = pd.read_csv(ec_en_csv.station_data)
|
154
196
|
|
197
|
+
df = pd.read_csv(ec_en_csv.station_data)
|
155
198
|
```
|
156
199
|
|
157
200
|
`ECHistoricalRange` provides historical weather data within a specific range and handles the update by itself.
|
@@ -170,21 +213,29 @@ from env_canada import ECHistoricalRange
|
|
170
213
|
from env_canada.ec_historical import get_historical_stations
|
171
214
|
from datetime import datetime
|
172
215
|
|
173
|
-
coordinates = [
|
216
|
+
coordinates = ["48.508333", "-68.467667"]
|
174
217
|
|
175
|
-
stations = pd.DataFrame(
|
176
|
-
|
218
|
+
stations = pd.DataFrame(
|
219
|
+
asyncio.run(
|
220
|
+
get_historical_stations(
|
221
|
+
coordinates, start_year=2022, end_year=2022, radius=200, limit=100
|
222
|
+
)
|
223
|
+
)
|
224
|
+
).T
|
177
225
|
|
178
|
-
ec = ECHistoricalRange(
|
179
|
-
|
226
|
+
ec = ECHistoricalRange(
|
227
|
+
station_id=int(stations.iloc[0, 2]),
|
228
|
+
timeframe="daily",
|
229
|
+
daterange=(datetime(2022, 7, 1, 12, 12), datetime(2022, 8, 1, 12, 12)),
|
230
|
+
)
|
180
231
|
|
181
232
|
ec.get_data()
|
182
233
|
|
183
|
-
#yield an XML formated str.
|
234
|
+
# yield an XML formated str.
|
184
235
|
# For more options, use ec.to_xml(*arg, **kwargs) with pandas options
|
185
236
|
ec.xml
|
186
237
|
|
187
|
-
#yield an CSV formated str.
|
238
|
+
# yield an CSV formated str.
|
188
239
|
# For more options, use ec.to_csv(*arg, **kwargs) with pandas options
|
189
240
|
ec.csv
|
190
241
|
```
|
@@ -0,0 +1,16 @@
|
|
1
|
+
env_canada/10x20.pbm,sha256=ClKTs2WUmhUhTHAQzPuGwPTICGVBzCvos5l-vHRBE5M,2463
|
2
|
+
env_canada/10x20.pil,sha256=Oki6-TD7b0xFtfm6vxCKsmpEpsZ5Jaia_0v_aDz8bfE,5143
|
3
|
+
env_canada/__init__.py,sha256=Qqtu4qEY1gvzPF4D0qzi8kVvtYUizJDzQk5FZVqoo38,314
|
4
|
+
env_canada/constants.py,sha256=RHa-Hp2H6XroFE9Z5-H0MIUPWlFXUVKmWEidwuWzakE,32
|
5
|
+
env_canada/ec_aqhi.py,sha256=-N4XLLgApaWZvtepJvS2lvqDSNjwV2X_fkmbtKQv8rA,7741
|
6
|
+
env_canada/ec_cache.py,sha256=zb3n79ul7hUTE0IohDfZbRBLY-siOHPjYzWldMbuPVk,798
|
7
|
+
env_canada/ec_exc.py,sha256=SBJwzmLf94lTx7KYVLfQYrMXYNYUoIxeVXc-BLkuXoE,67
|
8
|
+
env_canada/ec_historical.py,sha256=qMr4RE6vfNiNa_zFolQ0PQGraok8bQtIVjs_o6sJKD4,16276
|
9
|
+
env_canada/ec_hydro.py,sha256=JoBe-QVV8GEeZXCNFscIs2R_spgkbxCZpLt7tL6-NUI,4889
|
10
|
+
env_canada/ec_radar.py,sha256=0SKusJWDTFODdn3D9yrhlkOS-Bv9hhBJM9EBh8TNRlk,12965
|
11
|
+
env_canada/ec_weather.py,sha256=PSgb67PODo8Lv7A7O01q97SjvHCK0lwpcDtqTa70GI8,17048
|
12
|
+
env_canada-0.8.0.dist-info/LICENSE,sha256=BkgGIGgy9sv-OsI7mRi9dIQ3Su0m4IbjpZlfxv8oBbM,1073
|
13
|
+
env_canada-0.8.0.dist-info/METADATA,sha256=U548dMi4w3eX8MqFQrQseJthoggUFfC_a1AefMYjemA,12723
|
14
|
+
env_canada-0.8.0.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
|
15
|
+
env_canada-0.8.0.dist-info/top_level.txt,sha256=fw7Pcl9ULBXYvqnAdyBdmwPXW8GSRFmhO0sLZWVfOCc,11
|
16
|
+
env_canada-0.8.0.dist-info/RECORD,,
|
@@ -1,16 +0,0 @@
|
|
1
|
-
env_canada/10x20.pbm,sha256=ClKTs2WUmhUhTHAQzPuGwPTICGVBzCvos5l-vHRBE5M,2463
|
2
|
-
env_canada/10x20.pil,sha256=Oki6-TD7b0xFtfm6vxCKsmpEpsZ5Jaia_0v_aDz8bfE,5143
|
3
|
-
env_canada/__init__.py,sha256=wEx1BCwVUH__GoosSlhNMHuUKCKNZAvv5uuSa5ZWq_g,187
|
4
|
-
env_canada/constants.py,sha256=6oDJe86s1hRPyA0pj_MK0S_HHM8kCXd_RuHMWu0fh3E,32
|
5
|
-
env_canada/ec_aqhi.py,sha256=zEEt2U8gCxaLlePexl23r9zCfQYgmfhsP0ur2ZiupZc,7793
|
6
|
-
env_canada/ec_cache.py,sha256=xPlXBRLyrD6dTJWLRBy12J8kzBxMUC-20-xRuc56Hts,722
|
7
|
-
env_canada/ec_exc.py,sha256=SBJwzmLf94lTx7KYVLfQYrMXYNYUoIxeVXc-BLkuXoE,67
|
8
|
-
env_canada/ec_historical.py,sha256=slHaFwsoyW16uCVtE3_-IF3_BFhFD4IuWl7rpIRsCm4,15901
|
9
|
-
env_canada/ec_hydro.py,sha256=LBsWreTlaTKec6ObjI0ih8-zOKBNjD02oiXKTyUa1EQ,4898
|
10
|
-
env_canada/ec_radar.py,sha256=zh0tbazBbvLpuxrY0yfRm9EIaXNkM6HXPe1us99h4xM,12982
|
11
|
-
env_canada/ec_weather.py,sha256=M7nPeZIKLirRIcCENB8z2B8aBDZHrjltzMYPgRz9lz0,16789
|
12
|
-
env_canada-0.7.1.dist-info/LICENSE,sha256=c037dTHQWAgRgDqZNN-5d-CZvcteSYN37u39SNklO0I,1072
|
13
|
-
env_canada-0.7.1.dist-info/METADATA,sha256=y5JONQes6DXUWQlw4zN-XL4TjmOBdYvlVmuoxT4M0B8,10707
|
14
|
-
env_canada-0.7.1.dist-info/WHEEL,sha256=mguMlWGMX-VHnMpKOjjQidIo1ssRlCFu4a4mBpz1s2M,91
|
15
|
-
env_canada-0.7.1.dist-info/top_level.txt,sha256=fw7Pcl9ULBXYvqnAdyBdmwPXW8GSRFmhO0sLZWVfOCc,11
|
16
|
-
env_canada-0.7.1.dist-info/RECORD,,
|
File without changes
|