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.

Files changed (412) hide show
  1. plans/.velocity/metrics.json +96 -0
  2. plans/0-overview-template.md +268 -0
  3. plans/N-phase-template.md +106 -0
  4. plans/PLAN_AUDIT_SUMMARY.md +173 -0
  5. plans/TEMPLATE-USAGE-GUIDE.md +198 -0
  6. plans/__init__.py +1 -0
  7. plans/abandoned/compaction-agent-system/0-Overview.md +123 -0
  8. plans/abandoned/compaction-agent-system/agents-index-update-plan.md +109 -0
  9. plans/abandoned/compaction-agent-system/compacted_state.md +85 -0
  10. plans/abandoned/compaction-agent-system/implementation-plan.md +107 -0
  11. plans/abandoned/compaction-agent-system/system-validation-report.md +159 -0
  12. plans/abandoned/compaction-agent-system/usage-guide.md +210 -0
  13. plans/abandoned/hook-system-enhancement/0-Overview.md +214 -0
  14. plans/abandoned/hook-system-enhancement/1-Phase1-Core-Infrastructure.md +313 -0
  15. plans/abandoned/hook-system-enhancement/2-Phase2-Intelligent-Testing.md +385 -0
  16. plans/abandoned/hook-system-enhancement/3-Phase3-Physics-Validation.md +444 -0
  17. plans/abandoned/hook-system-enhancement/4-Phase4-Performance-Monitoring.md +458 -0
  18. plans/abandoned/hook-system-enhancement/5-Phase5-Developer-Experience.md +532 -0
  19. plans/abandoned/hook-system-enhancement/6-Implementation-Timeline.md +274 -0
  20. plans/abandoned/hook-system-enhancement/7-Risk-Management.md +376 -0
  21. plans/abandoned/hook-system-enhancement/8-Testing-Strategy.md +579 -0
  22. plans/abandoned/readthedocs-automation/0-Overview.md +247 -0
  23. plans/abandoned/readthedocs-automation/1-Emergency-Documentation-Fixes.md +270 -0
  24. plans/abandoned/readthedocs-automation/2-Template-System-Enhancement.md +811 -0
  25. plans/abandoned/readthedocs-automation/3-Quality-Audit-ReadTheDocs-Integration.md +844 -0
  26. plans/abandoned/readthedocs-automation/4-Plan-Consolidation-Cleanup.md +632 -0
  27. plans/abandoned/readthedocs-automation/9-Closeout.md +207 -0
  28. plans/abandoned/readthedocs-automation/ABANDONMENT_REASON.md +72 -0
  29. plans/cicd-architecture-redesign/0-Overview.md +193 -0
  30. plans/cicd-architecture-redesign/1-Workflow-Creation.md +103 -0
  31. plans/cicd-architecture-redesign/2-Version-Detection.md +123 -0
  32. plans/cicd-architecture-redesign/3-Deployment-Gates.md +169 -0
  33. plans/cicd-architecture-redesign/4-RC-Testing.md +194 -0
  34. plans/cicd-architecture-redesign/5-TestPyPI-Validation.md +264 -0
  35. plans/cicd-architecture-redesign/6-Production-Release.md +263 -0
  36. plans/cicd-architecture-redesign/7-Cleanup.md +243 -0
  37. plans/cicd-architecture-redesign/8-Documentation.md +285 -0
  38. plans/cicd-architecture-redesign/Closeout.md +225 -0
  39. plans/closeout-template.md +259 -0
  40. plans/completed/circular-import-audit/0-Overview.md +152 -0
  41. plans/completed/circular-import-audit/1-Static-Dependency-Analysis.md +62 -0
  42. plans/completed/circular-import-audit/2-Dynamic-Import-Testing.md +56 -0
  43. plans/completed/circular-import-audit/3-Performance-Impact-Assessment.md +56 -0
  44. plans/completed/circular-import-audit/4-Issue-Remediation.md +78 -0
  45. plans/completed/circular-import-audit/5-Preventive-Infrastructure.md +89 -0
  46. plans/completed/claude-settings-ecosystem-alignment/0-Overview.md +162 -0
  47. plans/completed/claude-settings-ecosystem-alignment/1-Security-Foundation.md +148 -0
  48. plans/completed/claude-settings-ecosystem-alignment/2-Hook-Integration.md +158 -0
  49. plans/completed/claude-settings-ecosystem-alignment/3-Agent-System-Integration.md +177 -0
  50. plans/completed/claude-settings-ecosystem-alignment/4-Enhanced-Workflow-Automation.md +159 -0
  51. plans/completed/claude-settings-ecosystem-alignment/5-Validation-Monitoring.md +181 -0
  52. plans/completed/claude-settings-ecosystem-alignment/compacted_session_state.md +290 -0
  53. plans/completed/combined_plan_with_checklist_documentation/1-Overview-and-Goals.md +51 -0
  54. plans/completed/combined_plan_with_checklist_documentation/2-Toolchain-and-Hosting.md +69 -0
  55. plans/completed/combined_plan_with_checklist_documentation/3-Repository-Structure.md +61 -0
  56. plans/completed/combined_plan_with_checklist_documentation/4-Configuration-and-Standards.md +70 -0
  57. plans/completed/combined_plan_with_checklist_documentation/5-Documentation-Content.md +62 -0
  58. plans/completed/combined_plan_with_checklist_documentation/6-CI-CD-and-Validation.md +58 -0
  59. plans/completed/combined_plan_with_checklist_documentation/7-Maintenance.md +55 -0
  60. plans/completed/combined_test_plan_with_checklist_fitfunctions/0-Overview.md +135 -0
  61. plans/completed/combined_test_plan_with_checklist_fitfunctions/1-Common-fixtures.md +59 -0
  62. plans/completed/combined_test_plan_with_checklist_fitfunctions/10-power_laws.md +56 -0
  63. plans/completed/combined_test_plan_with_checklist_fitfunctions/2-core.py-FitFunction.md +118 -0
  64. plans/completed/combined_test_plan_with_checklist_fitfunctions/3-gaussians.py-Gaussian-GaussianNormalized-GaussianLn.md +69 -0
  65. plans/completed/combined_test_plan_with_checklist_fitfunctions/4-trend_fits.py-TrendFit.md +99 -0
  66. plans/completed/combined_test_plan_with_checklist_fitfunctions/5-plots.py-FFPlot.md +98 -0
  67. plans/completed/combined_test_plan_with_checklist_fitfunctions/6-tex_info.py-TeXinfo.md +79 -0
  68. plans/completed/combined_test_plan_with_checklist_fitfunctions/7-Justification.md +49 -0
  69. plans/completed/combined_test_plan_with_checklist_fitfunctions/8-exponentials.md +64 -0
  70. plans/completed/combined_test_plan_with_checklist_fitfunctions/9-lines.md +58 -0
  71. plans/completed/combined_test_plan_with_checklist_plotting/0-Overview.md +142 -0
  72. plans/completed/combined_test_plan_with_checklist_plotting/1-base.py.md +90 -0
  73. plans/completed/combined_test_plan_with_checklist_plotting/10-labels-special.py.md +102 -0
  74. plans/completed/combined_test_plan_with_checklist_plotting/11-labels-chemistry.py.md +212 -0
  75. plans/completed/combined_test_plan_with_checklist_plotting/12-labels-composition.py.md +242 -0
  76. plans/completed/combined_test_plan_with_checklist_plotting/13-labels-datetime.py.md +247 -0
  77. plans/completed/combined_test_plan_with_checklist_plotting/14-labels-elemental_abundance.py.md +274 -0
  78. plans/completed/combined_test_plan_with_checklist_plotting/15-visual-validation.md +256 -0
  79. plans/completed/combined_test_plan_with_checklist_plotting/16-integration-testing.md +266 -0
  80. plans/completed/combined_test_plan_with_checklist_plotting/17-performance-benchmarks.md +267 -0
  81. plans/completed/combined_test_plan_with_checklist_plotting/18-Fixtures-and-Utilities.md +86 -0
  82. plans/completed/combined_test_plan_with_checklist_plotting/2-agg_plot.py.md +90 -0
  83. plans/completed/combined_test_plan_with_checklist_plotting/3-histograms.py.md +201 -0
  84. plans/completed/combined_test_plan_with_checklist_plotting/4-scatter.py.md +167 -0
  85. plans/completed/combined_test_plan_with_checklist_plotting/5-spiral.py.md +216 -0
  86. plans/completed/combined_test_plan_with_checklist_plotting/6-orbits.py.md +108 -0
  87. plans/completed/combined_test_plan_with_checklist_plotting/7-tools.py.md +86 -0
  88. plans/completed/combined_test_plan_with_checklist_plotting/8-select_data_from_figure.py.md +97 -0
  89. plans/completed/combined_test_plan_with_checklist_plotting/9-labels-base.py.md +88 -0
  90. plans/completed/combined_test_plan_with_checklist_solar_activity/.gitkeep +0 -0
  91. plans/completed/combined_test_plan_with_checklist_solar_activity/0-Overview.md +170 -0
  92. plans/completed/combined_test_plan_with_checklist_solar_activity/1-Package-Entry-Point-__init__.py.md +121 -0
  93. plans/completed/combined_test_plan_with_checklist_solar_activity/2-Core-Base-Classes-base.py.md +142 -0
  94. plans/completed/combined_test_plan_with_checklist_solar_activity/3-Plotting-Helpers-plots.py.md +123 -0
  95. plans/completed/combined_test_plan_with_checklist_solar_activity/4-LISIRD-Sub-package.md +119 -0
  96. plans/completed/combined_test_plan_with_checklist_solar_activity/5-Extrema-Calculator.md +103 -0
  97. plans/completed/combined_test_plan_with_checklist_solar_activity/6-Sunspot-Number-Sub-package.md +163 -0
  98. plans/completed/combined_test_plan_with_checklist_solar_activity/7-Sunspot-Number-Init.py.md +217 -0
  99. plans/completed/combined_test_plan_with_checklist_solar_activity/compacted_state.md +52 -0
  100. plans/completed/compaction-agent-modernization/0-Overview.md +156 -0
  101. plans/completed/compaction-agent-modernization/1-Architecture-Audit-Gap-Analysis.md +132 -0
  102. plans/completed/compaction-agent-modernization/2-Token-Baseline-Recalibration.md +153 -0
  103. plans/completed/compaction-agent-modernization/3-Agent-Reference-Updates.md +184 -0
  104. plans/completed/compaction-agent-modernization/4-Compression-Algorithm-Modernization.md +238 -0
  105. plans/completed/compaction-agent-modernization/5-Workflow-Integration-Streamlining.md +252 -0
  106. plans/completed/compaction-agent-modernization/6-Template-Structure-Optimization.md +240 -0
  107. plans/completed/compaction-agent-modernization/7-Integration-Testing-Validation.md +292 -0
  108. plans/completed/compaction-hook-enhancement/0-Overview.md +150 -0
  109. plans/completed/compaction-hook-enhancement/1-Token-Estimation-Enhancement.md +179 -0
  110. plans/completed/compaction-hook-enhancement/2-Compression-Intelligence.md +294 -0
  111. plans/completed/compaction-hook-enhancement/3-Git-Integration-Metadata.md +310 -0
  112. plans/completed/compaction-hook-enhancement/4-Session-Continuity-Features.md +358 -0
  113. plans/completed/compaction-hook-enhancement/5-Testing-Strategy.md +404 -0
  114. plans/completed/compaction-hook-enhancement/6-Integration-Roadmap.md +319 -0
  115. plans/completed/compaction-hook-enhancement/compacted_state.md +142 -0
  116. plans/completed/docstring-audit-enhancement/0-Overview.md +274 -0
  117. plans/completed/docstring-audit-enhancement/1-Infrastructure-Setup-and-Validation-Tools.md +206 -0
  118. plans/completed/docstring-audit-enhancement/2-Core-Physics-Modules-Enhancement.md +237 -0
  119. plans/completed/docstring-audit-enhancement/3-Fitfunctions-Mathematical-Modules-Enhancement.md +188 -0
  120. plans/completed/docstring-audit-enhancement/4-Plotting-Visualization-Modules-Enhancement.md +243 -0
  121. plans/completed/docstring-audit-enhancement/5-Specialized-Modules-Enhancement.md +216 -0
  122. plans/completed/docstring-audit-enhancement/6-Validation-and-Integration.md +216 -0
  123. plans/completed/fitfunctions-testing-implementation/0-Overview.md +130 -0
  124. plans/completed/fitfunctions-testing-implementation/1-Test-Infrastructure-Setup.md +79 -0
  125. plans/completed/fitfunctions-testing-implementation/2-Common-Fixtures-Test-Utilities.md +104 -0
  126. plans/completed/fitfunctions-testing-implementation/3-Core-FitFunction-Testing.md +168 -0
  127. plans/completed/fitfunctions-testing-implementation/4-Specialized-Function-Classes.md +210 -0
  128. plans/completed/fitfunctions-testing-implementation/5-Advanced-Classes-Testing.md +214 -0
  129. plans/completed/fitfunctions-testing-implementation/6-Plotting-Integration-Testing.md +231 -0
  130. plans/completed/fitfunctions-testing-implementation/7-Extended-Coverage-BONUS.md +184 -0
  131. plans/completed/numpy-docstring-conversion-plan/numpy-docstring-conversion-plan.md +118 -0
  132. plans/completed/pr-review-remediation/0-Overview.md +138 -0
  133. plans/completed/pr-review-remediation/1-Critical-Safety-Improvements.md +179 -0
  134. plans/completed/pr-review-remediation/2-Smart-Timeouts-Validation.md +399 -0
  135. plans/completed/pr-review-remediation/3-Enhanced-GitHub-Integration.md +258 -0
  136. plans/completed/pr-review-remediation/compacted_state.md +66 -0
  137. plans/completed/python-310-migration/0-Overview.md +390 -0
  138. plans/completed/python-310-migration/1-Planning-Setup.md +164 -0
  139. plans/completed/python-310-migration/2-Implementation.md +256 -0
  140. plans/completed/python-310-migration/3-Testing-Validation.md +335 -0
  141. plans/completed/python-310-migration/4-Documentation-Release.md +274 -0
  142. plans/completed/python-310-migration/5-Closeout.md +252 -0
  143. plans/completed/requirements-management-consolidation/0-Overview.md +118 -0
  144. plans/completed/requirements-management-consolidation/1-Documentation-Validation-Environment-Setup.md +116 -0
  145. plans/completed/requirements-management-consolidation/2-Requirements-Consolidation.md +161 -0
  146. plans/completed/requirements-management-consolidation/3-Workflow-Automation-Final-Integration.md +196 -0
  147. plans/completed/single-ecosystem-plan-implementation/0-Overview.md +83 -0
  148. plans/completed/single-ecosystem-plan-implementation/1-Plan-Preservation-Session-Management.md +38 -0
  149. plans/completed/single-ecosystem-plan-implementation/2-File-Structure-Optimization.md +43 -0
  150. plans/completed/single-ecosystem-plan-implementation/3-Plan-Migration-Archive-Setup.md +82 -0
  151. plans/completed/single-ecosystem-plan-implementation/4-Agent-System-Transformation.md +108 -0
  152. plans/completed/single-ecosystem-plan-implementation/5-Template-System-Enhancement.md +131 -0
  153. plans/completed/single-ecosystem-plan-implementation/6-Final-Validation-Testing.md +120 -0
  154. plans/completed/test-directory-consolidation/0-Overview.md +51 -0
  155. plans/completed/test-directory-consolidation/1-Structure-Preparation.md +82 -0
  156. plans/completed/test-directory-consolidation/2-File-Migration.md +100 -0
  157. plans/completed/test-directory-consolidation/3-Import-Transformation.md +117 -0
  158. plans/completed/test-directory-consolidation/4-Configuration-Consolidation.md +140 -0
  159. plans/completed/test-directory-consolidation/5-Validation.md +152 -0
  160. plans/completed/test-directory-consolidation/6-Cleanup.md +156 -0
  161. plans/completed/test-planning-agents-architecture/0-Overview.md +79 -0
  162. plans/completed/test-planning-agents-architecture/1-Branch-Isolation-Testing.md +49 -0
  163. plans/completed/test-planning-agents-architecture/2-Cross-Branch-Coordination.md +51 -0
  164. plans/completed/test-planning-agents-architecture/3-Merge-Workflow-Testing.md +48 -0
  165. plans/deployment-semver-pypi-rtd/0-Overview.md +463 -0
  166. plans/deployment-semver-pypi-rtd/1-Semantic-Versioning-Foundation.md +136 -0
  167. plans/deployment-semver-pypi-rtd/2-PyPI-Deployment-Infrastructure.md +168 -0
  168. plans/deployment-semver-pypi-rtd/3-Release-Automation.md +214 -0
  169. plans/deployment-semver-pypi-rtd/4-Plan-Closeout.md +543 -0
  170. plans/deployment-semver-pypi-rtd/compacted_session_state.md +172 -0
  171. plans/deployment-semver-pypi-rtd/compacted_state.md +131 -0
  172. plans/documentation-code-audit/0-Overview.md +393 -0
  173. plans/documentation-code-audit/1-Discovery-Inventory.md +183 -0
  174. plans/documentation-code-audit/2-Execution-Environment-Setup.md +263 -0
  175. plans/documentation-code-audit/3-Systematic-Validation.md +322 -0
  176. plans/documentation-code-audit/4-Code-Example-Remediation.md +358 -0
  177. plans/documentation-code-audit/5-Physics-MultiIndex-Compliance.md +464 -0
  178. plans/documentation-code-audit/6-Doctest-Integration.md +523 -0
  179. plans/documentation-code-audit/7-Reporting-Documentation.md +498 -0
  180. plans/documentation-code-audit/8-Closeout.md +456 -0
  181. plans/documentation-rebuild-session/compacted_state.md +109 -0
  182. plans/documentation-rendering-fixes/0-Overview.md +104 -0
  183. plans/documentation-rendering-fixes/1-Sphinx-Build-Diagnostics-Warning-Audit.md +101 -0
  184. plans/documentation-rendering-fixes/2-Configuration-Infrastructure-Fixes.md +113 -0
  185. plans/documentation-rendering-fixes/3-Docstring-Syntax-Audit-Repair.md +131 -0
  186. plans/documentation-rendering-fixes/4-HTML-Page-Rendering-Verification.md +113 -0
  187. plans/documentation-rendering-fixes/5-Advanced-Documentation-Quality-Assurance.md +119 -0
  188. plans/documentation-rendering-fixes/6-Documentation-Build-Optimization-Testing.md +129 -0
  189. plans/documentation-rendering-fixes/compacted_state.md +132 -0
  190. plans/documentation-template-fix/0-Overview.md +197 -0
  191. plans/documentation-template-fix/1-Template-System-Analysis.md +269 -0
  192. plans/documentation-template-fix/2-Template-Modification.md +609 -0
  193. plans/documentation-template-fix/3-Build-System-Integration.md +766 -0
  194. plans/documentation-template-fix/4-Testing-Validation.md +1399 -0
  195. plans/documentation-template-fix/5-Documentation-Training.md +602 -0
  196. plans/documentation-workflow-fix/0-Overview.md +222 -0
  197. plans/documentation-workflow-fix/1-Immediate-Fixes.md +238 -0
  198. plans/documentation-workflow-fix/2-Configuration-Setup.md +298 -0
  199. plans/documentation-workflow-fix/3-Pre-commit-Integration.md +382 -0
  200. plans/documentation-workflow-fix/4-Workflow-Improvements.md +446 -0
  201. plans/documentation-workflow-fix/5-Documentation-and-Training.md +527 -0
  202. plans/duplicate-object-warnings-fix-plan.md +130 -0
  203. plans/github-issues-migration/0-Overview.md +510 -0
  204. plans/github-issues-migration/1-Foundation-Label-System.md +180 -0
  205. plans/github-issues-migration/2-Migration-Tool-Rewrite.md +235 -0
  206. plans/github-issues-migration/3-CLI-Integration-Automation.md +169 -0
  207. plans/github-issues-migration/4-Validated-Migration.md +252 -0
  208. plans/github-issues-migration/5-Documentation-Training.md +171 -0
  209. plans/github-issues-migration/6-Closeout.md +179 -0
  210. plans/github-workflows-repair/repair-plan.md +299 -0
  211. plans/issues_from_plans.py +342 -0
  212. plans/pr-270-doc-validation-fixes/0-Overview.md +354 -0
  213. plans/pr-270-doc-validation-fixes/1-Critical-PR-Fixes.md +117 -0
  214. plans/pr-270-doc-validation-fixes/2-Framework-Right-Sizing.md +129 -0
  215. plans/pr-270-doc-validation-fixes/3-Sustainable-Documentation.md +126 -0
  216. plans/pr-270-doc-validation-fixes/4-Closeout-Migration.md +143 -0
  217. plans/pr-270-doc-validation-fixes/PLAN_COMPLETED.md +149 -0
  218. plans/python-310-migration/0-Overview.md +390 -0
  219. plans/python-310-migration/1-Planning-Setup.md +164 -0
  220. plans/python-310-migration/2-Implementation.md +256 -0
  221. plans/python-310-migration/3-Testing-Validation.md +335 -0
  222. plans/python-310-migration/4-Documentation-Release.md +274 -0
  223. plans/python-310-migration/5-Closeout.md +252 -0
  224. plans/readthedocs-simplified/0-Overview.md +243 -0
  225. plans/readthedocs-simplified/1-Immediate-Fixes.md +216 -0
  226. plans/readthedocs-simplified/2-Template-Simplification.md +278 -0
  227. plans/readthedocs-simplified/3-ReadTheDocs-Setup.md +298 -0
  228. plans/readthedocs-simplified/4-Testing-Validation.md +328 -0
  229. plans/readthedocs-simplified/5-Closeout.md +231 -0
  230. plans/readthedocs-simplified/compacted_state.md +127 -0
  231. plans/session-compaction-2025-08-12/compacted_state.md +114 -0
  232. plans/session-compaction-2025-08-13/compacted_state.md +145 -0
  233. plans/session-continuity-protocol/0-Overview.md +35 -0
  234. plans/session-continuity-protocol/1-Core-Principles-Framework.md +40 -0
  235. plans/session-continuity-protocol/2-Pre-Session-Validation-System.md +79 -0
  236. plans/session-continuity-protocol/3-Context-Switching-Prevention.md +87 -0
  237. plans/session-continuity-protocol/4-Progress-Tracking-Recovery.md +100 -0
  238. plans/sphinx-warnings-analysis.md +222 -0
  239. plans/systemprompt-optimization/0-Overview.md +447 -0
  240. plans/systemprompt-optimization/1-Deploy-SystemPrompt.md +114 -0
  241. plans/systemprompt-optimization/2-Documentation-Alignment.md +198 -0
  242. plans/systemprompt-optimization/3-Monitoring-Infrastructure.md +396 -0
  243. plans/systemprompt-optimization/4-Implementation-Script.md +450 -0
  244. plans/systemprompt-optimization/9-Closeout.md +165 -0
  245. plans/systemprompt-optimization/compacted_state.md +143 -0
  246. plans/template-value-propositions/0-Overview.md +357 -0
  247. plans/template-value-propositions/1-Value-Proposition-Framework-Design.md +144 -0
  248. plans/template-value-propositions/2-Plan-Template-Enhancement.md +178 -0
  249. plans/template-value-propositions/3-Value-Generator-Hook-Implementation.md +291 -0
  250. plans/template-value-propositions/4-Value-Validator-Hook-Implementation.md +274 -0
  251. plans/template-value-propositions/5-Documentation-Agent-Updates.md +219 -0
  252. plans/template-value-propositions/6-Integration-Testing-Validation.md +247 -0
  253. plans/tests-audit/0-Overview.md +410 -0
  254. plans/tests-audit/1-Discovery-Inventory.md +170 -0
  255. plans/tests-audit/2-Physics-Validation-Audit.md +195 -0
  256. plans/tests-audit/3-Architecture-Compliance.md +195 -0
  257. plans/tests-audit/4-Numerical-Stability-Analysis.md +203 -0
  258. plans/tests-audit/5-Documentation-Enhancement.md +220 -0
  259. plans/tests-audit/6-Audit-Deliverables.md +220 -0
  260. plans/tests-audit/7-Closeout.md +252 -0
  261. plans/tests-audit/artifacts/ARCHITECTURE_COMPLIANCE_REPORT.md +315 -0
  262. plans/tests-audit/artifacts/ARCHITECTURE_RECOMMENDATIONS.md +943 -0
  263. plans/tests-audit/artifacts/COMPREHENSIVE_AUDIT_REPORT.md +356 -0
  264. plans/tests-audit/artifacts/CONTRIBUTING_ENHANCED_TEMPLATE.md +419 -0
  265. plans/tests-audit/artifacts/COVERAGE_GAP_ANALYSIS.md +152 -0
  266. plans/tests-audit/artifacts/DOCUMENTATION_ENHANCEMENT_REPORT.md +502 -0
  267. plans/tests-audit/artifacts/EXECUTIVE_AUDIT_SUMMARY.md +129 -0
  268. plans/tests-audit/artifacts/IMPLEMENTATION_ROADMAP.md +647 -0
  269. plans/tests-audit/artifacts/NUMERICAL_RECOMMENDATIONS.md +739 -0
  270. plans/tests-audit/artifacts/NUMERICAL_STABILITY_GUIDE_TEMPLATE.rst +451 -0
  271. plans/tests-audit/artifacts/NUMERICAL_STABILITY_REPORT.md +301 -0
  272. plans/tests-audit/artifacts/PHASE_3_SUMMARY.md +280 -0
  273. plans/tests-audit/artifacts/PHASE_4_SUMMARY.md +229 -0
  274. plans/tests-audit/artifacts/PHASE_5_SUMMARY.md +292 -0
  275. plans/tests-audit/artifacts/PHASE_6_CLOSEOUT.md +278 -0
  276. plans/tests-audit/artifacts/PHYSICS_GUIDE_TEMPLATE.rst +268 -0
  277. plans/tests-audit/artifacts/PHYSICS_VALIDATION_REPORT.md +235 -0
  278. plans/tests-audit/artifacts/TECHNICAL_DELIVERABLES_PACKAGE.md +2502 -0
  279. plans/tests-audit/artifacts/TEST_INVENTORY.csv +1204 -0
  280. plans/tests-audit/artifacts/TEST_INVENTORY.md +135 -0
  281. plans/tests-audit/artifacts/test_discovery_analysis.py +231 -0
  282. plans/tests-audit/artifacts/test_parser.py +395 -0
  283. solarwindpy/README.md +3 -0
  284. solarwindpy/Untitled.ipynb +54 -0
  285. solarwindpy/__init__.py +74 -0
  286. solarwindpy/core/__init__.py +23 -0
  287. solarwindpy/core/alfvenic_turbulence.py +804 -0
  288. solarwindpy/core/base.py +267 -0
  289. solarwindpy/core/ions.py +309 -0
  290. solarwindpy/core/plasma.py +2133 -0
  291. solarwindpy/core/spacecraft.py +256 -0
  292. solarwindpy/core/tensor.py +90 -0
  293. solarwindpy/core/units_constants.py +199 -0
  294. solarwindpy/core/vector.py +328 -0
  295. solarwindpy/fitfunctions/__init__.py +20 -0
  296. solarwindpy/fitfunctions/core.py +734 -0
  297. solarwindpy/fitfunctions/exponentials.py +188 -0
  298. solarwindpy/fitfunctions/gaussians.py +264 -0
  299. solarwindpy/fitfunctions/lines.py +116 -0
  300. solarwindpy/fitfunctions/moyal.py +71 -0
  301. solarwindpy/fitfunctions/plots.py +751 -0
  302. solarwindpy/fitfunctions/power_laws.py +209 -0
  303. solarwindpy/fitfunctions/tex_info.py +568 -0
  304. solarwindpy/fitfunctions/trend_fits.py +482 -0
  305. solarwindpy/instabilities/__init__.py +16 -0
  306. solarwindpy/instabilities/beta_ani.py +82 -0
  307. solarwindpy/instabilities/verscharen2016.py +631 -0
  308. solarwindpy/plotting/__init__.py +33 -0
  309. solarwindpy/plotting/agg_plot.py +489 -0
  310. solarwindpy/plotting/base.py +465 -0
  311. solarwindpy/plotting/hist1d.py +405 -0
  312. solarwindpy/plotting/hist2d.py +1035 -0
  313. solarwindpy/plotting/histograms.py +1845 -0
  314. solarwindpy/plotting/labels/__init__.py +104 -0
  315. solarwindpy/plotting/labels/base.py +686 -0
  316. solarwindpy/plotting/labels/chemistry.py +19 -0
  317. solarwindpy/plotting/labels/composition.py +100 -0
  318. solarwindpy/plotting/labels/datetime.py +235 -0
  319. solarwindpy/plotting/labels/elemental_abundance.py +73 -0
  320. solarwindpy/plotting/labels/special.py +794 -0
  321. solarwindpy/plotting/orbits.py +515 -0
  322. solarwindpy/plotting/scatter.py +99 -0
  323. solarwindpy/plotting/select_data_from_figure.py +329 -0
  324. solarwindpy/plotting/spiral.py +980 -0
  325. solarwindpy/plotting/tools.py +434 -0
  326. solarwindpy/scripts/__init__.py +1 -0
  327. solarwindpy/scripts/logs/.gitignore +1 -0
  328. solarwindpy/solar_activity/__init__.py +53 -0
  329. solarwindpy/solar_activity/base.py +605 -0
  330. solarwindpy/solar_activity/lisird/__init__.py +3 -0
  331. solarwindpy/solar_activity/lisird/extrema_calculator.py +394 -0
  332. solarwindpy/solar_activity/lisird/lisird.py +319 -0
  333. solarwindpy/solar_activity/plots.py +116 -0
  334. solarwindpy/solar_activity/sunspot_number/.DS_Store +0 -0
  335. solarwindpy/solar_activity/sunspot_number/__init__.py +3 -0
  336. solarwindpy/solar_activity/sunspot_number/sidc.py +556 -0
  337. solarwindpy/solar_activity/sunspot_number/ssn_extrema.csv +72 -0
  338. solarwindpy/solar_activity/sunspot_number/ssn_extrema.csv.silso +72 -0
  339. solarwindpy/tools/__init__.py +162 -0
  340. solarwindpy-0.1.1.dist-info/METADATA +181 -0
  341. solarwindpy-0.1.1.dist-info/RECORD +409 -0
  342. {solarwindpy-0.0.1.dev0.dist-info → solarwindpy-0.1.1.dist-info}/WHEEL +1 -1
  343. solarwindpy-0.1.1.dist-info/licenses/LICENSE.rst +32 -0
  344. solarwindpy-0.1.1.dist-info/top_level.txt +3 -0
  345. tests/__init__.py +1 -0
  346. tests/conftest.py +10 -0
  347. tests/core/__init__.py +1 -0
  348. tests/core/test_alfvenic_turbulence.py +544 -0
  349. tests/core/test_base.py +112 -0
  350. tests/core/test_base_head_tail.py +29 -0
  351. tests/core/test_base_mi_tuples.py +11 -0
  352. tests/core/test_core_verify_datetimeindex.py +32 -0
  353. tests/core/test_ions.py +325 -0
  354. tests/core/test_plasma.py +2581 -0
  355. tests/core/test_plasma_io.py +12 -0
  356. tests/core/test_quantities.py +507 -0
  357. tests/core/test_spacecraft.py +210 -0
  358. tests/core/test_units_constants.py +22 -0
  359. tests/data/epoch.csv +4 -0
  360. tests/data/plasma.csv +4 -0
  361. tests/data/spacecraft.csv +4 -0
  362. tests/fitfunctions/conftest.py +60 -0
  363. tests/fitfunctions/test_core.py +193 -0
  364. tests/fitfunctions/test_exponentials.py +342 -0
  365. tests/fitfunctions/test_gaussians.py +142 -0
  366. tests/fitfunctions/test_lines.py +349 -0
  367. tests/fitfunctions/test_moyal.py +258 -0
  368. tests/fitfunctions/test_plots.py +258 -0
  369. tests/fitfunctions/test_power_laws.py +365 -0
  370. tests/fitfunctions/test_tex_info.py +183 -0
  371. tests/fitfunctions/test_trend_fit_properties.py +31 -0
  372. tests/fitfunctions/test_trend_fits.py +244 -0
  373. tests/plotting/__init__.py +1 -0
  374. tests/plotting/labels/__init__.py +1 -0
  375. tests/plotting/labels/test_chemistry.py +243 -0
  376. tests/plotting/labels/test_composition.py +345 -0
  377. tests/plotting/labels/test_datetime.py +445 -0
  378. tests/plotting/labels/test_elemental_abundance.py +366 -0
  379. tests/plotting/labels/test_init.py +66 -0
  380. tests/plotting/labels/test_labels_base.py +347 -0
  381. tests/plotting/labels/test_special.py +550 -0
  382. tests/plotting/test_agg_plot.py +602 -0
  383. tests/plotting/test_base.py +752 -0
  384. tests/plotting/test_fixtures_utilities.py +775 -0
  385. tests/plotting/test_histograms.py +546 -0
  386. tests/plotting/test_integration.py +675 -0
  387. tests/plotting/test_orbits.py +435 -0
  388. tests/plotting/test_performance.py +708 -0
  389. tests/plotting/test_scatter.py +752 -0
  390. tests/plotting/test_select_data_from_figure.py +1209 -0
  391. tests/plotting/test_spiral.py +573 -0
  392. tests/plotting/test_tools.py +607 -0
  393. tests/plotting/test_visual_validation.py +465 -0
  394. tests/solar_activity/__init__.py +1 -0
  395. tests/solar_activity/lisird/__init__.py +1 -0
  396. tests/solar_activity/lisird/test_extrema_calculator.py +593 -0
  397. tests/solar_activity/lisird/test_lisird_id.py +187 -0
  398. tests/solar_activity/sunspot_number/__init__.py +1 -0
  399. tests/solar_activity/sunspot_number/test_init.py +399 -0
  400. tests/solar_activity/sunspot_number/test_sidc.py +465 -0
  401. tests/solar_activity/sunspot_number/test_sidc_id.py +223 -0
  402. tests/solar_activity/sunspot_number/test_sidc_loader.py +275 -0
  403. tests/solar_activity/sunspot_number/test_ssn_extrema.py +406 -0
  404. tests/solar_activity/test_base.py +656 -0
  405. tests/solar_activity/test_init.py +396 -0
  406. tests/solar_activity/test_plots.py +371 -0
  407. tests/test_circular_imports.py +408 -0
  408. tests/test_issue_titles.py +25 -0
  409. tests/test_statusline.py +298 -0
  410. solarwindpy-0.0.1.dev0.dist-info/METADATA +0 -14
  411. solarwindpy-0.0.1.dev0.dist-info/RECORD +0 -4
  412. solarwindpy-0.0.1.dev0.dist-info/top_level.txt +0 -1
@@ -0,0 +1,258 @@
1
+ import numpy as np
2
+ import pytest
3
+ from pathlib import Path
4
+
5
+ from scipy.optimize import OptimizeResult
6
+
7
+ import matplotlib.pyplot as plt
8
+
9
+ from solarwindpy.fitfunctions.plots import FFPlot, AxesLabels, LogAxes
10
+ from solarwindpy.fitfunctions.core import Observations, UsedRawObs
11
+
12
+
13
+ class DummyTeX:
14
+ """Minimal TeXinfo replacement recording annotation calls."""
15
+
16
+ def __init__(self):
17
+ self.calls = 0
18
+
19
+ def annotate_info(self, ax, **kwargs): # pragma: no cover - simple recorder
20
+ self.calls += 1
21
+ ax.text(0.0, 0.0, "info")
22
+
23
+
24
+ class Label:
25
+ """Helper label providing a ``path`` attribute for testing ``FFPlot.path``."""
26
+
27
+ def __init__(self, label, path):
28
+ self.label = label
29
+ self.path = path
30
+
31
+ def __str__(self):
32
+ return self.label
33
+
34
+
35
+ def make_observations(n):
36
+ """Build ``UsedRawObs`` with ``n`` raw points and every other point used."""
37
+
38
+ x = np.arange(float(n))
39
+ y = 2.0 * x + 1.0
40
+ w = np.ones_like(x)
41
+ mask = np.zeros_like(x, dtype=bool)
42
+ mask[::2] = True
43
+ raw = Observations(x, y, w)
44
+ used = Observations(x[mask], y[mask], w[mask])
45
+ return UsedRawObs(used, raw, mask), y
46
+
47
+
48
+ def make_ffplot(n=5):
49
+ obs, y_fit = make_observations(n)
50
+ tex = DummyTeX()
51
+ fit_res = OptimizeResult(fun=y_fit[obs.tk_observed] - obs.used.y)
52
+ plot = FFPlot(obs, y_fit, tex, fit_res, fitfunction_name="dummy")
53
+ return plot, tex, obs, y_fit
54
+
55
+
56
+ def test_str_returns_class_name():
57
+ """Ensure ``FFPlot.__str__`` yields the class name."""
58
+
59
+ plot, *_ = make_ffplot()
60
+ assert str(plot) == plot.__class__.__name__ == "FFPlot"
61
+
62
+
63
+ def test_initial_properties_and_path():
64
+ plot, tex, obs, y_fit = make_ffplot()
65
+ assert plot.observations is obs
66
+ assert np.all(plot.y_fit == y_fit)
67
+ assert plot.TeX_info is tex
68
+ assert plot.labels == AxesLabels("x", "y")
69
+ assert plot.log == LogAxes(False, False)
70
+ expected = Path("FFPlot") / "dummy" / "x" / "y" / "linX_logY"
71
+ assert plot.path == expected
72
+
73
+ plot.set_labels(x=Label("X", "xp"), y=Label("Y", "yp"), z="Z")
74
+ plot.set_log(x=True, y=True)
75
+ plot.set_fitfunction_name("name")
76
+ expected = Path("FFPlot") / "name" / "xp" / "yp" / "Z" / "logX_logY"
77
+ assert plot.path == expected
78
+
79
+
80
+ def test_setters():
81
+ plot, tex, obs, y_fit = make_ffplot()
82
+ plot.set_fitfunction_name("new")
83
+ assert plot.fitfunction_name == "new"
84
+
85
+ res = OptimizeResult(x=np.array([1.0]))
86
+ plot.set_fit_result(res)
87
+ assert plot.fit_result is res
88
+
89
+ obs2, y_fit2 = make_observations(6)
90
+ plot.set_observations(obs2, y_fit2)
91
+ assert plot.observations is obs2
92
+ assert np.all(plot.y_fit == y_fit2)
93
+
94
+
95
+ def test_set_observations_mismatched_length():
96
+ plot, *_ = make_ffplot()
97
+ obs = plot.observations
98
+ bad_y_fit = np.ones(obs.raw.x.size + 1)
99
+ with pytest.raises(AssertionError):
100
+ plot.set_observations(obs, bad_y_fit)
101
+
102
+
103
+ def test_set_observations_short_y_fit():
104
+ """Ensure shorter ``y_fit`` arrays trigger an assertion."""
105
+ plot, *_ = make_ffplot()
106
+ obs = plot.observations
107
+ bad_y_fit = np.ones(obs.raw.x.size - 1)
108
+ with pytest.raises(AssertionError):
109
+ plot.set_observations(obs, bad_y_fit)
110
+
111
+
112
+ def test_estimate_markevery():
113
+ plot, *_ = make_ffplot(n=5)
114
+ assert plot._estimate_markevery() is None
115
+ plot_big, *_ = make_ffplot(n=1000)
116
+ assert plot_big._estimate_markevery() == 10
117
+
118
+
119
+ def test_format_helpers():
120
+ plot, *_ = make_ffplot()
121
+ plot.set_labels(x="time", y="value")
122
+ plot.set_log(x=True, y=False)
123
+
124
+ fig, ax = plt.subplots()
125
+ plot._format_hax(ax)
126
+ assert ax.get_xlabel() == "time"
127
+ assert ax.get_ylabel() == "value"
128
+ assert ax.get_xscale() == "log"
129
+ assert ax.get_yscale() == "linear"
130
+
131
+ fig2, rax = plt.subplots()
132
+ plot._format_rax(rax, pct=True)
133
+ assert rax.get_ylabel() == r"$\mathrm{Residual} \; [\%]$"
134
+ assert rax.get_xscale() == "log"
135
+ assert rax.get_yscale() == "symlog"
136
+ assert rax.get_ylim() == (-100, 100)
137
+
138
+ fig3, rax2 = plt.subplots()
139
+ plot._format_rax(rax2, pct=False)
140
+ assert rax2.get_ylabel() == r"$\mathrm{Residual} \; [\#]$"
141
+
142
+
143
+ def test_plot_methods_and_annotations(monkeypatch):
144
+ import solarwindpy.fitfunctions.plots as plots
145
+
146
+ plot, tex, *_ = make_ffplot()
147
+
148
+ calls = []
149
+ original = plots.plt.subplots
150
+
151
+ def fake_subplots(*args, **kwargs): # pragma: no cover - small wrapper
152
+ calls.append((args, kwargs))
153
+ return original(*args, **kwargs)
154
+
155
+ monkeypatch.setattr(plots.plt, "subplots", fake_subplots)
156
+
157
+ ax, *_ = plot.plot_raw()
158
+ assert calls and isinstance(ax, plt.Axes)
159
+ calls.clear()
160
+
161
+ ax, *_ = plot.plot_used()
162
+ assert calls
163
+ calls.clear()
164
+
165
+ plot.plot_fit()
166
+ assert calls and tex.calls == 1
167
+ calls.clear()
168
+
169
+ plot.plot_fit(annotate=False)
170
+ assert tex.calls == 1
171
+
172
+ ax = plot.plot_raw_used_fit()
173
+ labels = {t.get_text() for t in ax.get_legend().get_texts()}
174
+ assert labels == {r"$\mathrm{Obs}$", r"$\mathrm{Used}$", r"$\mathrm{Fit}$"}
175
+
176
+ calls.clear()
177
+ plot.plot_residuals()
178
+ assert calls
179
+
180
+
181
+ def test_plot_raw_used_fit_resid(monkeypatch):
182
+ import solarwindpy.fitfunctions.plots as plots
183
+
184
+ plot, tex, *_ = make_ffplot()
185
+
186
+ calls = []
187
+ original = plots.plt.subplots
188
+
189
+ def fake_subplots(*args, **kwargs): # pragma: no cover - small wrapper
190
+ calls.append((args, kwargs))
191
+ return original(*args, **kwargs)
192
+
193
+ monkeypatch.setattr(plots.plt, "subplots", fake_subplots)
194
+
195
+ hax, rax = plot.plot_raw_used_fit_resid()
196
+ assert isinstance(hax, plt.Axes)
197
+ assert isinstance(rax, plt.Axes)
198
+ labels = {t.get_text() for t in hax.get_legend().get_texts()}
199
+ assert labels == {r"$\mathrm{Obs}$", r"$\mathrm{Used}$", r"$\mathrm{Fit}$"}
200
+ assert tex.calls == 1
201
+
202
+ plot.plot_raw_used_fit_resid(annotate=False)
203
+ assert tex.calls == 1
204
+
205
+
206
+ def test_label_log_texinfo():
207
+ plot, tex, *_ = make_ffplot()
208
+ plot.set_labels(y="Y")
209
+ assert plot.labels == AxesLabels("x", "Y")
210
+ with pytest.raises(KeyError):
211
+ plot.set_labels(q="bad")
212
+
213
+ plot.set_log(x=True)
214
+ assert plot.log == LogAxes(True, False)
215
+
216
+ tex2 = DummyTeX()
217
+ plot.set_TeX_info(tex2)
218
+ assert plot.TeX_info is tex2
219
+
220
+
221
+ def test_plot_residuals_simple_pct_false():
222
+ plot, *_ = make_ffplot()
223
+ ax = plot.plot_residuals(kind="simple", pct=False)
224
+ assert isinstance(ax, plt.Axes)
225
+ line = ax.get_lines()[0]
226
+ expected = plot.y_fit[plot.observations.tk_observed] - plot.observations.used.y
227
+ assert np.allclose(line.get_ydata(), expected)
228
+ assert ax.get_ylabel() == r"$\mathrm{Residual} \; [\#]$"
229
+ ax.legend()
230
+ labels = {t.get_text() for t in ax.get_legend().get_texts()}
231
+ assert labels == {r"$\mathrm{ \; Simple}$"}
232
+
233
+
234
+ def test_plot_residuals_robust():
235
+ plot, *_ = make_ffplot()
236
+ ax = plot.plot_residuals(kind="robust")
237
+ assert isinstance(ax, plt.Axes)
238
+ line = ax.get_lines()[0]
239
+ y_fit_used = plot.y_fit[plot.observations.tk_observed]
240
+ expected = 100.0 * (plot.fit_result.fun / y_fit_used)
241
+ assert np.allclose(line.get_ydata(), expected)
242
+ ax.legend()
243
+ labels = {t.get_text() for t in ax.get_legend().get_texts()}
244
+ assert labels == {r"$\mathrm{ \; Robust}$"}
245
+ assert ax.get_ylabel() == r"$\mathrm{Residual} \; [\%]$"
246
+
247
+
248
+ def test_plot_residuals_missing_fun_no_exception():
249
+ plot, *_ = make_ffplot()
250
+ plot.set_fit_result(OptimizeResult())
251
+ ax = plot.plot_residuals(kind="both")
252
+ assert isinstance(ax, plt.Axes)
253
+ lines = ax.get_lines()
254
+ assert len(lines) == 1
255
+ ax.legend()
256
+ labels = {t.get_text() for t in ax.get_legend().get_texts()}
257
+ assert labels == {r"$\mathrm{ \; Simple}$"}
258
+ assert ax.get_ylabel() == r"$\mathrm{Residual} \; [\%]$"
@@ -0,0 +1,365 @@
1
+ """Tests for power law fit functions."""
2
+
3
+ import inspect
4
+ import numpy as np
5
+ import pytest
6
+
7
+ from solarwindpy.fitfunctions.power_laws import (
8
+ PowerLaw,
9
+ PowerLawPlusC,
10
+ PowerLawOffCenter,
11
+ )
12
+
13
+
14
+ @pytest.mark.parametrize(
15
+ "cls, expected_params, sample_args, input_x",
16
+ [
17
+ (PowerLaw, ("x", "A", "b"), (2.0, 3.0, 1.5), 2.0),
18
+ (PowerLawPlusC, ("x", "A", "b", "c"), (2.0, 3.0, 1.5, 1.0), 2.0),
19
+ (PowerLawOffCenter, ("x", "A", "b", "x0"), (2.0, 3.0, 1.5, 0.5), 2.0),
20
+ ],
21
+ )
22
+ def test_function_signature_and_output(cls, expected_params, sample_args, input_x):
23
+ """Test function signatures and basic output for power law classes."""
24
+ x = np.array([1.0, 2.0, 3.0])
25
+ y = np.array([1.0, 4.0, 9.0])
26
+ obj = cls(x, y)
27
+
28
+ # Test function signature
29
+ sig = inspect.signature(obj.function)
30
+ assert tuple(sig.parameters.keys()) == expected_params
31
+
32
+ # Test function call with positive arguments
33
+ result = obj.function(*sample_args)
34
+ assert np.isfinite(result)
35
+ assert result > 0 # Should be positive for positive inputs
36
+
37
+
38
+ @pytest.fixture
39
+ def power_law_data():
40
+ """Generate synthetic power law data for testing."""
41
+ np.random.seed(42)
42
+ x = np.linspace(0.5, 5.0, 20) # Avoid x=0 for power laws
43
+ A, b = 2.0, -1.5
44
+ noise = np.random.normal(0, 0.1, size=x.shape)
45
+ y = A * x**b + noise
46
+ # Ensure y stays positive for log stability
47
+ y = np.maximum(y, 0.01)
48
+ w = np.ones_like(x)
49
+ return x, y, w
50
+
51
+
52
+ @pytest.mark.parametrize("cls", [PowerLaw, PowerLawPlusC, PowerLawOffCenter])
53
+ def test_p0_zero_size_input(cls):
54
+ """Test p0 behavior with zero-size input arrays."""
55
+ x = np.array([])
56
+ y = np.array([])
57
+ obj = cls(x, y)
58
+
59
+ with pytest.raises((ValueError, AssertionError)):
60
+ _ = obj.p0
61
+
62
+
63
+ def test_power_law_p0_estimation(power_law_data):
64
+ """Test initial parameter estimation for PowerLaw class."""
65
+ x, y, w = power_law_data
66
+ obj = PowerLaw(x, y)
67
+
68
+ p0 = obj.p0
69
+ assert len(p0) == 2
70
+ assert isinstance(p0[0], (int, float)) # A
71
+ assert isinstance(p0[1], (int, float)) # b
72
+
73
+
74
+ def test_power_law_plus_c_p0_estimation(power_law_data):
75
+ """Test initial parameter estimation for PowerLawPlusC class."""
76
+ x, y, w = power_law_data
77
+ # Add constant offset
78
+ y_offset = y + 0.5
79
+ obj = PowerLawPlusC(x, y_offset)
80
+
81
+ p0 = obj.p0
82
+ assert len(p0) == 3
83
+ assert isinstance(p0[0], (int, float)) # A
84
+ assert isinstance(p0[1], (int, float)) # b
85
+ assert isinstance(p0[2], (int, float)) # c
86
+
87
+
88
+ def test_power_law_off_center_p0_estimation(power_law_data):
89
+ """Test initial parameter estimation for PowerLawOffCenter class."""
90
+ x, y, w = power_law_data
91
+ obj = PowerLawOffCenter(x, y)
92
+
93
+ p0 = obj.p0
94
+ assert len(p0) == 3
95
+ assert isinstance(p0[0], (int, float)) # A
96
+ assert isinstance(p0[1], (int, float)) # b
97
+ assert isinstance(p0[2], (int, float)) # x0
98
+
99
+
100
+ @pytest.mark.parametrize(
101
+ "cls, expected_tex",
102
+ [
103
+ (PowerLaw, r"f(x)=A x^b"),
104
+ (PowerLawPlusC, r"f(x)=A x^b + c"),
105
+ (PowerLawOffCenter, r"f(x)=A (x-x_0)^b"),
106
+ ],
107
+ )
108
+ def test_TeX_function_strings(cls, expected_tex):
109
+ """Test TeX function representation strings."""
110
+ x = np.array([1.0, 2.0, 4.0])
111
+ y = np.array([2.0, 1.0, 0.5])
112
+ obj = cls(x, y)
113
+ assert obj.TeX_function == expected_tex
114
+
115
+
116
+ @pytest.mark.parametrize("cls", [PowerLaw, PowerLawPlusC, PowerLawOffCenter])
117
+ def test_make_fit_success(cls, power_law_data):
118
+ """Test successful fitting for power law classes."""
119
+ x, y, w = power_law_data
120
+ obj = cls(x, y)
121
+
122
+ # Test fitting succeeds
123
+ obj.make_fit()
124
+
125
+ # Test fit results are available
126
+ assert obj.popt is not None
127
+ assert obj.pcov is not None
128
+ assert obj.chisq_dof is not None
129
+
130
+ # Test output shapes
131
+ assert len(obj.popt) == len(obj.p0)
132
+
133
+
134
+ @pytest.mark.parametrize("cls", [PowerLaw, PowerLawPlusC, PowerLawOffCenter])
135
+ def test_make_fit_insufficient_data(cls):
136
+ """Test fitting failure with insufficient data."""
137
+ x = np.array([1.0]) # Single point
138
+ y = np.array([1.0])
139
+ obj = cls(x, y)
140
+
141
+ # By default, make_fit returns exceptions rather than raising them
142
+ result = obj.make_fit()
143
+ assert isinstance(result, ValueError)
144
+ assert "insufficient data" in str(result).lower()
145
+
146
+
147
+ def test_power_law_perfect_fit():
148
+ """Test PowerLaw with perfect power law data."""
149
+ x = np.array([1.0, 2.0, 4.0, 8.0])
150
+ A, b = 16.0, -2.0
151
+ y = A * x**b # Perfect power law: 16, 4, 1, 0.25
152
+
153
+ obj = PowerLaw(x, y)
154
+ obj.make_fit()
155
+
156
+ # Should recover true parameters accurately
157
+ assert abs(obj.popt["A"] - A) < 1e-10 # A
158
+ assert abs(obj.popt["b"] - b) < 1e-10 # b
159
+
160
+ # Predicted values should match
161
+ y_pred = obj(x)
162
+ assert np.allclose(y_pred, y, rtol=1e-12)
163
+
164
+
165
+ def test_power_law_plus_c_perfect_fit():
166
+ """Test PowerLawPlusC with perfect data."""
167
+ x = np.array([1.0, 2.0, 4.0, 8.0])
168
+ A, b, c = 16.0, -2.0, 2.0
169
+ y = A * x**b + c # 18, 6, 3, 2.25
170
+
171
+ obj = PowerLawPlusC(x, y)
172
+ obj.make_fit()
173
+
174
+ # Should recover parameters accurately
175
+ assert abs(obj.popt["A"] - A) < 1e-10 # A
176
+ assert abs(obj.popt["b"] - b) < 1e-10 # b
177
+ assert abs(obj.popt["c"] - c) < 1e-10 # c
178
+
179
+ y_pred = obj(x)
180
+ assert np.allclose(y_pred, y, rtol=1e-12)
181
+
182
+
183
+ def test_power_law_off_center_perfect_fit():
184
+ """Test PowerLawOffCenter with perfect data."""
185
+ x = np.array([2.0, 3.0, 5.0, 9.0])
186
+ A, b, x0 = 4.0, 2.0, 1.0
187
+ y = A * (x - x0) ** b # 4*1^2, 4*2^2, 4*4^2, 4*8^2 = 4, 16, 64, 256
188
+
189
+ obj = PowerLawOffCenter(x, y)
190
+ obj.make_fit()
191
+
192
+ # Should recover parameters
193
+ assert abs(obj.popt["A"] - A) < 1e-10 # A
194
+ assert abs(obj.popt["b"] - b) < 1e-10 # b
195
+ assert abs(obj.popt["x0"] - x0) < 1e-10 # x0
196
+
197
+ y_pred = obj(x)
198
+ assert np.allclose(y_pred, y, rtol=1e-12)
199
+
200
+
201
+ def test_power_law_numerical_stability():
202
+ """Test power law functions handle extreme values."""
203
+ x = np.array([0.1, 1.0, 10.0])
204
+ y = np.array([10.0, 1.0, 0.1])
205
+
206
+ obj = PowerLaw(x, y)
207
+
208
+ # Test with extreme parameters
209
+ result1 = obj.function(0.1, 1.0, -10.0) # Very negative exponent
210
+ assert np.isfinite(result1)
211
+ assert result1 > 0
212
+
213
+ result2 = obj.function(10.0, 1.0, 0.1) # Very small exponent
214
+ assert np.isfinite(result2)
215
+ assert result2 > 0
216
+
217
+
218
+ def test_power_law_zero_handling():
219
+ """Test power law behavior with zero and near-zero values."""
220
+ x = np.array([0.01, 1.0, 100.0]) # Avoid exactly zero
221
+ y = np.array([1.0, 1.0, 1.0])
222
+
223
+ obj = PowerLaw(x, y)
224
+
225
+ # Test function behavior near zero
226
+ result = obj.function(0.01, 1.0, 1.0)
227
+ assert np.isfinite(result)
228
+
229
+ # Test with zero exponent (should give constant)
230
+ result_zero_exp = obj.function(2.0, 5.0, 0.0)
231
+ assert abs(result_zero_exp - 5.0) < 1e-10
232
+
233
+
234
+ def test_power_law_off_center_centering():
235
+ """Test that PowerLawOffCenter properly handles centering."""
236
+ x = np.array([2.0, 3.0, 4.0, 5.0])
237
+ x0 = 1.5
238
+
239
+ obj = PowerLawOffCenter(x, np.ones_like(x))
240
+
241
+ # Test that centering works correctly
242
+ result = obj.function(x, 2.0, 1.0, x0)
243
+ expected = 2.0 * (x - x0) ** 1.0
244
+ assert np.allclose(result, expected)
245
+
246
+
247
+ @pytest.mark.parametrize("cls", [PowerLaw, PowerLawPlusC, PowerLawOffCenter])
248
+ def test_str_and_call_methods(cls, power_law_data):
249
+ """Test string representation and callable interface."""
250
+ x, y, w = power_law_data
251
+ obj = cls(x, y)
252
+ obj.make_fit()
253
+
254
+ # Test string representation
255
+ str_repr = str(obj)
256
+ assert cls.__name__ in str_repr
257
+
258
+ # Test callable interface
259
+ x_test = np.array([1.0, 2.0, 3.0])
260
+ y_pred = obj(x_test)
261
+ assert y_pred.shape == x_test.shape
262
+ assert np.all(np.isfinite(y_pred))
263
+ assert np.all(y_pred > 0) # Power laws should be positive
264
+
265
+
266
+ def test_power_law_with_weights(power_law_data):
267
+ """Test power law fitting with observation weights."""
268
+ x, y, w = power_law_data
269
+
270
+ # Create varying weights
271
+ w_varied = np.linspace(0.5, 2.0, len(x))
272
+
273
+ obj = PowerLaw(x, y, weights=w_varied)
274
+ obj.make_fit()
275
+
276
+ # Should complete successfully
277
+ assert obj.popt is not None
278
+ assert len(obj.popt) == 2
279
+
280
+
281
+ def test_power_law_scaling_behavior():
282
+ """Test that PowerLaw exhibits proper scaling behavior."""
283
+ x = np.array([1.0, 2.0, 4.0, 8.0])
284
+ A, b = 2.0, -1.0
285
+ y = A * x**b
286
+
287
+ obj = PowerLaw(x, y)
288
+ obj.make_fit()
289
+
290
+ # Test scaling: if x doubles, y should change by factor of 2^b
291
+ x1, x2 = 2.0, 4.0
292
+ y1, y2 = obj(x1), obj(x2)
293
+ scaling_factor = y2 / y1
294
+ expected_factor = (x2 / x1) ** b
295
+
296
+ assert abs(scaling_factor - expected_factor) < 1e-8 # More realistic tolerance
297
+
298
+
299
+ @pytest.mark.parametrize("cls", [PowerLaw, PowerLawPlusC, PowerLawOffCenter])
300
+ def test_property_access_before_fit(cls):
301
+ """Test accessing properties before fitting."""
302
+ x = np.array([1.0, 2.0, 3.0])
303
+ y = np.array([2.0, 1.0, 0.5])
304
+ obj = cls(x, y)
305
+
306
+ # These should work before fitting
307
+ assert obj.TeX_function is not None
308
+ assert obj.p0 is not None
309
+
310
+ # These should raise AttributeError before fitting
311
+ with pytest.raises(AttributeError):
312
+ _ = obj.popt
313
+ with pytest.raises(AttributeError):
314
+ _ = obj.pcov
315
+
316
+
317
+ def test_power_law_negative_x_handling():
318
+ """Test power law behavior with negative x values."""
319
+ # Only test with even exponents to avoid complex numbers
320
+ x = np.array([-2.0, -1.0, 1.0, 2.0])
321
+
322
+ obj = PowerLaw(x, np.ones_like(x))
323
+
324
+ # Test with even exponent
325
+ result_even = obj.function(x, 1.0, 2.0) # x^2
326
+ assert np.all(np.isfinite(result_even))
327
+ assert np.all(result_even > 0)
328
+
329
+ # Test symmetry for even powers
330
+ assert abs(result_even[0] - result_even[3]) < 1e-10 # (-2)^2 = 2^2
331
+ assert abs(result_even[1] - result_even[2]) < 1e-10 # (-1)^2 = 1^2
332
+
333
+
334
+ def test_power_law_integer_vs_float_exponents():
335
+ """Test that integer and float exponents give consistent results."""
336
+ x = np.array([1.0, 2.0, 3.0])
337
+ A = 2.0
338
+
339
+ obj = PowerLaw(x, np.ones_like(x))
340
+
341
+ # Test integer vs float exponent
342
+ result_int = obj.function(x, A, 2) # Integer exponent
343
+ result_float = obj.function(x, A, 2.0) # Float exponent
344
+
345
+ assert np.allclose(result_int, result_float, rtol=1e-15)
346
+
347
+
348
+ def test_power_law_edge_case_exponents():
349
+ """Test power laws with edge case exponent values."""
350
+ x = np.array([1.0, 2.0, 4.0])
351
+ obj = PowerLaw(x, np.ones_like(x))
352
+
353
+ # Test with b = 1 (linear)
354
+ result_linear = obj.function(x, 3.0, 1.0)
355
+ expected_linear = 3.0 * x
356
+ assert np.allclose(result_linear, expected_linear)
357
+
358
+ # Test with b = 0 (constant)
359
+ result_constant = obj.function(x, 5.0, 0.0)
360
+ assert np.all(result_constant == 5.0)
361
+
362
+ # Test with b = -1 (inverse)
363
+ result_inverse = obj.function(x, 2.0, -1.0)
364
+ expected_inverse = 2.0 / x
365
+ assert np.allclose(result_inverse, expected_inverse)