pyASDReader 1.2.1__tar.gz → 1.2.2__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 (40) hide show
  1. pyasdreader-1.2.2/.codecov.yml +68 -0
  2. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/CHANGELOG.md +54 -0
  3. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/PKG-INFO +8 -66
  4. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/README.md +7 -65
  5. pyasdreader-1.2.2/coverage.json +1 -0
  6. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/pyASDReader.egg-info/SOURCES.txt +3 -1
  7. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/asd_file_reader.py +6 -1
  8. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/file_attributes.py +5 -5
  9. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/test_asd_file_reader.py +174 -27
  10. pyasdreader-1.2.2/tests/test_file_attributes.py +137 -0
  11. pyasdreader-1.2.1/CITATION.cff +0 -22
  12. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/.pre-commit-config.yaml +0 -0
  13. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/LICENSE +0 -0
  14. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/MANIFEST.in +0 -0
  15. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/VERSION_MANAGEMENT.md +0 -0
  16. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/examples/README.md +0 -0
  17. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/examples/basic_usage.py +0 -0
  18. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/pyproject.toml +0 -0
  19. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/scripts/publish.sh +0 -0
  20. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/setup.cfg +0 -0
  21. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/__init__.py +0 -0
  22. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/_version.py +0 -0
  23. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/constant.py +0 -0
  24. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/logger_setup.py +0 -0
  25. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/__init__.py +0 -0
  26. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v6sample/v6sample00000.asd +0 -0
  27. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v6sample/v6sample00001.asd +0 -0
  28. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v6sample/v6sample00002.asd +0 -0
  29. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00000.asd +0 -0
  30. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00001.asd +0 -0
  31. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00002.asd +0 -0
  32. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00003.asd +0 -0
  33. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00004.asd +0 -0
  34. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00005.asd +0 -0
  35. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample_field_spectroscopy/44231B009-1-FW300000.asd +0 -0
  36. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample_field_spectroscopy/44231B009-1-FW3R00000.asd +0 -0
  37. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample_field_spectroscopy/44231B174-1-FF300000.asd +0 -0
  38. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v8sample/v8sample00001.asd +0 -0
  39. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v8sample/v8sample00002.asd +0 -0
  40. {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/test_data.py +0 -0
@@ -0,0 +1,68 @@
1
+ codecov:
2
+ require_ci_to_pass: yes
3
+ notify:
4
+ wait_for_ci: yes
5
+
6
+ coverage:
7
+ precision: 2
8
+ round: down
9
+ range: "70...100"
10
+
11
+ status:
12
+ project:
13
+ default:
14
+ target: auto
15
+ threshold: 1%
16
+ informational: false
17
+ patch:
18
+ default:
19
+ target: auto
20
+ threshold: 1%
21
+ informational: false
22
+
23
+ comment:
24
+ layout: "reach,diff,flags,files,footer"
25
+ behavior: default
26
+ require_changes: false
27
+ require_base: false
28
+ require_head: true
29
+
30
+ flags:
31
+ ubuntu-latest-py3.8:
32
+ carryforward: false
33
+ ubuntu-latest-py3.9:
34
+ carryforward: false
35
+ ubuntu-latest-py3.10:
36
+ carryforward: false
37
+ ubuntu-latest-py3.11:
38
+ carryforward: false
39
+ ubuntu-latest-py3.12:
40
+ carryforward: false
41
+ windows-latest-py3.8:
42
+ carryforward: false
43
+ windows-latest-py3.9:
44
+ carryforward: false
45
+ windows-latest-py3.10:
46
+ carryforward: false
47
+ windows-latest-py3.11:
48
+ carryforward: false
49
+ windows-latest-py3.12:
50
+ carryforward: false
51
+ macos-latest-py3.8:
52
+ carryforward: false
53
+ macos-latest-py3.9:
54
+ carryforward: false
55
+ macos-latest-py3.10:
56
+ carryforward: false
57
+ macos-latest-py3.11:
58
+ carryforward: false
59
+ macos-latest-py3.12:
60
+ carryforward: false
61
+
62
+ ignore:
63
+ - "tests/"
64
+ - "examples/"
65
+ - "docs/"
66
+ - "scripts/"
67
+ - "**/__pycache__"
68
+ - "*.pyc"
@@ -13,6 +13,60 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
13
13
 
14
14
  ## [Unreleased]
15
15
 
16
+ ## [1.2.2] - 2025-10-05
17
+
18
+ ### Added
19
+ - 📋 **Codecov Configuration** - Added `.codecov.yml` for comprehensive code coverage tracking
20
+ - Multi-platform coverage flags (Ubuntu, Windows, macOS)
21
+ - Per-Python-version coverage tracking (3.8-3.12)
22
+ - Automatic coverage status checks on PRs
23
+ - Detailed coverage reporting with customizable thresholds
24
+ - ✅ **Enhanced Test Suite** - Significantly expanded test coverage
25
+ - Added `test_file_attributes.py` with 12 comprehensive test cases for FileAttributes class
26
+ - Expanded `test_asd_file_reader.py` with new property tests and validation tests
27
+ - Added tests for spectral data parsing, constituent types, BSTR, and audit events
28
+ - Improved test coverage for file version validation, GPS parsing, and datetime handling
29
+ - 📊 **Coverage Reporting** - Added `coverage.json` for detailed coverage metrics
30
+ - Per-file coverage statistics
31
+ - Function-level coverage tracking
32
+ - Class-level coverage analysis
33
+
34
+ ### Changed
35
+ - 🏗️ **Improved Code Structure** - Enhanced ASDFile class inheritance
36
+ - `ASDFile` now properly inherits from `FileAttributes` class
37
+ - Better integration of file handling capabilities
38
+ - Improved logger initialization with proper setup in module scope
39
+ - 🔧 **Optimized CI/CD Workflows** - Performance improvements for GitHub Actions
40
+ - Removed redundant pip caching from PyPI verification steps
41
+ - Streamlined publish workflows for faster deployments
42
+ - 📚 **Updated Documentation** - Improved README formatting
43
+ - Fixed test workflow badge to reference correct workflow file
44
+ - Cleaned up citation section for better readability
45
+ - Removed verbose contribution and community sections for conciseness
46
+
47
+ ### Fixed
48
+ - 🐛 **Fixed FileAttributes Methods** - Corrected attribute naming inconsistencies
49
+ - Fixed `set_file_name()` method to use `self.filename` instead of `self.file_name`
50
+ - Fixed `set_file_path()` method to use `self.filepath` instead of `self.file_path`
51
+ - Improved consistency across FileAttributes class methods
52
+ - 🔧 **Enhanced Test Robustness** - Improved test initialization and execution
53
+ - Fixed ASDFile test initialization to work without parent class conflicts
54
+ - Added proper subTest contexts for all file iteration tests
55
+ - Improved error handling in test cases
56
+
57
+ ### Removed
58
+ - ❌ **CITATION.cff** - Temporarily removed to streamline package metadata
59
+ - Citation information now maintained in README only
60
+ - Reduces maintenance overhead for version updates
61
+ - GitHub citation feature still available via repository metadata
62
+
63
+ ### Technical Improvements
64
+ - Better test organization with comprehensive property testing
65
+ - Improved code coverage from ~61% to higher levels across core modules
66
+ - Enhanced file attribute handling with proper inheritance chain
67
+ - More reliable CI/CD pipeline with optimized caching strategy
68
+ - Better separation of concerns between file I/O and ASD parsing logic
69
+
16
70
  ## [1.2.1] - 2025-10-05
17
71
 
18
72
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyASDReader
3
- Version: 1.2.1
3
+ Version: 1.2.2
4
4
  Summary: A Python library for reading and parsing all versions of ASD binary spectral files
5
5
  Author-email: Kai Cao <caokai_cgs@163.com>
6
6
  Maintainer-email: Kai Cao <caokai_cgs@163.com>
@@ -86,7 +86,7 @@ Dynamic: license-file
86
86
  [![PyPI version](https://img.shields.io/pypi/v/pyASDReader?style=flat-square)](https://pypi.org/project/pyASDReader/)
87
87
  [![Python versions](https://img.shields.io/pypi/pyversions/pyASDReader?style=flat-square)](https://pypi.org/project/pyASDReader/)
88
88
  [![License](https://img.shields.io/github/license/KaiTastic/pyASDReader?style=flat-square)](https://github.com/KaiTastic/pyASDReader/blob/main/LICENSE)
89
- [![Tests](https://img.shields.io/github/actions/workflow/status/KaiTastic/pyASDReader/test.yml?branch=main&label=tests&style=flat-square)](https://github.com/KaiTastic/pyASDReader/actions)
89
+ [![Tests](https://img.shields.io/github/actions/workflow/status/KaiTastic/pyASDReader/python-package.yml?branch=main&label=tests&style=flat-square)](https://github.com/KaiTastic/pyASDReader/actions)
90
90
  [![Coverage](https://img.shields.io/codecov/c/github/KaiTastic/pyASDReader?style=flat-square)](https://codecov.io/gh/KaiTastic/pyASDReader)
91
91
 
92
92
  pyASDReader is a robust Python library designed to read and parse all versions (v1-v8) of ASD (Analytical Spectral Devices) binary spectral files. It provides seamless access to spectral data, metadata, and calibration information from various ASD instruments including FieldSpec, LabSpec, TerraSpec, and more.
@@ -388,67 +388,9 @@ Comprehensive export capabilities beyond the standard ASCII format:
388
388
  - Integration with popular spectral analysis libraries
389
389
 
390
390
 
391
-
392
- ## Contributing
393
-
394
- ### Development Setup
395
-
396
- 1. **Fork and Clone**:
397
- ```bash
398
- git clone https://github.com/yourusername/pyASDReader.git
399
- cd pyASDReader
400
- ```
401
-
402
- 2. **Create Development Environment**:
403
- ```bash
404
- python -m venv venv
405
- source venv/bin/activate # On Windows: venv\Scripts\activate
406
- pip install -e ".[dev]"
407
- ```
408
-
409
- 3. **Run Tests**:
410
- ```bash
411
- pytest tests/
412
- python -m pytest --cov=src --cov-report=html
413
- ```
414
-
415
- ### Contribution Guidelines
416
-
417
- - **Bug Reports**: Use GitHub Issues with detailed reproduction steps
418
- - **Feature Requests**: Open an issue to discuss before implementing
419
- - **Code Style**: Follow PEP 8 and use provided pre-commit hooks
420
- - **Testing**: Add tests for new features and ensure all tests pass
421
- - **Documentation**: Update README and docstrings for any API changes
422
-
423
- ### Development Workflow
424
-
425
- 1. Create a feature branch: `git checkout -b feature/amazing-feature`
426
- 2. Make your changes with appropriate tests
427
- 3. Run the test suite: `pytest`
428
- 4. Commit your changes: `git commit -m 'Add amazing feature'`
429
- 5. Push to your fork: `git push origin feature/amazing-feature`
430
- 6. Submit a Pull Request
431
-
432
- ## � Support & Community
433
-
434
- ### Getting Help
435
-
436
- - 📋 **GitHub Issues**: [Report bugs or request features](https://github.com/KaiTastic/pyASDReader/issues)
437
- - 📧 **Email**: `caokai_cgs@163.com` for direct support
438
- - 🔒 **Security**: Report vulnerabilities via the [Security Policy](SECURITY.md)
439
-
440
- ### Community Guidelines
441
-
442
- - Be respectful and inclusive
443
- - Help others learn and grow
444
- - Share knowledge and experiences
445
- - Provide constructive feedback
446
-
447
391
  ## Citation
448
392
 
449
- If you use pyASDReader in your research, please cite it using the information from t he [CITATION.cff](CITATION.cff) file.
450
-
451
- GitHub provides a "Cite this repository" button in the sidebar that automatically generates citations in multiple formats.
393
+ If you use pyASDReader in your research, please cite it using the following information:
452
394
 
453
395
  **BibTeX format**:
454
396
  ```bibtex
@@ -457,16 +399,16 @@ GitHub provides a "Cite this repository" button in the sidebar that automaticall
457
399
  title = {pyASDReader: A Python Library for ASD Spectral File Reading},
458
400
  year = {2025},
459
401
  url = {https://github.com/KaiTastic/pyASDReader},
460
- version = {see CITATION.cff for latest version}
402
+ version = {1.2.1}
461
403
  }
462
404
  ```
463
405
 
464
406
  **Plain text citation**:
465
- > Cao, Kai. (2025). pyASDReader: A Python Library for ASD Spectral File Reading. Available at: https://github.com/KaiTastic/pyASDReader
466
-
467
- For the most up-to-date version number and citation details, please refer to the [CITATION.cff](CITATION.cff) file or use GitHub's citation feature.
407
+ ```
408
+ Cao, Kai. (2025). pyASDReader: A Python Library for ASD Spectral File Reading. Available at: https://github.com/KaiTastic/pyASDReader
409
+ ```
468
410
 
469
- ## 📖 References
411
+ ## References
470
412
 
471
413
  ### Official Documentation
472
414
  - [ASD Inc. (2017). ASD File Format: Version 8 (Revision): 1-10](https://www.malvernpanalytical.com/en/learn/knowledge-center/user-manuals/asd-file-format-v8)
@@ -3,7 +3,7 @@
3
3
  [![PyPI version](https://img.shields.io/pypi/v/pyASDReader?style=flat-square)](https://pypi.org/project/pyASDReader/)
4
4
  [![Python versions](https://img.shields.io/pypi/pyversions/pyASDReader?style=flat-square)](https://pypi.org/project/pyASDReader/)
5
5
  [![License](https://img.shields.io/github/license/KaiTastic/pyASDReader?style=flat-square)](https://github.com/KaiTastic/pyASDReader/blob/main/LICENSE)
6
- [![Tests](https://img.shields.io/github/actions/workflow/status/KaiTastic/pyASDReader/test.yml?branch=main&label=tests&style=flat-square)](https://github.com/KaiTastic/pyASDReader/actions)
6
+ [![Tests](https://img.shields.io/github/actions/workflow/status/KaiTastic/pyASDReader/python-package.yml?branch=main&label=tests&style=flat-square)](https://github.com/KaiTastic/pyASDReader/actions)
7
7
  [![Coverage](https://img.shields.io/codecov/c/github/KaiTastic/pyASDReader?style=flat-square)](https://codecov.io/gh/KaiTastic/pyASDReader)
8
8
 
9
9
  pyASDReader is a robust Python library designed to read and parse all versions (v1-v8) of ASD (Analytical Spectral Devices) binary spectral files. It provides seamless access to spectral data, metadata, and calibration information from various ASD instruments including FieldSpec, LabSpec, TerraSpec, and more.
@@ -305,67 +305,9 @@ Comprehensive export capabilities beyond the standard ASCII format:
305
305
  - Integration with popular spectral analysis libraries
306
306
 
307
307
 
308
-
309
- ## Contributing
310
-
311
- ### Development Setup
312
-
313
- 1. **Fork and Clone**:
314
- ```bash
315
- git clone https://github.com/yourusername/pyASDReader.git
316
- cd pyASDReader
317
- ```
318
-
319
- 2. **Create Development Environment**:
320
- ```bash
321
- python -m venv venv
322
- source venv/bin/activate # On Windows: venv\Scripts\activate
323
- pip install -e ".[dev]"
324
- ```
325
-
326
- 3. **Run Tests**:
327
- ```bash
328
- pytest tests/
329
- python -m pytest --cov=src --cov-report=html
330
- ```
331
-
332
- ### Contribution Guidelines
333
-
334
- - **Bug Reports**: Use GitHub Issues with detailed reproduction steps
335
- - **Feature Requests**: Open an issue to discuss before implementing
336
- - **Code Style**: Follow PEP 8 and use provided pre-commit hooks
337
- - **Testing**: Add tests for new features and ensure all tests pass
338
- - **Documentation**: Update README and docstrings for any API changes
339
-
340
- ### Development Workflow
341
-
342
- 1. Create a feature branch: `git checkout -b feature/amazing-feature`
343
- 2. Make your changes with appropriate tests
344
- 3. Run the test suite: `pytest`
345
- 4. Commit your changes: `git commit -m 'Add amazing feature'`
346
- 5. Push to your fork: `git push origin feature/amazing-feature`
347
- 6. Submit a Pull Request
348
-
349
- ## � Support & Community
350
-
351
- ### Getting Help
352
-
353
- - 📋 **GitHub Issues**: [Report bugs or request features](https://github.com/KaiTastic/pyASDReader/issues)
354
- - 📧 **Email**: `caokai_cgs@163.com` for direct support
355
- - 🔒 **Security**: Report vulnerabilities via the [Security Policy](SECURITY.md)
356
-
357
- ### Community Guidelines
358
-
359
- - Be respectful and inclusive
360
- - Help others learn and grow
361
- - Share knowledge and experiences
362
- - Provide constructive feedback
363
-
364
308
  ## Citation
365
309
 
366
- If you use pyASDReader in your research, please cite it using the information from t he [CITATION.cff](CITATION.cff) file.
367
-
368
- GitHub provides a "Cite this repository" button in the sidebar that automatically generates citations in multiple formats.
310
+ If you use pyASDReader in your research, please cite it using the following information:
369
311
 
370
312
  **BibTeX format**:
371
313
  ```bibtex
@@ -374,16 +316,16 @@ GitHub provides a "Cite this repository" button in the sidebar that automaticall
374
316
  title = {pyASDReader: A Python Library for ASD Spectral File Reading},
375
317
  year = {2025},
376
318
  url = {https://github.com/KaiTastic/pyASDReader},
377
- version = {see CITATION.cff for latest version}
319
+ version = {1.2.1}
378
320
  }
379
321
  ```
380
322
 
381
323
  **Plain text citation**:
382
- > Cao, Kai. (2025). pyASDReader: A Python Library for ASD Spectral File Reading. Available at: https://github.com/KaiTastic/pyASDReader
383
-
384
- For the most up-to-date version number and citation details, please refer to the [CITATION.cff](CITATION.cff) file or use GitHub's citation feature.
324
+ ```
325
+ Cao, Kai. (2025). pyASDReader: A Python Library for ASD Spectral File Reading. Available at: https://github.com/KaiTastic/pyASDReader
326
+ ```
385
327
 
386
- ## 📖 References
328
+ ## References
387
329
 
388
330
  ### Official Documentation
389
331
  - [ASD Inc. (2017). ASD File Format: Version 8 (Revision): 1-10](https://www.malvernpanalytical.com/en/learn/knowledge-center/user-manuals/asd-file-format-v8)
@@ -0,0 +1 @@
1
+ {"meta": {"format": 3, "version": "7.10.6", "timestamp": "2025-10-05T23:25:14.126255", "branch_coverage": false, "show_contexts": false}, "files": {"src/__init__.py": {"executed_lines": [1, 8, 9, 10, 25], "summary": {"covered_lines": 4, "num_statements": 4, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [1, 8, 9, 10, 25], "summary": {"covered_lines": 4, "num_statements": 4, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [1, 8, 9, 10, 25], "summary": {"covered_lines": 4, "num_statements": 4, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/_version.py": {"executed_lines": [5, 6, 8, 12], "summary": {"covered_lines": 4, "num_statements": 5, "percent_covered": 80.0, "percent_covered_display": "80", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [7], "excluded_lines": [], "functions": {"": {"executed_lines": [5, 6, 8, 12], "summary": {"covered_lines": 4, "num_statements": 5, "percent_covered": 80.0, "percent_covered_display": "80", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [7], "excluded_lines": []}}, "classes": {"": {"executed_lines": [5, 6, 8, 12], "summary": {"covered_lines": 4, "num_statements": 5, "percent_covered": 80.0, "percent_covered_display": "80", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [7], "excluded_lines": []}}}, "src/asd_file_reader.py": {"executed_lines": [1, 5, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 30, 31, 32, 34, 36, 38, 44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 65, 66, 68, 69, 72, 73, 74, 77, 78, 79, 81, 83, 84, 85, 86, 87, 93, 96, 99, 100, 101, 102, 106, 107, 110, 111, 112, 116, 117, 120, 121, 123, 127, 128, 131, 132, 134, 138, 139, 141, 142, 143, 144, 145, 146, 147, 148, 149, 154, 155, 157, 162, 163, 166, 167, 169, 172, 175, 176, 179, 180, 181, 183, 184, 186, 187, 188, 190, 191, 193, 194, 201, 202, 211, 212, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 241, 243, 244, 245, 246, 247, 248, 250, 255, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 271, 276, 277, 278, 279, 280, 281, 283, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 318, 319, 321, 322, 324, 325, 326, 327, 328, 329, 330, 331, 333, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 361, 362, 363, 364, 365, 367, 372, 373, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 393, 394, 396, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 414, 419, 420, 421, 422, 423, 424, 427, 428, 429, 433, 434, 436, 440, 441, 442, 443, 444, 445, 446, 447, 449, 455, 456, 457, 460, 461, 462, 463, 464, 465, 466, 467, 472, 473, 474, 475, 476, 477, 478, 479, 480, 481, 483, 488, 489, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 504, 505, 506, 507, 508, 509, 510, 511, 517, 518, 519, 520, 521, 522, 523, 524, 525, 529, 530, 533, 538, 558, 559, 561, 562, 563, 567, 569, 574, 575, 576, 577, 580, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 595, 597, 598, 599, 600, 601, 602, 607, 618, 619, 620, 622, 624, 626, 628, 630, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 650, 651, 654, 655, 661, 662, 677, 678, 681, 682, 688, 689, 697, 698, 706, 707, 710, 724, 733, 734, 740, 741, 748, 749, 752, 753, 759, 760, 766, 767, 775, 776, 798, 803, 859], "summary": {"covered_lines": 434, "num_statements": 708, "percent_covered": 61.29943502824859, "percent_covered_display": "61", "missing_lines": 274, "excluded_lines": 0}, "missing_lines": [88, 89, 90, 97, 98, 103, 104, 108, 109, 113, 114, 118, 119, 124, 125, 129, 130, 135, 136, 152, 153, 158, 159, 164, 165, 170, 173, 237, 238, 239, 251, 252, 253, 272, 273, 274, 284, 285, 286, 334, 335, 336, 368, 369, 370, 397, 398, 399, 415, 416, 417, 432, 450, 451, 452, 453, 458, 468, 469, 470, 484, 485, 486, 513, 514, 515, 526, 527, 528, 531, 532, 534, 535, 536, 539, 540, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 564, 570, 571, 572, 603, 604, 605, 608, 609, 610, 611, 612, 613, 614, 615, 616, 621, 623, 625, 627, 629, 645, 646, 647, 652, 656, 657, 659, 663, 664, 665, 666, 667, 669, 670, 671, 672, 674, 675, 679, 683, 684, 686, 690, 691, 693, 699, 700, 702, 708, 712, 713, 714, 715, 716, 718, 719, 720, 722, 725, 726, 727, 728, 731, 735, 736, 738, 742, 743, 745, 750, 754, 755, 757, 761, 762, 764, 768, 769, 771, 777, 778, 779, 780, 781, 782, 783, 784, 785, 787, 788, 789, 791, 792, 793, 795, 796, 799, 800, 801, 804, 805, 806, 807, 808, 809, 810, 812, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 825, 826, 827, 829, 830, 831, 832, 834, 835, 836, 837, 839, 840, 841, 842, 844, 845, 846, 848, 849, 850, 851, 853, 854, 855, 856, 861, 862, 863, 864, 866, 867, 869, 871, 872, 873, 874, 876, 884, 885, 887, 889, 890, 892, 894, 895, 896, 898, 899, 900, 901, 902, 904, 906, 908, 910, 912, 913, 915, 918, 919, 921, 922, 923, 924, 926], "excluded_lines": [], "functions": {"ASDFile.__init__": {"executed_lines": [44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 65, 66], "summary": {"covered_lines": 20, "num_statements": 20, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ASDFile.read": {"executed_lines": [69, 72, 73, 74, 77, 78, 79, 81, 83, 84, 85, 86, 87, 93, 96, 99, 100, 101, 102, 106, 107, 110, 111, 112, 116, 117, 120, 121, 123, 127, 128, 131, 132, 134, 138, 139, 141, 142, 143, 144, 145, 146, 147, 148, 149, 154, 155, 157, 162, 163, 166, 167], "summary": {"covered_lines": 52, "num_statements": 77, "percent_covered": 67.53246753246754, "percent_covered_display": "68", "missing_lines": 25, "excluded_lines": 0}, "missing_lines": [88, 89, 90, 97, 98, 103, 104, 108, 109, 113, 114, 118, 119, 124, 125, 129, 130, 135, 136, 152, 153, 158, 159, 164, 165], "excluded_lines": []}, "ASDFile.update": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [170], "excluded_lines": []}, "ASDFile.write": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [173], "excluded_lines": []}, "ASDFile.__check_offset": {"executed_lines": [176, 188], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ASDFile.__check_offset.wrapper": {"executed_lines": [179, 180, 181, 183, 184, 186, 187], "summary": {"covered_lines": 7, "num_statements": 7, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ASDFile.__parse_metadata": {"executed_lines": [193, 194, 201, 202, 211, 212, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 241], "summary": {"covered_lines": 23, "num_statements": 26, "percent_covered": 88.46153846153847, "percent_covered_display": "88", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [237, 238, 239], "excluded_lines": []}, "ASDFile.__parse_spectrumData": {"executed_lines": [245, 246, 247, 248, 250], "summary": {"covered_lines": 5, "num_statements": 8, "percent_covered": 62.5, "percent_covered_display": "62", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [251, 252, 253], "excluded_lines": []}, "ASDFile.__parse_referenceFileHeader": {"executed_lines": [257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 271], "summary": {"covered_lines": 14, "num_statements": 17, "percent_covered": 82.3529411764706, "percent_covered_display": "82", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [272, 273, 274], "excluded_lines": []}, "ASDFile.__parse_referenceData": {"executed_lines": [278, 279, 280, 281, 283], "summary": {"covered_lines": 5, "num_statements": 8, "percent_covered": 62.5, "percent_covered_display": "62", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [284, 285, 286], "excluded_lines": []}, "ASDFile.__parse_classifierData": {"executed_lines": [290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 318, 319, 321, 322, 324, 325, 326, 327, 328, 329, 330, 331, 333], "summary": {"covered_lines": 40, "num_statements": 43, "percent_covered": 93.02325581395348, "percent_covered_display": "93", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [334, 335, 336], "excluded_lines": []}, "ASDFile.__parse_dependentVariables": {"executed_lines": [340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 361, 362, 363, 364, 365, 367], "summary": {"covered_lines": 26, "num_statements": 29, "percent_covered": 89.65517241379311, "percent_covered_display": "90", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [368, 369, 370], "excluded_lines": []}, "ASDFile.__parse_calibrationHeader": {"executed_lines": [374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 393, 394, 396], "summary": {"covered_lines": 21, "num_statements": 24, "percent_covered": 87.5, "percent_covered_display": "88", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [397, 398, 399], "excluded_lines": []}, "ASDFile.__parse_auditLog": {"executed_lines": [403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 414], "summary": {"covered_lines": 11, "num_statements": 14, "percent_covered": 78.57142857142857, "percent_covered_display": "79", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [415, 416, 417], "excluded_lines": []}, "ASDFile.__parse_signature": {"executed_lines": [421, 422, 423, 424, 427, 428, 429, 433, 434, 436, 440, 441, 442, 443, 444, 445, 446, 447, 449, 455, 456, 457], "summary": {"covered_lines": 22, "num_statements": 28, "percent_covered": 78.57142857142857, "percent_covered_display": "79", "missing_lines": 6, "excluded_lines": 0}, "missing_lines": [432, 450, 451, 452, 453, 458], "excluded_lines": []}, "ASDFile.__parse_spectra": {"executed_lines": [462, 463, 464, 465, 466, 467], "summary": {"covered_lines": 6, "num_statements": 9, "percent_covered": 66.66666666666667, "percent_covered_display": "67", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [468, 469, 470], "excluded_lines": []}, "ASDFile.__parse_constituantType": {"executed_lines": [474, 475, 476, 477, 478, 479, 480, 481, 483], "summary": {"covered_lines": 9, "num_statements": 12, "percent_covered": 75.0, "percent_covered_display": "75", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [484, 485, 486], "excluded_lines": []}, "ASDFile.__parse_bstr": {"executed_lines": [490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502], "summary": {"covered_lines": 13, "num_statements": 13, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ASDFile.__parse_Bool": {"executed_lines": [506, 507, 508, 509, 510, 511], "summary": {"covered_lines": 6, "num_statements": 9, "percent_covered": 66.66666666666667, "percent_covered_display": "67", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [513, 514, 515], "excluded_lines": []}, "ASDFile.__parse_auditEvents": {"executed_lines": [519, 520, 521, 522, 523, 524, 525, 529, 530, 533], "summary": {"covered_lines": 10, "num_statements": 18, "percent_covered": 55.55555555555556, "percent_covered_display": "56", "missing_lines": 8, "excluded_lines": 0}, "missing_lines": [526, 527, 528, 531, 532, 534, 535, 536], "excluded_lines": []}, "ASDFile.__parse_auditLogEvent": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 16, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 16, "excluded_lines": 0}, "missing_lines": [539, 540, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556], "excluded_lines": []}, "ASDFile.__validate_fileVersion": {"executed_lines": [559, 561, 562, 563, 567, 569], "summary": {"covered_lines": 6, "num_statements": 10, "percent_covered": 60.0, "percent_covered_display": "60", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [564, 570, 571, 572], "excluded_lines": []}, "ASDFile.__parseVersion": {"executed_lines": [575, 576, 577], "summary": {"covered_lines": 3, "num_statements": 3, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ASDFile.__parse_ASDFilewhen": {"executed_lines": [581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593], "summary": {"covered_lines": 13, "num_statements": 13, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ASDFile.__parse_gps": {"executed_lines": [597, 598, 599, 600, 601, 602], "summary": {"covered_lines": 6, "num_statements": 9, "percent_covered": 66.66666666666667, "percent_covered_display": "67", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [603, 604, 605], "excluded_lines": []}, "ASDFile.__parse_SmartDetector": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 9, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 9, "excluded_lines": 0}, "missing_lines": [608, 609, 610, 611, 612, 613, 614, 615, 616], "excluded_lines": []}, "ASDFile.__parseSaturationError": {"executed_lines": [619, 620, 622, 624, 626, 628, 630], "summary": {"covered_lines": 7, "num_statements": 12, "percent_covered": 58.333333333333336, "percent_covered_display": "58", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [621, 623, 625, 627, 629], "excluded_lines": []}, "ASDFile.__parseTimeOLE": {"executed_lines": [633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644], "summary": {"covered_lines": 12, "num_statements": 15, "percent_covered": 80.0, "percent_covered_display": "80", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [645, 646, 647], "excluded_lines": []}, "ASDFile.digitalNumber": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [652], "excluded_lines": []}, "ASDFile.whiteReference": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [656, 657, 659], "excluded_lines": []}, "ASDFile.reflectance": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 11, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 11, "excluded_lines": 0}, "missing_lines": [663, 664, 665, 666, 667, 669, 670, 671, 672, 674, 675], "excluded_lines": []}, "ASDFile.reflectanceNoDeriv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [679], "excluded_lines": []}, "ASDFile.reflectance1stDeriv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [683, 684, 686], "excluded_lines": []}, "ASDFile.reflectance2ndDeriv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [690, 691, 693], "excluded_lines": []}, "ASDFile.reflectance3rdDeriv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [699, 700, 702], "excluded_lines": []}, "ASDFile.transmitance": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [708], "excluded_lines": []}, "ASDFile.__normalise_spectrum": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 9, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 9, "excluded_lines": 0}, "missing_lines": [712, 713, 714, 715, 716, 718, 719, 720, 722], "excluded_lines": []}, "ASDFile.__derivative": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 5, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 5, "excluded_lines": 0}, "missing_lines": [725, 726, 727, 728, 731], "excluded_lines": []}, "ASDFile.absoluteReflectance": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [735, 736, 738], "excluded_lines": []}, "ASDFile.log1R": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [742, 743, 745], "excluded_lines": []}, "ASDFile.log1T": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [750], "excluded_lines": []}, "ASDFile.log1RNoDeriv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [754, 755, 757], "excluded_lines": []}, "ASDFile.log1R1stDeriv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [761, 762, 764], "excluded_lines": []}, "ASDFile.log1R2ndDeriv": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [768, 769, 771], "excluded_lines": []}, "ASDFile.radiance": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 17, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 17, "excluded_lines": 0}, "missing_lines": [777, 778, 779, 780, 781, 782, 783, 784, 785, 787, 788, 789, 791, 792, 793, 795, 796], "excluded_lines": []}, "ASDFile.__calc_radiance": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [799, 800, 801], "excluded_lines": []}, "ASDFile.__calc_irradiance": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 44, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 44, "excluded_lines": 0}, "missing_lines": [804, 805, 806, 807, 808, 809, 810, 812, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 825, 826, 827, 829, 830, 831, 832, 834, 835, 836, 837, 839, 840, 841, 842, 844, 845, 846, 848, 849, 850, 851, 853, 854, 855, 856], "excluded_lines": []}, "ASDFile.__parabolic_correction": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 40, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 40, "excluded_lines": 0}, "missing_lines": [861, 862, 863, 864, 866, 867, 869, 871, 872, 873, 874, 876, 884, 885, 887, 889, 890, 892, 894, 895, 896, 898, 899, 900, 901, 902, 904, 906, 908, 910, 912, 913, 915, 918, 919, 921, 922, 923, 924, 926], "excluded_lines": []}, "": {"executed_lines": [1, 5, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 30, 31, 32, 34, 36, 38, 68, 169, 172, 175, 190, 191, 243, 244, 255, 256, 276, 277, 288, 289, 338, 339, 372, 373, 401, 402, 419, 420, 460, 461, 472, 473, 488, 489, 504, 505, 517, 518, 538, 558, 574, 580, 595, 607, 618, 632, 650, 651, 654, 655, 661, 662, 677, 678, 681, 682, 688, 689, 697, 698, 706, 707, 710, 724, 733, 734, 740, 741, 748, 749, 752, 753, 759, 760, 766, 767, 775, 776, 798, 803, 859], "summary": {"covered_lines": 95, "num_statements": 95, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"ASDFile": {"executed_lines": [44, 45, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 65, 66, 69, 72, 73, 74, 77, 78, 79, 81, 83, 84, 85, 86, 87, 93, 96, 99, 100, 101, 102, 106, 107, 110, 111, 112, 116, 117, 120, 121, 123, 127, 128, 131, 132, 134, 138, 139, 141, 142, 143, 144, 145, 146, 147, 148, 149, 154, 155, 157, 162, 163, 166, 167, 176, 179, 180, 181, 183, 184, 186, 187, 188, 193, 194, 201, 202, 211, 212, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 241, 245, 246, 247, 248, 250, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 271, 278, 279, 280, 281, 283, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 318, 319, 321, 322, 324, 325, 326, 327, 328, 329, 330, 331, 333, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, 357, 358, 359, 361, 362, 363, 364, 365, 367, 374, 375, 376, 377, 378, 379, 380, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, 391, 393, 394, 396, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 414, 421, 422, 423, 424, 427, 428, 429, 433, 434, 436, 440, 441, 442, 443, 444, 445, 446, 447, 449, 455, 456, 457, 462, 463, 464, 465, 466, 467, 474, 475, 476, 477, 478, 479, 480, 481, 483, 490, 491, 492, 493, 494, 495, 496, 497, 498, 499, 500, 501, 502, 506, 507, 508, 509, 510, 511, 519, 520, 521, 522, 523, 524, 525, 529, 530, 533, 559, 561, 562, 563, 567, 569, 575, 576, 577, 581, 582, 583, 584, 585, 586, 587, 588, 589, 590, 591, 592, 593, 597, 598, 599, 600, 601, 602, 619, 620, 622, 624, 626, 628, 630, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644], "summary": {"covered_lines": 339, "num_statements": 613, "percent_covered": 55.30179445350734, "percent_covered_display": "55", "missing_lines": 274, "excluded_lines": 0}, "missing_lines": [88, 89, 90, 97, 98, 103, 104, 108, 109, 113, 114, 118, 119, 124, 125, 129, 130, 135, 136, 152, 153, 158, 159, 164, 165, 170, 173, 237, 238, 239, 251, 252, 253, 272, 273, 274, 284, 285, 286, 334, 335, 336, 368, 369, 370, 397, 398, 399, 415, 416, 417, 432, 450, 451, 452, 453, 458, 468, 469, 470, 484, 485, 486, 513, 514, 515, 526, 527, 528, 531, 532, 534, 535, 536, 539, 540, 543, 544, 545, 546, 547, 548, 549, 550, 551, 552, 553, 554, 555, 556, 564, 570, 571, 572, 603, 604, 605, 608, 609, 610, 611, 612, 613, 614, 615, 616, 621, 623, 625, 627, 629, 645, 646, 647, 652, 656, 657, 659, 663, 664, 665, 666, 667, 669, 670, 671, 672, 674, 675, 679, 683, 684, 686, 690, 691, 693, 699, 700, 702, 708, 712, 713, 714, 715, 716, 718, 719, 720, 722, 725, 726, 727, 728, 731, 735, 736, 738, 742, 743, 745, 750, 754, 755, 757, 761, 762, 764, 768, 769, 771, 777, 778, 779, 780, 781, 782, 783, 784, 785, 787, 788, 789, 791, 792, 793, 795, 796, 799, 800, 801, 804, 805, 806, 807, 808, 809, 810, 812, 814, 815, 816, 817, 818, 819, 820, 821, 822, 823, 825, 826, 827, 829, 830, 831, 832, 834, 835, 836, 837, 839, 840, 841, 842, 844, 845, 846, 848, 849, 850, 851, 853, 854, 855, 856, 861, 862, 863, 864, 866, 867, 869, 871, 872, 873, 874, 876, 884, 885, 887, 889, 890, 892, 894, 895, 896, 898, 899, 900, 901, 902, 904, 906, 908, 910, 912, 913, 915, 918, 919, 921, 922, 923, 924, 926], "excluded_lines": []}, "": {"executed_lines": [1, 5, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 30, 31, 32, 34, 36, 38, 68, 169, 172, 175, 190, 191, 243, 244, 255, 256, 276, 277, 288, 289, 338, 339, 372, 373, 401, 402, 419, 420, 460, 461, 472, 473, 488, 489, 504, 505, 517, 518, 538, 558, 574, 580, 595, 607, 618, 632, 650, 651, 654, 655, 661, 662, 677, 678, 681, 682, 688, 689, 697, 698, 706, 707, 710, 724, 733, 734, 740, 741, 748, 749, 752, 753, 759, 760, 766, 767, 775, 776, 798, 803, 859], "summary": {"covered_lines": 95, "num_statements": 95, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/constant.py": {"executed_lines": [1, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 90, 91, 92, 93, 94, 97, 98, 99, 100, 101, 102, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 124, 125, 126, 127, 128, 129, 130, 133, 134, 135, 136, 137, 138], "summary": {"covered_lines": 104, "num_statements": 104, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": [], "functions": {"": {"executed_lines": [1, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 90, 91, 92, 93, 94, 97, 98, 99, 100, 101, 102, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 124, 125, 126, 127, 128, 129, 130, 133, 134, 135, 136, 137, 138], "summary": {"covered_lines": 104, "num_statements": 104, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"FileVersion_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "InstrumentType_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "InstrumentModel_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "SpectraType_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "SignatureState_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "AuditLogType_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "IT_ms_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "DataFormat_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "CalibrationType_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "DataType_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "ClassiferDataType_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "SaturationError_e": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 0, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "": {"executed_lines": [1, 4, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 31, 32, 34, 35, 36, 37, 38, 39, 42, 43, 44, 45, 46, 47, 48, 50, 51, 52, 53, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 90, 91, 92, 93, 94, 97, 98, 99, 100, 101, 102, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 124, 125, 126, 127, 128, 129, 130, 133, 134, 135, 136, 137, 138], "summary": {"covered_lines": 104, "num_statements": 104, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}}, "src/file_attributes.py": {"executed_lines": [1, 22, 23, 24, 27, 28, 30, 31, 33, 34, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 51, 52, 53, 55, 62, 67, 80, 84, 88, 99, 100, 105, 106, 112], "summary": {"covered_lines": 35, "num_statements": 56, "percent_covered": 62.5, "percent_covered_display": "62", "missing_lines": 21, "excluded_lines": 2}, "missing_lines": [56, 57, 59, 60, 63, 64, 65, 68, 69, 70, 81, 82, 85, 86, 89, 101, 102, 103, 107, 108, 109], "excluded_lines": [112, 113], "functions": {"FileAttributes.__init__": {"executed_lines": [30, 31, 33, 34, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49], "summary": {"covered_lines": 17, "num_statements": 17, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "FileAttributes.__get_data": {"executed_lines": [52, 53], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}, "FileAttributes.delete": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 4, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 4, "excluded_lines": 0}, "missing_lines": [56, 57, 59, 60], "excluded_lines": []}, "FileAttributes.read": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [63, 64, 65], "excluded_lines": []}, "FileAttributes.write": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [68, 69, 70], "excluded_lines": []}, "FileAttributes.set_file_name": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [81, 82], "excluded_lines": []}, "FileAttributes.set_file_path": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 2, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 2, "excluded_lines": 0}, "missing_lines": [85, 86], "excluded_lines": []}, "FileAttributes.__str__": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 1, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [89], "excluded_lines": []}, "FileAttributes.hashMD5": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [101, 102, 103], "excluded_lines": []}, "FileAttributes.hashSHA265": {"executed_lines": [], "summary": {"covered_lines": 0, "num_statements": 3, "percent_covered": 0.0, "percent_covered_display": "0", "missing_lines": 3, "excluded_lines": 0}, "missing_lines": [107, 108, 109], "excluded_lines": []}, "": {"executed_lines": [1, 22, 23, 24, 27, 28, 51, 55, 62, 67, 80, 84, 88, 99, 100, 105, 106, 112], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [112, 113]}}, "classes": {"FileAttributes": {"executed_lines": [30, 31, 33, 34, 35, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 52, 53], "summary": {"covered_lines": 19, "num_statements": 40, "percent_covered": 47.5, "percent_covered_display": "48", "missing_lines": 21, "excluded_lines": 0}, "missing_lines": [56, 57, 59, 60, 63, 64, 65, 68, 69, 70, 81, 82, 85, 86, 89, 101, 102, 103, 107, 108, 109], "excluded_lines": []}, "": {"executed_lines": [1, 22, 23, 24, 27, 28, 51, 55, 62, 67, 80, 84, 88, 99, 100, 105, 106, 112], "summary": {"covered_lines": 16, "num_statements": 16, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 2}, "missing_lines": [], "excluded_lines": [112, 113]}}}, "src/logger_setup.py": {"executed_lines": [1, 4, 9, 18, 22], "summary": {"covered_lines": 5, "num_statements": 6, "percent_covered": 83.33333333333333, "percent_covered_display": "83", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [19], "excluded_lines": [], "functions": {"setup_logging": {"executed_lines": [9, 18, 22], "summary": {"covered_lines": 3, "num_statements": 4, "percent_covered": 75.0, "percent_covered_display": "75", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [19], "excluded_lines": []}, "": {"executed_lines": [1, 4], "summary": {"covered_lines": 2, "num_statements": 2, "percent_covered": 100.0, "percent_covered_display": "100", "missing_lines": 0, "excluded_lines": 0}, "missing_lines": [], "excluded_lines": []}}, "classes": {"": {"executed_lines": [1, 4, 9, 18, 22], "summary": {"covered_lines": 5, "num_statements": 6, "percent_covered": 83.33333333333333, "percent_covered_display": "83", "missing_lines": 1, "excluded_lines": 0}, "missing_lines": [19], "excluded_lines": []}}}}, "totals": {"covered_lines": 586, "num_statements": 883, "percent_covered": 66.36466591166477, "percent_covered_display": "66", "missing_lines": 297, "excluded_lines": 2}}
@@ -1,10 +1,11 @@
1
+ .codecov.yml
1
2
  .pre-commit-config.yaml
2
3
  CHANGELOG.md
3
- CITATION.cff
4
4
  LICENSE
5
5
  MANIFEST.in
6
6
  README.md
7
7
  VERSION_MANAGEMENT.md
8
+ coverage.json
8
9
  pyproject.toml
9
10
  examples/README.md
10
11
  examples/basic_usage.py
@@ -18,6 +19,7 @@ src/logger_setup.py
18
19
  tests/__init__.py
19
20
  tests/test_asd_file_reader.py
20
21
  tests/test_data.py
22
+ tests/test_file_attributes.py
21
23
  tests/sample_data/v6sample/v6sample00000.asd
22
24
  tests/sample_data/v6sample/v6sample00001.asd
23
25
  tests/sample_data/v6sample/v6sample00002.asd
@@ -27,9 +27,11 @@ from .logger_setup import setup_logging
27
27
  from .file_attributes import FileAttributes
28
28
 
29
29
  # Initialize module-level logger
30
+ log_file = f"asd_reader_{datetime.now().strftime('%Y%m%d_%H%M%S')}.log"
31
+ setup_logging(log_file, logging.INFO)
30
32
  logger = logging.getLogger(__name__)
31
33
 
32
- class ASDFile(object):
34
+ class ASDFile(FileAttributes):
33
35
 
34
36
  DEFAULT_DERIVATIVE_GAP = 5
35
37
 
@@ -39,6 +41,9 @@ class ASDFile(object):
39
41
  Args:
40
42
  filepath: Optional path to ASD file. If provided, file will be read automatically.
41
43
  """
44
+ if filepath is not None:
45
+ super().__init__(filepath) # Initialize parent class
46
+
42
47
  self.asdFileVersion = 0
43
48
  self.metadata = None
44
49
  self.spectrumData = None
@@ -78,12 +78,12 @@ class FileAttributes(object):
78
78
  # file.write(filepath)
79
79
 
80
80
  def set_file_name(self, new_name):
81
- self.file_name = new_name
82
- self.file_path = os.path.join(os.path.dirname(self.file_path), new_name)
83
-
81
+ self.filename = new_name
82
+ self.filepath = os.path.join(os.path.dirname(self.filepath), new_name)
83
+
84
84
  def set_file_path(self, new_path):
85
- self.file_path = new_path
86
- self.file_name = os.path.basename(new_path)
85
+ self.filepath = new_path
86
+ self.filename = os.path.basename(new_path)
87
87
 
88
88
  def __str__(self):
89
89
  return f"File Name: \t\t{self.filename}\n" \
@@ -150,10 +150,10 @@ class TestASDFile(unittest.TestCase):
150
150
 
151
151
  # NOTE: 1. Directly test the decorator
152
152
  class TestASDFileCheckOffsetDecorator(unittest.TestCase):
153
-
153
+
154
154
  def setUp(self):
155
- # Setup a mock ASDFile object
156
- self.asd_file = ASDFile("full_file_path")
155
+ # Setup a mock ASDFile object without initializing parent class
156
+ self.asd_file = ASDFile()
157
157
  self.asd_file._ASDFile__asdFileStream = b'\x00' * 100
158
158
 
159
159
  # Mock a function to test the decorator
@@ -952,7 +952,12 @@ class TestASDFileParseSpectralData(unittest.TestCase):
952
952
  del self.asd_file
953
953
 
954
954
  def test_001_parse_spectral_data(self):
955
- pass
955
+ for file_path in all_asd_data_files:
956
+ with self.subTest(file_path):
957
+ self.asd_file.read(file_path)
958
+ self.assertIsNotNone(self.asd_file.spectrumData)
959
+ self.assertIsNotNone(self.asd_file.spectrumData.spectra)
960
+ self.assertEqual(len(self.asd_file.spectrumData.spectra), self.asd_file.metadata.channels)
956
961
 
957
962
 
958
963
  # TODO: to be completed
@@ -968,7 +973,12 @@ class TestASDFileParseConstituentType(unittest.TestCase):
968
973
  del self.asd_file
969
974
 
970
975
  def test_001_parse_constituent_type(self):
971
- pass
976
+ for file_path in all_asd_data_files:
977
+ with self.subTest(file_path):
978
+ self.asd_file.read(file_path)
979
+ if self.asd_file.classifierData is not None:
980
+ self.assertIsNotNone(self.asd_file.classifierData.yModelType)
981
+ self.assertEqual(type(self.asd_file.classifierData.yModelType), int)
972
982
 
973
983
 
974
984
  # TODO: to be completed
@@ -984,23 +994,20 @@ class TestASDFileParseBSTR(unittest.TestCase):
984
994
  del self.asd_file
985
995
 
986
996
  def test_001_parse_bstr(self):
987
- pass
988
-
989
-
990
- # TODO: to be completed
991
- # class TestASDFileParseBool(unittest.TestCase):
992
-
993
- def setUp(self):
994
- # Check if the ASDFile object is initialized correctly
995
- self.asd_file=ASDFile()
996
- self.assertIsNotNone(self.asd_file)
997
-
998
- def tearDown(self):
999
- # Clean up the ASDFile object
1000
- del self.asd_file
997
+ for file_path in all_asd_data_files:
998
+ with self.subTest(file_path):
999
+ self.asd_file.read(file_path)
1000
+ if self.asd_file.classifierData is not None:
1001
+ self.assertIsNotNone(self.asd_file.classifierData.title)
1002
+ self.assertEqual(type(self.asd_file.classifierData.title), str)
1001
1003
 
1002
1004
  def test_001_parse_bool(self):
1003
- pass
1005
+ for file_path in all_asd_data_files:
1006
+ with self.subTest(file_path):
1007
+ self.asd_file.read(file_path)
1008
+ if self.asd_file.referenceFileHeader is not None:
1009
+ self.assertIsNotNone(self.asd_file.referenceFileHeader.referenceFlag)
1010
+ self.assertEqual(type(self.asd_file.referenceFileHeader.referenceFlag), bool)
1004
1011
 
1005
1012
 
1006
1013
  # TODO: to be completed
@@ -1016,7 +1023,13 @@ class TestASDFileParseAuditEvents(unittest.TestCase):
1016
1023
  del self.asd_file
1017
1024
 
1018
1025
  def test_001_parse_audit_events(self):
1019
- pass
1026
+ for file_path in all_asd_data_files:
1027
+ with self.subTest(file_path):
1028
+ self.asd_file.read(file_path)
1029
+ if self.asd_file.metadata.asdFileVersion.value >= 7:
1030
+ if self.asd_file.auditLog is not None:
1031
+ self.assertIsNotNone(self.asd_file.auditLog.auditEvents)
1032
+ self.assertEqual(type(self.asd_file.auditLog.auditEvents), list)
1020
1033
 
1021
1034
 
1022
1035
  # TODO: to be completed
@@ -1032,7 +1045,11 @@ class TestASDFileValidateFileVersion(unittest.TestCase):
1032
1045
  del self.asd_file
1033
1046
 
1034
1047
  def test_001_validate_file_version(self):
1035
- pass
1048
+ for file_path in all_asd_data_files:
1049
+ with self.subTest(file_path):
1050
+ self.asd_file.read(file_path)
1051
+ self.assertIsNotNone(self.asd_file.metadata.asdFileVersion)
1052
+ self.assertIn(self.asd_file.metadata.asdFileVersion.value, [6, 7, 8])
1036
1053
 
1037
1054
 
1038
1055
  # TODO: to be completed
@@ -1048,7 +1065,11 @@ class TestASDFileParseeVersion(unittest.TestCase):
1048
1065
  del self.asd_file
1049
1066
 
1050
1067
  def test_001_parse_version(self):
1051
- pass
1068
+ for file_path in all_asd_data_files:
1069
+ with self.subTest(file_path):
1070
+ self.asd_file.read(file_path)
1071
+ self.assertIsNotNone(self.asd_file.metadata.programVersion)
1072
+ self.assertEqual(type(self.asd_file.metadata.programVersion), str)
1052
1073
 
1053
1074
 
1054
1075
  # TODO: to be completed
@@ -1061,7 +1082,12 @@ class TestASDFileParseASDFileWhen(unittest.TestCase):
1061
1082
  pass
1062
1083
 
1063
1084
  def test_parse_asd_file_when(self):
1064
- pass
1085
+ asd_file = ASDFile()
1086
+ for file_path in all_asd_data_files:
1087
+ with self.subTest(file_path):
1088
+ asd_file.read(file_path)
1089
+ self.assertIsNotNone(asd_file.metadata.when_datetime)
1090
+ self.assertEqual(type(asd_file.metadata.when_datetime), datetime)
1065
1091
 
1066
1092
 
1067
1093
  # TODO: to be completed
@@ -1115,9 +1141,11 @@ class TestASDFileSmartDetector(unittest.TestCase):
1115
1141
  # self.asd_file._ASDFile__asdFileStream = b'\x00' * 100
1116
1142
 
1117
1143
  def test_parse_asd_file_smart_detector(self):
1118
- # Mock the __parse_smart_detector method
1119
- # offset = self.asd_file._ASDFile__parse_SmartDetector(0)
1120
- pass
1144
+ for file_path in all_asd_data_files:
1145
+ with self.subTest(file_path):
1146
+ self.asd_file.read(file_path)
1147
+ if self.asd_file.metadata.smartDetectorType is not None:
1148
+ self.assertEqual(type(self.asd_file.metadata.smartDetectorType), bytes)
1121
1149
 
1122
1150
 
1123
1151
  # TODO: not applied in the main code
@@ -1298,5 +1326,124 @@ class TestASDFileBenchmark(unittest.TestCase):
1298
1326
  self.assertEqual(offset, 484)
1299
1327
 
1300
1328
 
1329
+ class TestASDFileProperties(unittest.TestCase):
1330
+
1331
+ def setUp(self):
1332
+ self.asd_file = ASDFile()
1333
+ self.assertIsNotNone(self.asd_file)
1334
+
1335
+ def tearDown(self):
1336
+ del self.asd_file
1337
+
1338
+ def test_001_digitalNumber(self):
1339
+ for file_path in all_asd_data_files:
1340
+ with self.subTest(file_path):
1341
+ self.asd_file.read(file_path)
1342
+ dn = self.asd_file.digitalNumber
1343
+ self.assertIsNotNone(dn)
1344
+ self.assertEqual(type(dn).__name__, 'ndarray')
1345
+ self.assertEqual(len(dn), self.asd_file.metadata.channels)
1346
+
1347
+ def test_002_whiteReference(self):
1348
+ for file_path in all_asd_data_files:
1349
+ with self.subTest(file_path):
1350
+ self.asd_file.read(file_path)
1351
+ if self.asd_file.metadata.asdFileVersion.value >= 2:
1352
+ white_ref = self.asd_file.whiteReference
1353
+ if self.asd_file.referenceData is not None:
1354
+ self.assertIsNotNone(white_ref)
1355
+ self.assertEqual(type(white_ref).__name__, 'ndarray')
1356
+
1357
+ def test_003_reflectance(self):
1358
+ for file_path in all_asd_data_files:
1359
+ with self.subTest(file_path):
1360
+ self.asd_file.read(file_path)
1361
+ if self.asd_file.metadata.asdFileVersion.value >= 2:
1362
+ refl = self.asd_file.reflectance
1363
+ if refl is not None:
1364
+ self.assertEqual(type(refl).__name__, 'ndarray')
1365
+ self.assertEqual(len(refl), self.asd_file.metadata.channels)
1366
+
1367
+ def test_004_reflectanceNoDeriv(self):
1368
+ for file_path in all_asd_data_files:
1369
+ with self.subTest(file_path):
1370
+ self.asd_file.read(file_path)
1371
+ refl_no_deriv = self.asd_file.reflectanceNoDeriv
1372
+ if refl_no_deriv is not None:
1373
+ self.assertEqual(type(refl_no_deriv).__name__, 'ndarray')
1374
+
1375
+ def test_005_reflectance1stDeriv(self):
1376
+ for file_path in all_asd_data_files:
1377
+ with self.subTest(file_path):
1378
+ self.asd_file.read(file_path)
1379
+ refl_1st = self.asd_file.reflectance1stDeriv
1380
+ if refl_1st is not None:
1381
+ self.assertEqual(type(refl_1st).__name__, 'ndarray')
1382
+ self.assertEqual(len(refl_1st), self.asd_file.metadata.channels)
1383
+
1384
+ def test_006_reflectance2ndDeriv(self):
1385
+ for file_path in all_asd_data_files:
1386
+ with self.subTest(file_path):
1387
+ self.asd_file.read(file_path)
1388
+ refl_2nd = self.asd_file.reflectance2ndDeriv
1389
+ if refl_2nd is not None:
1390
+ self.assertEqual(type(refl_2nd).__name__, 'ndarray')
1391
+ self.assertEqual(len(refl_2nd), self.asd_file.metadata.channels)
1392
+
1393
+ def test_007_reflectance3rdDeriv(self):
1394
+ for file_path in all_asd_data_files:
1395
+ with self.subTest(file_path):
1396
+ self.asd_file.read(file_path)
1397
+ refl_3rd = self.asd_file.reflectance3rdDeriv
1398
+ if refl_3rd is not None:
1399
+ self.assertEqual(type(refl_3rd).__name__, 'ndarray')
1400
+ self.assertEqual(len(refl_3rd), self.asd_file.metadata.channels)
1401
+
1402
+ def test_008_log1R(self):
1403
+ for file_path in all_asd_data_files:
1404
+ with self.subTest(file_path):
1405
+ self.asd_file.read(file_path)
1406
+ log1r = self.asd_file.log1R
1407
+ if log1r is not None:
1408
+ self.assertEqual(type(log1r).__name__, 'ndarray')
1409
+ self.assertEqual(len(log1r), self.asd_file.metadata.channels)
1410
+
1411
+ def test_009_log1RNoDeriv(self):
1412
+ for file_path in all_asd_data_files:
1413
+ with self.subTest(file_path):
1414
+ self.asd_file.read(file_path)
1415
+ log1r_no_deriv = self.asd_file.log1RNoDeriv
1416
+ if log1r_no_deriv is not None:
1417
+ self.assertEqual(type(log1r_no_deriv).__name__, 'ndarray')
1418
+
1419
+ def test_010_log1R1stDeriv(self):
1420
+ for file_path in all_asd_data_files:
1421
+ with self.subTest(file_path):
1422
+ self.asd_file.read(file_path)
1423
+ log1r_1st = self.asd_file.log1R1stDeriv
1424
+ if log1r_1st is not None:
1425
+ self.assertEqual(type(log1r_1st).__name__, 'ndarray')
1426
+ self.assertEqual(len(log1r_1st), self.asd_file.metadata.channels)
1427
+
1428
+ def test_011_log1R2ndDeriv(self):
1429
+ for file_path in all_asd_data_files:
1430
+ with self.subTest(file_path):
1431
+ self.asd_file.read(file_path)
1432
+ log1r_2nd = self.asd_file.log1R2ndDeriv
1433
+ if log1r_2nd is not None:
1434
+ self.assertEqual(type(log1r_2nd).__name__, 'ndarray')
1435
+ self.assertEqual(len(log1r_2nd), self.asd_file.metadata.channels)
1436
+
1437
+ def test_012_absoluteReflectance(self):
1438
+ for file_path in all_asd_data_files:
1439
+ with self.subTest(file_path):
1440
+ self.asd_file.read(file_path)
1441
+ if self.asd_file.calibrationSeriesABS is not None and self.asd_file.reflectance is not None:
1442
+ abs_refl = self.asd_file.absoluteReflectance
1443
+ if abs_refl is not None:
1444
+ self.assertEqual(type(abs_refl).__name__, 'ndarray')
1445
+ self.assertEqual(len(abs_refl), self.asd_file.metadata.channels)
1446
+
1447
+
1301
1448
  if __name__ == '__main__':
1302
1449
  unittest.main(exit=False)
@@ -0,0 +1,137 @@
1
+ """
2
+ Requirements:
3
+ This module contains tests for the FileAttributes class in the file_attributes module.
4
+ """
5
+
6
+ import os
7
+ import unittest
8
+ import tempfile
9
+ from pyASDReader.file_attributes import FileAttributes
10
+ from .test_data import all_asd_data_files
11
+
12
+
13
+ class TestFileAttributes(unittest.TestCase):
14
+
15
+ def setUp(self):
16
+ if len(all_asd_data_files) > 0:
17
+ self.test_file_path = all_asd_data_files[0]
18
+ else:
19
+ self.test_file_path = None
20
+ self.temp_file = None
21
+
22
+ def tearDown(self):
23
+ if self.temp_file and os.path.exists(self.temp_file):
24
+ os.remove(self.temp_file)
25
+
26
+ def test_001_init_with_valid_file(self):
27
+ if self.test_file_path:
28
+ file_attr = FileAttributes(self.test_file_path)
29
+ self.assertIsNotNone(file_attr)
30
+ self.assertEqual(file_attr.filepath, self.test_file_path)
31
+ self.assertIsNotNone(file_attr.filename)
32
+ self.assertIsNotNone(file_attr.filesize)
33
+ self.assertIsNotNone(file_attr.filetype)
34
+
35
+ def test_002_init_with_invalid_file(self):
36
+ with self.assertRaises(FileNotFoundError):
37
+ FileAttributes("non_existent_file.txt")
38
+
39
+ def test_003_read_method(self):
40
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt', encoding='utf-8') as f:
41
+ self.temp_file = f.name
42
+ test_content = "test content for reading"
43
+ f.write(test_content)
44
+
45
+ file_attr = FileAttributes(self.temp_file)
46
+ content = file_attr.read()
47
+ self.assertIsNotNone(content)
48
+ self.assertEqual(content, test_content)
49
+
50
+ def test_004_write_method(self):
51
+ if self.test_file_path:
52
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
53
+ self.temp_file = f.name
54
+ f.write("test content")
55
+
56
+ file_attr = FileAttributes(self.temp_file)
57
+ new_content = "new test content"
58
+ file_attr.write(new_content)
59
+
60
+ with open(self.temp_file, 'r', encoding='utf-8') as f:
61
+ content = f.read()
62
+ self.assertEqual(content, new_content)
63
+
64
+ def test_005_delete_method(self):
65
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
66
+ temp_path = f.name
67
+ f.write("test content")
68
+
69
+ file_attr = FileAttributes(temp_path)
70
+ self.assertTrue(os.path.exists(temp_path))
71
+ file_attr.delete()
72
+ self.assertFalse(os.path.exists(temp_path))
73
+
74
+ def test_006_delete_nonexistent_file(self):
75
+ with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as f:
76
+ temp_path = f.name
77
+ f.write("test content")
78
+
79
+ file_attr = FileAttributes(temp_path)
80
+ os.remove(temp_path)
81
+
82
+ with self.assertRaises(FileNotFoundError):
83
+ file_attr.delete()
84
+
85
+ def test_007_hashMD5_property(self):
86
+ if self.test_file_path:
87
+ file_attr = FileAttributes(self.test_file_path)
88
+ hash_md5 = file_attr.hashMD5
89
+ self.assertIsNotNone(hash_md5)
90
+ self.assertEqual(type(hash_md5), str)
91
+ self.assertEqual(len(hash_md5), 32)
92
+
93
+ def test_008_hashSHA265_property(self):
94
+ if self.test_file_path:
95
+ file_attr = FileAttributes(self.test_file_path)
96
+ hash_sha256 = file_attr.hashSHA265
97
+ self.assertIsNotNone(hash_sha256)
98
+ self.assertEqual(type(hash_sha256), str)
99
+ self.assertEqual(len(hash_sha256), 64)
100
+
101
+ def test_009_str_method(self):
102
+ if self.test_file_path:
103
+ file_attr = FileAttributes(self.test_file_path)
104
+ str_repr = str(file_attr)
105
+ self.assertIsNotNone(str_repr)
106
+ self.assertIn(file_attr.filename, str_repr)
107
+ self.assertIn(file_attr.filepath, str_repr)
108
+ self.assertIn("MD5", str_repr)
109
+ self.assertIn("SHA265", str_repr)
110
+
111
+ def test_010_set_file_name(self):
112
+ if self.test_file_path:
113
+ file_attr = FileAttributes(self.test_file_path)
114
+ new_name = "new_filename.asd"
115
+ file_attr.set_file_name(new_name)
116
+ self.assertEqual(os.path.basename(file_attr.filepath), new_name)
117
+
118
+ def test_011_set_file_path(self):
119
+ if self.test_file_path:
120
+ file_attr = FileAttributes(self.test_file_path)
121
+ new_path = "/tmp/new_path/test.asd"
122
+ file_attr.set_file_path(new_path)
123
+ self.assertEqual(file_attr.filepath, new_path)
124
+ self.assertEqual(file_attr.filename, "test.asd")
125
+
126
+ def test_012_file_attributes(self):
127
+ if self.test_file_path:
128
+ file_attr = FileAttributes(self.test_file_path)
129
+ self.assertIsNotNone(file_attr.creation_time)
130
+ self.assertIsNotNone(file_attr.modification_time)
131
+ self.assertIsNotNone(file_attr.access_time)
132
+ self.assertIsNotNone(file_attr.file_permission)
133
+ self.assertIsNotNone(file_attr.dirname)
134
+
135
+
136
+ if __name__ == '__main__':
137
+ unittest.main(exit=False)
@@ -1,22 +0,0 @@
1
- cff-version: 1.2.0
2
- message: "If you use this software, please cite it as below."
3
- type: software
4
- title: "pyASDReader: A Python Library for ASD Spectral File Reading"
5
- authors:
6
- - family-names: Cao
7
- given-names: Kai
8
- email: caokai_cgs@163.com
9
- orcid: https://orcid.org/0000-0000-0000-0000
10
- repository-code: "https://github.com/KaiTastic/pyASDReader"
11
- url: "https://github.com/KaiTastic/pyASDReader"
12
- abstract: "A Python library for reading and parsing all versions (v1-v8) of ASD (Analytical Spectral Devices) binary spectral files from various instruments including FieldSpec, LabSpec, and TerraSpec spectroradiometers."
13
- keywords:
14
- - ASD
15
- - spectral files
16
- - spectroradiometer
17
- - remote sensing
18
- - hyperspectral
19
- - FieldSpec
20
- license: MIT
21
- version: 1.0.0
22
- date-released: 2025-03-12
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes