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.
- pyasdreader-1.2.2/.codecov.yml +68 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/CHANGELOG.md +54 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/PKG-INFO +8 -66
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/README.md +7 -65
- pyasdreader-1.2.2/coverage.json +1 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/pyASDReader.egg-info/SOURCES.txt +3 -1
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/asd_file_reader.py +6 -1
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/file_attributes.py +5 -5
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/test_asd_file_reader.py +174 -27
- pyasdreader-1.2.2/tests/test_file_attributes.py +137 -0
- pyasdreader-1.2.1/CITATION.cff +0 -22
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/.pre-commit-config.yaml +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/LICENSE +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/MANIFEST.in +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/VERSION_MANAGEMENT.md +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/examples/README.md +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/examples/basic_usage.py +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/pyproject.toml +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/scripts/publish.sh +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/setup.cfg +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/__init__.py +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/_version.py +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/constant.py +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/src/logger_setup.py +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/__init__.py +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v6sample/v6sample00000.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v6sample/v6sample00001.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v6sample/v6sample00002.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00000.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00001.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00002.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00003.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00004.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample/v7sample00005.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample_field_spectroscopy/44231B009-1-FW300000.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample_field_spectroscopy/44231B009-1-FW3R00000.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v7sample_field_spectroscopy/44231B174-1-FF300000.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v8sample/v8sample00001.asd +0 -0
- {pyasdreader-1.2.1 → pyasdreader-1.2.2}/tests/sample_data/v8sample/v8sample00002.asd +0 -0
- {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.
|
|
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
|
[](https://pypi.org/project/pyASDReader/)
|
|
87
87
|
[](https://pypi.org/project/pyASDReader/)
|
|
88
88
|
[](https://github.com/KaiTastic/pyASDReader/blob/main/LICENSE)
|
|
89
|
-
[](https://github.com/KaiTastic/pyASDReader/actions)
|
|
90
90
|
[](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
|
|
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 = {
|
|
402
|
+
version = {1.2.1}
|
|
461
403
|
}
|
|
462
404
|
```
|
|
463
405
|
|
|
464
406
|
**Plain text citation**:
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
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
|
-
##
|
|
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
|
[](https://pypi.org/project/pyASDReader/)
|
|
4
4
|
[](https://pypi.org/project/pyASDReader/)
|
|
5
5
|
[](https://github.com/KaiTastic/pyASDReader/blob/main/LICENSE)
|
|
6
|
-
[](https://github.com/KaiTastic/pyASDReader/actions)
|
|
7
7
|
[](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
|
|
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 = {
|
|
319
|
+
version = {1.2.1}
|
|
378
320
|
}
|
|
379
321
|
```
|
|
380
322
|
|
|
381
323
|
**Plain text citation**:
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
##
|
|
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(
|
|
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.
|
|
82
|
-
self.
|
|
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.
|
|
86
|
-
self.
|
|
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(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
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)
|
pyasdreader-1.2.1/CITATION.cff
DELETED
|
@@ -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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|