pyadps 0.2.1b0__py3-none-any.whl → 0.3.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 (39) hide show
  1. pyadps/Home_Page.py +11 -5
  2. pyadps/pages/01_Read_File.py +623 -215
  3. pyadps/pages/02_View_Raw_Data.py +97 -41
  4. pyadps/pages/03_Download_Raw_File.py +200 -67
  5. pyadps/pages/04_Sensor_Health.py +905 -0
  6. pyadps/pages/05_QC_Test.py +493 -0
  7. pyadps/pages/06_Profile_Test.py +971 -0
  8. pyadps/pages/07_Velocity_Test.py +600 -0
  9. pyadps/pages/08_Write_File.py +623 -0
  10. pyadps/pages/09_Add-Ons.py +168 -0
  11. pyadps/utils/__init__.py +5 -3
  12. pyadps/utils/autoprocess.py +371 -80
  13. pyadps/utils/logging_utils.py +269 -0
  14. pyadps/utils/metadata/config.ini +22 -4
  15. pyadps/utils/metadata/demo.000 +0 -0
  16. pyadps/utils/metadata/flmeta.json +420 -420
  17. pyadps/utils/metadata/vlmeta.json +611 -565
  18. pyadps/utils/multifile.py +292 -0
  19. pyadps/utils/plotgen.py +505 -3
  20. pyadps/utils/profile_test.py +720 -125
  21. pyadps/utils/pyreadrdi.py +164 -92
  22. pyadps/utils/readrdi.py +436 -186
  23. pyadps/utils/script.py +197 -147
  24. pyadps/utils/sensor_health.py +120 -0
  25. pyadps/utils/signal_quality.py +472 -68
  26. pyadps/utils/velocity_test.py +79 -31
  27. pyadps/utils/writenc.py +222 -39
  28. {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/METADATA +13 -14
  29. pyadps-0.3.0.dist-info/RECORD +35 -0
  30. {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/WHEEL +1 -1
  31. {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/entry_points.txt +1 -0
  32. pyadps/pages/04_QC_Test.py +0 -334
  33. pyadps/pages/05_Profile_Test.py +0 -575
  34. pyadps/pages/06_Velocity_Test.py +0 -341
  35. pyadps/pages/07_Write_File.py +0 -452
  36. pyadps/utils/cutbin.py +0 -413
  37. pyadps/utils/regrid.py +0 -279
  38. pyadps-0.2.1b0.dist-info/RECORD +0 -31
  39. {pyadps-0.2.1b0.dist-info → pyadps-0.3.0.dist-info}/LICENSE +0 -0
@@ -0,0 +1,269 @@
1
+ """
2
+ Reusable Logging Utilities
3
+ A clean, configurable logging module that can be used across multiple projects.
4
+ """
5
+
6
+ import logging
7
+ import sys
8
+ from enum import Enum
9
+ from typing import Optional, Union
10
+ from pathlib import Path
11
+
12
+
13
+ class LogLevel(Enum):
14
+ """Log level enumeration"""
15
+
16
+ DEBUG = logging.DEBUG
17
+ INFO = logging.INFO
18
+ WARNING = logging.WARNING
19
+ ERROR = logging.ERROR
20
+ CRITICAL = logging.CRITICAL
21
+
22
+
23
+ class CustomFormatter(logging.Formatter):
24
+ """Custom colored formatter for console logging"""
25
+
26
+ COLORS = {
27
+ logging.DEBUG: "\x1b[36m", # Cyan
28
+ logging.INFO: "\x1b[32m", # Green
29
+ logging.WARNING: "\x1b[33m", # Yellow
30
+ logging.ERROR: "\x1b[31m", # Red
31
+ logging.CRITICAL: "\x1b[31;1m", # Bold Red
32
+ }
33
+ RESET = "\x1b[0m"
34
+
35
+ def __init__(self, include_timestamp: bool = True, include_module: bool = False):
36
+ """
37
+ Initialize formatter with optional components
38
+
39
+ Args:
40
+ include_timestamp: Whether to include timestamp in log format
41
+ include_module: Whether to include module name in log format
42
+ """
43
+ self.include_timestamp = include_timestamp
44
+ self.include_module = include_module
45
+ super().__init__()
46
+
47
+ def format(self, record):
48
+ """Format log record with colors and optional components"""
49
+ # Build format string based on options
50
+ format_parts = []
51
+
52
+ if self.include_timestamp:
53
+ format_parts.append("%(asctime)s")
54
+
55
+ format_parts.append("%(levelname)s")
56
+
57
+ if self.include_module:
58
+ format_parts.append("%(name)s")
59
+
60
+ format_parts.append("%(message)s")
61
+
62
+ log_format = " - ".join(format_parts)
63
+
64
+ # Apply color
65
+ color = self.COLORS.get(record.levelno, "")
66
+ colored_format = color + log_format + self.RESET
67
+
68
+ formatter = logging.Formatter(
69
+ colored_format,
70
+ datefmt="%Y-%m-%d %H:%M:%S" if self.include_timestamp else None,
71
+ )
72
+ return formatter.format(record)
73
+
74
+
75
+ class LoggerConfig:
76
+ """Configuration class for logger setup"""
77
+
78
+ def __init__(
79
+ self,
80
+ level: LogLevel = LogLevel.INFO,
81
+ include_timestamp: bool = True,
82
+ include_module: bool = False,
83
+ log_to_file: bool = False,
84
+ log_file_path: Optional[Union[str, Path]] = None,
85
+ file_log_level: Optional[LogLevel] = None,
86
+ max_file_size: int = 10 * 1024 * 1024, # 10MB
87
+ backup_count: int = 5,
88
+ ):
89
+ """
90
+ Initialize logger configuration
91
+
92
+ Args:
93
+ level: Console logging level
94
+ include_timestamp: Include timestamp in console output
95
+ include_module: Include module name in output
96
+ log_to_file: Whether to also log to file
97
+ log_file_path: Path for log file (if log_to_file is True)
98
+ file_log_level: File logging level (defaults to console level)
99
+ max_file_size: Maximum size of log file before rotation
100
+ backup_count: Number of backup files to keep
101
+ """
102
+ self.level = level
103
+ self.include_timestamp = include_timestamp
104
+ self.include_module = include_module
105
+ self.log_to_file = log_to_file
106
+ self.log_file_path = Path(log_file_path) if log_file_path else None
107
+ self.file_log_level = file_log_level or level
108
+ self.max_file_size = max_file_size
109
+ self.backup_count = backup_count
110
+
111
+
112
+ class LoggerManager:
113
+ """Manages logger configuration and setup"""
114
+
115
+ _loggers = {} # Cache for created loggers
116
+
117
+ @classmethod
118
+ def setup_logger(
119
+ self, name: str = "app", config: Optional[LoggerConfig] = None
120
+ ) -> logging.Logger:
121
+ """
122
+ Set up and configure logger with given configuration
123
+
124
+ Args:
125
+ name: Logger name
126
+ config: Logger configuration (uses defaults if None)
127
+
128
+ Returns:
129
+ Configured logger instance
130
+ """
131
+ # Use default config if none provided
132
+ if config is None:
133
+ config = LoggerConfig()
134
+
135
+ # Return cached logger if it exists
136
+ cache_key = f"{name}_{id(config)}"
137
+ if cache_key in self._loggers:
138
+ return self._loggers[cache_key]
139
+
140
+ logger = logging.getLogger(name)
141
+ logger.setLevel(config.level.value)
142
+
143
+ # Remove existing handlers to avoid duplicates
144
+ logger.handlers.clear()
145
+
146
+ # Create console handler
147
+ console_handler = logging.StreamHandler(sys.stdout)
148
+ console_handler.setLevel(config.level.value)
149
+ console_formatter = CustomFormatter(
150
+ include_timestamp=config.include_timestamp,
151
+ include_module=config.include_module,
152
+ )
153
+ console_handler.setFormatter(console_formatter)
154
+ logger.addHandler(console_handler)
155
+
156
+ # Add file handler if requested
157
+ if config.log_to_file and config.log_file_path:
158
+ self._add_file_handler(logger, config)
159
+
160
+ # Prevent propagation to root logger
161
+ logger.propagate = False
162
+
163
+ # Cache the logger
164
+ self._loggers[cache_key] = logger
165
+
166
+ return logger
167
+
168
+ @classmethod
169
+ def _add_file_handler(self, logger: logging.Logger, config: LoggerConfig):
170
+ """Add rotating file handler to logger"""
171
+ from logging.handlers import RotatingFileHandler
172
+
173
+ # Ensure log directory exists
174
+ config.log_file_path.parent.mkdir(parents=True, exist_ok=True)
175
+
176
+ file_handler = RotatingFileHandler(
177
+ config.log_file_path,
178
+ maxBytes=config.max_file_size,
179
+ backupCount=config.backup_count,
180
+ )
181
+ file_handler.setLevel(config.file_log_level.value)
182
+
183
+ # File logs typically include more detail
184
+ file_formatter = logging.Formatter(
185
+ "%(asctime)s - %(name)s - %(levelname)s - %(funcName)s:%(lineno)d - %(message)s",
186
+ datefmt="%Y-%m-%d %H:%M:%S",
187
+ )
188
+ file_handler.setFormatter(file_formatter)
189
+ logger.addHandler(file_handler)
190
+
191
+ @classmethod
192
+ def get_logger(self, name: str = "app") -> logging.Logger:
193
+ """Get existing logger or create with default config"""
194
+ return logging.getLogger(name) or self.setup_logger(name)
195
+
196
+ @classmethod
197
+ def clear_cache(self):
198
+ """Clear logger cache (useful for testing)"""
199
+ self._loggers.clear()
200
+
201
+
202
+ # Convenience functions for quick setup
203
+ def get_console_logger(
204
+ name: str = "app", level: LogLevel = LogLevel.INFO, include_timestamp: bool = True
205
+ ) -> logging.Logger:
206
+ """Quick setup for console-only logger"""
207
+ config = LoggerConfig(
208
+ level=level, include_timestamp=include_timestamp, include_module=False
209
+ )
210
+ return LoggerManager.setup_logger(name, config)
211
+
212
+
213
+ def get_file_logger(
214
+ name: str = "app",
215
+ log_file: Union[str, Path] = "app.log",
216
+ level: LogLevel = LogLevel.INFO,
217
+ file_level: Optional[LogLevel] = None,
218
+ ) -> logging.Logger:
219
+ """Quick setup for file + console logger"""
220
+ config = LoggerConfig(
221
+ level=level,
222
+ log_to_file=True,
223
+ log_file_path=log_file,
224
+ file_log_level=file_level or LogLevel.DEBUG,
225
+ )
226
+ return LoggerManager.setup_logger(name, config)
227
+
228
+
229
+ def get_detailed_logger(
230
+ name: str = "app",
231
+ log_file: Union[str, Path] = "app.log",
232
+ console_level: LogLevel = LogLevel.INFO,
233
+ file_level: LogLevel = LogLevel.DEBUG,
234
+ ) -> logging.Logger:
235
+ """Setup logger with detailed configuration"""
236
+ config = LoggerConfig(
237
+ level=console_level,
238
+ include_timestamp=True,
239
+ include_module=True,
240
+ log_to_file=True,
241
+ log_file_path=log_file,
242
+ file_log_level=file_level,
243
+ )
244
+ return LoggerManager.setup_logger(name, config)
245
+
246
+
247
+ # Example usage
248
+ if __name__ == "__main__":
249
+ # Test different logger configurations
250
+
251
+ # Simple console logger
252
+ simple_logger = get_console_logger("simple", LogLevel.DEBUG)
253
+ simple_logger.debug("Debug message")
254
+ simple_logger.info("Info message")
255
+ simple_logger.warning("Warning message")
256
+ simple_logger.error("Error message")
257
+
258
+ print("\n" + "=" * 50 + "\n")
259
+
260
+ # File + console logger
261
+ file_logger = get_file_logger("file_test", "test.log", LogLevel.INFO)
262
+ file_logger.info("This goes to both console and file")
263
+ file_logger.debug("This only goes to file")
264
+
265
+ print("\n" + "=" * 50 + "\n")
266
+
267
+ # Detailed logger
268
+ detailed_logger = get_detailed_logger("detailed", "detailed.log")
269
+ detailed_logger.info("Detailed logging with module names")
@@ -4,8 +4,9 @@ input_file_path = /home/user/data/
4
4
  input_file_name = adcp_raw.000
5
5
 
6
6
  # Output file settings. Do not enter file extension.
7
- output_file_path = /home/user/output/
7
+ output_file_path = /home/nio/Videos/output/
8
8
  output_file_name_raw = adcp_raw.nc
9
+ output_file_name_vlead = adcp_vlead.nc
9
10
  output_file_name_processed = adcp_proc.nc
10
11
 
11
12
  # Choose between 'netcdf' or 'csv' for the raw output format
@@ -16,11 +17,18 @@ output_format_processed = csv
16
17
 
17
18
  [DownloadOptions]
18
19
  # Options to download raw and/or processed output files
20
+ axis_option = ensemble
19
21
  download_raw = True
22
+ download_vlead = True
20
23
  download_processed = True
21
24
  apply_mask = True
22
25
  download_mask = True
23
26
 
27
+ [SensorTest]
28
+ sensor_test = True
29
+ transducer_depth = 200
30
+
31
+
24
32
  [QCTest]
25
33
  # Enable or Disable QC Test (True/False)
26
34
  qc_test = True
@@ -30,6 +38,8 @@ echo_intensity = 40
30
38
  false_target = 50
31
39
  three_beam = True
32
40
  percentage_good = 50
41
+ orientation = up
42
+
33
43
 
34
44
  [ProfileTest]
35
45
  # Enable or Disable Profile Test (True/False)
@@ -39,17 +49,22 @@ trim_ends_start_index = 2
39
49
  trim_ends_end_index = 17086
40
50
  cut_bins = True
41
51
  cut_bins_add_cells = 2
52
+ manual_cutbins = True
53
+ manual_cut_bins = [2,10,0,8000] [40,42,0,8000] [12,14,0,8000]
42
54
  regrid = True
43
- regrid_option = Bin
55
+ regrid_option = Cell
56
+ regrid_interpolation = nearest
57
+ transducer_depth = 200
58
+ water_column_depth = 200
44
59
 
45
60
  [VelocityTest]
46
61
  # Enable or Disable Velocity Test (True/False)
47
62
  velocity_test = True
48
63
  magnetic_declination = True
49
64
  latitude = 0.0
50
- longitude = 0.1
65
+ longitude = 83.0
51
66
  depth = 0
52
- year = 2024
67
+ year = 2025
53
68
  cutoff = True
54
69
  max_zonal_velocity = 250
55
70
  max_meridional_velocity = 250
@@ -79,3 +94,6 @@ file_created_by = xxxx
79
94
  contact = abcd
80
95
  comments = No comments
81
96
 
97
+
98
+
99
+
Binary file