solarwindpy 0.0.1.dev0__py3-none-any.whl → 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of solarwindpy might be problematic. Click here for more details.

Files changed (412) hide show
  1. plans/.velocity/metrics.json +96 -0
  2. plans/0-overview-template.md +268 -0
  3. plans/N-phase-template.md +106 -0
  4. plans/PLAN_AUDIT_SUMMARY.md +173 -0
  5. plans/TEMPLATE-USAGE-GUIDE.md +198 -0
  6. plans/__init__.py +1 -0
  7. plans/abandoned/compaction-agent-system/0-Overview.md +123 -0
  8. plans/abandoned/compaction-agent-system/agents-index-update-plan.md +109 -0
  9. plans/abandoned/compaction-agent-system/compacted_state.md +85 -0
  10. plans/abandoned/compaction-agent-system/implementation-plan.md +107 -0
  11. plans/abandoned/compaction-agent-system/system-validation-report.md +159 -0
  12. plans/abandoned/compaction-agent-system/usage-guide.md +210 -0
  13. plans/abandoned/hook-system-enhancement/0-Overview.md +214 -0
  14. plans/abandoned/hook-system-enhancement/1-Phase1-Core-Infrastructure.md +313 -0
  15. plans/abandoned/hook-system-enhancement/2-Phase2-Intelligent-Testing.md +385 -0
  16. plans/abandoned/hook-system-enhancement/3-Phase3-Physics-Validation.md +444 -0
  17. plans/abandoned/hook-system-enhancement/4-Phase4-Performance-Monitoring.md +458 -0
  18. plans/abandoned/hook-system-enhancement/5-Phase5-Developer-Experience.md +532 -0
  19. plans/abandoned/hook-system-enhancement/6-Implementation-Timeline.md +274 -0
  20. plans/abandoned/hook-system-enhancement/7-Risk-Management.md +376 -0
  21. plans/abandoned/hook-system-enhancement/8-Testing-Strategy.md +579 -0
  22. plans/abandoned/readthedocs-automation/0-Overview.md +247 -0
  23. plans/abandoned/readthedocs-automation/1-Emergency-Documentation-Fixes.md +270 -0
  24. plans/abandoned/readthedocs-automation/2-Template-System-Enhancement.md +811 -0
  25. plans/abandoned/readthedocs-automation/3-Quality-Audit-ReadTheDocs-Integration.md +844 -0
  26. plans/abandoned/readthedocs-automation/4-Plan-Consolidation-Cleanup.md +632 -0
  27. plans/abandoned/readthedocs-automation/9-Closeout.md +207 -0
  28. plans/abandoned/readthedocs-automation/ABANDONMENT_REASON.md +72 -0
  29. plans/cicd-architecture-redesign/0-Overview.md +193 -0
  30. plans/cicd-architecture-redesign/1-Workflow-Creation.md +103 -0
  31. plans/cicd-architecture-redesign/2-Version-Detection.md +123 -0
  32. plans/cicd-architecture-redesign/3-Deployment-Gates.md +169 -0
  33. plans/cicd-architecture-redesign/4-RC-Testing.md +194 -0
  34. plans/cicd-architecture-redesign/5-TestPyPI-Validation.md +264 -0
  35. plans/cicd-architecture-redesign/6-Production-Release.md +263 -0
  36. plans/cicd-architecture-redesign/7-Cleanup.md +243 -0
  37. plans/cicd-architecture-redesign/8-Documentation.md +285 -0
  38. plans/cicd-architecture-redesign/Closeout.md +225 -0
  39. plans/closeout-template.md +259 -0
  40. plans/completed/circular-import-audit/0-Overview.md +152 -0
  41. plans/completed/circular-import-audit/1-Static-Dependency-Analysis.md +62 -0
  42. plans/completed/circular-import-audit/2-Dynamic-Import-Testing.md +56 -0
  43. plans/completed/circular-import-audit/3-Performance-Impact-Assessment.md +56 -0
  44. plans/completed/circular-import-audit/4-Issue-Remediation.md +78 -0
  45. plans/completed/circular-import-audit/5-Preventive-Infrastructure.md +89 -0
  46. plans/completed/claude-settings-ecosystem-alignment/0-Overview.md +162 -0
  47. plans/completed/claude-settings-ecosystem-alignment/1-Security-Foundation.md +148 -0
  48. plans/completed/claude-settings-ecosystem-alignment/2-Hook-Integration.md +158 -0
  49. plans/completed/claude-settings-ecosystem-alignment/3-Agent-System-Integration.md +177 -0
  50. plans/completed/claude-settings-ecosystem-alignment/4-Enhanced-Workflow-Automation.md +159 -0
  51. plans/completed/claude-settings-ecosystem-alignment/5-Validation-Monitoring.md +181 -0
  52. plans/completed/claude-settings-ecosystem-alignment/compacted_session_state.md +290 -0
  53. plans/completed/combined_plan_with_checklist_documentation/1-Overview-and-Goals.md +51 -0
  54. plans/completed/combined_plan_with_checklist_documentation/2-Toolchain-and-Hosting.md +69 -0
  55. plans/completed/combined_plan_with_checklist_documentation/3-Repository-Structure.md +61 -0
  56. plans/completed/combined_plan_with_checklist_documentation/4-Configuration-and-Standards.md +70 -0
  57. plans/completed/combined_plan_with_checklist_documentation/5-Documentation-Content.md +62 -0
  58. plans/completed/combined_plan_with_checklist_documentation/6-CI-CD-and-Validation.md +58 -0
  59. plans/completed/combined_plan_with_checklist_documentation/7-Maintenance.md +55 -0
  60. plans/completed/combined_test_plan_with_checklist_fitfunctions/0-Overview.md +135 -0
  61. plans/completed/combined_test_plan_with_checklist_fitfunctions/1-Common-fixtures.md +59 -0
  62. plans/completed/combined_test_plan_with_checklist_fitfunctions/10-power_laws.md +56 -0
  63. plans/completed/combined_test_plan_with_checklist_fitfunctions/2-core.py-FitFunction.md +118 -0
  64. plans/completed/combined_test_plan_with_checklist_fitfunctions/3-gaussians.py-Gaussian-GaussianNormalized-GaussianLn.md +69 -0
  65. plans/completed/combined_test_plan_with_checklist_fitfunctions/4-trend_fits.py-TrendFit.md +99 -0
  66. plans/completed/combined_test_plan_with_checklist_fitfunctions/5-plots.py-FFPlot.md +98 -0
  67. plans/completed/combined_test_plan_with_checklist_fitfunctions/6-tex_info.py-TeXinfo.md +79 -0
  68. plans/completed/combined_test_plan_with_checklist_fitfunctions/7-Justification.md +49 -0
  69. plans/completed/combined_test_plan_with_checklist_fitfunctions/8-exponentials.md +64 -0
  70. plans/completed/combined_test_plan_with_checklist_fitfunctions/9-lines.md +58 -0
  71. plans/completed/combined_test_plan_with_checklist_plotting/0-Overview.md +142 -0
  72. plans/completed/combined_test_plan_with_checklist_plotting/1-base.py.md +90 -0
  73. plans/completed/combined_test_plan_with_checklist_plotting/10-labels-special.py.md +102 -0
  74. plans/completed/combined_test_plan_with_checklist_plotting/11-labels-chemistry.py.md +212 -0
  75. plans/completed/combined_test_plan_with_checklist_plotting/12-labels-composition.py.md +242 -0
  76. plans/completed/combined_test_plan_with_checklist_plotting/13-labels-datetime.py.md +247 -0
  77. plans/completed/combined_test_plan_with_checklist_plotting/14-labels-elemental_abundance.py.md +274 -0
  78. plans/completed/combined_test_plan_with_checklist_plotting/15-visual-validation.md +256 -0
  79. plans/completed/combined_test_plan_with_checklist_plotting/16-integration-testing.md +266 -0
  80. plans/completed/combined_test_plan_with_checklist_plotting/17-performance-benchmarks.md +267 -0
  81. plans/completed/combined_test_plan_with_checklist_plotting/18-Fixtures-and-Utilities.md +86 -0
  82. plans/completed/combined_test_plan_with_checklist_plotting/2-agg_plot.py.md +90 -0
  83. plans/completed/combined_test_plan_with_checklist_plotting/3-histograms.py.md +201 -0
  84. plans/completed/combined_test_plan_with_checklist_plotting/4-scatter.py.md +167 -0
  85. plans/completed/combined_test_plan_with_checklist_plotting/5-spiral.py.md +216 -0
  86. plans/completed/combined_test_plan_with_checklist_plotting/6-orbits.py.md +108 -0
  87. plans/completed/combined_test_plan_with_checklist_plotting/7-tools.py.md +86 -0
  88. plans/completed/combined_test_plan_with_checklist_plotting/8-select_data_from_figure.py.md +97 -0
  89. plans/completed/combined_test_plan_with_checklist_plotting/9-labels-base.py.md +88 -0
  90. plans/completed/combined_test_plan_with_checklist_solar_activity/.gitkeep +0 -0
  91. plans/completed/combined_test_plan_with_checklist_solar_activity/0-Overview.md +170 -0
  92. plans/completed/combined_test_plan_with_checklist_solar_activity/1-Package-Entry-Point-__init__.py.md +121 -0
  93. plans/completed/combined_test_plan_with_checklist_solar_activity/2-Core-Base-Classes-base.py.md +142 -0
  94. plans/completed/combined_test_plan_with_checklist_solar_activity/3-Plotting-Helpers-plots.py.md +123 -0
  95. plans/completed/combined_test_plan_with_checklist_solar_activity/4-LISIRD-Sub-package.md +119 -0
  96. plans/completed/combined_test_plan_with_checklist_solar_activity/5-Extrema-Calculator.md +103 -0
  97. plans/completed/combined_test_plan_with_checklist_solar_activity/6-Sunspot-Number-Sub-package.md +163 -0
  98. plans/completed/combined_test_plan_with_checklist_solar_activity/7-Sunspot-Number-Init.py.md +217 -0
  99. plans/completed/combined_test_plan_with_checklist_solar_activity/compacted_state.md +52 -0
  100. plans/completed/compaction-agent-modernization/0-Overview.md +156 -0
  101. plans/completed/compaction-agent-modernization/1-Architecture-Audit-Gap-Analysis.md +132 -0
  102. plans/completed/compaction-agent-modernization/2-Token-Baseline-Recalibration.md +153 -0
  103. plans/completed/compaction-agent-modernization/3-Agent-Reference-Updates.md +184 -0
  104. plans/completed/compaction-agent-modernization/4-Compression-Algorithm-Modernization.md +238 -0
  105. plans/completed/compaction-agent-modernization/5-Workflow-Integration-Streamlining.md +252 -0
  106. plans/completed/compaction-agent-modernization/6-Template-Structure-Optimization.md +240 -0
  107. plans/completed/compaction-agent-modernization/7-Integration-Testing-Validation.md +292 -0
  108. plans/completed/compaction-hook-enhancement/0-Overview.md +150 -0
  109. plans/completed/compaction-hook-enhancement/1-Token-Estimation-Enhancement.md +179 -0
  110. plans/completed/compaction-hook-enhancement/2-Compression-Intelligence.md +294 -0
  111. plans/completed/compaction-hook-enhancement/3-Git-Integration-Metadata.md +310 -0
  112. plans/completed/compaction-hook-enhancement/4-Session-Continuity-Features.md +358 -0
  113. plans/completed/compaction-hook-enhancement/5-Testing-Strategy.md +404 -0
  114. plans/completed/compaction-hook-enhancement/6-Integration-Roadmap.md +319 -0
  115. plans/completed/compaction-hook-enhancement/compacted_state.md +142 -0
  116. plans/completed/docstring-audit-enhancement/0-Overview.md +274 -0
  117. plans/completed/docstring-audit-enhancement/1-Infrastructure-Setup-and-Validation-Tools.md +206 -0
  118. plans/completed/docstring-audit-enhancement/2-Core-Physics-Modules-Enhancement.md +237 -0
  119. plans/completed/docstring-audit-enhancement/3-Fitfunctions-Mathematical-Modules-Enhancement.md +188 -0
  120. plans/completed/docstring-audit-enhancement/4-Plotting-Visualization-Modules-Enhancement.md +243 -0
  121. plans/completed/docstring-audit-enhancement/5-Specialized-Modules-Enhancement.md +216 -0
  122. plans/completed/docstring-audit-enhancement/6-Validation-and-Integration.md +216 -0
  123. plans/completed/fitfunctions-testing-implementation/0-Overview.md +130 -0
  124. plans/completed/fitfunctions-testing-implementation/1-Test-Infrastructure-Setup.md +79 -0
  125. plans/completed/fitfunctions-testing-implementation/2-Common-Fixtures-Test-Utilities.md +104 -0
  126. plans/completed/fitfunctions-testing-implementation/3-Core-FitFunction-Testing.md +168 -0
  127. plans/completed/fitfunctions-testing-implementation/4-Specialized-Function-Classes.md +210 -0
  128. plans/completed/fitfunctions-testing-implementation/5-Advanced-Classes-Testing.md +214 -0
  129. plans/completed/fitfunctions-testing-implementation/6-Plotting-Integration-Testing.md +231 -0
  130. plans/completed/fitfunctions-testing-implementation/7-Extended-Coverage-BONUS.md +184 -0
  131. plans/completed/numpy-docstring-conversion-plan/numpy-docstring-conversion-plan.md +118 -0
  132. plans/completed/pr-review-remediation/0-Overview.md +138 -0
  133. plans/completed/pr-review-remediation/1-Critical-Safety-Improvements.md +179 -0
  134. plans/completed/pr-review-remediation/2-Smart-Timeouts-Validation.md +399 -0
  135. plans/completed/pr-review-remediation/3-Enhanced-GitHub-Integration.md +258 -0
  136. plans/completed/pr-review-remediation/compacted_state.md +66 -0
  137. plans/completed/python-310-migration/0-Overview.md +390 -0
  138. plans/completed/python-310-migration/1-Planning-Setup.md +164 -0
  139. plans/completed/python-310-migration/2-Implementation.md +256 -0
  140. plans/completed/python-310-migration/3-Testing-Validation.md +335 -0
  141. plans/completed/python-310-migration/4-Documentation-Release.md +274 -0
  142. plans/completed/python-310-migration/5-Closeout.md +252 -0
  143. plans/completed/requirements-management-consolidation/0-Overview.md +118 -0
  144. plans/completed/requirements-management-consolidation/1-Documentation-Validation-Environment-Setup.md +116 -0
  145. plans/completed/requirements-management-consolidation/2-Requirements-Consolidation.md +161 -0
  146. plans/completed/requirements-management-consolidation/3-Workflow-Automation-Final-Integration.md +196 -0
  147. plans/completed/single-ecosystem-plan-implementation/0-Overview.md +83 -0
  148. plans/completed/single-ecosystem-plan-implementation/1-Plan-Preservation-Session-Management.md +38 -0
  149. plans/completed/single-ecosystem-plan-implementation/2-File-Structure-Optimization.md +43 -0
  150. plans/completed/single-ecosystem-plan-implementation/3-Plan-Migration-Archive-Setup.md +82 -0
  151. plans/completed/single-ecosystem-plan-implementation/4-Agent-System-Transformation.md +108 -0
  152. plans/completed/single-ecosystem-plan-implementation/5-Template-System-Enhancement.md +131 -0
  153. plans/completed/single-ecosystem-plan-implementation/6-Final-Validation-Testing.md +120 -0
  154. plans/completed/test-directory-consolidation/0-Overview.md +51 -0
  155. plans/completed/test-directory-consolidation/1-Structure-Preparation.md +82 -0
  156. plans/completed/test-directory-consolidation/2-File-Migration.md +100 -0
  157. plans/completed/test-directory-consolidation/3-Import-Transformation.md +117 -0
  158. plans/completed/test-directory-consolidation/4-Configuration-Consolidation.md +140 -0
  159. plans/completed/test-directory-consolidation/5-Validation.md +152 -0
  160. plans/completed/test-directory-consolidation/6-Cleanup.md +156 -0
  161. plans/completed/test-planning-agents-architecture/0-Overview.md +79 -0
  162. plans/completed/test-planning-agents-architecture/1-Branch-Isolation-Testing.md +49 -0
  163. plans/completed/test-planning-agents-architecture/2-Cross-Branch-Coordination.md +51 -0
  164. plans/completed/test-planning-agents-architecture/3-Merge-Workflow-Testing.md +48 -0
  165. plans/deployment-semver-pypi-rtd/0-Overview.md +463 -0
  166. plans/deployment-semver-pypi-rtd/1-Semantic-Versioning-Foundation.md +136 -0
  167. plans/deployment-semver-pypi-rtd/2-PyPI-Deployment-Infrastructure.md +168 -0
  168. plans/deployment-semver-pypi-rtd/3-Release-Automation.md +214 -0
  169. plans/deployment-semver-pypi-rtd/4-Plan-Closeout.md +543 -0
  170. plans/deployment-semver-pypi-rtd/compacted_session_state.md +172 -0
  171. plans/deployment-semver-pypi-rtd/compacted_state.md +131 -0
  172. plans/documentation-code-audit/0-Overview.md +393 -0
  173. plans/documentation-code-audit/1-Discovery-Inventory.md +183 -0
  174. plans/documentation-code-audit/2-Execution-Environment-Setup.md +263 -0
  175. plans/documentation-code-audit/3-Systematic-Validation.md +322 -0
  176. plans/documentation-code-audit/4-Code-Example-Remediation.md +358 -0
  177. plans/documentation-code-audit/5-Physics-MultiIndex-Compliance.md +464 -0
  178. plans/documentation-code-audit/6-Doctest-Integration.md +523 -0
  179. plans/documentation-code-audit/7-Reporting-Documentation.md +498 -0
  180. plans/documentation-code-audit/8-Closeout.md +456 -0
  181. plans/documentation-rebuild-session/compacted_state.md +109 -0
  182. plans/documentation-rendering-fixes/0-Overview.md +104 -0
  183. plans/documentation-rendering-fixes/1-Sphinx-Build-Diagnostics-Warning-Audit.md +101 -0
  184. plans/documentation-rendering-fixes/2-Configuration-Infrastructure-Fixes.md +113 -0
  185. plans/documentation-rendering-fixes/3-Docstring-Syntax-Audit-Repair.md +131 -0
  186. plans/documentation-rendering-fixes/4-HTML-Page-Rendering-Verification.md +113 -0
  187. plans/documentation-rendering-fixes/5-Advanced-Documentation-Quality-Assurance.md +119 -0
  188. plans/documentation-rendering-fixes/6-Documentation-Build-Optimization-Testing.md +129 -0
  189. plans/documentation-rendering-fixes/compacted_state.md +132 -0
  190. plans/documentation-template-fix/0-Overview.md +197 -0
  191. plans/documentation-template-fix/1-Template-System-Analysis.md +269 -0
  192. plans/documentation-template-fix/2-Template-Modification.md +609 -0
  193. plans/documentation-template-fix/3-Build-System-Integration.md +766 -0
  194. plans/documentation-template-fix/4-Testing-Validation.md +1399 -0
  195. plans/documentation-template-fix/5-Documentation-Training.md +602 -0
  196. plans/documentation-workflow-fix/0-Overview.md +222 -0
  197. plans/documentation-workflow-fix/1-Immediate-Fixes.md +238 -0
  198. plans/documentation-workflow-fix/2-Configuration-Setup.md +298 -0
  199. plans/documentation-workflow-fix/3-Pre-commit-Integration.md +382 -0
  200. plans/documentation-workflow-fix/4-Workflow-Improvements.md +446 -0
  201. plans/documentation-workflow-fix/5-Documentation-and-Training.md +527 -0
  202. plans/duplicate-object-warnings-fix-plan.md +130 -0
  203. plans/github-issues-migration/0-Overview.md +510 -0
  204. plans/github-issues-migration/1-Foundation-Label-System.md +180 -0
  205. plans/github-issues-migration/2-Migration-Tool-Rewrite.md +235 -0
  206. plans/github-issues-migration/3-CLI-Integration-Automation.md +169 -0
  207. plans/github-issues-migration/4-Validated-Migration.md +252 -0
  208. plans/github-issues-migration/5-Documentation-Training.md +171 -0
  209. plans/github-issues-migration/6-Closeout.md +179 -0
  210. plans/github-workflows-repair/repair-plan.md +299 -0
  211. plans/issues_from_plans.py +342 -0
  212. plans/pr-270-doc-validation-fixes/0-Overview.md +354 -0
  213. plans/pr-270-doc-validation-fixes/1-Critical-PR-Fixes.md +117 -0
  214. plans/pr-270-doc-validation-fixes/2-Framework-Right-Sizing.md +129 -0
  215. plans/pr-270-doc-validation-fixes/3-Sustainable-Documentation.md +126 -0
  216. plans/pr-270-doc-validation-fixes/4-Closeout-Migration.md +143 -0
  217. plans/pr-270-doc-validation-fixes/PLAN_COMPLETED.md +149 -0
  218. plans/python-310-migration/0-Overview.md +390 -0
  219. plans/python-310-migration/1-Planning-Setup.md +164 -0
  220. plans/python-310-migration/2-Implementation.md +256 -0
  221. plans/python-310-migration/3-Testing-Validation.md +335 -0
  222. plans/python-310-migration/4-Documentation-Release.md +274 -0
  223. plans/python-310-migration/5-Closeout.md +252 -0
  224. plans/readthedocs-simplified/0-Overview.md +243 -0
  225. plans/readthedocs-simplified/1-Immediate-Fixes.md +216 -0
  226. plans/readthedocs-simplified/2-Template-Simplification.md +278 -0
  227. plans/readthedocs-simplified/3-ReadTheDocs-Setup.md +298 -0
  228. plans/readthedocs-simplified/4-Testing-Validation.md +328 -0
  229. plans/readthedocs-simplified/5-Closeout.md +231 -0
  230. plans/readthedocs-simplified/compacted_state.md +127 -0
  231. plans/session-compaction-2025-08-12/compacted_state.md +114 -0
  232. plans/session-compaction-2025-08-13/compacted_state.md +145 -0
  233. plans/session-continuity-protocol/0-Overview.md +35 -0
  234. plans/session-continuity-protocol/1-Core-Principles-Framework.md +40 -0
  235. plans/session-continuity-protocol/2-Pre-Session-Validation-System.md +79 -0
  236. plans/session-continuity-protocol/3-Context-Switching-Prevention.md +87 -0
  237. plans/session-continuity-protocol/4-Progress-Tracking-Recovery.md +100 -0
  238. plans/sphinx-warnings-analysis.md +222 -0
  239. plans/systemprompt-optimization/0-Overview.md +447 -0
  240. plans/systemprompt-optimization/1-Deploy-SystemPrompt.md +114 -0
  241. plans/systemprompt-optimization/2-Documentation-Alignment.md +198 -0
  242. plans/systemprompt-optimization/3-Monitoring-Infrastructure.md +396 -0
  243. plans/systemprompt-optimization/4-Implementation-Script.md +450 -0
  244. plans/systemprompt-optimization/9-Closeout.md +165 -0
  245. plans/systemprompt-optimization/compacted_state.md +143 -0
  246. plans/template-value-propositions/0-Overview.md +357 -0
  247. plans/template-value-propositions/1-Value-Proposition-Framework-Design.md +144 -0
  248. plans/template-value-propositions/2-Plan-Template-Enhancement.md +178 -0
  249. plans/template-value-propositions/3-Value-Generator-Hook-Implementation.md +291 -0
  250. plans/template-value-propositions/4-Value-Validator-Hook-Implementation.md +274 -0
  251. plans/template-value-propositions/5-Documentation-Agent-Updates.md +219 -0
  252. plans/template-value-propositions/6-Integration-Testing-Validation.md +247 -0
  253. plans/tests-audit/0-Overview.md +410 -0
  254. plans/tests-audit/1-Discovery-Inventory.md +170 -0
  255. plans/tests-audit/2-Physics-Validation-Audit.md +195 -0
  256. plans/tests-audit/3-Architecture-Compliance.md +195 -0
  257. plans/tests-audit/4-Numerical-Stability-Analysis.md +203 -0
  258. plans/tests-audit/5-Documentation-Enhancement.md +220 -0
  259. plans/tests-audit/6-Audit-Deliverables.md +220 -0
  260. plans/tests-audit/7-Closeout.md +252 -0
  261. plans/tests-audit/artifacts/ARCHITECTURE_COMPLIANCE_REPORT.md +315 -0
  262. plans/tests-audit/artifacts/ARCHITECTURE_RECOMMENDATIONS.md +943 -0
  263. plans/tests-audit/artifacts/COMPREHENSIVE_AUDIT_REPORT.md +356 -0
  264. plans/tests-audit/artifacts/CONTRIBUTING_ENHANCED_TEMPLATE.md +419 -0
  265. plans/tests-audit/artifacts/COVERAGE_GAP_ANALYSIS.md +152 -0
  266. plans/tests-audit/artifacts/DOCUMENTATION_ENHANCEMENT_REPORT.md +502 -0
  267. plans/tests-audit/artifacts/EXECUTIVE_AUDIT_SUMMARY.md +129 -0
  268. plans/tests-audit/artifacts/IMPLEMENTATION_ROADMAP.md +647 -0
  269. plans/tests-audit/artifacts/NUMERICAL_RECOMMENDATIONS.md +739 -0
  270. plans/tests-audit/artifacts/NUMERICAL_STABILITY_GUIDE_TEMPLATE.rst +451 -0
  271. plans/tests-audit/artifacts/NUMERICAL_STABILITY_REPORT.md +301 -0
  272. plans/tests-audit/artifacts/PHASE_3_SUMMARY.md +280 -0
  273. plans/tests-audit/artifacts/PHASE_4_SUMMARY.md +229 -0
  274. plans/tests-audit/artifacts/PHASE_5_SUMMARY.md +292 -0
  275. plans/tests-audit/artifacts/PHASE_6_CLOSEOUT.md +278 -0
  276. plans/tests-audit/artifacts/PHYSICS_GUIDE_TEMPLATE.rst +268 -0
  277. plans/tests-audit/artifacts/PHYSICS_VALIDATION_REPORT.md +235 -0
  278. plans/tests-audit/artifacts/TECHNICAL_DELIVERABLES_PACKAGE.md +2502 -0
  279. plans/tests-audit/artifacts/TEST_INVENTORY.csv +1204 -0
  280. plans/tests-audit/artifacts/TEST_INVENTORY.md +135 -0
  281. plans/tests-audit/artifacts/test_discovery_analysis.py +231 -0
  282. plans/tests-audit/artifacts/test_parser.py +395 -0
  283. solarwindpy/README.md +3 -0
  284. solarwindpy/Untitled.ipynb +54 -0
  285. solarwindpy/__init__.py +74 -0
  286. solarwindpy/core/__init__.py +23 -0
  287. solarwindpy/core/alfvenic_turbulence.py +804 -0
  288. solarwindpy/core/base.py +267 -0
  289. solarwindpy/core/ions.py +309 -0
  290. solarwindpy/core/plasma.py +2133 -0
  291. solarwindpy/core/spacecraft.py +256 -0
  292. solarwindpy/core/tensor.py +90 -0
  293. solarwindpy/core/units_constants.py +199 -0
  294. solarwindpy/core/vector.py +328 -0
  295. solarwindpy/fitfunctions/__init__.py +20 -0
  296. solarwindpy/fitfunctions/core.py +734 -0
  297. solarwindpy/fitfunctions/exponentials.py +188 -0
  298. solarwindpy/fitfunctions/gaussians.py +264 -0
  299. solarwindpy/fitfunctions/lines.py +116 -0
  300. solarwindpy/fitfunctions/moyal.py +71 -0
  301. solarwindpy/fitfunctions/plots.py +751 -0
  302. solarwindpy/fitfunctions/power_laws.py +209 -0
  303. solarwindpy/fitfunctions/tex_info.py +568 -0
  304. solarwindpy/fitfunctions/trend_fits.py +482 -0
  305. solarwindpy/instabilities/__init__.py +16 -0
  306. solarwindpy/instabilities/beta_ani.py +82 -0
  307. solarwindpy/instabilities/verscharen2016.py +631 -0
  308. solarwindpy/plotting/__init__.py +33 -0
  309. solarwindpy/plotting/agg_plot.py +489 -0
  310. solarwindpy/plotting/base.py +465 -0
  311. solarwindpy/plotting/hist1d.py +405 -0
  312. solarwindpy/plotting/hist2d.py +1035 -0
  313. solarwindpy/plotting/histograms.py +1845 -0
  314. solarwindpy/plotting/labels/__init__.py +104 -0
  315. solarwindpy/plotting/labels/base.py +686 -0
  316. solarwindpy/plotting/labels/chemistry.py +19 -0
  317. solarwindpy/plotting/labels/composition.py +100 -0
  318. solarwindpy/plotting/labels/datetime.py +235 -0
  319. solarwindpy/plotting/labels/elemental_abundance.py +73 -0
  320. solarwindpy/plotting/labels/special.py +794 -0
  321. solarwindpy/plotting/orbits.py +515 -0
  322. solarwindpy/plotting/scatter.py +99 -0
  323. solarwindpy/plotting/select_data_from_figure.py +329 -0
  324. solarwindpy/plotting/spiral.py +980 -0
  325. solarwindpy/plotting/tools.py +434 -0
  326. solarwindpy/scripts/__init__.py +1 -0
  327. solarwindpy/scripts/logs/.gitignore +1 -0
  328. solarwindpy/solar_activity/__init__.py +53 -0
  329. solarwindpy/solar_activity/base.py +605 -0
  330. solarwindpy/solar_activity/lisird/__init__.py +3 -0
  331. solarwindpy/solar_activity/lisird/extrema_calculator.py +394 -0
  332. solarwindpy/solar_activity/lisird/lisird.py +319 -0
  333. solarwindpy/solar_activity/plots.py +116 -0
  334. solarwindpy/solar_activity/sunspot_number/.DS_Store +0 -0
  335. solarwindpy/solar_activity/sunspot_number/__init__.py +3 -0
  336. solarwindpy/solar_activity/sunspot_number/sidc.py +556 -0
  337. solarwindpy/solar_activity/sunspot_number/ssn_extrema.csv +72 -0
  338. solarwindpy/solar_activity/sunspot_number/ssn_extrema.csv.silso +72 -0
  339. solarwindpy/tools/__init__.py +162 -0
  340. solarwindpy-0.1.1.dist-info/METADATA +181 -0
  341. solarwindpy-0.1.1.dist-info/RECORD +409 -0
  342. {solarwindpy-0.0.1.dev0.dist-info → solarwindpy-0.1.1.dist-info}/WHEEL +1 -1
  343. solarwindpy-0.1.1.dist-info/licenses/LICENSE.rst +32 -0
  344. solarwindpy-0.1.1.dist-info/top_level.txt +3 -0
  345. tests/__init__.py +1 -0
  346. tests/conftest.py +10 -0
  347. tests/core/__init__.py +1 -0
  348. tests/core/test_alfvenic_turbulence.py +544 -0
  349. tests/core/test_base.py +112 -0
  350. tests/core/test_base_head_tail.py +29 -0
  351. tests/core/test_base_mi_tuples.py +11 -0
  352. tests/core/test_core_verify_datetimeindex.py +32 -0
  353. tests/core/test_ions.py +325 -0
  354. tests/core/test_plasma.py +2581 -0
  355. tests/core/test_plasma_io.py +12 -0
  356. tests/core/test_quantities.py +507 -0
  357. tests/core/test_spacecraft.py +210 -0
  358. tests/core/test_units_constants.py +22 -0
  359. tests/data/epoch.csv +4 -0
  360. tests/data/plasma.csv +4 -0
  361. tests/data/spacecraft.csv +4 -0
  362. tests/fitfunctions/conftest.py +60 -0
  363. tests/fitfunctions/test_core.py +193 -0
  364. tests/fitfunctions/test_exponentials.py +342 -0
  365. tests/fitfunctions/test_gaussians.py +142 -0
  366. tests/fitfunctions/test_lines.py +349 -0
  367. tests/fitfunctions/test_moyal.py +258 -0
  368. tests/fitfunctions/test_plots.py +258 -0
  369. tests/fitfunctions/test_power_laws.py +365 -0
  370. tests/fitfunctions/test_tex_info.py +183 -0
  371. tests/fitfunctions/test_trend_fit_properties.py +31 -0
  372. tests/fitfunctions/test_trend_fits.py +244 -0
  373. tests/plotting/__init__.py +1 -0
  374. tests/plotting/labels/__init__.py +1 -0
  375. tests/plotting/labels/test_chemistry.py +243 -0
  376. tests/plotting/labels/test_composition.py +345 -0
  377. tests/plotting/labels/test_datetime.py +445 -0
  378. tests/plotting/labels/test_elemental_abundance.py +366 -0
  379. tests/plotting/labels/test_init.py +66 -0
  380. tests/plotting/labels/test_labels_base.py +347 -0
  381. tests/plotting/labels/test_special.py +550 -0
  382. tests/plotting/test_agg_plot.py +602 -0
  383. tests/plotting/test_base.py +752 -0
  384. tests/plotting/test_fixtures_utilities.py +775 -0
  385. tests/plotting/test_histograms.py +546 -0
  386. tests/plotting/test_integration.py +675 -0
  387. tests/plotting/test_orbits.py +435 -0
  388. tests/plotting/test_performance.py +708 -0
  389. tests/plotting/test_scatter.py +752 -0
  390. tests/plotting/test_select_data_from_figure.py +1209 -0
  391. tests/plotting/test_spiral.py +573 -0
  392. tests/plotting/test_tools.py +607 -0
  393. tests/plotting/test_visual_validation.py +465 -0
  394. tests/solar_activity/__init__.py +1 -0
  395. tests/solar_activity/lisird/__init__.py +1 -0
  396. tests/solar_activity/lisird/test_extrema_calculator.py +593 -0
  397. tests/solar_activity/lisird/test_lisird_id.py +187 -0
  398. tests/solar_activity/sunspot_number/__init__.py +1 -0
  399. tests/solar_activity/sunspot_number/test_init.py +399 -0
  400. tests/solar_activity/sunspot_number/test_sidc.py +465 -0
  401. tests/solar_activity/sunspot_number/test_sidc_id.py +223 -0
  402. tests/solar_activity/sunspot_number/test_sidc_loader.py +275 -0
  403. tests/solar_activity/sunspot_number/test_ssn_extrema.py +406 -0
  404. tests/solar_activity/test_base.py +656 -0
  405. tests/solar_activity/test_init.py +396 -0
  406. tests/solar_activity/test_plots.py +371 -0
  407. tests/test_circular_imports.py +408 -0
  408. tests/test_issue_titles.py +25 -0
  409. tests/test_statusline.py +298 -0
  410. solarwindpy-0.0.1.dev0.dist-info/METADATA +0 -14
  411. solarwindpy-0.0.1.dev0.dist-info/RECORD +0 -4
  412. solarwindpy-0.0.1.dev0.dist-info/top_level.txt +0 -1
@@ -0,0 +1,116 @@
1
+ """Plotting helpers for solar activity indicators."""
2
+
3
+ import pdb # noqa: F401
4
+ from matplotlib import dates as mdates
5
+
6
+ # import numpy as np
7
+ # import pandas as pd
8
+
9
+ # from pathlib import Path
10
+ from abc import abstractmethod
11
+
12
+ from ..plotting import base, labels, subplots
13
+
14
+ # pd.set_option("mode.chained_assignment", "raise")
15
+
16
+
17
+ class IndicatorPlot(base.Base):
18
+ """Base class for plotting a solar activity indicator.
19
+
20
+ Parameters
21
+ ----------
22
+ indicator : ActivityIndicator
23
+ Object providing the time series to plot.
24
+ ykey : str
25
+ Column in ``indicator.data`` to display.
26
+ plasma_index : pandas.DatetimeIndex, optional
27
+ Restrict plotted data to this index.
28
+ """
29
+
30
+ def __init__(self, indicator, ykey, plasma_index=None):
31
+
32
+ self.set_data(indicator, ykey, plasma_index)
33
+ self.set_log(x=False, y=False)
34
+ self._labels = base.AxesLabels(x=labels.special.DateTime("Year"), y="y")
35
+
36
+ @abstractmethod
37
+ def _format_axis(self, ax):
38
+ ax.xaxis.set_major_formatter(mdates.DateFormatter("%Y"))
39
+ ax.xaxis.set_major_locator(mdates.YearLocator())
40
+ ax.xaxis.set_tick_params(which="major", rotation=45)
41
+
42
+ if self.log.x:
43
+ ax.set_xscale("log")
44
+ if self.log.y:
45
+ ax.set_yscale("log")
46
+
47
+ ax.set_xlabel(self.labels.x)
48
+ ax.set_ylabel(self.labels.y)
49
+
50
+ return ax
51
+
52
+ @property
53
+ def indicator(self):
54
+ return self._indicator
55
+
56
+ @property
57
+ def plasma_index(self):
58
+ return self._plasma_index
59
+
60
+ @property
61
+ def ykey(self):
62
+ return self._ykey
63
+
64
+ @property
65
+ def plot_data(self):
66
+ pidx = self.plasma_index
67
+ if pidx is not None:
68
+ pidx = pidx.min()
69
+ return self.indicator.data.loc[pidx:, self.ykey]
70
+
71
+ def set_path(self, new, add_scale=True):
72
+ path, x, y, z, scale_info = super(IndicatorPlot, self).set_path(new, add_scale)
73
+
74
+ if new == "auto":
75
+ path = path / x / y
76
+
77
+ else:
78
+ assert x is None
79
+ assert y is None
80
+
81
+ if add_scale:
82
+ assert scale_info is not None
83
+ scale_info = "-".join(scale_info)
84
+ path = path / scale_info
85
+
86
+ self._path = path
87
+
88
+ def set_data(self, indicator, ykey, plasma_index):
89
+ self._indicator = indicator
90
+ self._plasma_index = plasma_index
91
+ self._ykey = ykey
92
+
93
+ def make_plot(self, ax=None):
94
+ if ax is None:
95
+ fig, ax = subplots()
96
+
97
+ data = self.plot_data
98
+ x = mdates.date2num(data.index)
99
+ ax.plot(x, data, color="k", ls="--", marker=None)
100
+
101
+ self._format_axis(ax)
102
+
103
+
104
+ class SSNPlot(IndicatorPlot):
105
+ """Plotter specialised for sunspot number."""
106
+
107
+ def __init__(self, indicator, **kwargs):
108
+ super(SSNPlot, self).__init__(indicator, "ssn", **kwargs)
109
+ self.set_labels(y=labels.special.SSN(indicator.id.key))
110
+
111
+ def _format_axis(self, ax):
112
+ super(SSNPlot, self)._format_axis(ax)
113
+ ax.set_ylim(0, 200)
114
+
115
+
116
+ # SSNPlot(indicator, plasma_index=plasma.index).make_plot()
@@ -0,0 +1,3 @@
1
+ """Sunspot number data utilities."""
2
+
3
+ from . import sidc # noqa: F401
@@ -0,0 +1,556 @@
1
+ #!/usr/bin/env python
2
+ """Access sunspot-number data from the SIDC."""
3
+
4
+ import pdb # noqa: F401
5
+ import numpy as np
6
+ import pandas as pd
7
+ import matplotlib as mpl
8
+
9
+ from pathlib import Path
10
+ from collections import namedtuple
11
+
12
+ from .. import base
13
+
14
+ Base = base.Base
15
+ ID = base.ID
16
+ DataLoader = base.DataLoader
17
+ IndicatorExtrema = base.IndicatorExtrema
18
+ _Loader_Dtypes_Columns = base._Loader_Dtypes_Columns
19
+ ActivityIndicator = base.ActivityIndicator
20
+
21
+ # import Base, ID, DataLoader, _Loader_Dtypes_Columns, ActivityIndicator
22
+
23
+ pd.set_option("mode.chained_assignment", "raise")
24
+
25
+
26
+ _d_dtypes_columns = _Loader_Dtypes_Columns(
27
+ {0: int, 1: int, 2: int, 3: float, 4: float, 5: float, 6: int, 7: bool},
28
+ ["year", "month", "day", "year_fraction", "ssn", "std", "n_obs", "definitive"],
29
+ )
30
+
31
+ _m_dtypes_columns = _Loader_Dtypes_Columns(
32
+ {0: int, 1: int, 2: float, 3: float, 4: float, 5: int, 6: bool},
33
+ ["year", "month", "year_fraction", "ssn", "std", "n_obs", "definitive"],
34
+ )
35
+
36
+ _m13_dtypes_columns = _Loader_Dtypes_Columns(
37
+ {0: int, 1: int, 2: float, 3: float, 4: float, 5: int, 6: bool},
38
+ ("year", "month", "year_fraction", "ssn", "std", "n_obs", "definitive"),
39
+ )
40
+
41
+ _y_dtypes_columns = _Loader_Dtypes_Columns(
42
+ {0: float, 1: float, 2: float, 3: int, 4: bool},
43
+ ["year", "ssn", "std", "n_obs", "definitive"],
44
+ )
45
+
46
+ # Column 3: Date in fraction of year for the middle of the corresponding month (~ day 15)
47
+
48
+ _hm13_dtypes_columns = _Loader_Dtypes_Columns(
49
+ {
50
+ 0: int,
51
+ 1: int,
52
+ 2: float,
53
+ 3: float,
54
+ 4: float,
55
+ 5: float,
56
+ 6: float,
57
+ 7: float,
58
+ 8: float,
59
+ 9: int,
60
+ 10: int,
61
+ 11: int,
62
+ 12: bool,
63
+ },
64
+ (
65
+ "year",
66
+ "month",
67
+ "year_fraction",
68
+ "total_ssn",
69
+ "north_ssn",
70
+ "south_ssn",
71
+ "total_std",
72
+ "north_std",
73
+ "south_std",
74
+ "n_total",
75
+ "n_north",
76
+ "n_south",
77
+ "definitive",
78
+ ),
79
+ )
80
+
81
+ _hm_dtypes_columns = _Loader_Dtypes_Columns(
82
+ {
83
+ 0: int,
84
+ 1: int,
85
+ 2: float,
86
+ 3: float,
87
+ 4: float,
88
+ 5: float,
89
+ 6: float,
90
+ 7: float,
91
+ 8: float,
92
+ 9: int,
93
+ 10: int,
94
+ 11: int,
95
+ 12: bool,
96
+ },
97
+ (
98
+ "year",
99
+ "month",
100
+ "year_fraction",
101
+ "total_ssn",
102
+ "north_ssn",
103
+ "south_ssn",
104
+ "total_std",
105
+ "north_std",
106
+ "south_std",
107
+ "n_total",
108
+ "n_north",
109
+ "n_south",
110
+ "definitive",
111
+ ),
112
+ )
113
+
114
+ _hd_dtypes_columns = _Loader_Dtypes_Columns(
115
+ {
116
+ 0: int,
117
+ 1: int,
118
+ 2: int,
119
+ 3: float,
120
+ 4: float,
121
+ 5: float,
122
+ 6: float,
123
+ 7: float,
124
+ 8: float,
125
+ 9: float,
126
+ 10: int,
127
+ 11: int,
128
+ 12: int,
129
+ 13: bool,
130
+ },
131
+ (
132
+ "year",
133
+ "month",
134
+ "day",
135
+ "year_fraction",
136
+ "total_ssn",
137
+ "north_ssn",
138
+ "south_ssn",
139
+ "total_std",
140
+ "north_std",
141
+ "south_std",
142
+ "n_total",
143
+ "n_north",
144
+ "n_south",
145
+ "definitive",
146
+ ),
147
+ )
148
+
149
+
150
+ _Dtypes_Columns = namedtuple("Dtypes_Columns", "d,m,m13,y,hd,hm,hm13", defaults=(None,))
151
+
152
+ _Dtypes_Columns = _Dtypes_Columns(
153
+ _d_dtypes_columns,
154
+ _m_dtypes_columns,
155
+ _m13_dtypes_columns,
156
+ _y_dtypes_columns,
157
+ _hd_dtypes_columns,
158
+ _hm_dtypes_columns,
159
+ _hm13_dtypes_columns,
160
+ )
161
+
162
+
163
+ class SIDC_ID(ID):
164
+ def __init__(self, key):
165
+ r"""Key identifies the SSN used.
166
+
167
+ ====== =================== ================
168
+ Key Type URL
169
+ ====== =================== ================
170
+ d Daily total sndtotcsv.php
171
+ m Monthly total snmtotcsv.php
172
+ m13 13-month smoothed snmstotcsv.php
173
+ y Yearly total snytotcsv.php
174
+ hd Hemispheric Daily sndhemcsv.php
175
+ hm Hemispheric Monthly snmhemcsv.php
176
+ hm13 13-Month Smoothed snmshemcsv.php
177
+ Hemispheric
178
+ ====== =================== ================
179
+
180
+ URLs replace the wild card in ``http://www.sidc.be/silso/INFO/*``.
181
+ """
182
+ super(SIDC_ID, self).__init__(key)
183
+
184
+ @property
185
+ def _url_base(self):
186
+ return r"http://www.sidc.be/silso/INFO/"
187
+
188
+ @property
189
+ def _trans_url(self):
190
+ trans_url = (
191
+ ("d", r"sndtotcsv.php"),
192
+ ("m", r"snmtotcsv.php"),
193
+ ("m13", r"snmstotcsv.php"),
194
+ ("y", r"snytotcsv.php"),
195
+ ("hd", r"sndhemcsv.php"),
196
+ ("hm", r"snmhemcsv.php"),
197
+ ("hm13", r"snmshemcsv.php"),
198
+ )
199
+ return dict(trans_url)
200
+
201
+
202
+ class SIDCLoader(DataLoader):
203
+ @property
204
+ def data_path(self):
205
+ return super().data_path / "sidc" / self.key
206
+
207
+ def convert_nans(self, data):
208
+ data.replace(-1, np.nan, inplace=True)
209
+
210
+ def download_data(self, new_data_path, old_data_path):
211
+ r"""Download and save the data to `new_data_path`.
212
+
213
+ If `old_data_path` exists,
214
+ remove it.
215
+ """
216
+ url = self.url # self._trans_url.get(key)
217
+ self.logger.info("Downloading from SIDC sunspot number\nurl: %s", url)
218
+
219
+ key = self.key
220
+ dtypes_columns = _Dtypes_Columns._asdict().get(key)
221
+ if dtypes_columns is None:
222
+ raise NotImplementedError(
223
+ f"""You have not yet used the SSN specified by your key ({key}). Please verify the column labels before continuing."""
224
+ )
225
+
226
+ csv = pd.read_csv(self.url, sep=";", header=None, dtype=dtypes_columns.dtypes)
227
+ csv.columns = dtypes_columns.columns
228
+
229
+ if key in ("m13", "m", "hm", "hm13"):
230
+ dt = csv.loc[:, ["year", "month"]]
231
+ dt.loc[:, "day"] = 1
232
+ ts = pd.to_datetime(dt)
233
+
234
+ elif key in ("d", "hd"):
235
+ dt = csv.loc[:, ["year", "month", "day"]]
236
+ ts = pd.to_datetime(dt)
237
+
238
+ elif key in ("y",):
239
+ import astropy.time
240
+
241
+ dt = astropy.time.Time(csv.loc[:, "year"], format="decimalyear")
242
+ ts = pd.DatetimeIndex(dt.datetime)
243
+
244
+ else:
245
+ raise NotImplementedError(
246
+ f"Please specify how to build {key} datetime column"
247
+ )
248
+
249
+ if key.startswith("h"):
250
+ std = csv.loc[:, ["total_std", "north_std", "south_std"]]
251
+ cnt = csv.loc[:, ["n_total", "n_north", "n_south"]]
252
+
253
+ std.columns = (
254
+ std.columns.to_series().str.split("_").apply(lambda x: x[0]).values
255
+ )
256
+ cnt.columns = cnt.columns.to_series().str.split("_").apply(lambda x: x[1])
257
+ std_error = std.divide(cnt.apply(np.sqrt), axis=1)
258
+
259
+ std_error.columns = (std_error.columns.to_series() + "std_error").values
260
+
261
+ csv = pd.concat([csv, std_error], axis=1, sort=True)
262
+
263
+ else:
264
+ std_error = csv.loc[:, "std"].divide(
265
+ csv.loc[:, "n_obs"].apply(np.sqrt), axis=0
266
+ )
267
+ csv.loc[:, "std_error"] = std_error
268
+ csv.sort_index(axis=1, inplace=True)
269
+
270
+ csv.set_index(ts, inplace=True)
271
+ self.convert_nans(csv)
272
+
273
+ new_data_path = new_data_path.with_suffix(".csv")
274
+ csv.to_csv(new_data_path, sep=",", na_rep="NaN")
275
+ old_data_path = old_data_path.with_suffix(".csv")
276
+ try:
277
+ old_data_path.unlink()
278
+ except FileNotFoundError:
279
+ pass
280
+
281
+ def load_data(self):
282
+ super().load_data()
283
+
284
+ extrema = SSNExtrema()
285
+ # Calculate Cycle to which each mesurement belongs
286
+ data = self.data
287
+ cut = pd.cut(data.index, pd.IntervalIndex(extrema.cycle_intervals.Cycle.values))
288
+ cut = pd.Series(cut, index=data.index, name="cycle")
289
+ cut = cut.map(
290
+ extrema.cycle_intervals.Cycle.reset_index().set_index("Cycle").Number
291
+ )
292
+
293
+ data = pd.concat([data, cut], axis=1, sort=True)
294
+ self._data = data
295
+
296
+ self.logger.info("Load complete")
297
+
298
+
299
+ class SIDC(ActivityIndicator):
300
+ """Solar sunspot number data from the SIDC.
301
+
302
+ Parameters
303
+ ----------
304
+ key : str
305
+ Passed to :class:`SIDC_ID` to select the data series.
306
+ """
307
+
308
+ def __init__(self, key):
309
+ self._init_logger()
310
+ self.set_id(SIDC_ID(key))
311
+ self.load_data()
312
+ self.set_extrema()
313
+ self.calculate_extrema_kind()
314
+ self.calculate_edge()
315
+
316
+ # @property
317
+ # def extrema(self):
318
+ # return self._extrema
319
+
320
+ @property
321
+ def spec_by_ssn_band(self):
322
+ return self._spec_by_ssn_band
323
+
324
+ @property
325
+ def ssn_band_intervals(self):
326
+ return self._ssn_band_intervals
327
+
328
+ def load_data(self):
329
+ loader = SIDCLoader(self.id.key, self.id.url)
330
+ loader.load_data()
331
+ self._loader = loader
332
+
333
+ def set_extrema(self):
334
+ self._extrema = SSNExtrema()
335
+
336
+ def interpolate_data(self, target_index, key="ssn"):
337
+ interpolated = super(SIDC, self).interpolate_data(
338
+ self.data.loc[:, key].dropna(how="any", axis=0), target_index
339
+ )
340
+ self._interpolated = interpolated
341
+ return interpolated
342
+
343
+ def calculate_extrema_kind(self):
344
+ r"""Determine whether an SSN observation belongs to a cycle Minimum or Maximum.
345
+
346
+ Min: ssn < cycle mean
347
+ Max: ssn >= cycle mean
348
+
349
+ Labels for the extremum kind include indicators for which cycle the extremum
350
+ belongs to. These can be easily stripped with string manipulations, but are
351
+ difficult to calculate after the fact.
352
+ """
353
+ extrema = self.extrema.data
354
+ kind = pd.Series(np.nan, index=self.data.index, dtype=str)
355
+ for k, g in self.data.loc[:, ["cycle", "ssn"]].groupby("cycle"):
356
+ g = g.loc[:, "ssn"]
357
+ mid = 0.5 * g.max()
358
+ max_date = extrema.loc[k, "Max"]
359
+ before_max = g.index <= max_date
360
+ after_max = g.index > max_date
361
+
362
+ case = pd.Series(index=g.index, dtype=str)
363
+ case.loc[g >= mid] = f"{k}-Max"
364
+ case.loc[(g < mid) & before_max] = f"{k}-Min"
365
+ case.loc[(g < mid) & after_max] = f"{k + 1}-Min"
366
+
367
+ kind.update(case)
368
+
369
+ self.data.loc[:, "extremum"] = kind
370
+
371
+ def calculate_edge(self):
372
+ r"""Determine whether an SSN observation belongs to a rising or falling edge."""
373
+ extrema = self.extrema.data
374
+ kind = pd.Series(np.nan, index=self.data.index, dtype=str)
375
+
376
+ for k, g in self.data.loc[:, ["cycle", "ssn"]].groupby("cycle"):
377
+ g = g.loc[:, "ssn"]
378
+ max_date = extrema.loc[k, "Max"]
379
+ before_max = g.index <= max_date
380
+ after_max = g.index > max_date
381
+
382
+ case = pd.Series(index=g.index, dtype=str)
383
+ case.loc[before_max] = "Rise"
384
+ case.loc[after_max] = "Fall"
385
+
386
+ kind.update(case)
387
+
388
+ self.data.loc[:, "edge"] = kind
389
+
390
+ #################
391
+ # Normalize SSN #
392
+ #################
393
+ @property
394
+ def normalized(self):
395
+ try:
396
+ # return self._normalized_ssn
397
+ return self.data.loc[:, "nssn"]
398
+ except KeyError: # AttributeError:
399
+ return self.run_normalization()
400
+
401
+ def _run_normalization(self, indicator, norm_fcn):
402
+ cut = self.extrema.cut_spec_by_interval(indicator.index, kind="Cycle")
403
+ joint = pd.concat(
404
+ [indicator, cut], axis=1, keys=["indicator", "cycle"]
405
+ ).sort_index(axis=1)
406
+ grouped = joint.groupby("cycle")
407
+
408
+ normed = {}
409
+ for k, g in grouped:
410
+ g = g.loc[:, "indicator"]
411
+ normed[k] = norm_fcn(g)
412
+ normed = pd.concat(normed.values(), axis=0).sort_index()
413
+ return normed
414
+
415
+ def run_normalization(self, norm_by="max"):
416
+ # Note: "max" and "feature-scale" are the same if the min(SSN) = 0.
417
+ assert norm_by in ("max", "zscore", "feature-scale")
418
+ self.logger.info("Normalizing SSN by %s", norm_by)
419
+ self._norm_by = norm_by
420
+
421
+ if norm_by == "max":
422
+
423
+ def norm_fcn(g):
424
+ return g.divide(g.max())
425
+
426
+ elif norm_by == "zscore":
427
+
428
+ def norm_fcn(g):
429
+ return g.subtract(g.mean()).divide(g.std())
430
+
431
+ elif norm_by == "feature-scale":
432
+
433
+ def norm_fcn(g):
434
+ return g.subtract(g.min()).divide(g.max() - g.min())
435
+
436
+ ssn = self.data.loc[:, "ssn"]
437
+ normed = self._run_normalization(ssn, norm_fcn)
438
+
439
+ self.data.loc[:, "nssn"] = normed
440
+ self.data.sort_index(axis=1, inplace=True)
441
+
442
+ try:
443
+ interpolated = self.interpolated.loc[:, "ssn"]
444
+ normed_interpolated = self._run_normalization(interpolated, norm_fcn)
445
+ self.interpolated.loc[:, "nssn"] = normed_interpolated
446
+
447
+ except AttributeError:
448
+ pass
449
+
450
+ return normed
451
+
452
+ run_normalization.__doc__ = ActivityIndicator.run_normalization
453
+
454
+ def cut_spec_by_ssn_band(self, key="ssn", dssn=2.0):
455
+ r"""Cut the sunspot number at each spectrum in intervals of width +/- dssn."""
456
+
457
+ dssn = float(dssn)
458
+ if (key == "nssn") and (dssn >= 1):
459
+ raise ValueError("Normalized SSN requires that dssn < 1")
460
+
461
+ data = self.data.loc[:, key]
462
+ mids = np.arange(0, data.max(), 2.0 * dssn)
463
+
464
+ left = mids - dssn
465
+ right = mids + dssn
466
+ intervals = [pd.Interval(ll, rr) for ll, rr in zip(left, right)]
467
+ intervals = pd.IntervalIndex(intervals, name="ssn_intervals")
468
+ try:
469
+ cut = pd.cut(
470
+ self.interpolated.loc[:, key], # TODO: Fix this generalized hack
471
+ intervals,
472
+ )
473
+ except KeyError as e:
474
+ if np.isnan(e.args[0]):
475
+ # Check that intervals don't overlap.
476
+ for ll, rr in zip(intervals[:-1], intervals[1:]):
477
+ l_upper = ll.right
478
+ r_lower = rr.left
479
+ if l_upper > r_lower:
480
+ msg = f"""Your intervals can't overlap.
481
+ Interval 0: {ll}
482
+ Interval 1: {rr}
483
+ It causes a KeyError in `pd.cut`."""
484
+ raise ValueError(msg)
485
+ else:
486
+ raise
487
+
488
+ cut.name = f"{key}_band"
489
+ self._spec_by_ssn_band = cut
490
+ self._ssn_band_intervals = intervals
491
+ return cut
492
+
493
+ def plot_on_colorbar(self, cax, t0, t1, vertical_cbar=True):
494
+ r"""Plot SSN on the color bar."""
495
+ # TODO: Refactor and abstract to :pyclass:`ActivityIndicator`.
496
+ ssn = self.data.loc[t0:t1, "ssn"]
497
+
498
+ x = mpl.dates.date2num(ssn.index)
499
+ y = ssn # .values
500
+ # print("SSN values", y.min(), y.max())
501
+
502
+ if vertical_cbar:
503
+ y0, y1 = cax.get_xlim()
504
+ else:
505
+ y0, y1 = cax.get_ylim()
506
+
507
+ dy = y1 - y0
508
+ # s0, s1 = 0, 200
509
+ s0, s1 = np.array([0, np.round(ssn.max(), -2)], dtype=int)
510
+ y = ((y / s1) * dy) + y0
511
+ # print("Map Range", y0, y1)
512
+ # print("Scaled SSN", y.min(), y.max())
513
+
514
+ if vertical_cbar:
515
+ cax.plot(y, x, ls="-", color="w", lw=1)
516
+ cax.plot(y, x, ls=(0, (7, 3, 2, 3, 2, 3, 2, 3)), color="k", lw=1)
517
+ cax.set_xlabel(r"$\mathrm{SSN} \; [\#]$")
518
+ x0, x1 = cax.get_xlim()
519
+
520
+ # We force the maximum value to be even and minimum value to be
521
+ # odd, so the mid-point must be an even integer.
522
+ cax.xaxis.set_ticks([x0, 0.5 * (x0 + x1), x1])
523
+ cax.xaxis.set_ticklabels((s0, int(0.5 * (s0 + s1)), s1))
524
+ cax.xaxis.set_tick_params(rotation=25)
525
+ cax.xaxis.set_minor_locator(mpl.ticker.MultipleLocator(25))
526
+ cax.yaxis.set_tick_params(left=True)
527
+
528
+ else:
529
+ cax.plot(x, y, ls="-", color="w", lw=1)
530
+ cax.plot(x, y, ls=(0, (7, 3, 2, 3, 2, 3, 2, 3)), color="k", lw=1)
531
+ cax.set_ylabel(r"$\mathrm{SSN} \; [\#]$")
532
+ x0, x1 = cax.get_ylim()
533
+
534
+ # We force the maximum value to be even and minimum value to be
535
+ # odd, so the mid-point must be an even integer.
536
+ cax.yaxis.set_ticks([x0, 0.5 * (x0 + x1), x1])
537
+ cax.yaxis.set_ticklabels((s0, int(0.5 * (s0 + s1)), s1))
538
+ cax.yaxis.set_tick_params(rotation=25)
539
+ cax.yaxis.set_minor_locator(mpl.ticker.MultipleLocator(25))
540
+ cax.xaxis.set_tick_params(top=True)
541
+ cax.xaxis.set_ticks_position("top")
542
+ cax.xaxis.set_label_position("top")
543
+
544
+
545
+ class SSNExtrema(IndicatorExtrema):
546
+ def load_or_set_data(self, *args, **kwargs):
547
+ if len(args) or len(kwargs):
548
+ raise ValueError(
549
+ f"""{self.__class__.__name__} expects empty args and kwargs."""
550
+ )
551
+
552
+ path = Path(__file__).parent / "ssn_extrema.csv"
553
+ data = pd.read_csv(path, header=0, skiprows=45, index_col=0)
554
+ data = pd.to_datetime(data.stack(), format="%Y-%m-%d").unstack(level=1)
555
+ data.columns.names = ["kind"]
556
+ self._data = data