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.

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.0.dist-info/METADATA +181 -0
  341. solarwindpy-0.1.0.dist-info/RECORD +409 -0
  342. {solarwindpy-0.0.1.dev0.dist-info → solarwindpy-0.1.0.dist-info}/WHEEL +1 -1
  343. solarwindpy-0.1.0.dist-info/licenses/LICENSE.rst +32 -0
  344. solarwindpy-0.1.0.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,734 @@
1
+ #!/usr/bin/env python
2
+ r"""Base classes used to implement specific fit functions.
3
+
4
+ The :class:`FitFunction` abstract base class handles selecting the
5
+ observations to include in a fit, running SciPy optimizers and
6
+ providing convenient plotting helpers. Subclasses need only define
7
+ the functional form and an initial parameter guess.
8
+ """
9
+
10
+ import pdb # noqa: F401
11
+ import logging # noqa: F401
12
+ import warnings
13
+ import numpy as np
14
+
15
+ from abc import ABC, abstractproperty
16
+ from collections import namedtuple
17
+ from inspect import getfullargspec
18
+
19
+ # from scipy.optimize import curve_fit
20
+ from scipy.optimize import least_squares, OptimizeWarning
21
+
22
+ try:
23
+ from scipy.optimize._minpack_py import (
24
+ _wrap_func,
25
+ _wrap_jac,
26
+ _initialize_feasible,
27
+ )
28
+ except ImportError: # pragma: no cover - fall back for older SciPy versions
29
+ from scipy.optimize.minpack import (
30
+ _wrap_func,
31
+ _wrap_jac,
32
+ _initialize_feasible,
33
+ )
34
+ from scipy.optimize._lsq.least_squares import prepare_bounds
35
+ from scipy.linalg import svd, cholesky, LinAlgError
36
+
37
+ from .tex_info import TeXinfo
38
+ from .plots import FFPlot
39
+
40
+ Observations = namedtuple("Observations", "x,y,w")
41
+ UsedRawObs = namedtuple("UsedRawObs", "used,raw,tk_observed")
42
+ InitialGuessInfo = namedtuple("InitialGuessInfo", "p0,bounds")
43
+ ChisqPerDegreeOfFreedom = namedtuple("ChisqPerDegreeOfFreedom", "linear,robust")
44
+ FitBounds = namedtuple("FitBounds", "lower,upper")
45
+
46
+ # def __huber(z):
47
+ # cost = np.array(z)
48
+ # mask = z <= 1
49
+ # cost[~mask] = 2 * z[~mask]**0.5 - 1
50
+ # return cost
51
+ #
52
+ # def __soft_l1(z):
53
+ # t = 1 + z
54
+ # cost = 2 * (t**0.5 - 1)
55
+ # return cost
56
+ #
57
+ # _loss_fcns = {"huber": __huber,
58
+ # "soft_l1": __soft_l1,
59
+ # "cauchy": np.log1p,
60
+ # "arctan": np.arctan}
61
+
62
+
63
+ class FitFunction(ABC):
64
+ r"""Assuming that you don't want special formatting, call order is:
65
+
66
+ fit_function = FitFunction(function, TeX_string)
67
+ fit_function.make_fit()
68
+
69
+ Instances are callable. If the fit fails, calling the instance will return
70
+ an array of NaNs the same shape as the x-values.
71
+ """
72
+
73
+ def __init__(
74
+ self,
75
+ xobs,
76
+ yobs,
77
+ xmin=None,
78
+ xmax=None,
79
+ xoutside=None,
80
+ ymin=None,
81
+ ymax=None,
82
+ youtside=None,
83
+ weights=None,
84
+ wmin=None,
85
+ wmax=None,
86
+ logx=False,
87
+ logy=False,
88
+ ):
89
+ """Initialize a ``FitFunction`` with observed data.
90
+
91
+ Parameters
92
+ ----------
93
+ xobs, yobs : array-like
94
+ Observed ``x`` and ``y`` values.
95
+ xmin, xmax : float, optional
96
+ Range limits for ``x`` used in fitting.
97
+ xoutside : tuple(float, float), optional
98
+ Include data outside this range in the fit.
99
+ ymin, ymax : float, optional
100
+ Range limits for ``y`` used in fitting.
101
+ youtside : tuple(float, float), optional
102
+ Include data outside this range.
103
+ weights : array-like, optional
104
+ Uncertainties associated with ``y``.
105
+ wmin, wmax : float, optional
106
+ Weight limits.
107
+ logx, logy : bool, default False
108
+ Whether to interpret ``x`` or ``y`` on a log10 scale.
109
+ """
110
+
111
+ self._init_logger()
112
+ self._set_argnames()
113
+
114
+ if weights is None:
115
+ assert wmin is None
116
+ assert wmax is None
117
+
118
+ self.set_fit_obs(
119
+ xobs,
120
+ yobs,
121
+ weights,
122
+ xmin=xmin,
123
+ xmax=xmax,
124
+ xoutside=xoutside,
125
+ ymin=ymin,
126
+ ymax=ymax,
127
+ youtside=youtside,
128
+ wmin=wmin,
129
+ wmax=wmax,
130
+ logx=logx,
131
+ logy=logy,
132
+ )
133
+
134
+ def __str__(self):
135
+ return f"{self.__class__.__name__} ({self.TeX_function})"
136
+
137
+ def __call__(self, x):
138
+ """Evaluate the fitted model at ``x``."""
139
+
140
+ # TODO
141
+ # Do you want to have this function accept optional kwarg parameters?
142
+ # It adds a layer of complexity, but could be helfpul.
143
+
144
+ # Sort the parameter keywords into the proper order to pass to the
145
+ # numerical function.
146
+
147
+ # try:
148
+ popt_ = self.popt
149
+ popt_ = [popt_[k] for k in self.argnames]
150
+
151
+ # NOTE
152
+ # An instance of FitFunction is for a given function. To change the
153
+ # function itself, a new instance of FitFunction should be required.
154
+ # Therefore, we access the function directly.
155
+ y = self.function(x, *popt_)
156
+
157
+ # except AttributeError as e:
158
+ # if "'PowerLaw' object has no attribute '_popt'" in str(e):
159
+ # y = np.full_like(x, np.nan, dtype=np.float64)
160
+
161
+ return y
162
+
163
+ @property
164
+ def logger(self):
165
+ return self._logger
166
+
167
+ def _init_logger(self):
168
+ """Create a module-level logger for the instance."""
169
+
170
+ logger = logging.getLogger(f"{__name__}.{self.__class__.__name__}")
171
+ self._logger = logger
172
+
173
+ @abstractproperty
174
+ def function(self):
175
+ r"""Get the function that`curve_fit` fits.
176
+
177
+ The function is set at instantiation. It doesn't make sense to change
178
+ it unless you redefine the entire FitFunction, so there is no `new`
179
+ kwarg.
180
+ """
181
+ pass
182
+
183
+ @abstractproperty
184
+ def p0(self):
185
+ r"""The initial guess for the FitFunction."""
186
+ pass
187
+
188
+ @abstractproperty
189
+ def TeX_function(self):
190
+ r"""Function written in LaTeX."""
191
+ pass
192
+
193
+ @property
194
+ def argnames(self):
195
+ r"""The names of the actual function arguments pulled by getfullargspec."""
196
+ return self._argnames
197
+
198
+ @property
199
+ def fit_bounds(self):
200
+ r"""Bounds used when running the fit."""
201
+ return dict(self._fit_bounds)
202
+
203
+ @property
204
+ def chisq_dof(self):
205
+ r"""Chisq per degree of freedom :math:`\chi^2_\nu`.
206
+
207
+ If None, not calculated by `make_fit_old`. If `np.nan`, fit failed.
208
+ """
209
+ # r = self.residuals(pct=False)
210
+ # sigma = self.observations.used.w
211
+ # if sigma is not None:
212
+ # r = r / sigma
213
+ #
214
+ # chisq = (r ** 2).sum()
215
+ # dof = r.size - len(self.p0)
216
+ # chisq_dof = chisq / dof
217
+ # return chisq_dof
218
+ try:
219
+ return self._chisq_dof
220
+ except AttributeError:
221
+ return None
222
+
223
+ @property
224
+ def dof(self):
225
+ r"""Degrees of freedom in the fit."""
226
+ return self.observations.used.y.size - len(self.p0)
227
+
228
+ @property
229
+ def fit_result(self):
230
+ return self._fit_result
231
+
232
+ @property
233
+ def initial_guess_info(self):
234
+
235
+ # If failed to make an initial guess, then don't build the info.
236
+ try:
237
+ p0 = self.p0
238
+ bounds = self.fit_bounds
239
+ except AttributeError:
240
+ return None
241
+
242
+ names = self.argnames
243
+ info = {
244
+ name: InitialGuessInfo(guess, tuple(bounds[name]))
245
+ for name, guess in zip(names, p0)
246
+ }
247
+
248
+ # info = ["\n".join(param) for param in info]
249
+ # info = "\n\n".join(info)
250
+
251
+ return info
252
+
253
+ @property
254
+ def nobs(self):
255
+ r"""The total number of observations used in the fit."""
256
+ return self.observations.tk_observed.sum()
257
+
258
+ @property
259
+ def observations(self):
260
+ return self._observations
261
+
262
+ @property
263
+ def plotter(self):
264
+ # try:
265
+ return self._plotter
266
+
267
+ # except AttributeError:
268
+ # return self.build_plotter()
269
+
270
+ @property
271
+ def popt(self):
272
+ r"""Optimized fit parameters."""
273
+ return dict(self._popt)
274
+
275
+ @property
276
+ def psigma(self):
277
+ return dict(self._psigma)
278
+
279
+ @property
280
+ def psigma_relative(self):
281
+ return {k: v / self.popt[k] for k, v in self.psigma.items()}
282
+
283
+ @property
284
+ def combined_popt_psigma(self):
285
+ r"""Convenience to extract all versions of the optimized parameters."""
286
+ # try:
287
+ popt = self.popt
288
+ psigma = self.psigma
289
+ prel = self.psigma_relative
290
+ # except AttributeError:
291
+ # popt = {k: np.nan for k in self.argnames}
292
+ # psigma = {k: np.nan for k in self.argnames}
293
+ # prel = {k: np.nan for k in self.argnames}
294
+
295
+ return {"popt": popt, "psigma": psigma, "psigma_relative": prel}
296
+
297
+ @property
298
+ def pcov(self):
299
+ r"""Returns a copy so that the matrix isn't accidentally edited."""
300
+ return self._pcov.copy()
301
+
302
+ @property
303
+ def rsq(self):
304
+ r"""Coefficient of determination.
305
+
306
+ Source: <en.wikipedia.org/wiki/Coefficient_of_determination#Definitions>
307
+ """
308
+ y = self.observations.used.y
309
+ ybar = y.mean()
310
+ yfit = self(self.observations.used.x)
311
+ sum_squares_total = ((y - ybar) ** 2).sum()
312
+ sum_squares_residual = ((y - yfit) ** 2).sum()
313
+ rsq = 1 - (sum_squares_residual / sum_squares_total)
314
+
315
+ return rsq
316
+
317
+ @property
318
+ def sufficient_data(self):
319
+ r"""Ensure that we can fit the data before doing any computations."""
320
+ chk = self.nobs >= len(self.argnames)
321
+ if not chk:
322
+ msg = "There is insufficient data to fit the model."
323
+ raise ValueError(msg)
324
+ else:
325
+ return True
326
+
327
+ @property
328
+ def TeX_info(self):
329
+ # try:
330
+ return self._TeX_info
331
+
332
+ # except AttributeError:
333
+ # return self.build_TeX_info()
334
+
335
+ def _clean_raw_obs(self, xobs, yobs, weights):
336
+ r"""Set the raw x- and y-values along with weights for the fit.
337
+
338
+ Doesn't account for extrema, finite data, etc.
339
+ """
340
+ xobs = np.asarray(xobs)
341
+ yobs = np.asarray(yobs)
342
+ if weights is not None:
343
+ weights = np.asarray(weights)
344
+
345
+ if xobs.shape != yobs.shape:
346
+ raise ValueError(
347
+ f"""xobs and yobs must have the same shape.,
348
+ xobs: {xobs.shape},
349
+ yobs: {yobs.shape}"""
350
+ )
351
+
352
+ if weights is not None and weights.shape != xobs.shape:
353
+ raise ValueError(
354
+ f"""weights and xobs must have the same shape.,
355
+ weighs: {weights.shape}",
356
+ xobs: {xobs.shape}"""
357
+ )
358
+
359
+ return xobs, yobs, weights
360
+
361
+ def _build_one_obs_mask(self, axis, x, xmin, xmax):
362
+ # mask = np.full_like(x, True, dtype=bool)
363
+
364
+ mask = np.isfinite(x)
365
+
366
+ if xmin is not None:
367
+ xmin_mask = x >= xmin
368
+ mask = mask & xmin_mask
369
+
370
+ if xmax is not None:
371
+ xmax_mask = x <= xmax
372
+ mask = mask & xmax_mask
373
+
374
+ return mask
375
+
376
+ def _build_outside_mask(self, axis, x, outside):
377
+ r"""Take data outside of the range `outside[0]:outside[1]`."""
378
+
379
+ if outside is None:
380
+ return np.full_like(x, True, dtype=bool)
381
+
382
+ lower, upper = outside
383
+ assert lower < upper
384
+ l_mask = x <= lower
385
+ u_mask = x >= upper
386
+ mask = l_mask | u_mask
387
+
388
+ return mask
389
+
390
+ def _set_argnames(self):
391
+ r"""Set the arguments of the function/
392
+
393
+ Assume that the first is dependent variable.
394
+ Should be called after function is set.
395
+ """
396
+ args = getfullargspec(self.function).args[1:]
397
+ self._argnames = args
398
+
399
+ def build_plotter(self):
400
+ obs = self.observations
401
+ try:
402
+ yfit = self(self.observations.raw.x)
403
+ except AttributeError:
404
+ yfit = np.full_like(self.observations.raw.x, np.nan)
405
+ # robust_residuals = self.fit_result.fun
406
+ tex_info = self.TeX_info
407
+ fit_result = self.fit_result
408
+
409
+ # try:
410
+ # fit_result = self.fit_result
411
+ # except AttributeError:
412
+ # fit_result = None
413
+
414
+ plotter = FFPlot(
415
+ obs,
416
+ yfit,
417
+ # robust_residuals,
418
+ tex_info,
419
+ fit_result,
420
+ fitfunction_name=self.__class__.__name__,
421
+ )
422
+ self._plotter = plotter
423
+ return plotter
424
+
425
+ def build_TeX_info(self):
426
+
427
+ # Allows annotating of TeX_info when fit fails in a manner
428
+ # that is easily identifiable.
429
+ try:
430
+ popt = self.popt
431
+ except AttributeError:
432
+ popt = {k: np.nan for k in self.argnames}
433
+
434
+ try:
435
+ psigma = self.psigma
436
+ except AttributeError:
437
+ psigma = {k: np.nan for k in self.argnames}
438
+
439
+ tex_info = TeXinfo(
440
+ popt,
441
+ psigma,
442
+ self.TeX_function,
443
+ self.chisq_dof,
444
+ self.rsq,
445
+ initial_guess_info=self.initial_guess_info,
446
+ )
447
+ self._TeX_info = tex_info
448
+ return tex_info
449
+
450
+ def residuals(self, pct=False):
451
+ r"""Calculate the fit residuals.
452
+
453
+ If pct, normalize by fit yvalues.
454
+ """
455
+
456
+ # TODO: calculate with all values
457
+ # Make it an option to calculate with either
458
+ # the values used in the fit or all the values,
459
+ # including those excluded by `set_extrema`.
460
+
461
+ r = self(self.observations.used.x) - self.observations.used.y
462
+ # r = self.fit_result.fun
463
+
464
+ if pct:
465
+ r = 100.0 * (r / self(self.observations.used.x))
466
+
467
+ return r
468
+
469
+ def set_fit_obs(
470
+ self,
471
+ xobs_raw,
472
+ yobs_raw,
473
+ weights_raw,
474
+ xmin=None,
475
+ xmax=None,
476
+ xoutside=None,
477
+ ymin=None,
478
+ ymax=None,
479
+ youtside=None,
480
+ wmin=None,
481
+ wmax=None,
482
+ logx=False,
483
+ logy=False,
484
+ ):
485
+ r"""Set the observed values we'll actually use in the fit.
486
+
487
+ By applying limits to xobs_raw and yobs_raw and checking for finite values.
488
+
489
+ All boundaries are inclusive <= or >=.
490
+
491
+ If logy, then make selection of `wmin` and `wmax` based on :math:`w/(y \ln(10))`.
492
+ """
493
+
494
+ xobs_raw, yobs_raw, weights_raw = self._clean_raw_obs(
495
+ xobs_raw, yobs_raw, weights_raw
496
+ )
497
+
498
+ xmask = self._build_one_obs_mask("xobs", xobs_raw, xmin, xmax)
499
+ ymask = self._build_one_obs_mask("yobs", yobs_raw, ymin, ymax)
500
+ xout_mask = self._build_outside_mask("xobs", xobs_raw, xoutside)
501
+ yout_mask = self._build_outside_mask("yobs", yobs_raw, youtside)
502
+
503
+ mask = xmask & ymask & xout_mask & yout_mask
504
+ if weights_raw is not None:
505
+ weights_for_mask = weights_raw
506
+
507
+ if logy:
508
+ # Enables picking weights based on normalized scale for log stuff
509
+ weights_for_mask = weights_for_mask / (yobs_raw * np.log(10))
510
+
511
+ wmask = self._build_one_obs_mask("weights", weights_for_mask, wmin, wmax)
512
+ mask = mask & wmask
513
+
514
+ xobs = xobs_raw[mask]
515
+ yobs = yobs_raw[mask]
516
+ weights = None
517
+ if weights_raw is not None:
518
+ weights = weights_raw[mask]
519
+
520
+ used = Observations(xobs, yobs, weights)
521
+ raw = Observations(xobs_raw, yobs_raw, weights_raw)
522
+ usedrawobs = UsedRawObs(used, raw, mask)
523
+ self._observations = usedrawobs
524
+
525
+ def _run_least_squares(self, **kwargs):
526
+ """Execute :func:`scipy.optimize.least_squares` with defaults."""
527
+
528
+ p0 = kwargs.pop("p0", self.p0)
529
+ bounds = kwargs.pop("bounds", (-np.inf, np.inf))
530
+ method = kwargs.pop("method", "trf")
531
+ loss = kwargs.pop("loss", "huber")
532
+ max_nfev = kwargs.pop("max_nfev", 10000)
533
+ f_scale = kwargs.pop("f_scale", 0.1)
534
+ jac = kwargs.pop("jac", "2-point")
535
+
536
+ # loss_fcn = _loss_fcns.pop(loss, loss)
537
+
538
+ # Copied from `curve_fit` line 704 (20200527)
539
+ if p0 is None:
540
+ # determine number of parameters by inspecting the function
541
+ from scipy._lib._util import getargspec_no_self as _getargspec
542
+
543
+ args, varargs, varkw, defaults = _getargspec(self.function)
544
+ if len(args) < 2:
545
+ raise ValueError("Unable to determine number of fit parameters.")
546
+ n = len(args) - 1
547
+ else:
548
+ p0 = np.atleast_1d(p0)
549
+ n = p0.size
550
+
551
+ if isinstance(bounds, dict):
552
+ # Monkey patch to work with bounds being stored as
553
+ # dict for TeX_info. (20201202)
554
+ bounds = [bounds[k] for k in self.argnames]
555
+ bounds = np.array(bounds).T
556
+
557
+ # Copied from `curve_fit` line 715 (20200527)
558
+ lb, ub = prepare_bounds(bounds, n)
559
+ if p0 is None:
560
+ p0 = _initialize_feasible(lb, ub)
561
+
562
+ if "args" in kwargs:
563
+ raise ValueError(
564
+ "Adopted `curve_fit` convention for which'args' is not a supported keyword argument."
565
+ )
566
+
567
+ xdata = self.observations.used.x
568
+ ydata = self.observations.used.y
569
+ sigma = self.observations.used.w
570
+
571
+ # Copied from `curve_fit` line 749 (20200527)
572
+ # Determine type of sigma
573
+ if sigma is not None:
574
+ sigma = np.asarray(sigma)
575
+ # sigma = sigma / np.nansum(sigma)
576
+
577
+ # if 1-d, sigma are errors, define transform = 1/sigma
578
+ if sigma.shape == (ydata.size,):
579
+ transform = 1.0 / sigma
580
+ # if 2-d, sigma is the covariance matrix,
581
+ # define transform = L such that L L^T = C
582
+ elif sigma.shape == (ydata.size, ydata.size):
583
+ try:
584
+ # scipy.linalg.cholesky requires lower=True to return L L^T = A
585
+ transform = cholesky(sigma, lower=True)
586
+ except LinAlgError:
587
+ raise ValueError("`sigma` must be positive definite.")
588
+ else:
589
+ raise ValueError("`sigma` has incorrect shape.")
590
+ else:
591
+ transform = None
592
+
593
+ # Copied from `curve_fit` line 769 (20200527)
594
+ loss_func = _wrap_func(self.function, xdata, ydata, transform)
595
+ # Already define default `jac` with `kwargs`. Don't need ELSE clause.
596
+ if callable(jac):
597
+ jac = _wrap_jac(jac, xdata, transform)
598
+
599
+ res = least_squares(
600
+ loss_func,
601
+ p0,
602
+ jac=jac,
603
+ bounds=bounds,
604
+ method=method,
605
+ loss=loss,
606
+ max_nfev=max_nfev,
607
+ f_scale=f_scale,
608
+ **kwargs,
609
+ )
610
+
611
+ if not res.success:
612
+ raise RuntimeError("Optimal parameters not found: " + res.message)
613
+
614
+ fit_bounds = np.concatenate([lb, ub]).reshape((2, -1)).T
615
+ fit_bounds = {k: FitBounds(*b) for k, b in zip(self.argnames, fit_bounds)}
616
+ fit_bounds = tuple(fit_bounds.items())
617
+ self._fit_bounds = fit_bounds
618
+
619
+ # self._loss_fcn = loss_fcn
620
+ return res, p0
621
+
622
+ def _calc_popt_pcov_psigma_chisq(self, res, p0):
623
+ """Compute optimized parameters and statistics from the result."""
624
+
625
+ xdata = self.observations.used.x
626
+ ydata = self.observations.used.y
627
+ sigma = self.observations.used.w
628
+
629
+ # The following is from `curve_fit` line 801 and following. (20200625)
630
+ # `cost` is the robust loss, i.e. residuals passed through loss funciton.
631
+ ysize = len(res.fun)
632
+ cost = 2 * res.cost # res.cost is half sum of squares!
633
+ popt = res.x
634
+
635
+ # Linear chisq_dof value.
636
+ dof = ydata.size - len(p0)
637
+ chisq_dof = np.inf # Divide by zero => infinity
638
+ if dof:
639
+ r = self.function(xdata, *popt) - ydata
640
+ if sigma is not None:
641
+ r /= sigma
642
+ chisq_dof = (r**2).sum() / dof
643
+
644
+ # Do Moore-Penrose inverse discarding zero singular values.
645
+ _, s, VT = svd(res.jac, full_matrices=False)
646
+ threshold = np.finfo(float).eps * max(res.jac.shape) * s[0]
647
+ s = s[s > threshold]
648
+ VT = VT[: s.size]
649
+ pcov = np.dot(VT.T / (s**2), VT)
650
+
651
+ warn_cov = False
652
+ if ysize > p0.size:
653
+ # Cost is robust residuals, so this is robust chisq per dof.
654
+ s_sq = cost / (ysize - p0.size)
655
+ pcov = pcov * s_sq
656
+ else:
657
+ s_sq = np.nan
658
+ pcov.fill(np.inf)
659
+ warn_cov = True
660
+
661
+ if warn_cov:
662
+ warnings.warn(
663
+ "Covariance of the parameters could not be estimated",
664
+ category=OptimizeWarning,
665
+ )
666
+
667
+ psigma = np.sqrt(np.diag(pcov))
668
+
669
+ # Based on `curve_fit`'s `absolute_sigma` documentation and reading
670
+ # `least_square`, `s_sq` should be chisq_nu based on robust residuals
671
+ # that account for `f_scale`(20200527).
672
+ all_chisq = ChisqPerDegreeOfFreedom(chisq_dof, s_sq)
673
+
674
+ return popt, pcov, psigma, all_chisq
675
+
676
+ def make_fit(self, return_exception=False, **kwargs):
677
+ """Fit the function with the independent `xobs` and dependent `yobs`.
678
+
679
+ Uses `least_squares` and returns the `OptimizeResult` object, but
680
+ treats weights as in `curve_fit`.
681
+
682
+ Parameters
683
+ ----------
684
+ return_exception: bool
685
+ If True, return exceptions from fitting routine, instead of raising.
686
+ This is useful when looping through many fits and wanting to
687
+ identify failed fits after the fact.
688
+
689
+ kwargs:
690
+ Unless specified here, defaults are as defined by `curve_fit`.
691
+
692
+ ============= ======================================
693
+ kwarg default
694
+ ============= ======================================
695
+ p0 Setup by `{self.__class__.__name__}`
696
+ return_full False
697
+ method "trf"
698
+ loss "huber"
699
+ max_nfev 10000
700
+ f_scale 0.1
701
+ ============= ======================================
702
+ """
703
+ try:
704
+ assert self.sufficient_data # Check we have enough data to fit.
705
+ except (AssertionError, ValueError) as e:
706
+ # raise
707
+ if isinstance(e, AssertionError):
708
+ e = ValueError("Insufficient data to fit the model")
709
+ return e
710
+
711
+ absolute_sigma = kwargs.pop("absolute_sigma", False)
712
+ if absolute_sigma:
713
+ raise NotImplementedError("We want to rescale fit errors by chisq_dof")
714
+
715
+ try:
716
+ res, p0 = self._run_least_squares(**kwargs)
717
+ except (RuntimeError, ValueError) as e:
718
+ # print("fitting failed", flush=True)
719
+ # raise
720
+ if return_exception:
721
+ return e
722
+ else:
723
+ raise
724
+
725
+ popt, pcov, psigma, all_chisq = self._calc_popt_pcov_psigma_chisq(res, p0)
726
+
727
+ self._popt = list(zip(self.argnames, popt))
728
+ self._psigma = list(zip(self.argnames, psigma))
729
+ self._pcov = pcov
730
+ self._chisq_dof = all_chisq
731
+ self._fit_result = res
732
+
733
+ self.build_TeX_info()
734
+ self.build_plotter()