ClimateGraph 0.4.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.
Files changed (44) hide show
  1. ClimateGraph/__init__.py +9 -0
  2. ClimateGraph/appkernel.py +148 -0
  3. ClimateGraph/cli.py +63 -0
  4. ClimateGraph/data/__init__.py +8 -0
  5. ClimateGraph/data/data.py +508 -0
  6. ClimateGraph/data/point_surface.py +91 -0
  7. ClimateGraph/data/regular_grid.py +25 -0
  8. ClimateGraph/data/satellite_swath.py +21 -0
  9. ClimateGraph/domain/__init__.py +11 -0
  10. ClimateGraph/domain/domain.py +181 -0
  11. ClimateGraph/domain/domains.py +279 -0
  12. ClimateGraph/plot/__init__.py +11 -0
  13. ClimateGraph/plot/plot.py +402 -0
  14. ClimateGraph/plot/plots.py +1054 -0
  15. ClimateGraph/plot/primitive.py +99 -0
  16. ClimateGraph/plot/primitives.py +160 -0
  17. ClimateGraph/reader/__init__.py +15 -0
  18. ClimateGraph/reader/reader/__init__.py +14 -0
  19. ClimateGraph/reader/reader/point_surface/__init__.py +7 -0
  20. ClimateGraph/reader/reader/point_surface/csv_base.py +135 -0
  21. ClimateGraph/reader/reader/point_surface/default.py +36 -0
  22. ClimateGraph/reader/reader/point_surface/dmc.py +10 -0
  23. ClimateGraph/reader/reader/point_surface/sinca.py +10 -0
  24. ClimateGraph/reader/reader/point_surface/single_file.py +60 -0
  25. ClimateGraph/reader/reader/point_surface/station_per_file.py +55 -0
  26. ClimateGraph/reader/reader/point_surface/variable_per_file.py +91 -0
  27. ClimateGraph/reader/reader/reader.py +353 -0
  28. ClimateGraph/reader/reader/regular_grid/__init__.py +7 -0
  29. ClimateGraph/reader/reader/regular_grid/chimere.py +24 -0
  30. ClimateGraph/reader/reader/regular_grid/default.py +51 -0
  31. ClimateGraph/reader/reader/regular_grid/wrf.py +53 -0
  32. ClimateGraph/utils/__init__.py +1 -0
  33. ClimateGraph/utils/control_model.py +292 -0
  34. ClimateGraph/utils/dataset_utils.py +287 -0
  35. ClimateGraph/utils/general_utils.py +259 -0
  36. ClimateGraph/utils/parser.py +269 -0
  37. ClimateGraph/utils/registry.py +81 -0
  38. ClimateGraph/utils/resample_engine.py +156 -0
  39. climategraph-0.4.0.dist-info/METADATA +177 -0
  40. climategraph-0.4.0.dist-info/RECORD +44 -0
  41. climategraph-0.4.0.dist-info/WHEEL +5 -0
  42. climategraph-0.4.0.dist-info/entry_points.txt +2 -0
  43. climategraph-0.4.0.dist-info/licenses/LICENSE +21 -0
  44. climategraph-0.4.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,156 @@
1
+ """Pluggable spatial resampling backends.
2
+
3
+ A protocol plus the pyresample implementation, so another backend can be added
4
+ without changing the code that calls for a resample.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from collections.abc import Callable
10
+ from typing import Any, Protocol, runtime_checkable
11
+
12
+ import numpy as np
13
+ from pyresample import kd_tree
14
+
15
+
16
+ @runtime_checkable
17
+ class ResampleEngine(Protocol):
18
+ """Protocol for spatial resampling backends.
19
+
20
+ Two-step design: ``prepare`` computes reusable indices/weights from the
21
+ source and destination geometries (expensive, done once per geometry pair),
22
+ and ``make_resampler`` returns a callable that applies those to a single
23
+ 2-D array (cheap, called per variable per timestep via apply_ufunc).
24
+ """
25
+
26
+ def prepare(
27
+ self,
28
+ src_geom,
29
+ dst_geom,
30
+ radius_of_influence: int,
31
+ **kwargs,
32
+ ) -> Any:
33
+ """Compute resampling info (indices, weights, etc.).
34
+
35
+ The returned object is opaque — it is passed back into
36
+ ``make_resampler`` without inspection by the caller.
37
+ """
38
+ ...
39
+
40
+ def make_resampler(
41
+ self,
42
+ info: Any,
43
+ dst_shape: tuple,
44
+ src_shape: tuple,
45
+ ) -> Callable[[np.ndarray], np.ndarray]:
46
+ """Return a function ``f(block) -> resampled`` using precomputed info.
47
+
48
+ ``block`` carries the source spatial dims *last* (``(*lead, *src_shape)``,
49
+ the layout ``xr.apply_ufunc`` hands a non-vectorized ufunc); any leading
50
+ dims (time, z, …) are batched into a single pyresample call. A bare
51
+ ``src_shape`` block (no leading dims) is the 2-D legacy case.
52
+ """
53
+ ...
54
+
55
+
56
+ class PyresampleEngine:
57
+ """Pyresample KD-tree backend. Supports nearest and gaussian methods."""
58
+
59
+ def __init__(
60
+ self,
61
+ method: str = "nearest",
62
+ sigmas: float = 10000,
63
+ neighbours: int | None = None,
64
+ ):
65
+ """Configure the engine with the resampling method and its options."""
66
+ self.method = method
67
+ self.sigmas = sigmas
68
+ self.neighbours = neighbours or (1 if method == "nearest" else 8)
69
+
70
+ def prepare(self, src_geom, dst_geom, radius_of_influence: int, **kwargs) -> tuple:
71
+ """Build whatever the backend needs before resampling onto a geometry."""
72
+ return kd_tree.get_neighbour_info(
73
+ src_geom,
74
+ dst_geom,
75
+ radius_of_influence=radius_of_influence,
76
+ neighbours=self.neighbours,
77
+ )
78
+
79
+ def make_resampler(
80
+ self, info: tuple, dst_shape: tuple, src_shape: tuple
81
+ ) -> Callable:
82
+ """Return a callable that resamples one array onto the target geometry."""
83
+ valid_input, valid_output, index_array, dist_array = info
84
+
85
+ if self.method == "nearest":
86
+
87
+ def _run(data: np.ndarray) -> np.ndarray:
88
+ return kd_tree.get_sample_from_neighbour_info(
89
+ "nn",
90
+ dst_shape,
91
+ data,
92
+ valid_input,
93
+ valid_output,
94
+ index_array,
95
+ dist_array,
96
+ fill_value=np.nan,
97
+ )
98
+
99
+ elif self.method == "gaussian":
100
+ sigma = self.sigmas
101
+ n_neighbours = index_array.shape[1] if index_array.ndim > 1 else 1
102
+
103
+ def _weight(dist):
104
+ return np.exp(-(dist**2) / (2 * sigma**2))
105
+
106
+ def _run(data: np.ndarray) -> np.ndarray:
107
+ return kd_tree.get_sample_from_neighbour_info(
108
+ "custom",
109
+ dst_shape,
110
+ data,
111
+ valid_input,
112
+ valid_output,
113
+ index_array,
114
+ dist_array,
115
+ weight_funcs=[_weight] * n_neighbours,
116
+ fill_value=np.nan,
117
+ )
118
+
119
+ else:
120
+ raise ValueError(
121
+ f"PyresampleEngine does not support method {self.method!r}. "
122
+ f"Available: nearest, gaussian."
123
+ )
124
+
125
+ src_ndim = len(src_shape)
126
+
127
+ def _resample(block: np.ndarray) -> np.ndarray:
128
+ lead = block.shape[: block.ndim - src_ndim]
129
+ if not lead:
130
+ return _run(block)
131
+ k = int(np.prod(lead))
132
+ moved = np.moveaxis(block, range(len(lead)), range(-len(lead), 0))
133
+ out = _run(moved.reshape((*src_shape, k)))
134
+ out = out.reshape((*dst_shape, *lead))
135
+ return np.moveaxis(out, range(-len(lead), 0), range(len(lead)))
136
+
137
+ return _resample
138
+
139
+
140
+ ENGINES: dict[str, type] = {
141
+ "pyresample": PyresampleEngine,
142
+ }
143
+
144
+
145
+ def get_engine(
146
+ backend: str | ResampleEngine = "pyresample", **kwargs
147
+ ) -> ResampleEngine:
148
+ """Resolve an engine by backend name or return an already-instantiated one."""
149
+ if isinstance(backend, str):
150
+ cls = ENGINES.get(backend.lower())
151
+ if cls is None:
152
+ raise ValueError(
153
+ f"Unknown resample backend {backend!r}. Available: {list(ENGINES)}"
154
+ )
155
+ return cls(**kwargs)
156
+ return backend
@@ -0,0 +1,177 @@
1
+ Metadata-Version: 2.4
2
+ Name: ClimateGraph
3
+ Version: 0.4.0
4
+ Summary: A CLI tool for graphing Climate Data
5
+ Author-email: Antonio Andrés Torga Mellado <antonio.torga@ug.uchile.cl>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/AntonioTorga/ClimateGraph
8
+ Project-URL: Documentation, https://climategraph.readthedocs.io
9
+ Project-URL: Repository, https://github.com/AntonioTorga/ClimateGraph
10
+ Project-URL: Issues, https://github.com/AntonioTorga/ClimateGraph/issues
11
+ Project-URL: Changelog, https://github.com/AntonioTorga/ClimateGraph/blob/main/CHANGELOG.md
12
+ Keywords: climate,air quality,xarray,visualization,netcdf,wrf,chimere
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Science/Research
16
+ Classifier: Natural Language :: English
17
+ Classifier: Operating System :: OS Independent
18
+ Classifier: Programming Language :: Python :: 3
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Scientific/Engineering :: Atmospheric Science
22
+ Classifier: Topic :: Scientific/Engineering :: Visualization
23
+ Requires-Python: >=3.12
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Requires-Dist: typer>=0.12
27
+ Requires-Dist: xarray
28
+ Requires-Dist: pandas
29
+ Requires-Dist: openpyxl
30
+ Requires-Dist: dask
31
+ Requires-Dist: netcdf4
32
+ Requires-Dist: numpy
33
+ Requires-Dist: matplotlib
34
+ Requires-Dist: pyyaml
35
+ Requires-Dist: pyresample
36
+ Requires-Dist: cartopy
37
+ Requires-Dist: pydantic
38
+ Requires-Dist: pint
39
+ Requires-Dist: pint_xarray
40
+ Requires-Dist: geopandas
41
+ Requires-Dist: regionmask
42
+ Requires-Dist: h5netcdf
43
+ Requires-Dist: h5py
44
+ Requires-Dist: dask
45
+ Provides-Extra: dev
46
+ Requires-Dist: ruff>=0.6; extra == "dev"
47
+ Requires-Dist: pre-commit>=3.7; extra == "dev"
48
+ Provides-Extra: test
49
+ Requires-Dist: pytest; extra == "test"
50
+ Requires-Dist: pytest-cov; extra == "test"
51
+ Requires-Dist: pillow; extra == "test"
52
+ Provides-Extra: docs
53
+ Requires-Dist: sphinx>=7.2; extra == "docs"
54
+ Requires-Dist: furo; extra == "docs"
55
+ Requires-Dist: myst-parser; extra == "docs"
56
+ Requires-Dist: sphinx-gallery; extra == "docs"
57
+ Requires-Dist: sphinx-copybutton; extra == "docs"
58
+ Requires-Dist: sphinx-design; extra == "docs"
59
+ Requires-Dist: pylint; extra == "docs"
60
+ Requires-Dist: pydeps; extra == "docs"
61
+ Provides-Extra: doc
62
+ Requires-Dist: sphinx; extra == "doc"
63
+ Requires-Dist: sphinx-rtd-theme; extra == "doc"
64
+ Requires-Dist: myst-parser; extra == "doc"
65
+ Dynamic: license-file
66
+
67
+ # 🌍 ClimateGraph
68
+
69
+ [![CI](https://github.com/AntonioTorga/ClimateGraph/actions/workflows/ci.yml/badge.svg)](https://github.com/AntonioTorga/ClimateGraph/actions/workflows/ci.yml)
70
+ [![Documentation](https://readthedocs.org/projects/climategraph/badge/?version=latest)](https://climategraph.readthedocs.io/en/latest/)
71
+ [![Python](https://img.shields.io/badge/python-3.12%2B-blue)](https://www.python.org/)
72
+ [![License: MIT](https://img.shields.io/badge/license-MIT-green)](LICENSE)
73
+
74
+ **ClimateGraph** reads, transforms and visualizes climate and environmental data
75
+ from sources that have nothing in common — a gridded model output, a network of
76
+ monitoring stations, a folder of CSVs — and lets you compare them without
77
+ writing code for each one.
78
+
79
+ A single control file says what data exists, how to filter it, and what to draw.
80
+
81
+ ![Hourly PM2.5 from a station network and a model](https://raw.githubusercontent.com/AntonioTorga/ClimateGraph/main/docs/source/_static/examples/timeseries.png)
82
+
83
+ ```yaml
84
+ analysis:
85
+ output_path: "./results"
86
+
87
+ data:
88
+ STATIONS:
89
+ path: "./data/stations.nc"
90
+ topology: PointSurface
91
+ reader: defaultpointsurface
92
+ vars: {PM25: {name: pm25, unit: "ug/m**3"}}
93
+ MODEL:
94
+ path: "./data/model.nc"
95
+ topology: RegularGrid
96
+ reader: defaultgrid
97
+ vars: {PM25: {name: pm25, unit: "ug/m**3"}}
98
+
99
+ plots:
100
+ comparison:
101
+ type: timeseries
102
+ data: [STATIONS, MODEL]
103
+ time: "1/6/2021 - 10/6/2021"
104
+ vars: {PM25: "ug/m**3"}
105
+ ```
106
+
107
+ ```console
108
+ $ ClimateGraph run config.yaml
109
+ ```
110
+
111
+ That simple config file creates the picture above comparing PM2.5 between monitoring stations and a model.
112
+
113
+ ## Why
114
+
115
+ - **Topology agnostic** — grids and station networks are compared directly;
116
+ resampling between them is a configuration option, not your problem.
117
+ - **Config-driven** — the analysis lives in YAML or JSON, not in a script.
118
+ - **Lazy** — nothing is read until it is actually needed.
119
+ - **Extensible** — a new reader, plot type or domain is one subclass. It
120
+ registers itself and the configuration schema picks it up automatically.
121
+
122
+ ## Install
123
+
124
+ Requires Python 3.12+. Some dependencies build against system libraries:
125
+
126
+ ```console
127
+ $ sudo apt-get install -y libgeos-dev libproj-dev libhdf5-dev libnetcdf-dev
128
+ $ git clone https://github.com/AntonioTorga/ClimateGraph.git
129
+ $ cd ClimateGraph
130
+ $ pip install -e .
131
+ ```
132
+
133
+ The sample NetCDFs under `test_data/data/` are Git LFS and excluded from clones
134
+ by default, so this is quick and the fast test suite runs without them.
135
+
136
+ ## Documentation
137
+
138
+ **[climategraph.readthedocs.io](https://climategraph.readthedocs.io)**
139
+
140
+ | | |
141
+ |---|---|
142
+ | [Quickstart](https://climategraph.readthedocs.io/en/latest/getting-started/quickstart.html) | From a blank file to a figure |
143
+ | [Examples](https://climategraph.readthedocs.io/en/latest/examples.html) | One per plot type, each with the config that produced it |
144
+ | [Control file reference](https://climategraph.readthedocs.io/en/latest/reference/control-file.html) | Every field of every block |
145
+ | [Architecture](https://climategraph.readthedocs.io/en/latest/about/overview.html) | How it works, module by module, and how to extend it |
146
+ | [API reference](https://climategraph.readthedocs.io/en/latest/api/index.html) | Generated from the source |
147
+
148
+ Try the examples straight from a clone — the data is in the repository:
149
+
150
+ ```console
151
+ $ python docs/examples/make_data.py
152
+ $ ClimateGraph run docs/examples/configs/timeseries.yaml
153
+ ```
154
+
155
+ ## Development
156
+
157
+ ```console
158
+ $ pip install -e ".[dev,test,docs]"
159
+ $ pre-commit install # once per clone
160
+ $ pytest -m "not slow"
161
+ $ make -C docs html
162
+ ```
163
+
164
+ Every push and every pull request against `main` or `develop` runs lint, the
165
+ fast test suite on Python 3.12 and 3.13, a coverage gate, and a strict
166
+ documentation build. Slow tests touch the LFS sample data and skip automatically
167
+ when it is absent.
168
+
169
+ ## Funding
170
+
171
+ This project is funded by ANID (Agencia Nacional de Investigación y Desarrollo)
172
+ Chile, through the FONDECYT Regular project N° 1231717, directed by Nicolas
173
+ Huneeus.
174
+
175
+ ## License
176
+
177
+ MIT — see [LICENSE](LICENSE).
@@ -0,0 +1,44 @@
1
+ ClimateGraph/__init__.py,sha256=UlLtQwiKVRDrEEvdt1S7hIpDWrPxar3Ulgjpt4uY36Y,259
2
+ ClimateGraph/appkernel.py,sha256=izwjJk44POfTw6Rt9Mk41HzX8Z3hIwfzAz0ymsI45So,5378
3
+ ClimateGraph/cli.py,sha256=y51TD9b4SRiOLWd0BFs1efS2sTBuTsElUR1M6iRN4QQ,1928
4
+ ClimateGraph/data/__init__.py,sha256=IsMCXa9m8VwdaBbywtHv3Z_Fyq2_QJ5fIR8HPv8sBQU,273
5
+ ClimateGraph/data/data.py,sha256=gJWya74UzmzRv7mdEkRLtBKOBHPdxbkEGNaYHPoJkOk,18132
6
+ ClimateGraph/data/point_surface.py,sha256=iQXFrGrsfWEtqyYQXR-3D_J0AnYeTpjDmbF5pIefe6I,3095
7
+ ClimateGraph/data/regular_grid.py,sha256=TQ7L80vHE5mPLWVRYPn9Gcc3YPyKXgaH3OYuRyGwkg8,783
8
+ ClimateGraph/data/satellite_swath.py,sha256=80n-pZsxS5217UdUvUrxbvGxHO217YfLdumFQKXFq5U,583
9
+ ClimateGraph/domain/__init__.py,sha256=eMNvkrwpANJPrXu-ssyY3MRSyACmLlnoV9FiJj5u4NY,247
10
+ ClimateGraph/domain/domain.py,sha256=RSXq6REqxEpRrfCnYbj_SOskrj0MYJIF7vRrEFpMwmU,6279
11
+ ClimateGraph/domain/domains.py,sha256=BNa8O-7cciKdd02q-PqsMKl-Tj_ktXVc4hnafjQ7j7I,9428
12
+ ClimateGraph/plot/__init__.py,sha256=R7kXia-IKilZe6wkx4MdXZNorzZrktK_sm-6MzuJDms,235
13
+ ClimateGraph/plot/plot.py,sha256=0WgPaTAP0K3k7BVRrqZ4m2VAkOO7nZt8XOoqCMIvpA0,13772
14
+ ClimateGraph/plot/plots.py,sha256=tw9lhBxsusIOAXBi5-4FDf6S2_lz2TZxEP9hxsrnpN8,43457
15
+ ClimateGraph/plot/primitive.py,sha256=fk1r_JpfjTj4bQ8in9Z9muWsSYASj3kOZcJcYusReiM,3328
16
+ ClimateGraph/plot/primitives.py,sha256=8dcAS_vMUVwz_Qv8RlsYCNhEemJ1hPaIrAV2vf-GY1Y,5158
17
+ ClimateGraph/reader/__init__.py,sha256=lWeUhbU_LilagEF11UqaKL9ydFoJZsXqJXJvPd1_Q7o,268
18
+ ClimateGraph/reader/reader/__init__.py,sha256=yI_SZTp9zzzF5r171iy6uWcTDbC1mPPQMIuonTbqoD4,283
19
+ ClimateGraph/reader/reader/reader.py,sha256=uNhG_dEjmt59k4dQ5TkiV-Nwbvkt9X8NfVYyRkIRXz4,13591
20
+ ClimateGraph/reader/reader/point_surface/__init__.py,sha256=Fk4ctPwe_loxMyLahMu5ZfESUc17mmfJjJx9VyK2fc4,191
21
+ ClimateGraph/reader/reader/point_surface/csv_base.py,sha256=m7Jc2FCEiUagUr4pPeu8JlBlzJsT_qrqakbJBotGa3M,5806
22
+ ClimateGraph/reader/reader/point_surface/default.py,sha256=kKc13WImwzB5nKDCnWE1tzxnAs4iEIeY9bdxz72hVXI,1407
23
+ ClimateGraph/reader/reader/point_surface/dmc.py,sha256=PF0sxeEKskPn4piYYiM8uZhqJXc20m8D2FapWk3Ksgs,341
24
+ ClimateGraph/reader/reader/point_surface/sinca.py,sha256=gzi3hyB_f_1hD8IpBKf_qoLvoE7cUXty3K3yNEqOM3g,357
25
+ ClimateGraph/reader/reader/point_surface/single_file.py,sha256=dE1QkFKAoCDmYfmELOiDUf2TahjIMb-eMTxIWXB6p30,2436
26
+ ClimateGraph/reader/reader/point_surface/station_per_file.py,sha256=MtTlZ7ofDHM0RNI3auzaWsgeJqRqZ8ATWV3ntq_e3sU,2137
27
+ ClimateGraph/reader/reader/point_surface/variable_per_file.py,sha256=5gV7Dm9-hSJp3_SV1KNPwis1IEJ6GnDBGxQoo4-NJfM,3790
28
+ ClimateGraph/reader/reader/regular_grid/__init__.py,sha256=5-Ndsw2QHTPvTbn2eDTTESVqEK0fFQ9mOnh0bEsGwVY,169
29
+ ClimateGraph/reader/reader/regular_grid/chimere.py,sha256=QzP3Ccztr0lw2L6cqzDpuWAzoHi3AY78UvwQ437TVm0,547
30
+ ClimateGraph/reader/reader/regular_grid/default.py,sha256=L7QmoTD7lknjShAogTtuoZi4ccTJk60mW6g8AsrS8AY,2109
31
+ ClimateGraph/reader/reader/regular_grid/wrf.py,sha256=9HDWS8Of76Wt3FmJ9tJ67bm7I0XIBFa5oVM0BwyADUU,2069
32
+ ClimateGraph/utils/__init__.py,sha256=AB8zKTXq0qfM0k5Yt4TUpnrVutIrNL7t4IonZjCJyC0,78
33
+ ClimateGraph/utils/control_model.py,sha256=2IsHU8Nlr1LU3zcTqvXmgifL1KSoz0WFn9B24eDayYk,11403
34
+ ClimateGraph/utils/dataset_utils.py,sha256=9bWdemHMoYEmp6N0tS1YinjsA72GX7AdK7SpS1iq9LU,9886
35
+ ClimateGraph/utils/general_utils.py,sha256=CIv2NcKB_0NOyti3kjq-9Egu42fHUn8p_IH7SxPeyr8,7811
36
+ ClimateGraph/utils/parser.py,sha256=o5hf92XIYB7is0RehQ43wf-xMeKA9owK-AVhkZ4IwUU,10525
37
+ ClimateGraph/utils/registry.py,sha256=ISMPLr7K7CwH9HDnWDkWXv-U9zeIXEBdSaxF78dONAo,3035
38
+ ClimateGraph/utils/resample_engine.py,sha256=PaPjC8EZ61BvgjqJMD4lETAPM-U6DX5btU58GN4jRt0,5129
39
+ climategraph-0.4.0.dist-info/licenses/LICENSE,sha256=gG29UruQPO9wQm3Q6SZq83YC6epHzwdNhSRfdUv8eD4,1091
40
+ climategraph-0.4.0.dist-info/METADATA,sha256=uv4m16GKHwDXLZhV5hznHwxGwlNxYdG54adipi6IMWA,6509
41
+ climategraph-0.4.0.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
42
+ climategraph-0.4.0.dist-info/entry_points.txt,sha256=AwEWGaxK-Eb_37LFjGmrmDnMIWXr7e7Nmgp79LrVeMc,54
43
+ climategraph-0.4.0.dist-info/top_level.txt,sha256=wfJevfLxGeFuV1IwtKWwPZU_odgKjUHhAGCwPyyfJSs,13
44
+ climategraph-0.4.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (84.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ClimateGraph = ClimateGraph.cli:app
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Antonio Torga and Nicolás Huneeus
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ ClimateGraph