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,751 @@
1
+ #!/usr/bin/env python
2
+ r"""Plotting utilities for :mod:`solarwindpy.fitfunctions`.
3
+
4
+ This module contains :class:`FFPlot`, a helper for visualizing fitted
5
+ models, residuals and associated annotations.
6
+ """
7
+
8
+ import pdb # noqa: F401
9
+ import logging # noqa: F401
10
+
11
+ import numpy as np
12
+ import matplotlib as mpl
13
+
14
+ from pathlib import Path
15
+ from collections import namedtuple
16
+ from matplotlib import pyplot as plt
17
+
18
+ AxesLabels = namedtuple("AxesLabels", "x,y,z", defaults=(None,))
19
+ LogAxes = namedtuple("LogAxes", "x,y", defaults=(False,))
20
+
21
+
22
+ class FFPlot(object):
23
+ def __init__(self, observations, y_fit, TeX_info, fit_result, fitfunction_name=""):
24
+ """Container for plotting a :class:`~solarwindpy.fitfunctions.FitFunction`.
25
+
26
+ Parameters
27
+ ----------
28
+ observations : :class:`~solarwindpy.fitfunctions.core.Observations`
29
+ Observed data used in the fit.
30
+ y_fit : array-like
31
+ Model evaluated at the observed ``x`` values.
32
+ TeX_info : :class:`~solarwindpy.fitfunctions.tex_info.TeXinfo`
33
+ Object describing the fit for annotation.
34
+ fit_result : scipy.optimize.OptimizeResult
35
+ Result object returned from the fitting routine.
36
+ fitfunction_name : str, optional
37
+ Name of the originating fit function.
38
+ """
39
+
40
+ self.set_observations(observations, y_fit)
41
+ self.set_TeX_info(TeX_info)
42
+ self.set_fit_result(fit_result)
43
+ self.set_fitfunction_name(fitfunction_name)
44
+ self._log = LogAxes(x=False, y=False)
45
+ self._labels = AxesLabels("x", "y")
46
+
47
+ def __str__(self):
48
+ return self.__class__.__name__
49
+
50
+ @property
51
+ def labels(self):
52
+ return self._labels
53
+
54
+ @property
55
+ def log(self):
56
+ return self._log
57
+
58
+ @property
59
+ def observations(self):
60
+ return self._observations
61
+
62
+ @property
63
+ def fitfunction_name(self):
64
+ return self._fitfunction_name
65
+
66
+ @property
67
+ def fit_result(self):
68
+ return self._fit_result
69
+
70
+ @property
71
+ def path(self):
72
+ base = Path(self.__class__.__name__) / self.fitfunction_name
73
+
74
+ try:
75
+ base /= self.labels.x.path
76
+ except AttributeError:
77
+ base /= str(self.labels.x)
78
+
79
+ try:
80
+ base /= self.labels.y.path
81
+ except AttributeError:
82
+ base /= str(self.labels.y)
83
+
84
+ if self.labels.z is not None:
85
+ try:
86
+ base = base / self.labels.z.path
87
+ except AttributeError:
88
+ base = base / str(self.labels.z)
89
+
90
+ x_scale = "logX" if self.log.x else "linX"
91
+ y_scale = "logY" if self.log.y else "logY"
92
+ scale_info = "_".join([x_scale, y_scale])
93
+
94
+ path = base / scale_info
95
+ return path
96
+
97
+ @property
98
+ def TeX_info(self):
99
+ return self._TeX_info
100
+
101
+ @property
102
+ def y_fit(self):
103
+ return self._y_fit
104
+
105
+ def set_fitfunction_name(self, new):
106
+ """Set the descriptive name for saved plots."""
107
+
108
+ self._fitfunction_name = str(new)
109
+
110
+ def set_fit_result(self, new):
111
+ """Store the optimization result object."""
112
+
113
+ self._fit_result = new
114
+
115
+ def set_observations(self, observations, y_fit):
116
+ """Set raw and fitted values used for plotting."""
117
+
118
+ assert y_fit.shape == observations.raw.x.shape
119
+ assert y_fit[observations.tk_observed].shape == observations.used.x.shape
120
+ self._observations = observations
121
+ self._y_fit = y_fit
122
+
123
+ # self._robust_residuals = robust_residuals
124
+
125
+ def _estimate_markevery(self):
126
+ """Heuristic marker spacing for large datasets."""
127
+
128
+ try:
129
+ # Estimate marker density for readability
130
+ markevery = int(
131
+ 10.0 ** (np.floor(np.log10(self.observations.used.x.size) - 1))
132
+ )
133
+ except OverflowError:
134
+ # Or we have a huge number of data points, so lets only
135
+ # mark a few of them.
136
+ markevery = 1000
137
+
138
+ if not markevery:
139
+ markevery = None
140
+
141
+ return markevery
142
+
143
+ def _format_hax(self, ax, with_rax=False):
144
+ r"""Format the plot axes.
145
+
146
+ Format the :py:meth:`plot_bins`, :py:meth:`plot_in_fit`, and
147
+ :py:meth:`plot_fit` results.
148
+ """
149
+ ax.grid(True, which="major", axis="both")
150
+
151
+ # ax.legend(loc=1, framealpha=0) # loc chosen so annotation text defaults work.
152
+
153
+ # Copied from plt.hist. (20161107_0112)
154
+ x = self.observations.raw.x
155
+ if x.size:
156
+ ax.update_datalim([(x[0], 0), (x[-1], 0)], updatey=False)
157
+
158
+ ax.set_xlabel(self.labels.x)
159
+ ax.set_ylabel(self.labels.y)
160
+ if self.log.x:
161
+ ax.set_xscale("log")
162
+ if self.log.y:
163
+ ax.set_yscale("log")
164
+
165
+ # if with_rax:
166
+ # ax.xaxis.get_label().set_visible(False)
167
+ # [t.set_visible(False) for t in ax.xaxis.get_ticklabels()]
168
+
169
+ ax.label_outer()
170
+
171
+ def _format_rax(self, ax, pct):
172
+ ax.grid(True, which="major", axis="both")
173
+
174
+ ax.set_xlabel(self.labels.x)
175
+ if self.log.x:
176
+ ax.set_xscale("log", nonpositive="clip")
177
+
178
+ if pct:
179
+ ax.set_ylabel(r"$\mathrm{Residual} \; [\%]$")
180
+ ax.set_yscale("symlog", linthresh=10)
181
+ ax.set_ylim(-100, 100)
182
+
183
+ else:
184
+ ax.set_ylabel(r"$\mathrm{Residual} \; [\#]$")
185
+
186
+ x = self.observations.raw.x
187
+ if x.size:
188
+ ax.update_datalim([(x[0], 0), (x[-1], 0)], updatey=False)
189
+
190
+ # ax.legend(loc=0, framealpha=0, ncol=2)
191
+
192
+ ax.label_outer()
193
+
194
+ return ax
195
+
196
+ def plot_raw(self, ax=None, plot_window=True, edge_kwargs=None, **kwargs):
197
+ r"""Plot the observations used in the fit from raw data.
198
+
199
+ Plot from :py:meth:`self.observations.raw.x`,
200
+ :py:meth:`self.observations.raw.y`, :py:meth:`self.observations.raw.w`.
201
+
202
+ Parameters
203
+ ----------
204
+ edge_kwargs: None, dict
205
+ If not None, plot edges on the window using these kwargs.
206
+ """
207
+ if ax is None:
208
+ fig, ax = plt.subplots()
209
+
210
+ window_kwargs = kwargs.pop("window_kwargs", dict())
211
+
212
+ kwargs = mpl.cbook.normalize_kwargs(kwargs, mpl.lines.Line2D._alias_map)
213
+ color = kwargs.pop("color", "k")
214
+ label = kwargs.pop("label", r"$\mathrm{Obs}$")
215
+
216
+ x = self.observations.raw.x
217
+ y = self.observations.raw.y
218
+ w = self.observations.raw.w
219
+ # if self.log.y and w is not None:
220
+ # w = w / (y * np.log(10.0))
221
+ # w = np.log10(np.exp(1)) * w / y
222
+
223
+ # # Plot the raw data histograms.
224
+ # plotline, caplines, barlines = ax.errorbar(
225
+ # x, y, yerr=w, label=label, color=color, **kwargs
226
+ # )
227
+
228
+ def _plot_window_edges(ax, **kwargs):
229
+ kwargs = mpl.cbook.normalize_kwargs(
230
+ kwargs, mpl.collections.Collection._alias_map
231
+ )
232
+
233
+ edge1 = ax.plot(x, y1, **kwargs)
234
+ edge2 = ax.plot(x, y2, **kwargs)
235
+
236
+ return edge1, edge2
237
+
238
+ if plot_window:
239
+ if w is None:
240
+ logging.getLogger().warning(
241
+ "No weights. Need weights to plot a window for FitFunction. Setting w to 0."
242
+ )
243
+ w = 0
244
+
245
+ window_kwargs = mpl.cbook.normalize_kwargs(
246
+ window_kwargs, mpl.collections.Collection._alias_map
247
+ )
248
+ window_color = window_kwargs.pop("color", color)
249
+ window_alpha = window_kwargs.pop("alpha", 0.15)
250
+
251
+ line = ax.plot(x, y, label=label, color=color, **kwargs)
252
+
253
+ y1 = y - w
254
+ y2 = y + w
255
+ window = ax.fill_between(
256
+ x,
257
+ y1,
258
+ y2,
259
+ color=window_color,
260
+ alpha=window_alpha,
261
+ **window_kwargs,
262
+ )
263
+
264
+ edges = None
265
+ if edge_kwargs is not None:
266
+ edge_kwargs = mpl.cbook.normalize_kwargs(
267
+ edge_kwargs, mpl.collections.Collection._alias_map
268
+ )
269
+ edge_color = edge_kwargs.pop("color", window_color)
270
+ edges = _plot_window_edges(ax, color=edge_color, **edge_kwargs)
271
+
272
+ plotted = (line, window, edges)
273
+
274
+ else:
275
+ # Plot the raw data histograms.
276
+ plotted = ax.errorbar(
277
+ x,
278
+ y,
279
+ yerr=w,
280
+ label=label,
281
+ color=color,
282
+ **kwargs,
283
+ )
284
+
285
+ self._format_hax(ax)
286
+
287
+ return ax, plotted
288
+
289
+ def plot_used(self, ax=None, plot_window=True, edge_kwargs=None, **kwargs):
290
+ r"""Plot the observations used in the fit from used data.
291
+
292
+ Plot from :py:meth:`self.observations.used.x`,
293
+ :py:meth:`self.observations.used.y`, and :py:meth:`self.observations.used.w`.
294
+ """
295
+ if ax is None:
296
+ fig, ax = plt.subplots()
297
+
298
+ window_kwargs = kwargs.pop("window_kwargs", dict())
299
+
300
+ kwargs = mpl.cbook.normalize_kwargs(kwargs, mpl.lines.Line2D._alias_map)
301
+ color = kwargs.pop("color", "forestgreen")
302
+ marker = kwargs.pop("marker", "P")
303
+ markerfacecolor = kwargs.pop("markerfacecolor", "none")
304
+ markersize = kwargs.pop("markersize", 8)
305
+ markevery = kwargs.pop("markevery", None)
306
+ label = kwargs.pop("label", r"$\mathrm{Used}$")
307
+
308
+ x = self.observations.used.x
309
+ y = self.observations.used.y
310
+ w = self.observations.used.w
311
+ # if self.log.y and w is not None:
312
+ # w = w / (y * np.log(10.0))
313
+ # w = np.log10(np.exp(1)) * w / y
314
+
315
+ if markevery is None:
316
+ markevery = self._estimate_markevery()
317
+
318
+ if plot_window:
319
+ if w is None:
320
+ logging.getLogger().warning(
321
+ "No weights. Need weights to plot a window for FitFunction. Setting w to 0."
322
+ )
323
+ w = 0
324
+
325
+ window_kwargs = mpl.cbook.normalize_kwargs(
326
+ window_kwargs, mpl.collections.Collection._alias_map
327
+ )
328
+ window_color = window_kwargs.pop("color", color)
329
+ window_alpha = window_kwargs.pop("alpha", 0.15)
330
+
331
+ line = ax.plot(
332
+ x,
333
+ y,
334
+ label=label,
335
+ color=color,
336
+ marker=marker,
337
+ markerfacecolor=markerfacecolor,
338
+ markersize=markersize,
339
+ markevery=markevery,
340
+ **kwargs,
341
+ )
342
+
343
+ y1 = y - w
344
+ y2 = y + w
345
+ window = ax.fill_between(
346
+ x,
347
+ y1,
348
+ y2,
349
+ color=window_color,
350
+ alpha=window_alpha,
351
+ **window_kwargs,
352
+ )
353
+
354
+ edges = None
355
+ if edge_kwargs is not None:
356
+
357
+ def _plot_window_edges(ax, **kwargs):
358
+ kwargs = mpl.cbook.normalize_kwargs(
359
+ kwargs, mpl.collections.Collection._alias_map
360
+ )
361
+
362
+ edge1 = ax.plot(x, y1, **kwargs)
363
+ edge2 = ax.plot(x, y2, **kwargs)
364
+
365
+ return edge1, edge2
366
+
367
+ edge_kwargs = mpl.cbook.normalize_kwargs(
368
+ edge_kwargs, mpl.collections.Collection._alias_map
369
+ )
370
+ edge_color = edge_kwargs.pop("color", window_color)
371
+ edges = _plot_window_edges(ax, color=edge_color, **edge_kwargs)
372
+ # edge_kwargs = mpl.cbook.normalize_kwargs(edge_kwargs, mpl.collections.Collection._alias_map)
373
+
374
+ # edge1 = ax.plot(x, y1,
375
+ # color=window_color,
376
+ # **edge_kwargs)
377
+ # edge2 = ax.plot(x, y2,
378
+ # color=window_color,
379
+ # **edge_kwargs)
380
+
381
+ # edges = (edge1, edge2)
382
+
383
+ plotted = (line, window, edges)
384
+
385
+ else:
386
+ # Plot the raw data histograms.
387
+ plotted = ax.errorbar(
388
+ x,
389
+ y,
390
+ yerr=w,
391
+ label=label,
392
+ color=color,
393
+ marker=marker,
394
+ markerfacecolor=markerfacecolor,
395
+ markersize=markersize,
396
+ markevery=markevery,
397
+ **kwargs,
398
+ )
399
+
400
+ self._format_hax(ax)
401
+
402
+ return ax, plotted
403
+
404
+ def plot_fit(self, ax=None, annotate=True, annotate_kwargs=None, **kwargs):
405
+ r"""Plot the fit."""
406
+ if ax is None:
407
+ fig, ax = plt.subplots()
408
+
409
+ if annotate_kwargs is None:
410
+ annotate_kwargs = {}
411
+
412
+ kwargs = mpl.cbook.normalize_kwargs(kwargs, mpl.lines.Line2D._alias_map)
413
+ color = kwargs.pop("color", "darkorange")
414
+ label = kwargs.pop("label", r"$\mathrm{Fit}$")
415
+ linestyle = kwargs.pop("linestyle", (0, (7, 3, 1, 3, 1, 3, 1, 3)))
416
+ # zorder = kwargs.pop("zorder", 2.005) # Ensure it's the top line
417
+
418
+ # Overplot the fit.
419
+ ax.plot(
420
+ self.observations.raw.x,
421
+ self.y_fit,
422
+ label=label,
423
+ color=color,
424
+ linestyle=linestyle,
425
+ # zorder=zorder,
426
+ **kwargs,
427
+ )
428
+
429
+ if annotate:
430
+ self.TeX_info.annotate_info(ax, **annotate_kwargs)
431
+ # self.annotate_TeX_info(ax, **annotate_kwargs)
432
+
433
+ self._format_hax(ax)
434
+
435
+ return ax
436
+
437
+ def plot_raw_used_fit(
438
+ self,
439
+ ax=None,
440
+ drawstyle=None,
441
+ annotate=True,
442
+ raw_kwargs=None,
443
+ used_kwargs=None,
444
+ fit_kwargs=None,
445
+ annotate_kwargs=None,
446
+ ):
447
+ r"""Make a plot of the raw observations, observations in fit, and the fit.
448
+
449
+ Combines the outputs of :py:meth:`self.plot_raw`, :py:meth:`self.plot_used`,
450
+ and :py:meth:`self.plot_fit`.
451
+
452
+ Parameters
453
+ ----------
454
+ ax: None, mpl.Axes.axis_subplot
455
+
456
+ drawstyle: str, None
457
+ `mpl` `drawstyle`, shared by :py:meth:`self.plot_raw` and :py:meth:`self.plot_used`.
458
+ If None, defaults to "steps-mid".
459
+ annotate: True
460
+ If True, add fit info to the annotation using ax.text.
461
+ raw_kwargs: dict
462
+ Passed to `ax.plot(**kwargs)` in :py:meth:`self.plot_raw`.
463
+ used_kwargs: dict
464
+ Passed to `ax.plot(**kwargs)` in :py:meth:`self.plot_used`.
465
+ fit_kwargs: dict
466
+ Passed to `ax.plot(**fit_kwargs)` for plotting fit.
467
+ annotate_kwargs:
468
+ Passed to `ax.text`.
469
+
470
+ Returns
471
+ -------
472
+ ax: mpl.Axes.axis_subplot
473
+ """
474
+
475
+ if ax is None:
476
+ fig, ax = plt.subplots()
477
+
478
+ if raw_kwargs is None:
479
+ raw_kwargs = (
480
+ dict()
481
+ ) # dict(color="darkgreen", markerfacecolor="none", marker="P")
482
+
483
+ if used_kwargs is None:
484
+ used_kwargs = dict() # dict(color="k")
485
+
486
+ if fit_kwargs is None:
487
+ # fit_kwargs = dict() # dict(color="darkorange")
488
+ fit_kwargs = dict(zorder=2.2)
489
+
490
+ if drawstyle is None:
491
+ drawstyle = "steps-mid"
492
+
493
+ self.plot_raw(ax=ax, drawstyle=drawstyle, **raw_kwargs)
494
+ self.plot_used(ax=ax, drawstyle=drawstyle, **used_kwargs)
495
+ self.plot_fit(
496
+ ax=ax, annotate=annotate, annotate_kwargs=annotate_kwargs, **fit_kwargs
497
+ )
498
+
499
+ ax.legend(loc=1, framealpha=0) # loc chosen so annotation text defaults work.
500
+
501
+ # # Copied from plt.hist. (20161107_0112)
502
+ # ax.update_datalim(
503
+ # [(self.observations.raw.x[0], 0), (self.observations.raw.x[-1], 0)], updatey=False
504
+ # )
505
+
506
+ self._format_hax(ax)
507
+
508
+ return ax
509
+
510
+ def plot_residuals(
511
+ self, ax=None, pct=True, subplots_kwargs=None, kind="both", **kwargs
512
+ ):
513
+ r"""Plot residuals for the data used in the fit.
514
+
515
+ Residuals are shown on a symlog scale with ``linthresh=10``. By default
516
+ they are expressed as percentages of the fitted model.
517
+
518
+ Parameters
519
+ ----------
520
+ ax : mpl.axes.Axes, optional
521
+ Axis to draw on. If ``None`` a new figure and axis are created.
522
+ pct : bool, default True
523
+ If ``True``, show residuals as percentages.
524
+ subplots_kwargs : dict, optional
525
+ Passed to ``plt.subplots`` when ``ax`` is ``None``.
526
+ kind : {'simple', 'robust', 'both'}, default "both"
527
+ Which residuals to plot.
528
+ **kwargs
529
+ Additional keyword arguments passed to ``ax.plot``.
530
+
531
+ Returns
532
+ -------
533
+ ax : mpl.axes.Axes
534
+ Axis with residuals plotted.
535
+ """
536
+
537
+ if subplots_kwargs is None:
538
+ subplots_kwargs = {}
539
+
540
+ if ax is None:
541
+ fig, ax = plt.subplots(**subplots_kwargs)
542
+
543
+ kwargs = mpl.cbook.normalize_kwargs(kwargs, mpl.lines.Line2D._alias_map)
544
+ drawstyle = kwargs.pop("drawstyle", "steps-mid")
545
+ # color = kwargs.pop("color", "darkgreen")
546
+ # marker = kwargs.pop("marker", "P")
547
+ markerfacecolor = kwargs.pop("markerfacecolor", "none")
548
+ markersize = kwargs.pop("markersize", 8)
549
+ markevery = kwargs.pop("markevery", None)
550
+ label = kwargs.pop("label", r"").strip("$")
551
+ kind = kind.lower()
552
+
553
+ if markevery is None:
554
+ markevery = self._estimate_markevery()
555
+
556
+ if kind in ("simple", "robust"):
557
+ residuals = self.residuals(
558
+ pct=pct, robust=True if kind == "robust" else False
559
+ )
560
+
561
+ color = kwargs.pop("color", "forestgreen")
562
+ marker = kwargs.pop("marker", "P")
563
+ linestyle = kwargs.pop("linestyle", "-")
564
+
565
+ # Handle empty label case to preserve spacing
566
+ if not label:
567
+ label = r" \; %s" % kind.title()
568
+ label = r"$\mathrm{%s}$" % label
569
+ else:
570
+ label = r" \; ".join([label, kind.title()]).lstrip(r" \; ")
571
+ label = r"$\mathrm{%s}$" % label
572
+ # label = (r"$\mathrm{%s \; %s}$" % (label, kind.title()).replace(" \; ", "")
573
+
574
+ ax.plot(
575
+ self.observations.used.x,
576
+ residuals,
577
+ label=label,
578
+ drawstyle=drawstyle,
579
+ color=color,
580
+ marker=marker,
581
+ linestyle=linestyle,
582
+ markerfacecolor=markerfacecolor,
583
+ markersize=markersize,
584
+ markevery=markevery,
585
+ **kwargs,
586
+ )
587
+
588
+ elif kind == "both":
589
+ # Handle label formatting to preserve spacing correctly
590
+ simple_label = r"$\mathrm{ \; Simple}$" if not label else r"$\mathrm{%s \; Simple}$" % label
591
+ robust_label = r"$\mathrm{ \; Robust}$" if not label else r"$\mathrm{%s \; Robust}$" % label
592
+
593
+ ax.plot(
594
+ self.observations.used.x,
595
+ self.residuals(pct=pct, robust=False),
596
+ label=simple_label,
597
+ drawstyle=drawstyle,
598
+ color="forestgreen",
599
+ marker="P",
600
+ linestyle="-",
601
+ markerfacecolor=markerfacecolor,
602
+ markersize=markersize,
603
+ markevery=markevery,
604
+ **kwargs,
605
+ )
606
+
607
+ try:
608
+ r = self.residuals(pct=pct, robust=True)
609
+ ax.plot(
610
+ self.observations.used.x,
611
+ r,
612
+ label=robust_label,
613
+ drawstyle=drawstyle,
614
+ color="darkorange",
615
+ marker="X",
616
+ linestyle="-",
617
+ markerfacecolor=markerfacecolor,
618
+ markersize=markersize,
619
+ markevery=markevery,
620
+ **kwargs,
621
+ )
622
+ except AttributeError as e:
623
+ if "NoneType" in str(e):
624
+ pass
625
+
626
+ self._format_rax(ax, pct)
627
+ return ax
628
+
629
+ def plot_raw_used_fit_resid(
630
+ self,
631
+ annotate=True,
632
+ fit_resid_axes=None,
633
+ figsize=(6, 4),
634
+ resid_kwargs=None,
635
+ **kwargs,
636
+ ):
637
+ """Make a stacked fit, residual plot.
638
+
639
+ Parameters
640
+ ----------
641
+ annotate: bool
642
+ If True, add fit annotation to axis.
643
+ fit_resid_axes: None, 2-tuple of mpl.axis.Axis
644
+ If not None, (fit, resid) axis pair to plot the (raw, used, fit)
645
+ and residual on, respectively. Otherwise, use `GridSpec` to build
646
+ a pair of axes where the `raw_used_fit` axis is 3 times the `resid_axis`.
647
+ Additionally, if `fit_resid_axes` is None, the `hax` and `rax` will share
648
+ an x-axis and `hax`'s x-ticks and label will be set invisible.
649
+ figsize:
650
+ Any valid argument for :py:meth:`plt.figure(figsize=figsize)`. This code
651
+ was developed with default size 6x4 and this size helps accomodate annotation.
652
+ So we persist it here.
653
+ resid_kwargs: dict, None
654
+ Passed to :py:meth:`{self.__class__.__name__}.plot_residuals`.
655
+ kwargs:
656
+ Passed to :py:meth:`{self.__class__.__name__}.plot_raw_used_fit`.
657
+
658
+ Returns
659
+ -------
660
+ hax: mpl.axis.Axis
661
+ Axis with raw observations, used observations, and fit plotted on it.
662
+ rax: mpl.axis.Axis
663
+ Axis with residuals plotted on it.
664
+ """
665
+
666
+ if fit_resid_axes is not None:
667
+ hax, rax = fit_resid_axes
668
+
669
+ else:
670
+ fig = plt.figure(figsize=figsize)
671
+ gs = mpl.gridspec.GridSpec(2, 1, height_ratios=[3, 1], hspace=0.1)
672
+ # sharex in this code requires that I pass the axis object with which the x-axis is being shared.
673
+ # Source for sharex option: http://stackoverflow.com/questions/22511550/gridspec-with-shared-axes-in-python
674
+ rax = fig.add_subplot(gs[1])
675
+ hax = fig.add_subplot(gs[0], sharex=rax)
676
+
677
+ if resid_kwargs is None:
678
+ resid_kwargs = dict()
679
+
680
+ resid_pct = resid_kwargs.pop("resid_pct", True)
681
+
682
+ self.plot_raw_used_fit(ax=hax, annotate=annotate, **kwargs)
683
+ self.plot_residuals(ax=rax, pct=resid_pct, **resid_kwargs)
684
+
685
+ # if fit_resid_axes is None:
686
+ hax.xaxis.get_label().set_visible(False)
687
+ [t.set_visible(False) for t in hax.xaxis.get_ticklabels()]
688
+
689
+ return hax, rax
690
+
691
+ def residuals(self, pct=False, robust=False):
692
+ r"""Calculate the fit residuals.
693
+
694
+ If pct, normalize by fit yvalues.
695
+ """
696
+
697
+ y_fit_used = self.y_fit[self.observations.tk_observed]
698
+
699
+ if robust:
700
+ r = self.fit_result.fun
701
+ else:
702
+ r = y_fit_used - self.observations.used.y
703
+
704
+ if pct:
705
+ r = 100.0 * (r / y_fit_used)
706
+
707
+ return r
708
+
709
+ # def robust_residuals(self, pct=False):
710
+ # r"""Return the fit residuals.
711
+ # If pct, normalize by fit yvalues.
712
+ # """
713
+ # r = self._robust_residuals
714
+ #
715
+ # if pct:
716
+ # y_fit_used = self.y_fit[self.observations.tk_observed]
717
+ # r = 100.0 * (r / y_fit_used)
718
+ #
719
+ # return r
720
+
721
+ def set_labels(self, **kwargs):
722
+ r"""Set or update x, y, or z labels.
723
+
724
+ Any label not specified in kwargs is propagated from `self.labels.<x, y, or z>`.
725
+ """
726
+
727
+ x = kwargs.pop("x", self.labels.x)
728
+ y = kwargs.pop("y", self.labels.y)
729
+ z = kwargs.pop("z", self.labels.z)
730
+
731
+ if len(kwargs.keys()):
732
+ extra = "\n".join([f"{k}: {v}" for k, v in kwargs.items()])
733
+ raise KeyError(f"Unexpected kwarg\n{extra}")
734
+
735
+ self._labels = AxesLabels(x, y, z)
736
+
737
+ def set_log(self, **kwargs):
738
+ r"""Set :py:class:`LogAxes`.
739
+
740
+ Only used for determining if weights should be :math:`w/(y \ln(10))`.
741
+ """
742
+ log = self._log._asdict()
743
+ for k, v in kwargs.items():
744
+ log[k] = v
745
+
746
+ self._log = LogAxes(**log)
747
+
748
+ def set_TeX_info(self, new):
749
+ """Assign :class:`TeXinfo` used for annotations."""
750
+
751
+ self._TeX_info = new