solarwindpy 0.0.1.dev0__py3-none-any.whl → 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.0.dist-info/METADATA +181 -0
- solarwindpy-0.1.0.dist-info/RECORD +409 -0
- {solarwindpy-0.0.1.dev0.dist-info → solarwindpy-0.1.0.dist-info}/WHEEL +1 -1
- solarwindpy-0.1.0.dist-info/licenses/LICENSE.rst +32 -0
- solarwindpy-0.1.0.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,573 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""Tests for solarwindpy.plotting.spiral module.
|
|
3
|
+
|
|
4
|
+
This module provides comprehensive test coverage for the spiral mesh plotting and
|
|
5
|
+
binning utilities, including numba-accelerated functions.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import pytest
|
|
9
|
+
import logging
|
|
10
|
+
import pandas as pd
|
|
11
|
+
import numpy as np
|
|
12
|
+
from pathlib import Path
|
|
13
|
+
from unittest.mock import patch, MagicMock
|
|
14
|
+
from collections import namedtuple
|
|
15
|
+
|
|
16
|
+
import matplotlib
|
|
17
|
+
|
|
18
|
+
matplotlib.use("Agg") # Use non-interactive backend
|
|
19
|
+
from matplotlib import pyplot as plt
|
|
20
|
+
from matplotlib.collections import PatchCollection
|
|
21
|
+
|
|
22
|
+
import solarwindpy.plotting.spiral as spiral_module
|
|
23
|
+
from solarwindpy.plotting.spiral import (
|
|
24
|
+
get_counts_per_bin,
|
|
25
|
+
calculate_bin_number_with_numba,
|
|
26
|
+
SpiralMesh,
|
|
27
|
+
SpiralPlot2D,
|
|
28
|
+
InitialSpiralEdges,
|
|
29
|
+
SpiralMeshBinID,
|
|
30
|
+
SpiralFilterThresholds,
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
class TestSpiralModuleStructure:
|
|
35
|
+
"""Test spiral module structure and imports."""
|
|
36
|
+
|
|
37
|
+
def test_module_imports(self):
|
|
38
|
+
"""Test that all required imports are accessible."""
|
|
39
|
+
# Test basic imports
|
|
40
|
+
assert hasattr(spiral_module, "base")
|
|
41
|
+
assert hasattr(spiral_module, "labels_module")
|
|
42
|
+
assert hasattr(spiral_module, "plt")
|
|
43
|
+
assert hasattr(spiral_module, "np")
|
|
44
|
+
assert hasattr(spiral_module, "pd")
|
|
45
|
+
|
|
46
|
+
def test_numba_functions_available(self):
|
|
47
|
+
"""Test that numba-accelerated functions are accessible."""
|
|
48
|
+
assert hasattr(spiral_module, "get_counts_per_bin")
|
|
49
|
+
assert hasattr(spiral_module, "calculate_bin_number_with_numba")
|
|
50
|
+
assert callable(spiral_module.get_counts_per_bin)
|
|
51
|
+
assert callable(spiral_module.calculate_bin_number_with_numba)
|
|
52
|
+
|
|
53
|
+
def test_classes_available(self):
|
|
54
|
+
"""Test that spiral classes are accessible."""
|
|
55
|
+
assert hasattr(spiral_module, "SpiralMesh")
|
|
56
|
+
assert hasattr(spiral_module, "SpiralPlot2D")
|
|
57
|
+
assert callable(spiral_module.SpiralMesh)
|
|
58
|
+
assert callable(spiral_module.SpiralPlot2D)
|
|
59
|
+
|
|
60
|
+
def test_namedtuple_definitions(self):
|
|
61
|
+
"""Test that named tuples are properly defined."""
|
|
62
|
+
assert hasattr(spiral_module, "InitialSpiralEdges")
|
|
63
|
+
assert hasattr(spiral_module, "SpiralMeshBinID")
|
|
64
|
+
assert hasattr(spiral_module, "SpiralFilterThresholds")
|
|
65
|
+
|
|
66
|
+
# Test that they are indeed named tuples
|
|
67
|
+
assert issubclass(InitialSpiralEdges, tuple)
|
|
68
|
+
assert issubclass(SpiralMeshBinID, tuple)
|
|
69
|
+
assert issubclass(SpiralFilterThresholds, tuple)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
class TestNamedTuples:
|
|
73
|
+
"""Test named tuple structures and functionality."""
|
|
74
|
+
|
|
75
|
+
def test_initial_spiral_edges_structure(self):
|
|
76
|
+
"""Test InitialSpiralEdges named tuple."""
|
|
77
|
+
# Test creation
|
|
78
|
+
x_edges = np.array([0, 1, 2, 3])
|
|
79
|
+
y_edges = np.array([0, 1, 2])
|
|
80
|
+
edges = InitialSpiralEdges(x_edges, y_edges)
|
|
81
|
+
|
|
82
|
+
assert edges.x is x_edges
|
|
83
|
+
assert edges.y is y_edges
|
|
84
|
+
assert len(edges) == 2
|
|
85
|
+
|
|
86
|
+
def test_spiral_mesh_bin_id_structure(self):
|
|
87
|
+
"""Test SpiralMeshBinID named tuple."""
|
|
88
|
+
bin_ids = np.array([0, 1, 2, 1, 0])
|
|
89
|
+
fill_value = -9999
|
|
90
|
+
visited = np.array([1, 1, 1])
|
|
91
|
+
|
|
92
|
+
bin_id = SpiralMeshBinID(bin_ids, fill_value, visited)
|
|
93
|
+
|
|
94
|
+
assert np.array_equal(bin_id.id, bin_ids)
|
|
95
|
+
assert bin_id.fill == fill_value
|
|
96
|
+
assert np.array_equal(bin_id.visited, visited)
|
|
97
|
+
assert len(bin_id) == 3
|
|
98
|
+
|
|
99
|
+
def test_spiral_filter_thresholds_structure(self):
|
|
100
|
+
"""Test SpiralFilterThresholds named tuple with defaults."""
|
|
101
|
+
# Test with defaults
|
|
102
|
+
thresholds = SpiralFilterThresholds(density=0.5)
|
|
103
|
+
assert thresholds.density == 0.5
|
|
104
|
+
assert thresholds.size is False # Default value
|
|
105
|
+
|
|
106
|
+
# Test without defaults
|
|
107
|
+
thresholds2 = SpiralFilterThresholds(density=0.3, size=0.9)
|
|
108
|
+
assert thresholds2.density == 0.3
|
|
109
|
+
assert thresholds2.size == 0.9
|
|
110
|
+
|
|
111
|
+
def test_namedtuple_immutability(self):
|
|
112
|
+
"""Test that named tuples are immutable."""
|
|
113
|
+
edges = InitialSpiralEdges([1, 2, 3], [4, 5, 6])
|
|
114
|
+
|
|
115
|
+
with pytest.raises(AttributeError):
|
|
116
|
+
edges.x = [7, 8, 9]
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
class TestNumbaFunctions:
|
|
120
|
+
"""Test numba-accelerated functions."""
|
|
121
|
+
|
|
122
|
+
def setup_method(self):
|
|
123
|
+
"""Set up test data for numba functions."""
|
|
124
|
+
# Create simple test bins: 2x2 grid
|
|
125
|
+
self.bins = np.array(
|
|
126
|
+
[
|
|
127
|
+
[0, 1, 0, 1], # Lower-left bin
|
|
128
|
+
[1, 2, 0, 1], # Lower-right bin
|
|
129
|
+
[0, 1, 1, 2], # Upper-left bin
|
|
130
|
+
[1, 2, 1, 2], # Upper-right bin
|
|
131
|
+
],
|
|
132
|
+
dtype=np.float64,
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Test points
|
|
136
|
+
self.x = np.array([0.5, 1.5, 0.5, 1.5, 0.1])
|
|
137
|
+
self.y = np.array([0.5, 0.5, 1.5, 1.5, 0.1])
|
|
138
|
+
|
|
139
|
+
def test_get_counts_per_bin_basic(self):
|
|
140
|
+
"""Test basic functionality of get_counts_per_bin."""
|
|
141
|
+
counts = get_counts_per_bin(self.bins, self.x, self.y)
|
|
142
|
+
|
|
143
|
+
assert isinstance(counts, np.ndarray)
|
|
144
|
+
assert counts.dtype == np.int64
|
|
145
|
+
assert len(counts) == len(self.bins)
|
|
146
|
+
|
|
147
|
+
# Should have one point in each of the 4 bins, plus one more in bin 0
|
|
148
|
+
expected = np.array([2, 1, 1, 1]) # Two points in first bin
|
|
149
|
+
assert np.array_equal(counts, expected)
|
|
150
|
+
|
|
151
|
+
def test_get_counts_per_bin_empty_bins(self):
|
|
152
|
+
"""Test get_counts_per_bin with empty bins."""
|
|
153
|
+
# Points outside all bins
|
|
154
|
+
x_out = np.array([5, 6])
|
|
155
|
+
y_out = np.array([5, 6])
|
|
156
|
+
|
|
157
|
+
counts = get_counts_per_bin(self.bins, x_out, y_out)
|
|
158
|
+
|
|
159
|
+
assert isinstance(counts, np.ndarray)
|
|
160
|
+
assert len(counts) == len(self.bins)
|
|
161
|
+
assert np.all(counts == 0)
|
|
162
|
+
|
|
163
|
+
def test_get_counts_per_bin_boundary_points(self):
|
|
164
|
+
"""Test boundary point handling in get_counts_per_bin."""
|
|
165
|
+
# Points exactly on boundaries (should be included in left/bottom bin)
|
|
166
|
+
x_boundary = np.array([1.0, 0.0])
|
|
167
|
+
y_boundary = np.array([0.0, 1.0])
|
|
168
|
+
|
|
169
|
+
counts = get_counts_per_bin(self.bins, x_boundary, y_boundary)
|
|
170
|
+
|
|
171
|
+
# Point at (1,0) should be in lower-left bin (x>=0 & x<1 is false, x>=1 & x<2 is true)
|
|
172
|
+
# Point at (0,1) should be in upper-left bin
|
|
173
|
+
expected = np.array([0, 1, 1, 0])
|
|
174
|
+
assert np.array_equal(counts, expected)
|
|
175
|
+
|
|
176
|
+
def test_calculate_bin_number_with_numba_basic(self):
|
|
177
|
+
"""Test basic functionality of calculate_bin_number_with_numba."""
|
|
178
|
+
zbin, fill, bin_visited = calculate_bin_number_with_numba(
|
|
179
|
+
self.bins, self.x, self.y
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
assert isinstance(zbin, np.ndarray)
|
|
183
|
+
assert isinstance(fill, (int, np.integer))
|
|
184
|
+
assert isinstance(bin_visited, np.ndarray)
|
|
185
|
+
|
|
186
|
+
assert len(zbin) == len(self.x)
|
|
187
|
+
assert zbin.dtype == np.int64
|
|
188
|
+
assert fill == -9999
|
|
189
|
+
|
|
190
|
+
# Check that points are assigned to correct bins
|
|
191
|
+
expected_bins = np.array([0, 1, 2, 3, 0]) # Last point also in bin 0
|
|
192
|
+
assert np.array_equal(zbin, expected_bins)
|
|
193
|
+
|
|
194
|
+
def test_calculate_bin_number_with_numba_outside_points(self):
|
|
195
|
+
"""Test calculate_bin_number_with_numba with points outside mesh."""
|
|
196
|
+
# Add points outside the mesh
|
|
197
|
+
x_with_outside = np.append(self.x, [5, -1])
|
|
198
|
+
y_with_outside = np.append(self.y, [5, -1])
|
|
199
|
+
|
|
200
|
+
zbin, fill, bin_visited = calculate_bin_number_with_numba(
|
|
201
|
+
self.bins, x_with_outside, y_with_outside
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
# Points outside mesh should have fill value
|
|
205
|
+
assert zbin[-2] == fill
|
|
206
|
+
assert zbin[-1] == fill
|
|
207
|
+
|
|
208
|
+
# Other points should still be assigned correctly
|
|
209
|
+
assert zbin[0] == 0 # First point in bin 0
|
|
210
|
+
|
|
211
|
+
def test_numba_function_performance(self):
|
|
212
|
+
"""Test that numba functions handle reasonably large datasets."""
|
|
213
|
+
# Create larger dataset
|
|
214
|
+
n_points = 10000
|
|
215
|
+
large_x = np.random.uniform(0, 2, n_points)
|
|
216
|
+
large_y = np.random.uniform(0, 2, n_points)
|
|
217
|
+
|
|
218
|
+
# Should not raise memory errors or take excessive time
|
|
219
|
+
counts = get_counts_per_bin(self.bins, large_x, large_y)
|
|
220
|
+
assert len(counts) == len(self.bins)
|
|
221
|
+
assert counts.sum() <= n_points # Some points might be outside
|
|
222
|
+
|
|
223
|
+
zbin, fill, bin_visited = calculate_bin_number_with_numba(
|
|
224
|
+
self.bins, large_x, large_y
|
|
225
|
+
)
|
|
226
|
+
assert len(zbin) == n_points
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
class TestSpiralMesh:
|
|
230
|
+
"""Test SpiralMesh class functionality."""
|
|
231
|
+
|
|
232
|
+
def setup_method(self):
|
|
233
|
+
"""Set up test data for SpiralMesh tests."""
|
|
234
|
+
self.x_data = pd.Series(np.random.uniform(0, 10, 100))
|
|
235
|
+
self.y_data = pd.Series(np.random.uniform(0, 10, 100))
|
|
236
|
+
self.x_edges = np.linspace(0, 10, 6) # 5 bins
|
|
237
|
+
self.y_edges = np.linspace(0, 10, 6) # 5 bins
|
|
238
|
+
self.min_per_bin = 5
|
|
239
|
+
|
|
240
|
+
def test_spiral_mesh_initialization(self):
|
|
241
|
+
"""Test SpiralMesh initialization."""
|
|
242
|
+
mesh = SpiralMesh(
|
|
243
|
+
self.x_data,
|
|
244
|
+
self.y_data,
|
|
245
|
+
self.x_edges,
|
|
246
|
+
self.y_edges,
|
|
247
|
+
min_per_bin=self.min_per_bin,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
assert mesh is not None
|
|
251
|
+
assert hasattr(mesh, "data")
|
|
252
|
+
assert hasattr(mesh, "initial_edges")
|
|
253
|
+
assert hasattr(mesh, "min_per_bin")
|
|
254
|
+
assert hasattr(mesh, "cell_filter_thresholds")
|
|
255
|
+
|
|
256
|
+
def test_spiral_mesh_properties(self):
|
|
257
|
+
"""Test SpiralMesh property access."""
|
|
258
|
+
mesh = SpiralMesh(
|
|
259
|
+
self.x_data,
|
|
260
|
+
self.y_data,
|
|
261
|
+
self.x_edges,
|
|
262
|
+
self.y_edges,
|
|
263
|
+
min_per_bin=self.min_per_bin,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
# Test property access
|
|
267
|
+
assert isinstance(mesh.data, pd.DataFrame)
|
|
268
|
+
assert isinstance(mesh.initial_edges, InitialSpiralEdges)
|
|
269
|
+
assert isinstance(mesh.min_per_bin, int)
|
|
270
|
+
assert isinstance(mesh.cell_filter_thresholds, SpiralFilterThresholds)
|
|
271
|
+
|
|
272
|
+
# Test data structure
|
|
273
|
+
assert "x" in mesh.data.columns
|
|
274
|
+
assert "y" in mesh.data.columns
|
|
275
|
+
assert len(mesh.data) == len(self.x_data)
|
|
276
|
+
|
|
277
|
+
def test_spiral_mesh_set_methods(self):
|
|
278
|
+
"""Test SpiralMesh setter methods."""
|
|
279
|
+
mesh = SpiralMesh(
|
|
280
|
+
self.x_data, self.y_data, self.x_edges, self.y_edges, min_per_bin=10
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
# Test set_min_per_bin
|
|
284
|
+
mesh.set_min_per_bin(20)
|
|
285
|
+
assert mesh.min_per_bin == 20
|
|
286
|
+
|
|
287
|
+
# Test set_cell_filter_thresholds
|
|
288
|
+
mesh.set_cell_filter_thresholds(density=0.5, size=0.9)
|
|
289
|
+
assert mesh.cell_filter_thresholds.density == 0.5
|
|
290
|
+
assert mesh.cell_filter_thresholds.size == 0.9
|
|
291
|
+
|
|
292
|
+
# Test set_initial_edges
|
|
293
|
+
new_x_edges = np.linspace(0, 5, 4)
|
|
294
|
+
new_y_edges = np.linspace(0, 5, 4)
|
|
295
|
+
mesh.set_initial_edges(new_x_edges, new_y_edges)
|
|
296
|
+
assert np.array_equal(mesh.initial_edges.x, new_x_edges)
|
|
297
|
+
assert np.array_equal(mesh.initial_edges.y, new_y_edges)
|
|
298
|
+
|
|
299
|
+
def test_spiral_mesh_initialize_bins(self):
|
|
300
|
+
"""Test spiral mesh bin initialization."""
|
|
301
|
+
mesh = SpiralMesh(
|
|
302
|
+
self.x_data,
|
|
303
|
+
self.y_data,
|
|
304
|
+
self.x_edges,
|
|
305
|
+
self.y_edges,
|
|
306
|
+
min_per_bin=self.min_per_bin,
|
|
307
|
+
)
|
|
308
|
+
|
|
309
|
+
initial_mesh = mesh.initialize_bins()
|
|
310
|
+
|
|
311
|
+
assert isinstance(initial_mesh, np.ndarray)
|
|
312
|
+
assert initial_mesh.shape[1] == 4 # x0, x1, y0, y1
|
|
313
|
+
|
|
314
|
+
# Should have (nx-1) * (ny-1) bins
|
|
315
|
+
expected_n_bins = (len(self.x_edges) - 1) * (len(self.y_edges) - 1)
|
|
316
|
+
assert initial_mesh.shape[0] == expected_n_bins
|
|
317
|
+
|
|
318
|
+
# All values should be finite
|
|
319
|
+
assert np.isfinite(initial_mesh).all()
|
|
320
|
+
|
|
321
|
+
def test_spiral_mesh_cell_filter_invalid_kwargs(self):
|
|
322
|
+
"""Test that invalid kwargs raise errors."""
|
|
323
|
+
mesh = SpiralMesh(
|
|
324
|
+
self.x_data,
|
|
325
|
+
self.y_data,
|
|
326
|
+
self.x_edges,
|
|
327
|
+
self.y_edges,
|
|
328
|
+
min_per_bin=self.min_per_bin,
|
|
329
|
+
)
|
|
330
|
+
|
|
331
|
+
with pytest.raises(KeyError, match="Unexpected kwarg"):
|
|
332
|
+
mesh.set_cell_filter_thresholds(invalid_param=0.5)
|
|
333
|
+
|
|
334
|
+
|
|
335
|
+
class TestSpiralPlot2D:
|
|
336
|
+
"""Test SpiralPlot2D class functionality."""
|
|
337
|
+
|
|
338
|
+
def setup_method(self):
|
|
339
|
+
"""Set up test data for SpiralPlot2D tests."""
|
|
340
|
+
self.x_data = pd.Series(np.random.uniform(1, 100, 50)) # Positive for log
|
|
341
|
+
self.y_data = pd.Series(np.random.uniform(1, 100, 50)) # Positive for log
|
|
342
|
+
self.z_data = pd.Series(np.random.uniform(0, 10, 50))
|
|
343
|
+
|
|
344
|
+
def test_spiral_plot_2d_initialization(self):
|
|
345
|
+
"""Test SpiralPlot2D initialization."""
|
|
346
|
+
splot = SpiralPlot2D(self.x_data, self.y_data)
|
|
347
|
+
|
|
348
|
+
assert splot is not None
|
|
349
|
+
assert hasattr(splot, "data")
|
|
350
|
+
assert hasattr(splot, "initial_bins")
|
|
351
|
+
assert hasattr(splot, "clim")
|
|
352
|
+
|
|
353
|
+
def test_spiral_plot_2d_with_z_data(self):
|
|
354
|
+
"""Test SpiralPlot2D initialization with z data."""
|
|
355
|
+
splot = SpiralPlot2D(self.x_data, self.y_data, self.z_data)
|
|
356
|
+
|
|
357
|
+
assert "z" in splot.data.columns
|
|
358
|
+
assert len(splot.data) == len(self.x_data)
|
|
359
|
+
|
|
360
|
+
def test_spiral_plot_2d_log_scaling(self):
|
|
361
|
+
"""Test SpiralPlot2D with logarithmic scaling."""
|
|
362
|
+
splot = SpiralPlot2D(self.x_data, self.y_data, logx=True, logy=True)
|
|
363
|
+
|
|
364
|
+
# With log scaling, data should be log-transformed
|
|
365
|
+
original_data_range = self.x_data.max() - self.x_data.min()
|
|
366
|
+
plot_data_range = splot.data["x"].max() - splot.data["x"].min()
|
|
367
|
+
|
|
368
|
+
# Log-transformed range should be smaller than original
|
|
369
|
+
assert plot_data_range < original_data_range
|
|
370
|
+
|
|
371
|
+
def test_spiral_plot_2d_initial_bins_calculation(self):
|
|
372
|
+
"""Test initial bins calculation."""
|
|
373
|
+
splot = SpiralPlot2D(self.x_data, self.y_data, initial_bins=5)
|
|
374
|
+
|
|
375
|
+
bins = splot.initial_bins
|
|
376
|
+
assert isinstance(bins, dict)
|
|
377
|
+
assert "x" in bins
|
|
378
|
+
assert "y" in bins
|
|
379
|
+
|
|
380
|
+
# Each should have 6 edges for 5 bins
|
|
381
|
+
assert len(bins["x"]) == 6
|
|
382
|
+
assert len(bins["y"]) == 6
|
|
383
|
+
|
|
384
|
+
def test_spiral_plot_2d_clim_setting(self):
|
|
385
|
+
"""Test color limit setting."""
|
|
386
|
+
splot = SpiralPlot2D(self.x_data, self.y_data, self.z_data)
|
|
387
|
+
|
|
388
|
+
# Test setting color limits
|
|
389
|
+
splot.set_clim(lower=1, upper=9)
|
|
390
|
+
assert splot.clim.lower == 1
|
|
391
|
+
assert splot.clim.upper == 9
|
|
392
|
+
|
|
393
|
+
# Test with None values
|
|
394
|
+
splot.set_clim(lower=None, upper=10)
|
|
395
|
+
assert splot.clim.lower is None
|
|
396
|
+
assert splot.clim.upper == 10
|
|
397
|
+
|
|
398
|
+
@patch("matplotlib.pyplot.subplots")
|
|
399
|
+
def test_spiral_plot_2d_initialization_mesh(self, mock_subplots):
|
|
400
|
+
"""Test mesh initialization in SpiralPlot2D."""
|
|
401
|
+
splot = SpiralPlot2D(self.x_data, self.y_data, initial_bins=3)
|
|
402
|
+
|
|
403
|
+
# Initialize mesh with small min_per_bin for testing
|
|
404
|
+
splot.initialize_mesh(min_per_bin=2)
|
|
405
|
+
|
|
406
|
+
assert hasattr(splot, "_mesh")
|
|
407
|
+
assert isinstance(splot._mesh, SpiralMesh)
|
|
408
|
+
assert hasattr(splot._mesh, "mesh")
|
|
409
|
+
|
|
410
|
+
|
|
411
|
+
class TestSpiralIntegration:
|
|
412
|
+
"""Test integration between spiral components."""
|
|
413
|
+
|
|
414
|
+
def setup_method(self):
|
|
415
|
+
"""Set up test data for integration tests."""
|
|
416
|
+
# Create structured test data
|
|
417
|
+
np.random.seed(42) # For reproducible tests
|
|
418
|
+
self.x_data = pd.Series(np.random.uniform(0, 10, 100))
|
|
419
|
+
self.y_data = pd.Series(np.random.uniform(0, 10, 100))
|
|
420
|
+
self.z_data = pd.Series(np.random.uniform(0, 5, 100))
|
|
421
|
+
|
|
422
|
+
def test_spiral_mesh_full_workflow(self):
|
|
423
|
+
"""Test complete spiral mesh workflow."""
|
|
424
|
+
x_edges = np.linspace(0, 10, 6)
|
|
425
|
+
y_edges = np.linspace(0, 10, 6)
|
|
426
|
+
|
|
427
|
+
mesh = SpiralMesh(self.x_data, self.y_data, x_edges, y_edges, min_per_bin=3)
|
|
428
|
+
|
|
429
|
+
# Initialize and generate mesh
|
|
430
|
+
initial_bins = mesh.initialize_bins()
|
|
431
|
+
assert initial_bins is not None
|
|
432
|
+
|
|
433
|
+
# The generate_mesh method is complex and involves iterative refinement
|
|
434
|
+
# For testing, we'll just verify the basic structure exists
|
|
435
|
+
assert hasattr(mesh, "generate_mesh")
|
|
436
|
+
assert callable(mesh.generate_mesh)
|
|
437
|
+
|
|
438
|
+
def test_numba_functions_integration(self):
|
|
439
|
+
"""Test integration between numba functions."""
|
|
440
|
+
# Create simple mesh
|
|
441
|
+
bins = np.array(
|
|
442
|
+
[
|
|
443
|
+
[0, 5, 0, 5],
|
|
444
|
+
[5, 10, 0, 5],
|
|
445
|
+
[0, 5, 5, 10],
|
|
446
|
+
[5, 10, 5, 10],
|
|
447
|
+
],
|
|
448
|
+
dtype=np.float64,
|
|
449
|
+
)
|
|
450
|
+
|
|
451
|
+
x = self.x_data.values
|
|
452
|
+
y = self.y_data.values
|
|
453
|
+
|
|
454
|
+
# Test that both functions work together
|
|
455
|
+
counts = get_counts_per_bin(bins, x, y)
|
|
456
|
+
zbin, fill, visited = calculate_bin_number_with_numba(bins, x, y)
|
|
457
|
+
|
|
458
|
+
# Counts should match the assigned bins
|
|
459
|
+
manual_counts = np.bincount(zbin[zbin != fill], minlength=len(bins))
|
|
460
|
+
assert np.array_equal(counts, manual_counts)
|
|
461
|
+
|
|
462
|
+
|
|
463
|
+
class TestSpiralErrorHandling:
|
|
464
|
+
"""Test error handling and edge cases."""
|
|
465
|
+
|
|
466
|
+
def test_empty_data_handling(self):
|
|
467
|
+
"""Test handling of empty data."""
|
|
468
|
+
empty_x = pd.Series([], dtype=float)
|
|
469
|
+
empty_y = pd.Series([], dtype=float)
|
|
470
|
+
edges = np.array([0, 1, 2])
|
|
471
|
+
|
|
472
|
+
# Should not crash with empty data
|
|
473
|
+
mesh = SpiralMesh(empty_x, empty_y, edges, edges, min_per_bin=1)
|
|
474
|
+
assert len(mesh.data) == 0
|
|
475
|
+
|
|
476
|
+
def test_invalid_bin_parameters(self):
|
|
477
|
+
"""Test invalid bin parameter handling."""
|
|
478
|
+
x_data = pd.Series([1, 2, 3])
|
|
479
|
+
y_data = pd.Series([1, 2, 3])
|
|
480
|
+
|
|
481
|
+
# Invalid min_per_bin type
|
|
482
|
+
with pytest.raises((TypeError, ValueError)):
|
|
483
|
+
SpiralMesh(x_data, y_data, [0, 1], [0, 1], min_per_bin="invalid")
|
|
484
|
+
|
|
485
|
+
def test_mismatched_data_lengths(self):
|
|
486
|
+
"""Test handling of mismatched x, y data lengths."""
|
|
487
|
+
x_data = pd.Series([1, 2, 3])
|
|
488
|
+
y_data = pd.Series([1, 2]) # Different length
|
|
489
|
+
edges = np.array([0, 1, 2])
|
|
490
|
+
|
|
491
|
+
# pandas concat fills missing values with NaN
|
|
492
|
+
mesh = SpiralMesh(x_data, y_data, edges, edges, min_per_bin=1)
|
|
493
|
+
# Data preserves the longer length but has NaN values
|
|
494
|
+
assert len(mesh.data) == 3
|
|
495
|
+
assert mesh.data.isnull().any().any() # Should have NaN values
|
|
496
|
+
|
|
497
|
+
def test_numba_function_edge_cases(self):
|
|
498
|
+
"""Test numba functions with edge case inputs."""
|
|
499
|
+
# Single bin
|
|
500
|
+
single_bin = np.array([[0, 1, 0, 1]], dtype=np.float64)
|
|
501
|
+
x = np.array([0.5])
|
|
502
|
+
y = np.array([0.5])
|
|
503
|
+
|
|
504
|
+
counts = get_counts_per_bin(single_bin, x, y)
|
|
505
|
+
assert len(counts) == 1
|
|
506
|
+
assert counts[0] == 1
|
|
507
|
+
|
|
508
|
+
zbin, fill, visited = calculate_bin_number_with_numba(single_bin, x, y)
|
|
509
|
+
assert len(zbin) == 1
|
|
510
|
+
assert zbin[0] == 0 # Should be assigned to bin 0
|
|
511
|
+
|
|
512
|
+
|
|
513
|
+
class TestSpiralPerformance:
|
|
514
|
+
"""Test performance characteristics of spiral components."""
|
|
515
|
+
|
|
516
|
+
def test_numba_compilation(self):
|
|
517
|
+
"""Test that numba functions compile successfully."""
|
|
518
|
+
# Small test to trigger JIT compilation
|
|
519
|
+
bins = np.array([[0, 1, 0, 1]], dtype=np.float64)
|
|
520
|
+
x = np.array([0.5])
|
|
521
|
+
y = np.array([0.5])
|
|
522
|
+
|
|
523
|
+
# First call triggers compilation
|
|
524
|
+
counts1 = get_counts_per_bin(bins, x, y)
|
|
525
|
+
|
|
526
|
+
# Second call should use compiled version
|
|
527
|
+
counts2 = get_counts_per_bin(bins, x, y)
|
|
528
|
+
|
|
529
|
+
assert np.array_equal(counts1, counts2)
|
|
530
|
+
|
|
531
|
+
def test_large_dataset_handling(self):
|
|
532
|
+
"""Test handling of reasonably large datasets."""
|
|
533
|
+
# Create larger dataset (but not too large for CI)
|
|
534
|
+
n_points = 5000
|
|
535
|
+
x_large = pd.Series(np.random.uniform(0, 10, n_points))
|
|
536
|
+
y_large = pd.Series(np.random.uniform(0, 10, n_points))
|
|
537
|
+
edges = np.linspace(0, 10, 11) # 10 bins
|
|
538
|
+
|
|
539
|
+
mesh = SpiralMesh(x_large, y_large, edges, edges, min_per_bin=10)
|
|
540
|
+
|
|
541
|
+
# Should handle large datasets without memory issues
|
|
542
|
+
initial_bins = mesh.initialize_bins()
|
|
543
|
+
assert initial_bins.shape[0] == 100 # 10x10 grid
|
|
544
|
+
assert len(mesh.data) == n_points
|
|
545
|
+
|
|
546
|
+
|
|
547
|
+
class TestSpiralDocumentation:
|
|
548
|
+
"""Test documentation and docstrings."""
|
|
549
|
+
|
|
550
|
+
def test_module_docstring(self):
|
|
551
|
+
"""Test that module has docstring."""
|
|
552
|
+
assert spiral_module.__doc__ is not None
|
|
553
|
+
assert len(spiral_module.__doc__.strip()) > 0
|
|
554
|
+
|
|
555
|
+
def test_function_docstrings(self):
|
|
556
|
+
"""Test that functions have docstrings."""
|
|
557
|
+
# Note: numba functions may not preserve docstrings
|
|
558
|
+
# Just test that they are callable
|
|
559
|
+
assert callable(get_counts_per_bin)
|
|
560
|
+
assert callable(calculate_bin_number_with_numba)
|
|
561
|
+
|
|
562
|
+
def test_class_docstrings(self):
|
|
563
|
+
"""Test that classes have docstrings."""
|
|
564
|
+
# SpiralMesh may not have docstrings, just test it exists and is callable
|
|
565
|
+
assert callable(SpiralMesh)
|
|
566
|
+
|
|
567
|
+
# SpiralPlot2D should have docstring
|
|
568
|
+
assert SpiralPlot2D.__doc__ is not None
|
|
569
|
+
assert len(SpiralPlot2D.__doc__.strip()) > 0
|
|
570
|
+
|
|
571
|
+
|
|
572
|
+
if __name__ == "__main__":
|
|
573
|
+
pytest.main([__file__])
|