tonik 0.0.8__py3-none-any.whl → 0.0.10__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.
tonik/api.py CHANGED
@@ -1,22 +1,21 @@
1
- from argparse import ArgumentParser
2
- from datetime import timedelta, datetime, timezone
3
1
  import logging
4
2
  import os
3
+ from argparse import ArgumentParser
4
+ from datetime import datetime
5
+ from typing import Annotated
5
6
  from urllib.parse import unquote
6
7
 
7
- from cftime import num2date, date2num
8
8
  import datashader as dsh
9
9
  import numpy as np
10
10
  import pandas as pd
11
11
  import uvicorn
12
+ from cftime import date2num, num2date
12
13
  from fastapi import FastAPI, HTTPException, Query
13
14
  from fastapi.middleware.cors import CORSMiddleware
14
15
  from fastapi.responses import HTMLResponse, StreamingResponse
15
- from pydantic import BaseModel
16
- from typing import Annotated
17
16
 
18
- from .storage import Storage
19
17
  from . import get_data
18
+ from .storage import Storage
20
19
 
21
20
  logger = logging.getLogger(__name__)
22
21
 
@@ -67,7 +66,8 @@ class TonikAPI:
67
66
  _st = self.preprocess_datetime(starttime)
68
67
  _et = self.preprocess_datetime(endtime)
69
68
  g = Storage(group, rootdir=self.rootdir,
70
- starttime=_st, endtime=_et)
69
+ starttime=_st, endtime=_et,
70
+ create=False)
71
71
  if subdir is None:
72
72
  c = g
73
73
  else:
@@ -103,13 +103,15 @@ class TonikAPI:
103
103
  else:
104
104
  df = pd.DataFrame(data=feat.to_pandas(), columns=[feat.name])
105
105
  df['dates'] = df.index
106
- try:
107
- current_resolution = pd.Timedelta(df['dates'].diff().mean())
108
- if current_resolution < pd.Timedelta(resolution):
109
- df = df.resample(pd.Timedelta(resolution)).mean()
110
- except ValueError as e:
111
- logger.warning(
112
- f"Cannot resample {feat.name} to {resolution}: e")
106
+ if resolution != 'full':
107
+ try:
108
+ current_resolution = pd.Timedelta(
109
+ df['dates'].diff().mean())
110
+ if current_resolution < pd.Timedelta(resolution):
111
+ df = df.resample(pd.Timedelta(resolution)).mean()
112
+ except ValueError:
113
+ logger.warning(
114
+ f"Cannot resample {feat.name} to {resolution}: e")
113
115
  df.rename(columns={feat.name: 'feature'}, inplace=True)
114
116
  output = df.to_csv(index=False, columns=['dates', 'feature'])
115
117
  return StreamingResponse(iter([output]),
@@ -143,7 +145,7 @@ class TonikAPI:
143
145
  c = sg.get_substore(*subdir)
144
146
  except TypeError:
145
147
  c = sg
146
- except FileNotFoundError as e:
148
+ except FileNotFoundError:
147
149
  msg = "Directory {} not found.".format(
148
150
  '/'.join([sg.path] + subdir))
149
151
  raise HTTPException(status_code=404, detail=msg)
tonik/utils.py CHANGED
@@ -8,8 +8,8 @@ import xarray as xr
8
8
  def generate_test_data(dim=1, ndays=30, nfreqs=10,
9
9
  tstart=datetime.now(),
10
10
  freq='10min', intervals=None,
11
- feature_name=None, seed=42,
12
- freq_name=None, add_nans=True):
11
+ feature_names=None, seed=42,
12
+ freq_names=None, add_nans=True):
13
13
  """
14
14
  Generate a 1D or 2D feature for testing.
15
15
  """
@@ -28,25 +28,31 @@ def generate_test_data(dim=1, ndays=30, nfreqs=10,
28
28
  data = np.tile(data, (nfreqs, 1))
29
29
  # Add 10% NaNs
30
30
  idx_nan = rs.integers(0, nints-1, int(0.1*nints))
31
+
32
+ xds_dict = {}
31
33
  if dim == 1:
32
34
  if add_nans:
33
35
  data[idx_nan] = np.nan
34
- if feature_name is None:
35
- feature_name = 'rsam'
36
- xrd = xr.Dataset({feature_name: xr.DataArray(
37
- data, coords=[dates], dims=['datetime'])})
36
+ if feature_names is None:
37
+ feature_names = ['rsam', 'dsar']
38
+ for feature in feature_names:
39
+ xds_dict[feature] = xr.DataArray(
40
+ data, coords=[dates], dims=['datetime'])
38
41
  if dim == 2:
39
42
  if add_nans:
40
43
  data[:, idx_nan] = np.nan
41
44
  freqs = np.arange(nfreqs)
42
- if feature_name is None:
43
- feature_name = 'ssam'
44
- if freq_name is None:
45
- freq_name = 'frequency'
46
- xrd = xr.Dataset({feature_name: xr.DataArray(
47
- data, coords=[freqs, dates], dims=[freq_name, 'datetime'])})
48
- xrd.attrs['starttime'] = dates[0].isoformat()
49
- xrd.attrs['endtime'] = dates[-1].isoformat()
50
- xrd.attrs['station'] = 'MDR'
51
- xrd.attrs['interval'] = '10min'
52
- return xrd
45
+ if feature_names is None:
46
+ feature_names = ['ssam', 'filterbank']
47
+ if freq_names is None:
48
+ freq_names = ['frequency', 'fbfrequency']
49
+
50
+ for feature_name, freq_name in zip(feature_names, freq_names):
51
+ xds_dict[feature_name] = xr.DataArray(
52
+ data, coords=[freqs, dates], dims=[freq_name, 'datetime'])
53
+ xds = xr.Dataset(xds_dict)
54
+ xds.attrs['starttime'] = dates[0].isoformat()
55
+ xds.attrs['endtime'] = dates[-1].isoformat()
56
+ xds.attrs['station'] = 'MDR'
57
+ xds.attrs['interval'] = '10min'
58
+ return xds
tonik/xarray2zarr.py CHANGED
@@ -1,7 +1,10 @@
1
+ import logging
1
2
  import os
2
3
 
3
4
  import xarray as xr
4
5
 
6
+ logger = logging.getLogger(__name__)
7
+
5
8
 
6
9
  def xarray2zarr(xds, path, mode='a'):
7
10
  for feature in xds.data_vars.keys():
@@ -11,13 +14,24 @@ def xarray2zarr(xds, path, mode='a'):
11
14
  fout, group='original', mode='w')
12
15
  else:
13
16
  xds_existing = xr.open_zarr(fout, group='original')
14
- overlap = xds_existing.datetime.where(
15
- xds_existing.datetime == xds.datetime)
16
- if overlap.size > 0:
17
- xds.loc[dict(datetime=overlap)].to_zarr(
18
- fout, group='original', mode='r+', region='auto')
19
- xds.drop_sel(datetime=overlap).to_zarr(
20
- fout, group='original', mode='a', append_dim="datetime")
21
- else:
22
- xds[feature].to_zarr(
23
- fout, group='original', append_dim='datetime')
17
+ try:
18
+ overlap = xds_existing.datetime.where(
19
+ xds_existing.datetime == xds.datetime)
20
+ if overlap.size > 0:
21
+ xds[feature].loc[dict(datetime=overlap)].to_zarr(
22
+ fout, group='original', mode='r+', region='auto')
23
+ xds[feature].drop_sel(datetime=overlap).to_zarr(
24
+ fout, group='original', mode='a', append_dim="datetime")
25
+ else:
26
+ xds[feature].to_zarr(
27
+ fout, group='original', append_dim='datetime')
28
+ except Exception as e:
29
+ msg = f"Appending {feature} to {fout} failed: {e}\n"
30
+ msg += "Attempting to merge the two datasets."
31
+ logger.error(msg)
32
+ # remove duplicate datetime entries
33
+ xda_existing = xds_existing[feature].drop_duplicates(
34
+ 'datetime', keep='last')
35
+ xda_new = xds[feature].drop_duplicates('datetime', keep='last')
36
+ xda_new = xda_new.combine_first(xda_existing)
37
+ xda_new.to_zarr(fout, group='original', mode='w')
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: tonik
3
- Version: 0.0.8
3
+ Version: 0.0.10
4
4
  Summary: Store time series data as HDF5 files and access them through an API.
5
5
  Project-URL: Homepage, https://tsc-tools.github.io/tonik
6
6
  Project-URL: Issues, https://github.com/tsc-tools/tonik/issues
@@ -0,0 +1,12 @@
1
+ tonik/__init__.py,sha256=ZBVGh4dm_l9xwiBGb33O5QV9MfZeNiEd3DBDAm6DiHk,511
2
+ tonik/api.py,sha256=8YS0WCMlm5xs2N6V8n9BiP87ywJC_BUzYsPvWR9KWJk,6499
3
+ tonik/storage.py,sha256=sScIFA4KXURNPwTnV-rvDh6cWCy9sRrErr9BshZpw2I,11303
4
+ tonik/utils.py,sha256=_TxXf9o9fOvtuOvGO6-ww9F5m0QelHyfQzQw8RGjTV4,1868
5
+ tonik/xarray2hdf5.py,sha256=cekO9vo9ZRlr0VndswJjPC27CEVD3TpRVKLAJ-aAO0g,4465
6
+ tonik/xarray2zarr.py,sha256=9gvm7vFnoe-O39-ow2pqK4xoFSg9Tg865qdqKYI-Zy8,1605
7
+ tonik/package_data/index.html,sha256=GKDClUhIam_fAYbNfzAolORhSCG3ae1wW3VjWCg4PMk,2732
8
+ tonik-0.0.10.dist-info/METADATA,sha256=IN-k1gZOtxQrsVlYDtpiJuBW4gIJCXRsqFO4pNCT_uo,1939
9
+ tonik-0.0.10.dist-info/WHEEL,sha256=1yFddiXMmvYK7QYTqtRNtX66WJ0Mz8PYEiEUoOUUxRY,87
10
+ tonik-0.0.10.dist-info/entry_points.txt,sha256=VnGfC5qAzpntEHAb5pooUEpYABSgOfQoNhCEtLDJyf8,45
11
+ tonik-0.0.10.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
12
+ tonik-0.0.10.dist-info/RECORD,,
@@ -1,4 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.17.1
2
+ Generator: hatchling 1.25.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
@@ -1,12 +0,0 @@
1
- tonik/__init__.py,sha256=ZBVGh4dm_l9xwiBGb33O5QV9MfZeNiEd3DBDAm6DiHk,511
2
- tonik/api.py,sha256=vdsWHNGGWo4sbqlDyZQj2tX5oe6hAWCzyL6ffsfpCB4,6437
3
- tonik/storage.py,sha256=sScIFA4KXURNPwTnV-rvDh6cWCy9sRrErr9BshZpw2I,11303
4
- tonik/utils.py,sha256=YD2zZx5nKGfTJKTYTsEZVV78uNRCSakvU_6X6Mgwx-s,1664
5
- tonik/xarray2hdf5.py,sha256=cekO9vo9ZRlr0VndswJjPC27CEVD3TpRVKLAJ-aAO0g,4465
6
- tonik/xarray2zarr.py,sha256=d7FAOe7DESbKC9CZS41r62DjlNy0S8ik01lMGXBvJKw,901
7
- tonik/package_data/index.html,sha256=GKDClUhIam_fAYbNfzAolORhSCG3ae1wW3VjWCg4PMk,2732
8
- tonik-0.0.8.dist-info/METADATA,sha256=uqrHvBl01n05hqWN8lnNETuoYIGZ8vNq9QWnRmajcEY,1938
9
- tonik-0.0.8.dist-info/WHEEL,sha256=KGYbc1zXlYddvwxnNty23BeaKzh7YuoSIvIMO4jEhvw,87
10
- tonik-0.0.8.dist-info/entry_points.txt,sha256=VnGfC5qAzpntEHAb5pooUEpYABSgOfQoNhCEtLDJyf8,45
11
- tonik-0.0.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
12
- tonik-0.0.8.dist-info/RECORD,,