edmt 1.0.6.dev1__tar.gz → 1.0.7.dev1__tar.gz

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 (39) hide show
  1. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/PKG-INFO +42 -27
  2. edmt-1.0.7.dev1/README.md +70 -0
  3. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/base/base.py +13 -8
  4. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/contrib/utils.py +11 -6
  5. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/conversion/__init__.py +7 -4
  6. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/conversion/conversion.py +5 -7
  7. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/models/drones.py +18 -343
  8. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/workflow/__init__.py +4 -5
  9. edmt-1.0.7.dev1/edmt/workflow/builder.py +644 -0
  10. edmt-1.0.7.dev1/edmt/workflow/connector.py +611 -0
  11. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/workflow/workflow.py +25 -47
  12. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt.egg-info/PKG-INFO +42 -27
  13. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt.egg-info/requires.txt +0 -1
  14. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/pyproject.toml +3 -4
  15. edmt-1.0.7.dev1/tests/test_conversion.py +161 -0
  16. edmt-1.0.7.dev1/tests/test_models.py +240 -0
  17. edmt-1.0.6.dev1/README.md +0 -54
  18. edmt-1.0.6.dev1/edmt/workflow/builder.py +0 -895
  19. edmt-1.0.6.dev1/edmt/workflow/connector.py +0 -535
  20. edmt-1.0.6.dev1/tests/test_conversion.py +0 -68
  21. edmt-1.0.6.dev1/tests/test_models.py +0 -0
  22. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/LICENSE +0 -0
  23. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/__init__.py +0 -0
  24. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/_edmt.py +0 -0
  25. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/analysis/__init__.py +0 -0
  26. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/base/__init__.py +0 -0
  27. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/contrib/__init__.py +0 -0
  28. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/mapping/__init__.py +0 -0
  29. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/models/__init__.py +0 -0
  30. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt/plotting/__init__.py +0 -0
  31. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt.egg-info/SOURCES.txt +0 -0
  32. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt.egg-info/dependency_links.txt +0 -0
  33. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt.egg-info/entry_points.txt +0 -0
  34. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/edmt.egg-info/top_level.txt +0 -0
  35. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/setup.cfg +0 -0
  36. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/tests/test_analysis.py +0 -0
  37. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/tests/test_base.py +0 -0
  38. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/tests/test_mapping.py +0 -0
  39. {edmt-1.0.6.dev1 → edmt-1.0.7.dev1}/tests/test_plotting.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: edmt
3
- Version: 1.0.6.dev1
3
+ Version: 1.0.7.dev1
4
4
  Summary: Environmental Data Management Toolbox
5
5
  Author-email: "Odero, Kuloba & musasia" <francisodero10@gmail.com>
6
6
  License: MIT License
@@ -26,8 +26,8 @@ License: MIT License
26
26
  SOFTWARE.
27
27
 
28
28
  Project-URL: Homepage, https://github.com/envdmt/EDMT/
29
+ Project-URL: Documentation, https://envdmt.github.io/EDMT/
29
30
  Keywords: geospatial,gis,earth-engine,remote-sensing,conservation,spatial-analysis,geopandas
30
- Classifier: Development Status :: 4 - Beta
31
31
  Classifier: Intended Audience :: Developers
32
32
  Classifier: Intended Audience :: Science/Research
33
33
  Classifier: Intended Audience :: Education
@@ -53,7 +53,6 @@ Requires-Dist: fiona<1.10.1,>=1.9.6
53
53
  Requires-Dist: tqdm>=4
54
54
  Requires-Dist: requests<3,>=2.28
55
55
  Requires-Dist: matplotlib>=3.9
56
- Requires-Dist: mapclassify>=2.7
57
56
  Dynamic: license-file
58
57
 
59
58
  <h1 align="center">EDMT — Environmental Data Management Toolbox</h1>
@@ -63,18 +62,16 @@ Dynamic: license-file
63
62
  <a href="https://pypi.org/project/edmt/">
64
63
  <img src="https://img.shields.io/pypi/v/edmt.svg" alt="PyPI version" />
65
64
  </a>
66
-
67
- <!-- Codecov -->
68
- <!-- <a href="https://codecov.io/gh/envdmt/EDMT">
69
- <img src="https://codecov.io/gh/envdmt/EDMT/branch/main/graph/badge.svg" alt="codecov" />
70
- </a> -->
71
-
72
-
73
65
  <!-- Docs -->
74
66
  <a href="https://envdmt.github.io/EDMT/">
75
67
  <img src="https://img.shields.io/badge/docs-passing-brightgreen.svg" alt="docs" />
76
68
  </a>
77
69
 
70
+ <!-- Tests -->
71
+ <a href="https://github.com/envdmt/EDMT/actions?query=workflow%3ATests">
72
+ <img src="https://github.com/envdmt/EDMT/workflows/Tests/badge.svg" alt="tests" />
73
+ </a>
74
+
78
75
  <!-- Jupyter -->
79
76
  <img src="https://img.shields.io/badge/Jupyter-Lab-orange.svg" alt="Jupyter Lab" />
80
77
 
@@ -83,30 +80,48 @@ Dynamic: license-file
83
80
  </p>
84
81
 
85
82
 
86
- ## Overview
83
+ ------------------------------------------------------------------------
87
84
 
88
- **EDMT (Environmental Data Management Toolbox)** is a lightweight Python library designed to make environmental data ingestion, cleaning, transformation, and basic analysis workflows easier and more reproducible. It provides a set of tools and helper functions tailored to the common needs of environmental scientists, data engineers, and analysts working with diverse observational and sensor-derived datasets.
85
+ # Overview
89
86
 
90
- It provides modular tools for:
87
+ EDMT (Environmental Data Management Toolbox) is a lightweight Python library for working with environmental and geospatial datasets. It provides practical utilities for data ingestion, cleaning, transformation, and exploratory analysis, helping researchers and analysts build reproducible data workflows.
91
88
 
92
- - Data ingestion (CSV, sensors, exports, logs)
93
- - Cleaning & quality control
94
- - Time-series handling
95
- - Spatial & temporal transformations
96
- - Basic analytics & summaries
97
- - Reusable, reproducible workflows
89
+ EDMT integrates well with the Python scientific stack and is particularly useful when working with time-series environmental data, spatial datasets, and monitoring data pipelines.
98
90
 
99
- Why EDMT?
91
+ It is designed for:
100
92
 
101
- Environmental data workflows often require stitching together formats, checks, and cleaning steps that are repetitive and error-prone. EDMT centralizes these common operations into reusable Python functions and classes, helping you:
93
+ - Environmental scientists
94
+ - Conservation and wildlife monitoring teams
95
+ - GIS and geospatial developers
96
+ - Data analysts working with environmental datasets
102
97
 
103
- - Save development time and reduce duplication
104
- - Standardize procedures across different projects
105
- - Improve reproducibility and traceability of results
98
+ ------------------------------------------------------------------------
106
99
 
107
- ---
100
+ # Installation
108
101
 
109
- ## Installation
102
+ Install directly from PyPI:
110
103
 
111
- ```bash
104
+ ``` bash
112
105
  pip install edmt
106
+ ```
107
+
108
+ ------------------------------------------------------------------------
109
+
110
+ # Typical Use Cases
111
+
112
+ EDMT can support workflows such as:
113
+
114
+ - Environmental monitoring pipelines
115
+ - Remote sensing preprocessing
116
+ - Field data quality control
117
+ - Environmental research and reporting
118
+
119
+ ------------------------------------------------------------------------
120
+
121
+ # Documentation
122
+
123
+ Full documentation is available here:
124
+
125
+ https://envdmt.github.io/EDMT/
126
+
127
+ ------------------------------------------------------------------------
@@ -0,0 +1,70 @@
1
+ <h1 align="center">EDMT — Environmental Data Management Toolbox</h1>
2
+
3
+ <p align="center">
4
+ <!-- PyPI -->
5
+ <a href="https://pypi.org/project/edmt/">
6
+ <img src="https://img.shields.io/pypi/v/edmt.svg" alt="PyPI version" />
7
+ </a>
8
+ <!-- Docs -->
9
+ <a href="https://envdmt.github.io/EDMT/">
10
+ <img src="https://img.shields.io/badge/docs-passing-brightgreen.svg" alt="docs" />
11
+ </a>
12
+
13
+ <!-- Tests -->
14
+ <a href="https://github.com/envdmt/EDMT/actions?query=workflow%3ATests">
15
+ <img src="https://github.com/envdmt/EDMT/workflows/Tests/badge.svg" alt="tests" />
16
+ </a>
17
+
18
+ <!-- Jupyter -->
19
+ <img src="https://img.shields.io/badge/Jupyter-Lab-orange.svg" alt="Jupyter Lab" />
20
+
21
+ <!-- License -->
22
+ <img src="https://img.shields.io/badge/license-MIT-blue.svg" alt="license" />
23
+ </p>
24
+
25
+
26
+ ------------------------------------------------------------------------
27
+
28
+ # Overview
29
+
30
+ EDMT (Environmental Data Management Toolbox) is a lightweight Python library for working with environmental and geospatial datasets. It provides practical utilities for data ingestion, cleaning, transformation, and exploratory analysis, helping researchers and analysts build reproducible data workflows.
31
+
32
+ EDMT integrates well with the Python scientific stack and is particularly useful when working with time-series environmental data, spatial datasets, and monitoring data pipelines.
33
+
34
+ It is designed for:
35
+
36
+ - Environmental scientists
37
+ - Conservation and wildlife monitoring teams
38
+ - GIS and geospatial developers
39
+ - Data analysts working with environmental datasets
40
+
41
+ ------------------------------------------------------------------------
42
+
43
+ # Installation
44
+
45
+ Install directly from PyPI:
46
+
47
+ ``` bash
48
+ pip install edmt
49
+ ```
50
+
51
+ ------------------------------------------------------------------------
52
+
53
+ # Typical Use Cases
54
+
55
+ EDMT can support workflows such as:
56
+
57
+ - Environmental monitoring pipelines
58
+ - Remote sensing preprocessing
59
+ - Field data quality control
60
+ - Environmental research and reporting
61
+
62
+ ------------------------------------------------------------------------
63
+
64
+ # Documentation
65
+
66
+ Full documentation is available here:
67
+
68
+ https://envdmt.github.io/EDMT/
69
+
70
+ ------------------------------------------------------------------------
@@ -1,22 +1,27 @@
1
1
  import logging
2
- logger = logging.getLogger(__name__)
3
2
  import base64
4
3
  import http.client
4
+ from typing import Optional, Union
5
5
  import requests
6
6
  import pandas as pd
7
7
  from io import StringIO
8
8
  import time
9
9
 
10
+ logger = logging.getLogger(__name__)
10
11
  logging.basicConfig(level=logging.WARNING)
11
12
 
12
13
  class AirdataBaseClass:
13
- def __init__(self, api_key):
14
+ def __init__(self, api_key: str, skip_auth: bool = False):
14
15
  self.api_key = api_key
15
16
  self.base_url = "api.airdata.com"
16
17
  self.authenticated = False
17
18
  self.auth_header = self._get_auth_header()
18
19
 
19
- self.authenticate(validate=True)
20
+ if not skip_auth:
21
+ self.authenticate(validate=True)
22
+ else:
23
+ self.authenticated = True
24
+ self.auth_header = {"Authorization": "Bearer fake_token"}
20
25
 
21
26
  def _get_auth_header(self):
22
27
  key_with_colon = self.api_key + ":"
@@ -62,11 +67,11 @@ class AirdataBaseClass:
62
67
 
63
68
 
64
69
  def ExtractCSV(
65
- row,
66
- col : str,
67
- max_retries : int = 3,
68
- timeout : int = 15
69
- ) -> pd.DataFrame:
70
+ row: Union[dict, pd.Series],
71
+ col: str,
72
+ max_retries: int = 3,
73
+ timeout: int = 15
74
+ ) -> Optional[pd.DataFrame]:
70
75
  """
71
76
  Fetches a CSV file from a URL specified in a given column of a metadata record.
72
77
 
@@ -12,7 +12,6 @@ def clean_vars(addl_kwargs={}, **kwargs):
12
12
 
13
13
 
14
14
  def normalize_column(df, col):
15
- # print(col)
16
15
  for k, v in pd.json_normalize(df.pop(col), sep="__").add_prefix(f"{col}__").items():
17
16
  df[k] = v.values
18
17
 
@@ -30,10 +29,17 @@ def clean_time_cols(df,columns = []):
30
29
 
31
30
  def format_iso_time(date_string: str) -> str:
32
31
  try:
33
- return pd.to_datetime(date_string).isoformat()
34
- except ValueError:
35
- raise ValueError(f"Failed to parse timestamp'{date_string}'")
36
-
32
+ dt = pd.to_datetime(date_string)
33
+ if isinstance(dt, (pd.DatetimeIndex, pd.Series)):
34
+ if len(dt) == 0:
35
+ raise ValueError("Empty datetime collection")
36
+ dt = dt[0]
37
+ if pd.isna(dt):
38
+ raise ValueError("Invalid timestamp (NaT)")
39
+ return dt.isoformat()
40
+ except (ValueError, TypeError, AttributeError):
41
+ raise ValueError(f"Failed to parse timestamp '{date_string}'")
42
+
37
43
 
38
44
  def norm_exp(df: pd.DataFrame, cols : Union[str, list]) -> pd.DataFrame:
39
45
  """
@@ -97,7 +103,6 @@ def append_cols(df: pd.DataFrame, cols: Union[str, list]):
97
103
  return df[remaining_cols + cols]
98
104
 
99
105
 
100
-
101
106
  def dict_expand(data,cols):
102
107
  dfs_to_join = []
103
108
  df_processed = data.copy()
@@ -3,19 +3,22 @@ from .conversion import (
3
3
  generate_uuid,
4
4
  generate_cmap,
5
5
  get_utm_epsg,
6
- convert_distance,
7
6
  convert_time,
8
7
  convert_speed,
9
- convert_temperature
8
+ convert_distance,
9
+ convert_temperature,
10
+ format_temperature
10
11
  )
11
12
 
13
+
12
14
  __all__ = [
13
15
  'sdf_to_gdf',
14
16
  'generate_uuid',
15
17
  'generate_cmap',
16
18
  'get_utm_epsg',
17
- 'convert_distance',
18
19
  'convert_time',
19
20
  'convert_speed',
20
- 'convert_temperature'
21
+ 'convert_distance',
22
+ 'convert_temperature',
23
+ 'format_temperature'
21
24
  ]
@@ -158,6 +158,7 @@ def sdf_to_gdf(sdf, crs=None):
158
158
 
159
159
  return gdf
160
160
 
161
+
161
162
  def _is_valid_uuid(val) -> bool:
162
163
  if pd.isna(val):
163
164
  return False
@@ -551,14 +552,13 @@ def convert_temperature(value: float, unit_from: str, unit_to: str) -> float:
551
552
  return round(out, 3)
552
553
 
553
554
 
554
- def format_temperature(value: float, unit: str, decimals: int = 1, symbol: bool = True) -> str:
555
+ def format_temperature(value: float, unit: str, symbol: bool = True) -> str:
555
556
  """
556
557
  Formats a temperature value with unit, e.g. '23.5 °C' or '296.6 K'.
557
558
 
558
559
  Args:
559
560
  value (float): Temperature value.
560
561
  unit (str): Unit to display (C, F, K).
561
- decimals (int): Decimal places.
562
562
  symbol (bool): If True, uses °C/°F, and K without degree symbol.
563
563
 
564
564
  Returns:
@@ -568,14 +568,12 @@ def format_temperature(value: float, unit: str, decimals: int = 1, symbol: bool
568
568
  if u not in temp_units:
569
569
  raise ValueError(f"Unsupported temperature unit: {unit!r}. Valid: {', '.join(temp_units)}")
570
570
 
571
- val_str = f"{float(value):.{int(decimals)}f}"
572
-
573
571
  if not symbol:
574
- return f"{val_str} {u}"
572
+ return f"{value} {u}"
575
573
 
576
574
  if u in ("C", "F"):
577
- return f"{val_str} °{u}"
578
- return f"{val_str} K"
575
+ return f"{value} °{u}"
576
+ return f"{value} K"
579
577
 
580
578
 
581
579