solarwindpy 0.0.1.dev0__py3-none-any.whl → 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of solarwindpy might be problematic. Click here for more details.
- plans/.velocity/metrics.json +96 -0
- plans/0-overview-template.md +268 -0
- plans/N-phase-template.md +106 -0
- plans/PLAN_AUDIT_SUMMARY.md +173 -0
- plans/TEMPLATE-USAGE-GUIDE.md +198 -0
- plans/__init__.py +1 -0
- plans/abandoned/compaction-agent-system/0-Overview.md +123 -0
- plans/abandoned/compaction-agent-system/agents-index-update-plan.md +109 -0
- plans/abandoned/compaction-agent-system/compacted_state.md +85 -0
- plans/abandoned/compaction-agent-system/implementation-plan.md +107 -0
- plans/abandoned/compaction-agent-system/system-validation-report.md +159 -0
- plans/abandoned/compaction-agent-system/usage-guide.md +210 -0
- plans/abandoned/hook-system-enhancement/0-Overview.md +214 -0
- plans/abandoned/hook-system-enhancement/1-Phase1-Core-Infrastructure.md +313 -0
- plans/abandoned/hook-system-enhancement/2-Phase2-Intelligent-Testing.md +385 -0
- plans/abandoned/hook-system-enhancement/3-Phase3-Physics-Validation.md +444 -0
- plans/abandoned/hook-system-enhancement/4-Phase4-Performance-Monitoring.md +458 -0
- plans/abandoned/hook-system-enhancement/5-Phase5-Developer-Experience.md +532 -0
- plans/abandoned/hook-system-enhancement/6-Implementation-Timeline.md +274 -0
- plans/abandoned/hook-system-enhancement/7-Risk-Management.md +376 -0
- plans/abandoned/hook-system-enhancement/8-Testing-Strategy.md +579 -0
- plans/abandoned/readthedocs-automation/0-Overview.md +247 -0
- plans/abandoned/readthedocs-automation/1-Emergency-Documentation-Fixes.md +270 -0
- plans/abandoned/readthedocs-automation/2-Template-System-Enhancement.md +811 -0
- plans/abandoned/readthedocs-automation/3-Quality-Audit-ReadTheDocs-Integration.md +844 -0
- plans/abandoned/readthedocs-automation/4-Plan-Consolidation-Cleanup.md +632 -0
- plans/abandoned/readthedocs-automation/9-Closeout.md +207 -0
- plans/abandoned/readthedocs-automation/ABANDONMENT_REASON.md +72 -0
- plans/cicd-architecture-redesign/0-Overview.md +193 -0
- plans/cicd-architecture-redesign/1-Workflow-Creation.md +103 -0
- plans/cicd-architecture-redesign/2-Version-Detection.md +123 -0
- plans/cicd-architecture-redesign/3-Deployment-Gates.md +169 -0
- plans/cicd-architecture-redesign/4-RC-Testing.md +194 -0
- plans/cicd-architecture-redesign/5-TestPyPI-Validation.md +264 -0
- plans/cicd-architecture-redesign/6-Production-Release.md +263 -0
- plans/cicd-architecture-redesign/7-Cleanup.md +243 -0
- plans/cicd-architecture-redesign/8-Documentation.md +285 -0
- plans/cicd-architecture-redesign/Closeout.md +225 -0
- plans/closeout-template.md +259 -0
- plans/completed/circular-import-audit/0-Overview.md +152 -0
- plans/completed/circular-import-audit/1-Static-Dependency-Analysis.md +62 -0
- plans/completed/circular-import-audit/2-Dynamic-Import-Testing.md +56 -0
- plans/completed/circular-import-audit/3-Performance-Impact-Assessment.md +56 -0
- plans/completed/circular-import-audit/4-Issue-Remediation.md +78 -0
- plans/completed/circular-import-audit/5-Preventive-Infrastructure.md +89 -0
- plans/completed/claude-settings-ecosystem-alignment/0-Overview.md +162 -0
- plans/completed/claude-settings-ecosystem-alignment/1-Security-Foundation.md +148 -0
- plans/completed/claude-settings-ecosystem-alignment/2-Hook-Integration.md +158 -0
- plans/completed/claude-settings-ecosystem-alignment/3-Agent-System-Integration.md +177 -0
- plans/completed/claude-settings-ecosystem-alignment/4-Enhanced-Workflow-Automation.md +159 -0
- plans/completed/claude-settings-ecosystem-alignment/5-Validation-Monitoring.md +181 -0
- plans/completed/claude-settings-ecosystem-alignment/compacted_session_state.md +290 -0
- plans/completed/combined_plan_with_checklist_documentation/1-Overview-and-Goals.md +51 -0
- plans/completed/combined_plan_with_checklist_documentation/2-Toolchain-and-Hosting.md +69 -0
- plans/completed/combined_plan_with_checklist_documentation/3-Repository-Structure.md +61 -0
- plans/completed/combined_plan_with_checklist_documentation/4-Configuration-and-Standards.md +70 -0
- plans/completed/combined_plan_with_checklist_documentation/5-Documentation-Content.md +62 -0
- plans/completed/combined_plan_with_checklist_documentation/6-CI-CD-and-Validation.md +58 -0
- plans/completed/combined_plan_with_checklist_documentation/7-Maintenance.md +55 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/0-Overview.md +135 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/1-Common-fixtures.md +59 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/10-power_laws.md +56 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/2-core.py-FitFunction.md +118 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/3-gaussians.py-Gaussian-GaussianNormalized-GaussianLn.md +69 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/4-trend_fits.py-TrendFit.md +99 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/5-plots.py-FFPlot.md +98 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/6-tex_info.py-TeXinfo.md +79 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/7-Justification.md +49 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/8-exponentials.md +64 -0
- plans/completed/combined_test_plan_with_checklist_fitfunctions/9-lines.md +58 -0
- plans/completed/combined_test_plan_with_checklist_plotting/0-Overview.md +142 -0
- plans/completed/combined_test_plan_with_checklist_plotting/1-base.py.md +90 -0
- plans/completed/combined_test_plan_with_checklist_plotting/10-labels-special.py.md +102 -0
- plans/completed/combined_test_plan_with_checklist_plotting/11-labels-chemistry.py.md +212 -0
- plans/completed/combined_test_plan_with_checklist_plotting/12-labels-composition.py.md +242 -0
- plans/completed/combined_test_plan_with_checklist_plotting/13-labels-datetime.py.md +247 -0
- plans/completed/combined_test_plan_with_checklist_plotting/14-labels-elemental_abundance.py.md +274 -0
- plans/completed/combined_test_plan_with_checklist_plotting/15-visual-validation.md +256 -0
- plans/completed/combined_test_plan_with_checklist_plotting/16-integration-testing.md +266 -0
- plans/completed/combined_test_plan_with_checklist_plotting/17-performance-benchmarks.md +267 -0
- plans/completed/combined_test_plan_with_checklist_plotting/18-Fixtures-and-Utilities.md +86 -0
- plans/completed/combined_test_plan_with_checklist_plotting/2-agg_plot.py.md +90 -0
- plans/completed/combined_test_plan_with_checklist_plotting/3-histograms.py.md +201 -0
- plans/completed/combined_test_plan_with_checklist_plotting/4-scatter.py.md +167 -0
- plans/completed/combined_test_plan_with_checklist_plotting/5-spiral.py.md +216 -0
- plans/completed/combined_test_plan_with_checklist_plotting/6-orbits.py.md +108 -0
- plans/completed/combined_test_plan_with_checklist_plotting/7-tools.py.md +86 -0
- plans/completed/combined_test_plan_with_checklist_plotting/8-select_data_from_figure.py.md +97 -0
- plans/completed/combined_test_plan_with_checklist_plotting/9-labels-base.py.md +88 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/.gitkeep +0 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/0-Overview.md +170 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/1-Package-Entry-Point-__init__.py.md +121 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/2-Core-Base-Classes-base.py.md +142 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/3-Plotting-Helpers-plots.py.md +123 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/4-LISIRD-Sub-package.md +119 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/5-Extrema-Calculator.md +103 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/6-Sunspot-Number-Sub-package.md +163 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/7-Sunspot-Number-Init.py.md +217 -0
- plans/completed/combined_test_plan_with_checklist_solar_activity/compacted_state.md +52 -0
- plans/completed/compaction-agent-modernization/0-Overview.md +156 -0
- plans/completed/compaction-agent-modernization/1-Architecture-Audit-Gap-Analysis.md +132 -0
- plans/completed/compaction-agent-modernization/2-Token-Baseline-Recalibration.md +153 -0
- plans/completed/compaction-agent-modernization/3-Agent-Reference-Updates.md +184 -0
- plans/completed/compaction-agent-modernization/4-Compression-Algorithm-Modernization.md +238 -0
- plans/completed/compaction-agent-modernization/5-Workflow-Integration-Streamlining.md +252 -0
- plans/completed/compaction-agent-modernization/6-Template-Structure-Optimization.md +240 -0
- plans/completed/compaction-agent-modernization/7-Integration-Testing-Validation.md +292 -0
- plans/completed/compaction-hook-enhancement/0-Overview.md +150 -0
- plans/completed/compaction-hook-enhancement/1-Token-Estimation-Enhancement.md +179 -0
- plans/completed/compaction-hook-enhancement/2-Compression-Intelligence.md +294 -0
- plans/completed/compaction-hook-enhancement/3-Git-Integration-Metadata.md +310 -0
- plans/completed/compaction-hook-enhancement/4-Session-Continuity-Features.md +358 -0
- plans/completed/compaction-hook-enhancement/5-Testing-Strategy.md +404 -0
- plans/completed/compaction-hook-enhancement/6-Integration-Roadmap.md +319 -0
- plans/completed/compaction-hook-enhancement/compacted_state.md +142 -0
- plans/completed/docstring-audit-enhancement/0-Overview.md +274 -0
- plans/completed/docstring-audit-enhancement/1-Infrastructure-Setup-and-Validation-Tools.md +206 -0
- plans/completed/docstring-audit-enhancement/2-Core-Physics-Modules-Enhancement.md +237 -0
- plans/completed/docstring-audit-enhancement/3-Fitfunctions-Mathematical-Modules-Enhancement.md +188 -0
- plans/completed/docstring-audit-enhancement/4-Plotting-Visualization-Modules-Enhancement.md +243 -0
- plans/completed/docstring-audit-enhancement/5-Specialized-Modules-Enhancement.md +216 -0
- plans/completed/docstring-audit-enhancement/6-Validation-and-Integration.md +216 -0
- plans/completed/fitfunctions-testing-implementation/0-Overview.md +130 -0
- plans/completed/fitfunctions-testing-implementation/1-Test-Infrastructure-Setup.md +79 -0
- plans/completed/fitfunctions-testing-implementation/2-Common-Fixtures-Test-Utilities.md +104 -0
- plans/completed/fitfunctions-testing-implementation/3-Core-FitFunction-Testing.md +168 -0
- plans/completed/fitfunctions-testing-implementation/4-Specialized-Function-Classes.md +210 -0
- plans/completed/fitfunctions-testing-implementation/5-Advanced-Classes-Testing.md +214 -0
- plans/completed/fitfunctions-testing-implementation/6-Plotting-Integration-Testing.md +231 -0
- plans/completed/fitfunctions-testing-implementation/7-Extended-Coverage-BONUS.md +184 -0
- plans/completed/numpy-docstring-conversion-plan/numpy-docstring-conversion-plan.md +118 -0
- plans/completed/pr-review-remediation/0-Overview.md +138 -0
- plans/completed/pr-review-remediation/1-Critical-Safety-Improvements.md +179 -0
- plans/completed/pr-review-remediation/2-Smart-Timeouts-Validation.md +399 -0
- plans/completed/pr-review-remediation/3-Enhanced-GitHub-Integration.md +258 -0
- plans/completed/pr-review-remediation/compacted_state.md +66 -0
- plans/completed/python-310-migration/0-Overview.md +390 -0
- plans/completed/python-310-migration/1-Planning-Setup.md +164 -0
- plans/completed/python-310-migration/2-Implementation.md +256 -0
- plans/completed/python-310-migration/3-Testing-Validation.md +335 -0
- plans/completed/python-310-migration/4-Documentation-Release.md +274 -0
- plans/completed/python-310-migration/5-Closeout.md +252 -0
- plans/completed/requirements-management-consolidation/0-Overview.md +118 -0
- plans/completed/requirements-management-consolidation/1-Documentation-Validation-Environment-Setup.md +116 -0
- plans/completed/requirements-management-consolidation/2-Requirements-Consolidation.md +161 -0
- plans/completed/requirements-management-consolidation/3-Workflow-Automation-Final-Integration.md +196 -0
- plans/completed/single-ecosystem-plan-implementation/0-Overview.md +83 -0
- plans/completed/single-ecosystem-plan-implementation/1-Plan-Preservation-Session-Management.md +38 -0
- plans/completed/single-ecosystem-plan-implementation/2-File-Structure-Optimization.md +43 -0
- plans/completed/single-ecosystem-plan-implementation/3-Plan-Migration-Archive-Setup.md +82 -0
- plans/completed/single-ecosystem-plan-implementation/4-Agent-System-Transformation.md +108 -0
- plans/completed/single-ecosystem-plan-implementation/5-Template-System-Enhancement.md +131 -0
- plans/completed/single-ecosystem-plan-implementation/6-Final-Validation-Testing.md +120 -0
- plans/completed/test-directory-consolidation/0-Overview.md +51 -0
- plans/completed/test-directory-consolidation/1-Structure-Preparation.md +82 -0
- plans/completed/test-directory-consolidation/2-File-Migration.md +100 -0
- plans/completed/test-directory-consolidation/3-Import-Transformation.md +117 -0
- plans/completed/test-directory-consolidation/4-Configuration-Consolidation.md +140 -0
- plans/completed/test-directory-consolidation/5-Validation.md +152 -0
- plans/completed/test-directory-consolidation/6-Cleanup.md +156 -0
- plans/completed/test-planning-agents-architecture/0-Overview.md +79 -0
- plans/completed/test-planning-agents-architecture/1-Branch-Isolation-Testing.md +49 -0
- plans/completed/test-planning-agents-architecture/2-Cross-Branch-Coordination.md +51 -0
- plans/completed/test-planning-agents-architecture/3-Merge-Workflow-Testing.md +48 -0
- plans/deployment-semver-pypi-rtd/0-Overview.md +463 -0
- plans/deployment-semver-pypi-rtd/1-Semantic-Versioning-Foundation.md +136 -0
- plans/deployment-semver-pypi-rtd/2-PyPI-Deployment-Infrastructure.md +168 -0
- plans/deployment-semver-pypi-rtd/3-Release-Automation.md +214 -0
- plans/deployment-semver-pypi-rtd/4-Plan-Closeout.md +543 -0
- plans/deployment-semver-pypi-rtd/compacted_session_state.md +172 -0
- plans/deployment-semver-pypi-rtd/compacted_state.md +131 -0
- plans/documentation-code-audit/0-Overview.md +393 -0
- plans/documentation-code-audit/1-Discovery-Inventory.md +183 -0
- plans/documentation-code-audit/2-Execution-Environment-Setup.md +263 -0
- plans/documentation-code-audit/3-Systematic-Validation.md +322 -0
- plans/documentation-code-audit/4-Code-Example-Remediation.md +358 -0
- plans/documentation-code-audit/5-Physics-MultiIndex-Compliance.md +464 -0
- plans/documentation-code-audit/6-Doctest-Integration.md +523 -0
- plans/documentation-code-audit/7-Reporting-Documentation.md +498 -0
- plans/documentation-code-audit/8-Closeout.md +456 -0
- plans/documentation-rebuild-session/compacted_state.md +109 -0
- plans/documentation-rendering-fixes/0-Overview.md +104 -0
- plans/documentation-rendering-fixes/1-Sphinx-Build-Diagnostics-Warning-Audit.md +101 -0
- plans/documentation-rendering-fixes/2-Configuration-Infrastructure-Fixes.md +113 -0
- plans/documentation-rendering-fixes/3-Docstring-Syntax-Audit-Repair.md +131 -0
- plans/documentation-rendering-fixes/4-HTML-Page-Rendering-Verification.md +113 -0
- plans/documentation-rendering-fixes/5-Advanced-Documentation-Quality-Assurance.md +119 -0
- plans/documentation-rendering-fixes/6-Documentation-Build-Optimization-Testing.md +129 -0
- plans/documentation-rendering-fixes/compacted_state.md +132 -0
- plans/documentation-template-fix/0-Overview.md +197 -0
- plans/documentation-template-fix/1-Template-System-Analysis.md +269 -0
- plans/documentation-template-fix/2-Template-Modification.md +609 -0
- plans/documentation-template-fix/3-Build-System-Integration.md +766 -0
- plans/documentation-template-fix/4-Testing-Validation.md +1399 -0
- plans/documentation-template-fix/5-Documentation-Training.md +602 -0
- plans/documentation-workflow-fix/0-Overview.md +222 -0
- plans/documentation-workflow-fix/1-Immediate-Fixes.md +238 -0
- plans/documentation-workflow-fix/2-Configuration-Setup.md +298 -0
- plans/documentation-workflow-fix/3-Pre-commit-Integration.md +382 -0
- plans/documentation-workflow-fix/4-Workflow-Improvements.md +446 -0
- plans/documentation-workflow-fix/5-Documentation-and-Training.md +527 -0
- plans/duplicate-object-warnings-fix-plan.md +130 -0
- plans/github-issues-migration/0-Overview.md +510 -0
- plans/github-issues-migration/1-Foundation-Label-System.md +180 -0
- plans/github-issues-migration/2-Migration-Tool-Rewrite.md +235 -0
- plans/github-issues-migration/3-CLI-Integration-Automation.md +169 -0
- plans/github-issues-migration/4-Validated-Migration.md +252 -0
- plans/github-issues-migration/5-Documentation-Training.md +171 -0
- plans/github-issues-migration/6-Closeout.md +179 -0
- plans/github-workflows-repair/repair-plan.md +299 -0
- plans/issues_from_plans.py +342 -0
- plans/pr-270-doc-validation-fixes/0-Overview.md +354 -0
- plans/pr-270-doc-validation-fixes/1-Critical-PR-Fixes.md +117 -0
- plans/pr-270-doc-validation-fixes/2-Framework-Right-Sizing.md +129 -0
- plans/pr-270-doc-validation-fixes/3-Sustainable-Documentation.md +126 -0
- plans/pr-270-doc-validation-fixes/4-Closeout-Migration.md +143 -0
- plans/pr-270-doc-validation-fixes/PLAN_COMPLETED.md +149 -0
- plans/python-310-migration/0-Overview.md +390 -0
- plans/python-310-migration/1-Planning-Setup.md +164 -0
- plans/python-310-migration/2-Implementation.md +256 -0
- plans/python-310-migration/3-Testing-Validation.md +335 -0
- plans/python-310-migration/4-Documentation-Release.md +274 -0
- plans/python-310-migration/5-Closeout.md +252 -0
- plans/readthedocs-simplified/0-Overview.md +243 -0
- plans/readthedocs-simplified/1-Immediate-Fixes.md +216 -0
- plans/readthedocs-simplified/2-Template-Simplification.md +278 -0
- plans/readthedocs-simplified/3-ReadTheDocs-Setup.md +298 -0
- plans/readthedocs-simplified/4-Testing-Validation.md +328 -0
- plans/readthedocs-simplified/5-Closeout.md +231 -0
- plans/readthedocs-simplified/compacted_state.md +127 -0
- plans/session-compaction-2025-08-12/compacted_state.md +114 -0
- plans/session-compaction-2025-08-13/compacted_state.md +145 -0
- plans/session-continuity-protocol/0-Overview.md +35 -0
- plans/session-continuity-protocol/1-Core-Principles-Framework.md +40 -0
- plans/session-continuity-protocol/2-Pre-Session-Validation-System.md +79 -0
- plans/session-continuity-protocol/3-Context-Switching-Prevention.md +87 -0
- plans/session-continuity-protocol/4-Progress-Tracking-Recovery.md +100 -0
- plans/sphinx-warnings-analysis.md +222 -0
- plans/systemprompt-optimization/0-Overview.md +447 -0
- plans/systemprompt-optimization/1-Deploy-SystemPrompt.md +114 -0
- plans/systemprompt-optimization/2-Documentation-Alignment.md +198 -0
- plans/systemprompt-optimization/3-Monitoring-Infrastructure.md +396 -0
- plans/systemprompt-optimization/4-Implementation-Script.md +450 -0
- plans/systemprompt-optimization/9-Closeout.md +165 -0
- plans/systemprompt-optimization/compacted_state.md +143 -0
- plans/template-value-propositions/0-Overview.md +357 -0
- plans/template-value-propositions/1-Value-Proposition-Framework-Design.md +144 -0
- plans/template-value-propositions/2-Plan-Template-Enhancement.md +178 -0
- plans/template-value-propositions/3-Value-Generator-Hook-Implementation.md +291 -0
- plans/template-value-propositions/4-Value-Validator-Hook-Implementation.md +274 -0
- plans/template-value-propositions/5-Documentation-Agent-Updates.md +219 -0
- plans/template-value-propositions/6-Integration-Testing-Validation.md +247 -0
- plans/tests-audit/0-Overview.md +410 -0
- plans/tests-audit/1-Discovery-Inventory.md +170 -0
- plans/tests-audit/2-Physics-Validation-Audit.md +195 -0
- plans/tests-audit/3-Architecture-Compliance.md +195 -0
- plans/tests-audit/4-Numerical-Stability-Analysis.md +203 -0
- plans/tests-audit/5-Documentation-Enhancement.md +220 -0
- plans/tests-audit/6-Audit-Deliverables.md +220 -0
- plans/tests-audit/7-Closeout.md +252 -0
- plans/tests-audit/artifacts/ARCHITECTURE_COMPLIANCE_REPORT.md +315 -0
- plans/tests-audit/artifacts/ARCHITECTURE_RECOMMENDATIONS.md +943 -0
- plans/tests-audit/artifacts/COMPREHENSIVE_AUDIT_REPORT.md +356 -0
- plans/tests-audit/artifacts/CONTRIBUTING_ENHANCED_TEMPLATE.md +419 -0
- plans/tests-audit/artifacts/COVERAGE_GAP_ANALYSIS.md +152 -0
- plans/tests-audit/artifacts/DOCUMENTATION_ENHANCEMENT_REPORT.md +502 -0
- plans/tests-audit/artifacts/EXECUTIVE_AUDIT_SUMMARY.md +129 -0
- plans/tests-audit/artifacts/IMPLEMENTATION_ROADMAP.md +647 -0
- plans/tests-audit/artifacts/NUMERICAL_RECOMMENDATIONS.md +739 -0
- plans/tests-audit/artifacts/NUMERICAL_STABILITY_GUIDE_TEMPLATE.rst +451 -0
- plans/tests-audit/artifacts/NUMERICAL_STABILITY_REPORT.md +301 -0
- plans/tests-audit/artifacts/PHASE_3_SUMMARY.md +280 -0
- plans/tests-audit/artifacts/PHASE_4_SUMMARY.md +229 -0
- plans/tests-audit/artifacts/PHASE_5_SUMMARY.md +292 -0
- plans/tests-audit/artifacts/PHASE_6_CLOSEOUT.md +278 -0
- plans/tests-audit/artifacts/PHYSICS_GUIDE_TEMPLATE.rst +268 -0
- plans/tests-audit/artifacts/PHYSICS_VALIDATION_REPORT.md +235 -0
- plans/tests-audit/artifacts/TECHNICAL_DELIVERABLES_PACKAGE.md +2502 -0
- plans/tests-audit/artifacts/TEST_INVENTORY.csv +1204 -0
- plans/tests-audit/artifacts/TEST_INVENTORY.md +135 -0
- plans/tests-audit/artifacts/test_discovery_analysis.py +231 -0
- plans/tests-audit/artifacts/test_parser.py +395 -0
- solarwindpy/README.md +3 -0
- solarwindpy/Untitled.ipynb +54 -0
- solarwindpy/__init__.py +74 -0
- solarwindpy/core/__init__.py +23 -0
- solarwindpy/core/alfvenic_turbulence.py +804 -0
- solarwindpy/core/base.py +267 -0
- solarwindpy/core/ions.py +309 -0
- solarwindpy/core/plasma.py +2133 -0
- solarwindpy/core/spacecraft.py +256 -0
- solarwindpy/core/tensor.py +90 -0
- solarwindpy/core/units_constants.py +199 -0
- solarwindpy/core/vector.py +328 -0
- solarwindpy/fitfunctions/__init__.py +20 -0
- solarwindpy/fitfunctions/core.py +734 -0
- solarwindpy/fitfunctions/exponentials.py +188 -0
- solarwindpy/fitfunctions/gaussians.py +264 -0
- solarwindpy/fitfunctions/lines.py +116 -0
- solarwindpy/fitfunctions/moyal.py +71 -0
- solarwindpy/fitfunctions/plots.py +751 -0
- solarwindpy/fitfunctions/power_laws.py +209 -0
- solarwindpy/fitfunctions/tex_info.py +568 -0
- solarwindpy/fitfunctions/trend_fits.py +482 -0
- solarwindpy/instabilities/__init__.py +16 -0
- solarwindpy/instabilities/beta_ani.py +82 -0
- solarwindpy/instabilities/verscharen2016.py +631 -0
- solarwindpy/plotting/__init__.py +33 -0
- solarwindpy/plotting/agg_plot.py +489 -0
- solarwindpy/plotting/base.py +465 -0
- solarwindpy/plotting/hist1d.py +405 -0
- solarwindpy/plotting/hist2d.py +1035 -0
- solarwindpy/plotting/histograms.py +1845 -0
- solarwindpy/plotting/labels/__init__.py +104 -0
- solarwindpy/plotting/labels/base.py +686 -0
- solarwindpy/plotting/labels/chemistry.py +19 -0
- solarwindpy/plotting/labels/composition.py +100 -0
- solarwindpy/plotting/labels/datetime.py +235 -0
- solarwindpy/plotting/labels/elemental_abundance.py +73 -0
- solarwindpy/plotting/labels/special.py +794 -0
- solarwindpy/plotting/orbits.py +515 -0
- solarwindpy/plotting/scatter.py +99 -0
- solarwindpy/plotting/select_data_from_figure.py +329 -0
- solarwindpy/plotting/spiral.py +980 -0
- solarwindpy/plotting/tools.py +434 -0
- solarwindpy/scripts/__init__.py +1 -0
- solarwindpy/scripts/logs/.gitignore +1 -0
- solarwindpy/solar_activity/__init__.py +53 -0
- solarwindpy/solar_activity/base.py +605 -0
- solarwindpy/solar_activity/lisird/__init__.py +3 -0
- solarwindpy/solar_activity/lisird/extrema_calculator.py +394 -0
- solarwindpy/solar_activity/lisird/lisird.py +319 -0
- solarwindpy/solar_activity/plots.py +116 -0
- solarwindpy/solar_activity/sunspot_number/.DS_Store +0 -0
- solarwindpy/solar_activity/sunspot_number/__init__.py +3 -0
- solarwindpy/solar_activity/sunspot_number/sidc.py +556 -0
- solarwindpy/solar_activity/sunspot_number/ssn_extrema.csv +72 -0
- solarwindpy/solar_activity/sunspot_number/ssn_extrema.csv.silso +72 -0
- solarwindpy/tools/__init__.py +162 -0
- solarwindpy-0.1.1.dist-info/METADATA +181 -0
- solarwindpy-0.1.1.dist-info/RECORD +409 -0
- {solarwindpy-0.0.1.dev0.dist-info → solarwindpy-0.1.1.dist-info}/WHEEL +1 -1
- solarwindpy-0.1.1.dist-info/licenses/LICENSE.rst +32 -0
- solarwindpy-0.1.1.dist-info/top_level.txt +3 -0
- tests/__init__.py +1 -0
- tests/conftest.py +10 -0
- tests/core/__init__.py +1 -0
- tests/core/test_alfvenic_turbulence.py +544 -0
- tests/core/test_base.py +112 -0
- tests/core/test_base_head_tail.py +29 -0
- tests/core/test_base_mi_tuples.py +11 -0
- tests/core/test_core_verify_datetimeindex.py +32 -0
- tests/core/test_ions.py +325 -0
- tests/core/test_plasma.py +2581 -0
- tests/core/test_plasma_io.py +12 -0
- tests/core/test_quantities.py +507 -0
- tests/core/test_spacecraft.py +210 -0
- tests/core/test_units_constants.py +22 -0
- tests/data/epoch.csv +4 -0
- tests/data/plasma.csv +4 -0
- tests/data/spacecraft.csv +4 -0
- tests/fitfunctions/conftest.py +60 -0
- tests/fitfunctions/test_core.py +193 -0
- tests/fitfunctions/test_exponentials.py +342 -0
- tests/fitfunctions/test_gaussians.py +142 -0
- tests/fitfunctions/test_lines.py +349 -0
- tests/fitfunctions/test_moyal.py +258 -0
- tests/fitfunctions/test_plots.py +258 -0
- tests/fitfunctions/test_power_laws.py +365 -0
- tests/fitfunctions/test_tex_info.py +183 -0
- tests/fitfunctions/test_trend_fit_properties.py +31 -0
- tests/fitfunctions/test_trend_fits.py +244 -0
- tests/plotting/__init__.py +1 -0
- tests/plotting/labels/__init__.py +1 -0
- tests/plotting/labels/test_chemistry.py +243 -0
- tests/plotting/labels/test_composition.py +345 -0
- tests/plotting/labels/test_datetime.py +445 -0
- tests/plotting/labels/test_elemental_abundance.py +366 -0
- tests/plotting/labels/test_init.py +66 -0
- tests/plotting/labels/test_labels_base.py +347 -0
- tests/plotting/labels/test_special.py +550 -0
- tests/plotting/test_agg_plot.py +602 -0
- tests/plotting/test_base.py +752 -0
- tests/plotting/test_fixtures_utilities.py +775 -0
- tests/plotting/test_histograms.py +546 -0
- tests/plotting/test_integration.py +675 -0
- tests/plotting/test_orbits.py +435 -0
- tests/plotting/test_performance.py +708 -0
- tests/plotting/test_scatter.py +752 -0
- tests/plotting/test_select_data_from_figure.py +1209 -0
- tests/plotting/test_spiral.py +573 -0
- tests/plotting/test_tools.py +607 -0
- tests/plotting/test_visual_validation.py +465 -0
- tests/solar_activity/__init__.py +1 -0
- tests/solar_activity/lisird/__init__.py +1 -0
- tests/solar_activity/lisird/test_extrema_calculator.py +593 -0
- tests/solar_activity/lisird/test_lisird_id.py +187 -0
- tests/solar_activity/sunspot_number/__init__.py +1 -0
- tests/solar_activity/sunspot_number/test_init.py +399 -0
- tests/solar_activity/sunspot_number/test_sidc.py +465 -0
- tests/solar_activity/sunspot_number/test_sidc_id.py +223 -0
- tests/solar_activity/sunspot_number/test_sidc_loader.py +275 -0
- tests/solar_activity/sunspot_number/test_ssn_extrema.py +406 -0
- tests/solar_activity/test_base.py +656 -0
- tests/solar_activity/test_init.py +396 -0
- tests/solar_activity/test_plots.py +371 -0
- tests/test_circular_imports.py +408 -0
- tests/test_issue_titles.py +25 -0
- tests/test_statusline.py +298 -0
- solarwindpy-0.0.1.dev0.dist-info/METADATA +0 -14
- solarwindpy-0.0.1.dev0.dist-info/RECORD +0 -4
- solarwindpy-0.0.1.dev0.dist-info/top_level.txt +0 -1
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
"""Tests for :mod:`solarwindpy.plotting.labels.chemistry` constants."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from solarwindpy.plotting.labels import chemistry
|
|
8
|
+
from solarwindpy.plotting.labels.special import ManualLabel
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.parametrize(
|
|
12
|
+
"label, expected_tex, expected_unit, expected_path",
|
|
13
|
+
[
|
|
14
|
+
(
|
|
15
|
+
chemistry.mass_per_charge,
|
|
16
|
+
r"\mathrm{M/Q}",
|
|
17
|
+
r"\mathrm{AMU \, e^{-1}}",
|
|
18
|
+
Path("M-OV-Q"),
|
|
19
|
+
),
|
|
20
|
+
(
|
|
21
|
+
chemistry.fip,
|
|
22
|
+
r"\mathrm{FIP}",
|
|
23
|
+
r"\mathrm{eV}",
|
|
24
|
+
Path("FIP"),
|
|
25
|
+
),
|
|
26
|
+
(
|
|
27
|
+
chemistry.charge,
|
|
28
|
+
r"\mathrm{Q}",
|
|
29
|
+
r"\mathrm{e}",
|
|
30
|
+
Path("IonCharge"),
|
|
31
|
+
),
|
|
32
|
+
(
|
|
33
|
+
chemistry.mass,
|
|
34
|
+
r"\mathrm{M}",
|
|
35
|
+
r"\mathrm{AMU}",
|
|
36
|
+
Path("IonMass"),
|
|
37
|
+
),
|
|
38
|
+
],
|
|
39
|
+
)
|
|
40
|
+
def test_manual_label_attributes(label, expected_tex, expected_unit, expected_path):
|
|
41
|
+
"""Ensure each ``ManualLabel`` exposes the correct values."""
|
|
42
|
+
|
|
43
|
+
assert label.tex == expected_tex
|
|
44
|
+
assert label.unit == expected_unit
|
|
45
|
+
assert label.path == expected_path
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class TestChemistryLabels:
|
|
49
|
+
"""Test chemistry label constants comprehensively."""
|
|
50
|
+
|
|
51
|
+
def test_all_labels_are_manual_labels(self):
|
|
52
|
+
"""Test that all chemistry labels are ManualLabel instances."""
|
|
53
|
+
labels = [
|
|
54
|
+
chemistry.mass_per_charge,
|
|
55
|
+
chemistry.fip,
|
|
56
|
+
chemistry.charge,
|
|
57
|
+
chemistry.mass,
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
for label in labels:
|
|
61
|
+
assert isinstance(label, ManualLabel)
|
|
62
|
+
|
|
63
|
+
def test_mass_per_charge_properties(self):
|
|
64
|
+
"""Test mass per charge label properties."""
|
|
65
|
+
label = chemistry.mass_per_charge
|
|
66
|
+
assert "M/Q" in label.tex
|
|
67
|
+
assert "AMU" in label.unit
|
|
68
|
+
assert "e^{-1}" in label.unit
|
|
69
|
+
assert str(label.path) == "M-OV-Q"
|
|
70
|
+
|
|
71
|
+
def test_fip_properties(self):
|
|
72
|
+
"""Test First Ionization Potential label properties."""
|
|
73
|
+
label = chemistry.fip
|
|
74
|
+
assert "FIP" in label.tex
|
|
75
|
+
assert "eV" in label.unit
|
|
76
|
+
assert str(label.path) == "FIP"
|
|
77
|
+
|
|
78
|
+
def test_charge_properties(self):
|
|
79
|
+
"""Test ion charge label properties."""
|
|
80
|
+
label = chemistry.charge
|
|
81
|
+
assert "Q" in label.tex
|
|
82
|
+
assert "e" in label.unit
|
|
83
|
+
assert str(label.path) == "IonCharge"
|
|
84
|
+
|
|
85
|
+
def test_mass_properties(self):
|
|
86
|
+
"""Test ion mass label properties."""
|
|
87
|
+
label = chemistry.mass
|
|
88
|
+
assert "M" in label.tex
|
|
89
|
+
assert "AMU" in label.unit
|
|
90
|
+
assert str(label.path) == "IonMass"
|
|
91
|
+
|
|
92
|
+
def test_string_representation(self):
|
|
93
|
+
"""Test string representations of chemistry labels."""
|
|
94
|
+
labels = [
|
|
95
|
+
chemistry.mass_per_charge,
|
|
96
|
+
chemistry.fip,
|
|
97
|
+
chemistry.charge,
|
|
98
|
+
chemistry.mass,
|
|
99
|
+
]
|
|
100
|
+
|
|
101
|
+
for label in labels:
|
|
102
|
+
str_repr = str(label)
|
|
103
|
+
assert str_repr.startswith("$")
|
|
104
|
+
assert str_repr.endswith("$")
|
|
105
|
+
assert "[" in str_repr # Units are included
|
|
106
|
+
assert "]" in str_repr
|
|
107
|
+
|
|
108
|
+
def test_label_uniqueness(self):
|
|
109
|
+
"""Test that all labels have unique tex, units, and paths."""
|
|
110
|
+
labels = [
|
|
111
|
+
chemistry.mass_per_charge,
|
|
112
|
+
chemistry.fip,
|
|
113
|
+
chemistry.charge,
|
|
114
|
+
chemistry.mass,
|
|
115
|
+
]
|
|
116
|
+
|
|
117
|
+
# Test unique tex
|
|
118
|
+
tex_values = [label.tex for label in labels]
|
|
119
|
+
assert len(tex_values) == len(set(tex_values))
|
|
120
|
+
|
|
121
|
+
# Test unique units
|
|
122
|
+
unit_values = [label.unit for label in labels]
|
|
123
|
+
assert len(unit_values) == len(set(unit_values))
|
|
124
|
+
|
|
125
|
+
# Test unique paths
|
|
126
|
+
path_values = [str(label.path) for label in labels]
|
|
127
|
+
assert len(path_values) == len(set(path_values))
|
|
128
|
+
|
|
129
|
+
def test_label_inheritance(self):
|
|
130
|
+
"""Test that labels inherit from base classes correctly."""
|
|
131
|
+
from solarwindpy.plotting.labels.base import Base
|
|
132
|
+
|
|
133
|
+
labels = [
|
|
134
|
+
chemistry.mass_per_charge,
|
|
135
|
+
chemistry.fip,
|
|
136
|
+
chemistry.charge,
|
|
137
|
+
chemistry.mass,
|
|
138
|
+
]
|
|
139
|
+
|
|
140
|
+
for label in labels:
|
|
141
|
+
assert isinstance(label, Base) # Should inherit from Base
|
|
142
|
+
assert hasattr(label, "logger") # Should have logger from Base
|
|
143
|
+
|
|
144
|
+
def test_tex_formatting(self):
|
|
145
|
+
"""Test TeX formatting is correct."""
|
|
146
|
+
# Test that math mode indicators are properly stripped from tex
|
|
147
|
+
assert chemistry.mass_per_charge.tex == r"\mathrm{M/Q}"
|
|
148
|
+
assert chemistry.fip.tex == r"\mathrm{FIP}"
|
|
149
|
+
assert chemistry.charge.tex == r"\mathrm{Q}"
|
|
150
|
+
assert chemistry.mass.tex == r"\mathrm{M}"
|
|
151
|
+
|
|
152
|
+
def test_unit_formatting(self):
|
|
153
|
+
"""Test unit formatting is correct."""
|
|
154
|
+
# Test specific unit formatting
|
|
155
|
+
assert chemistry.mass_per_charge.unit == r"\mathrm{AMU \, e^{-1}}"
|
|
156
|
+
assert chemistry.fip.unit == r"\mathrm{eV}"
|
|
157
|
+
assert chemistry.charge.unit == r"\mathrm{e}"
|
|
158
|
+
assert chemistry.mass.unit == r"\mathrm{AMU}"
|
|
159
|
+
|
|
160
|
+
def test_path_types(self):
|
|
161
|
+
"""Test that all paths are Path objects."""
|
|
162
|
+
labels = [
|
|
163
|
+
chemistry.mass_per_charge,
|
|
164
|
+
chemistry.fip,
|
|
165
|
+
chemistry.charge,
|
|
166
|
+
chemistry.mass,
|
|
167
|
+
]
|
|
168
|
+
|
|
169
|
+
for label in labels:
|
|
170
|
+
assert isinstance(label.path, Path)
|
|
171
|
+
|
|
172
|
+
def test_label_comparison(self):
|
|
173
|
+
"""Test label comparison based on string representation."""
|
|
174
|
+
# Labels should be comparable
|
|
175
|
+
labels = [
|
|
176
|
+
chemistry.mass_per_charge,
|
|
177
|
+
chemistry.fip,
|
|
178
|
+
chemistry.charge,
|
|
179
|
+
chemistry.mass,
|
|
180
|
+
]
|
|
181
|
+
|
|
182
|
+
# Test equality (should be equal to themselves)
|
|
183
|
+
for label in labels:
|
|
184
|
+
assert label == label
|
|
185
|
+
|
|
186
|
+
# Test inequality (different labels should not be equal)
|
|
187
|
+
for i, label1 in enumerate(labels):
|
|
188
|
+
for j, label2 in enumerate(labels):
|
|
189
|
+
if i != j:
|
|
190
|
+
assert label1 != label2
|
|
191
|
+
|
|
192
|
+
def test_label_hashing(self):
|
|
193
|
+
"""Test that labels can be hashed."""
|
|
194
|
+
labels = [
|
|
195
|
+
chemistry.mass_per_charge,
|
|
196
|
+
chemistry.fip,
|
|
197
|
+
chemistry.charge,
|
|
198
|
+
chemistry.mass,
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
# Should be able to create a set (requires hashing)
|
|
202
|
+
label_set = set(labels)
|
|
203
|
+
assert len(label_set) == len(labels)
|
|
204
|
+
|
|
205
|
+
# Should be able to use as dictionary keys
|
|
206
|
+
label_dict = {label: str(label) for label in labels}
|
|
207
|
+
assert len(label_dict) == len(labels)
|
|
208
|
+
|
|
209
|
+
def test_module_attributes(self):
|
|
210
|
+
"""Test that the chemistry module has all expected attributes."""
|
|
211
|
+
expected_attrs = ["mass_per_charge", "fip", "charge", "mass"]
|
|
212
|
+
|
|
213
|
+
for attr in expected_attrs:
|
|
214
|
+
assert hasattr(chemistry, attr)
|
|
215
|
+
label = getattr(chemistry, attr)
|
|
216
|
+
assert isinstance(label, ManualLabel)
|
|
217
|
+
|
|
218
|
+
def test_label_immutability(self):
|
|
219
|
+
"""Test that label properties are effectively immutable."""
|
|
220
|
+
original_tex = chemistry.mass.tex
|
|
221
|
+
original_unit = chemistry.mass.unit
|
|
222
|
+
original_path = chemistry.mass.path
|
|
223
|
+
|
|
224
|
+
# These properties should be read-only
|
|
225
|
+
# (We can't directly test immutability, but we can test they return consistent values)
|
|
226
|
+
assert chemistry.mass.tex == original_tex
|
|
227
|
+
assert chemistry.mass.unit == original_unit
|
|
228
|
+
assert chemistry.mass.path == original_path
|
|
229
|
+
|
|
230
|
+
def test_scientific_accuracy(self):
|
|
231
|
+
"""Test that labels represent scientifically accurate concepts."""
|
|
232
|
+
# Mass per charge should use atomic mass units per elementary charge
|
|
233
|
+
assert "AMU" in chemistry.mass_per_charge.unit
|
|
234
|
+
assert "e^{-1}" in chemistry.mass_per_charge.unit
|
|
235
|
+
|
|
236
|
+
# FIP should use electron volts
|
|
237
|
+
assert "eV" in chemistry.fip.unit
|
|
238
|
+
|
|
239
|
+
# Charge should use elementary charge units
|
|
240
|
+
assert "e" in chemistry.charge.unit
|
|
241
|
+
|
|
242
|
+
# Mass should use atomic mass units
|
|
243
|
+
assert "AMU" in chemistry.mass.unit
|
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import pytest
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from solarwindpy.plotting.labels import composition
|
|
6
|
+
from solarwindpy.plotting.labels.base import Base
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class IonWithUnits(composition.Ion):
|
|
10
|
+
"""Ion subclass that allows overriding units."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, species, charge, units):
|
|
13
|
+
super().__init__(species, charge)
|
|
14
|
+
self._units_override = units
|
|
15
|
+
|
|
16
|
+
@property
|
|
17
|
+
def units(self):
|
|
18
|
+
return self._units_override
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def test_set_species_charge_known_species(caplog):
|
|
22
|
+
"""Check that a known species does not trigger a warning.
|
|
23
|
+
|
|
24
|
+
Parameters
|
|
25
|
+
----------
|
|
26
|
+
caplog : pytest.LogCaptureFixture
|
|
27
|
+
Logging capture fixture.
|
|
28
|
+
"""
|
|
29
|
+
with caplog.at_level(logging.WARNING):
|
|
30
|
+
ion = composition.Ion("Fe", "2")
|
|
31
|
+
assert ion.species == "Fe"
|
|
32
|
+
assert ion.charge == "2"
|
|
33
|
+
assert "Unknown species" not in caplog.text
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def test_set_species_charge_unknown_species(caplog):
|
|
37
|
+
"""Check that an unknown species logs a warning.
|
|
38
|
+
|
|
39
|
+
Parameters
|
|
40
|
+
----------
|
|
41
|
+
caplog : pytest.LogCaptureFixture
|
|
42
|
+
Logging capture fixture.
|
|
43
|
+
"""
|
|
44
|
+
with caplog.at_level(logging.WARNING):
|
|
45
|
+
composition.Ion("Xe", "2")
|
|
46
|
+
assert "Unknown species (Xe)" in caplog.text
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def test_set_species_charge_invalid_charge():
|
|
50
|
+
"""Ensure invalid charge raises ``ValueError``."""
|
|
51
|
+
with pytest.raises(ValueError):
|
|
52
|
+
composition.Ion("Fe", "a")
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def test_charge_state_units_equal():
|
|
56
|
+
"""``ChargeState`` has ``#`` units when ion units match."""
|
|
57
|
+
cs = composition.ChargeState(("O", "2"), ("Fe", "3"))
|
|
58
|
+
assert cs.units == r"\#"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def test_charge_state_units_different():
|
|
62
|
+
"""``ChargeState`` units combine when ion units differ."""
|
|
63
|
+
ion_a = IonWithUnits("O", "2", "cm-3")
|
|
64
|
+
ion_b = IonWithUnits("Fe", "3", "km/s")
|
|
65
|
+
cs = composition.ChargeState(ion_a, ion_b)
|
|
66
|
+
assert cs.units == "cm-3/km/s"
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class TestIon:
|
|
70
|
+
"""Test Ion class functionality."""
|
|
71
|
+
|
|
72
|
+
def test_ion_initialization(self):
|
|
73
|
+
"""Test basic Ion initialization."""
|
|
74
|
+
ion = composition.Ion("Fe", "2")
|
|
75
|
+
assert ion.species == "Fe"
|
|
76
|
+
assert ion.charge == "2"
|
|
77
|
+
|
|
78
|
+
def test_ion_inheritance(self):
|
|
79
|
+
"""Test that Ion inherits from Base."""
|
|
80
|
+
ion = composition.Ion("O", "6")
|
|
81
|
+
assert isinstance(ion, Base)
|
|
82
|
+
assert hasattr(ion, "logger")
|
|
83
|
+
|
|
84
|
+
def test_species_title_case(self):
|
|
85
|
+
"""Test that species is converted to title case."""
|
|
86
|
+
ion = composition.Ion("fe", "2")
|
|
87
|
+
assert ion.species == "Fe"
|
|
88
|
+
|
|
89
|
+
ion2 = composition.Ion("FE", "3")
|
|
90
|
+
assert ion2.species == "Fe"
|
|
91
|
+
|
|
92
|
+
def test_tex_property(self):
|
|
93
|
+
"""Test TeX representation of ion."""
|
|
94
|
+
ion = composition.Ion("Fe", "2")
|
|
95
|
+
assert ion.tex == "{Fe}^{2}"
|
|
96
|
+
|
|
97
|
+
# Test with different charge formats
|
|
98
|
+
ion_plus = composition.Ion("O", "6")
|
|
99
|
+
assert ion_plus.tex == "{O}^{6}"
|
|
100
|
+
|
|
101
|
+
def test_units_property(self):
|
|
102
|
+
"""Test ion units property."""
|
|
103
|
+
ion = composition.Ion("Ne", "8")
|
|
104
|
+
assert ion.units == "\\#"
|
|
105
|
+
|
|
106
|
+
def test_path_property(self):
|
|
107
|
+
"""Test path generation for ions."""
|
|
108
|
+
ion = composition.Ion("Si", "4")
|
|
109
|
+
assert isinstance(ion.path, Path)
|
|
110
|
+
assert str(ion.path) == "Si_4"
|
|
111
|
+
|
|
112
|
+
def test_path_with_valid_charges(self):
|
|
113
|
+
"""Test path generation with various valid charges."""
|
|
114
|
+
# Test basic numeric charges
|
|
115
|
+
ion1 = composition.Ion("Fe", "2")
|
|
116
|
+
assert str(ion1.path) == "Fe_2"
|
|
117
|
+
|
|
118
|
+
# Test special charges
|
|
119
|
+
ion_i = composition.Ion("Fe", "i")
|
|
120
|
+
expected_path = "Fe_i"
|
|
121
|
+
assert str(ion_i.path) == expected_path
|
|
122
|
+
|
|
123
|
+
ion_j = composition.Ion("O", "j")
|
|
124
|
+
expected_path = "O_j"
|
|
125
|
+
assert str(ion_j.path) == expected_path
|
|
126
|
+
|
|
127
|
+
def test_known_species_list(self):
|
|
128
|
+
"""Test the known species list."""
|
|
129
|
+
expected_species = ("C", "Fe", "He", "Mg", "Ne", "N", "O", "Si", "S")
|
|
130
|
+
assert composition.known_species == expected_species
|
|
131
|
+
|
|
132
|
+
def test_all_known_species_no_warning(self, caplog):
|
|
133
|
+
"""Test that all known species don't trigger warnings."""
|
|
134
|
+
with caplog.at_level(logging.WARNING):
|
|
135
|
+
for species in composition.known_species:
|
|
136
|
+
composition.Ion(species, "2")
|
|
137
|
+
assert "Unknown species" not in caplog.text
|
|
138
|
+
|
|
139
|
+
def test_valid_charges(self):
|
|
140
|
+
"""Test various valid charge formats."""
|
|
141
|
+
valid_charges = ["1", "2", "3", "10", "i", "j"]
|
|
142
|
+
|
|
143
|
+
for charge in valid_charges:
|
|
144
|
+
ion = composition.Ion("O", charge)
|
|
145
|
+
assert ion.charge == charge
|
|
146
|
+
|
|
147
|
+
def test_invalid_charges(self):
|
|
148
|
+
"""Test invalid charge formats raise ValueError."""
|
|
149
|
+
invalid_charges = ["a", "x", "1.5", "+", "-", ""]
|
|
150
|
+
|
|
151
|
+
for charge in invalid_charges:
|
|
152
|
+
with pytest.raises(ValueError, match="Invalid charge"):
|
|
153
|
+
composition.Ion("O", charge)
|
|
154
|
+
|
|
155
|
+
def test_string_representation(self):
|
|
156
|
+
"""Test string representations through base class."""
|
|
157
|
+
ion = composition.Ion("Fe", "2")
|
|
158
|
+
# Ion inherits from Base, so it should have with_units property
|
|
159
|
+
str_repr = str(ion)
|
|
160
|
+
assert isinstance(str_repr, str)
|
|
161
|
+
|
|
162
|
+
def test_ion_comparison(self):
|
|
163
|
+
"""Test ion comparison functionality."""
|
|
164
|
+
ion1 = composition.Ion("Fe", "2")
|
|
165
|
+
ion2 = composition.Ion("Fe", "2")
|
|
166
|
+
ion3 = composition.Ion("O", "6")
|
|
167
|
+
|
|
168
|
+
# Same ions should be equal
|
|
169
|
+
assert ion1 == ion2
|
|
170
|
+
|
|
171
|
+
# Different ions should not be equal
|
|
172
|
+
assert ion1 != ion3
|
|
173
|
+
|
|
174
|
+
def test_ion_hashing(self):
|
|
175
|
+
"""Test that ions can be hashed."""
|
|
176
|
+
ion1 = composition.Ion("Fe", "2")
|
|
177
|
+
ion2 = composition.Ion("O", "6")
|
|
178
|
+
|
|
179
|
+
# Should be able to create a set
|
|
180
|
+
ion_set = {ion1, ion2}
|
|
181
|
+
assert len(ion_set) == 2
|
|
182
|
+
|
|
183
|
+
# Should be able to use as dictionary keys
|
|
184
|
+
ion_dict = {ion1: "iron", ion2: "oxygen"}
|
|
185
|
+
assert len(ion_dict) == 2
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class TestChargeState:
|
|
189
|
+
"""Test ChargeState class functionality."""
|
|
190
|
+
|
|
191
|
+
def test_charge_state_initialization_with_tuples(self):
|
|
192
|
+
"""Test ChargeState initialization with tuples."""
|
|
193
|
+
cs = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
194
|
+
assert cs.ionA.species == "O"
|
|
195
|
+
assert cs.ionA.charge == "6"
|
|
196
|
+
assert cs.ionB.species == "O"
|
|
197
|
+
assert cs.ionB.charge == "7"
|
|
198
|
+
|
|
199
|
+
def test_charge_state_initialization_with_ions(self):
|
|
200
|
+
"""Test ChargeState initialization with Ion objects."""
|
|
201
|
+
ion_a = composition.Ion("Fe", "10")
|
|
202
|
+
ion_b = composition.Ion("Fe", "11")
|
|
203
|
+
cs = composition.ChargeState(ion_a, ion_b)
|
|
204
|
+
assert cs.ionA == ion_a
|
|
205
|
+
assert cs.ionB == ion_b
|
|
206
|
+
|
|
207
|
+
def test_charge_state_inheritance(self):
|
|
208
|
+
"""Test that ChargeState inherits from Base."""
|
|
209
|
+
cs = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
210
|
+
assert isinstance(cs, Base)
|
|
211
|
+
assert hasattr(cs, "logger")
|
|
212
|
+
|
|
213
|
+
def test_charge_state_tex(self):
|
|
214
|
+
"""Test TeX representation of charge state."""
|
|
215
|
+
cs = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
216
|
+
assert cs.tex == "{O}^{6}/{O}^{7}"
|
|
217
|
+
|
|
218
|
+
def test_charge_state_path(self):
|
|
219
|
+
"""Test path generation for charge state."""
|
|
220
|
+
cs = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
|
|
221
|
+
assert isinstance(cs.path, Path)
|
|
222
|
+
expected_path = "Fe_10-OV-Fe_11"
|
|
223
|
+
assert str(cs.path) == expected_path
|
|
224
|
+
|
|
225
|
+
def test_charge_state_same_units(self):
|
|
226
|
+
"""Test charge state units when both ions have same units."""
|
|
227
|
+
# Default Ion units are "\#"
|
|
228
|
+
cs = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
229
|
+
assert cs.units == r"\#"
|
|
230
|
+
|
|
231
|
+
def test_charge_state_different_units(self):
|
|
232
|
+
"""Test charge state units when ions have different units."""
|
|
233
|
+
ion_a = IonWithUnits("O", "6", "cm^-3")
|
|
234
|
+
ion_b = IonWithUnits("O", "7", "km/s")
|
|
235
|
+
cs = composition.ChargeState(ion_a, ion_b)
|
|
236
|
+
assert cs.units == "cm^-3/km/s"
|
|
237
|
+
|
|
238
|
+
def test_charge_state_mixed_initialization(self):
|
|
239
|
+
"""Test ChargeState with mix of Ion and tuple."""
|
|
240
|
+
ion_a = composition.Ion("Fe", "2")
|
|
241
|
+
cs = composition.ChargeState(ion_a, ("O", "6"))
|
|
242
|
+
assert cs.ionA == ion_a
|
|
243
|
+
assert cs.ionB.species == "O"
|
|
244
|
+
assert cs.ionB.charge == "6"
|
|
245
|
+
|
|
246
|
+
def test_charge_state_comparison(self):
|
|
247
|
+
"""Test charge state comparison functionality."""
|
|
248
|
+
cs1 = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
249
|
+
cs2 = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
250
|
+
cs3 = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
|
|
251
|
+
|
|
252
|
+
# Same charge states should be equal
|
|
253
|
+
assert cs1 == cs2
|
|
254
|
+
|
|
255
|
+
# Different charge states should not be equal
|
|
256
|
+
assert cs1 != cs3
|
|
257
|
+
|
|
258
|
+
def test_charge_state_hashing(self):
|
|
259
|
+
"""Test that charge states can be hashed."""
|
|
260
|
+
cs1 = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
261
|
+
cs2 = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
|
|
262
|
+
|
|
263
|
+
# Should be able to create a set
|
|
264
|
+
cs_set = {cs1, cs2}
|
|
265
|
+
assert len(cs_set) == 2
|
|
266
|
+
|
|
267
|
+
# Should be able to use as dictionary keys
|
|
268
|
+
cs_dict = {cs1: "oxygen", cs2: "iron"}
|
|
269
|
+
assert len(cs_dict) == 2
|
|
270
|
+
|
|
271
|
+
def test_charge_state_string_representation(self):
|
|
272
|
+
"""Test string representation of charge state."""
|
|
273
|
+
cs = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
274
|
+
str_repr = str(cs)
|
|
275
|
+
assert isinstance(str_repr, str)
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class TestCompositionModule:
|
|
279
|
+
"""Test module-level functionality."""
|
|
280
|
+
|
|
281
|
+
def test_module_all(self):
|
|
282
|
+
"""Test module __all__ exports."""
|
|
283
|
+
assert composition.__all__ == ["Ion", "ChargeState"]
|
|
284
|
+
|
|
285
|
+
def test_module_attributes(self):
|
|
286
|
+
"""Test module has expected attributes."""
|
|
287
|
+
assert hasattr(composition, "Ion")
|
|
288
|
+
assert hasattr(composition, "ChargeState")
|
|
289
|
+
assert hasattr(composition, "known_species")
|
|
290
|
+
|
|
291
|
+
def test_known_species_completeness(self):
|
|
292
|
+
"""Test that known_species covers common solar wind ions."""
|
|
293
|
+
expected_common_ions = ["C", "Fe", "He", "Mg", "Ne", "N", "O", "Si", "S"]
|
|
294
|
+
for ion in expected_common_ions:
|
|
295
|
+
assert ion in composition.known_species
|
|
296
|
+
|
|
297
|
+
def test_scientific_accuracy(self):
|
|
298
|
+
"""Test that composition labels represent scientifically accurate concepts."""
|
|
299
|
+
# Test common solar wind charge states
|
|
300
|
+
o6_o7 = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
301
|
+
assert "O" in o6_o7.tex
|
|
302
|
+
assert "6" in o6_o7.tex
|
|
303
|
+
assert "7" in o6_o7.tex
|
|
304
|
+
|
|
305
|
+
# Test iron charge states
|
|
306
|
+
fe10_fe11 = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
|
|
307
|
+
assert "Fe" in fe10_fe11.tex
|
|
308
|
+
assert "10" in fe10_fe11.tex
|
|
309
|
+
assert "11" in fe10_fe11.tex
|
|
310
|
+
|
|
311
|
+
|
|
312
|
+
class TestCompositionIntegration:
|
|
313
|
+
"""Test integration between Ion and ChargeState classes."""
|
|
314
|
+
|
|
315
|
+
def test_ion_in_charge_state_roundtrip(self):
|
|
316
|
+
"""Test creating ions and using them in charge states."""
|
|
317
|
+
# Create ions
|
|
318
|
+
o6 = composition.Ion("O", "6")
|
|
319
|
+
o7 = composition.Ion("O", "7")
|
|
320
|
+
|
|
321
|
+
# Use in charge state
|
|
322
|
+
cs = composition.ChargeState(o6, o7)
|
|
323
|
+
|
|
324
|
+
# Verify roundtrip
|
|
325
|
+
assert cs.ionA.species == "O"
|
|
326
|
+
assert cs.ionA.charge == "6"
|
|
327
|
+
assert cs.ionB.species == "O"
|
|
328
|
+
assert cs.ionB.charge == "7"
|
|
329
|
+
|
|
330
|
+
def test_complex_charge_state_ratios(self):
|
|
331
|
+
"""Test complex charge state ratios with different species."""
|
|
332
|
+
# O6+ / Fe10+ ratio
|
|
333
|
+
cs = composition.ChargeState(("O", "6"), ("Fe", "10"))
|
|
334
|
+
assert "O" in cs.tex
|
|
335
|
+
assert "Fe" in cs.tex
|
|
336
|
+
assert "{O}^{6}/{Fe}^{10}" == cs.tex
|
|
337
|
+
|
|
338
|
+
def test_charge_state_path_uniqueness(self):
|
|
339
|
+
"""Test that different charge states have unique paths."""
|
|
340
|
+
cs1 = composition.ChargeState(("O", "6"), ("O", "7"))
|
|
341
|
+
cs2 = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
|
|
342
|
+
cs3 = composition.ChargeState(("O", "7"), ("O", "6")) # Reversed
|
|
343
|
+
|
|
344
|
+
paths = [str(cs1.path), str(cs2.path), str(cs3.path)]
|
|
345
|
+
assert len(paths) == len(set(paths)) # All unique
|