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,465 @@
1
+ #!/usr/bin/env python
2
+ """Test SIDC class.
3
+
4
+ This module tests the SIDC main class from solar_activity.sunspot_number.sidc:
5
+ - Initialization with loader and SSNExtrema
6
+ - Extrema calculation and edge detection
7
+ - Normalization functionality
8
+ - SSN band cutting and plotting
9
+ """
10
+
11
+ import pytest
12
+ import pandas as pd
13
+ import numpy as np
14
+ from pathlib import Path
15
+ from unittest.mock import Mock, patch, MagicMock
16
+
17
+ from solarwindpy.solar_activity.sunspot_number.sidc import SIDC, SIDCLoader, SSNExtrema
18
+
19
+
20
+ @pytest.fixture
21
+ def mock_loader_data():
22
+ """Create mock loader data for testing."""
23
+ dates = pd.date_range("2008-01-01", "2020-12-31", freq="MS")
24
+ # Simulate solar cycle 24 data with realistic SSN values
25
+ cycle_data = []
26
+ cycle_numbers = []
27
+ ssn_values = []
28
+
29
+ for i, date in enumerate(dates):
30
+ if date < pd.Timestamp("2019-12-01"):
31
+ cycle_numbers.append(24)
32
+ # Simple sine wave for cycle 24 with realistic SSN range
33
+ phase = (i / len(dates)) * 2 * np.pi
34
+ ssn_values.append(50 + 100 * np.sin(phase) + np.random.normal(0, 10))
35
+ else:
36
+ cycle_numbers.append(25)
37
+ # Beginning of cycle 25
38
+ phase = ((i - 144) / 20) * 0.5 * np.pi
39
+ ssn_values.append(10 + 30 * np.sin(phase) + np.random.normal(0, 5))
40
+
41
+ return pd.DataFrame(
42
+ {
43
+ "ssn": ssn_values,
44
+ "std": np.random.uniform(5, 15, len(dates)),
45
+ "n_obs": np.random.randint(10, 25, len(dates)),
46
+ "cycle": cycle_numbers,
47
+ "definitive": True,
48
+ },
49
+ index=dates,
50
+ )
51
+
52
+
53
+ @pytest.fixture
54
+ def mock_extrema_data():
55
+ """Create mock extrema data for testing."""
56
+ return pd.DataFrame(
57
+ {
58
+ "Min": [pd.Timestamp("2008-12-01"), pd.Timestamp("2019-12-01")],
59
+ "Max": [pd.Timestamp("2014-04-01"), pd.Timestamp("2025-04-01")],
60
+ },
61
+ index=[24, 25],
62
+ )
63
+
64
+
65
+ class TestSIDC:
66
+ """Test the SIDC main class for sunspot number analysis."""
67
+
68
+ @patch("solarwindpy.solar_activity.sunspot_number.sidc.SIDCLoader")
69
+ @patch("solarwindpy.solar_activity.sunspot_number.sidc.SSNExtrema")
70
+ @patch("solarwindpy.solar_activity.sunspot_number.sidc.SIDC_ID")
71
+ def test_initialization(
72
+ self,
73
+ mock_sidc_id_class,
74
+ mock_ssn_extrema_class,
75
+ mock_sidc_loader_class,
76
+ mock_loader_data,
77
+ mock_extrema_data,
78
+ ):
79
+ """Test SIDC initialization with dummy loader and SSNExtrema."""
80
+ # Setup mocks - use spec to make it pass isinstance check
81
+ from solarwindpy.solar_activity.base import ID
82
+ mock_id = Mock(spec=ID)
83
+ mock_id.key = "m"
84
+ mock_id.url = "http://example.com"
85
+ mock_sidc_id_class.return_value = mock_id
86
+
87
+ mock_loader = Mock()
88
+ mock_loader.data = mock_loader_data
89
+ mock_sidc_loader_class.return_value = mock_loader
90
+
91
+ mock_extrema = Mock()
92
+ mock_extrema.data = mock_extrema_data
93
+ mock_ssn_extrema_class.return_value = mock_extrema
94
+
95
+ # Mock methods that get called during initialization
96
+ with (
97
+ patch.object(SIDC, "_init_logger"),
98
+ patch.object(SIDC, "calculate_extrema_kind"),
99
+ patch.object(SIDC, "calculate_edge"),
100
+ ):
101
+
102
+ sidc = SIDC("m")
103
+
104
+ # Verify initialization steps
105
+ mock_sidc_id_class.assert_called_once_with("m")
106
+ mock_ssn_extrema_class.assert_called_once()
107
+ assert hasattr(sidc, "_loader")
108
+ assert hasattr(sidc, "_extrema")
109
+
110
+ @patch("solarwindpy.solar_activity.sunspot_number.sidc.SIDCLoader")
111
+ def test_load_data(self, mock_sidc_loader_class):
112
+ """Test load_data method."""
113
+ mock_loader = Mock()
114
+ mock_sidc_loader_class.return_value = mock_loader
115
+
116
+ with patch.object(SIDC, "_init_logger"):
117
+ sidc = SIDC.__new__(SIDC)
118
+ sidc._id = Mock()
119
+ sidc._id.key = "m"
120
+ sidc._id.url = "http://example.com"
121
+
122
+ sidc.load_data()
123
+
124
+ # Verify loader was created and loaded
125
+ mock_sidc_loader_class.assert_called_once_with("m", "http://example.com")
126
+ mock_loader.load_data.assert_called_once()
127
+ assert sidc._loader == mock_loader
128
+
129
+ @patch("solarwindpy.solar_activity.sunspot_number.sidc.SSNExtrema")
130
+ def test_set_extrema(self, mock_ssn_extrema_class):
131
+ """Test set_extrema method."""
132
+ mock_extrema = Mock()
133
+ mock_ssn_extrema_class.return_value = mock_extrema
134
+
135
+ with patch.object(SIDC, "_init_logger"):
136
+ sidc = SIDC.__new__(SIDC)
137
+
138
+ sidc.set_extrema()
139
+
140
+ mock_ssn_extrema_class.assert_called_once()
141
+ assert sidc._extrema == mock_extrema
142
+
143
+ def test_calculate_extrema_kind(self, mock_loader_data, mock_extrema_data):
144
+ """Test calculate_extrema_kind method."""
145
+ with patch.object(SIDC, "_init_logger"):
146
+ sidc = SIDC.__new__(SIDC)
147
+ sidc._loader = Mock()
148
+ sidc._loader.data = mock_loader_data.copy()
149
+ sidc._extrema = Mock()
150
+ sidc._extrema.data = mock_extrema_data.copy()
151
+
152
+ # Ensure data columns match expected format
153
+ sidc._extrema.data.columns.names = ["kind"]
154
+ sidc._extrema.data.index.name = "Number"
155
+
156
+ sidc.calculate_extrema_kind()
157
+
158
+ # Verify extremum column was added
159
+ assert "extremum" in sidc._loader.data.columns
160
+
161
+ # Check that values are labeled correctly (should contain cycle numbers and Min/Max)
162
+ extremum_values = sidc._loader.data["extremum"].dropna()
163
+ assert len(extremum_values) > 0
164
+
165
+ # Values should contain cycle indicators like "24-Min", "24-Max", "25-Min"
166
+ for val in extremum_values:
167
+ assert isinstance(val, str)
168
+ assert any(cycle_str in val for cycle_str in ["24", "25"])
169
+ assert any(ext_str in val for ext_str in ["Min", "Max"])
170
+
171
+ def test_calculate_edge(self, mock_loader_data, mock_extrema_data):
172
+ """Test calculate_edge method."""
173
+ with patch.object(SIDC, "_init_logger"):
174
+ sidc = SIDC.__new__(SIDC)
175
+ sidc._loader = Mock()
176
+ sidc._loader.data = mock_loader_data.copy()
177
+ sidc._extrema = Mock()
178
+ sidc._extrema.data = mock_extrema_data.copy()
179
+
180
+ # Ensure data columns match expected format
181
+ sidc._extrema.data.columns.names = ["kind"]
182
+ sidc._extrema.data.index.name = "Number"
183
+
184
+ sidc.calculate_edge()
185
+
186
+ # Verify edge column was added
187
+ assert "edge" in sidc._loader.data.columns
188
+
189
+ # Check that values are either "Rise" or "Fall"
190
+ edge_values = sidc._loader.data["edge"].dropna()
191
+ assert len(edge_values) > 0
192
+
193
+ for val in edge_values:
194
+ assert val in ["Rise", "Fall"]
195
+
196
+ def test_run_normalization_max(self, mock_loader_data, mock_extrema_data):
197
+ """Test run_normalization with max normalization."""
198
+ from solarwindpy.solar_activity.base import ID
199
+ with patch.object(SIDC, "_init_logger"):
200
+ sidc = SIDC.__new__(SIDC)
201
+ sidc._logger = Mock()
202
+ sidc._id = Mock(spec=ID) # Add missing _id attribute
203
+ sidc._loader = Mock()
204
+ sidc._loader.data = mock_loader_data.copy()
205
+ sidc._extrema = Mock()
206
+ sidc._extrema.data = mock_extrema_data.copy()
207
+
208
+ # Mock the extrema.cut_spec_by_interval method
209
+ sidc._extrema.cut_spec_by_interval = Mock()
210
+ cut_data = pd.Series(
211
+ [pd.Interval(0, 100)] * len(mock_loader_data),
212
+ index=mock_loader_data.index,
213
+ name="cycle",
214
+ )
215
+ sidc._extrema.cut_spec_by_interval.return_value = cut_data
216
+
217
+ result = sidc.run_normalization(norm_by="max")
218
+
219
+ # Verify normalization was applied
220
+ assert isinstance(result, pd.Series)
221
+ assert "nssn" in sidc._loader.data.columns
222
+
223
+ # Max normalization divides by max value - can produce negative values if input has negatives
224
+ nssn_values = sidc._loader.data["nssn"].dropna()
225
+ assert nssn_values.max() <= 1 # Max should always be 1 after normalization
226
+
227
+ def test_run_normalization_zscore(self, mock_loader_data, mock_extrema_data):
228
+ """Test run_normalization with zscore normalization."""
229
+ with patch.object(SIDC, "_init_logger"):
230
+ sidc = SIDC.__new__(SIDC)
231
+ sidc._logger = Mock()
232
+ sidc._loader = Mock()
233
+ sidc._loader.data = mock_loader_data.copy()
234
+ sidc._extrema = Mock()
235
+ sidc._extrema.data = mock_extrema_data.copy()
236
+
237
+ # Mock the extrema.cut_spec_by_interval method
238
+ sidc._extrema.cut_spec_by_interval = Mock()
239
+ cut_data = pd.Series(
240
+ [pd.Interval(0, 100)] * len(mock_loader_data),
241
+ index=mock_loader_data.index,
242
+ name="cycle",
243
+ )
244
+ sidc._extrema.cut_spec_by_interval.return_value = cut_data
245
+
246
+ result = sidc.run_normalization(norm_by="zscore")
247
+
248
+ # Verify normalization was applied
249
+ assert isinstance(result, pd.Series)
250
+ assert "nssn" in sidc._loader.data.columns
251
+
252
+ # Z-score normalized values should have roughly mean=0, std=1
253
+ nssn_values = sidc._loader.data["nssn"].dropna()
254
+ assert abs(nssn_values.mean()) < 0.1 # Close to 0
255
+ assert abs(nssn_values.std() - 1.0) < 0.1 # Close to 1
256
+
257
+ def test_run_normalization_invalid_method(self, mock_loader_data):
258
+ """Test run_normalization with invalid method raises error."""
259
+ with patch.object(SIDC, "_init_logger"):
260
+ sidc = SIDC.__new__(SIDC)
261
+ sidc._loader = Mock()
262
+ sidc._loader.data = mock_loader_data.copy()
263
+
264
+ with pytest.raises(AssertionError):
265
+ sidc.run_normalization(norm_by="invalid_method")
266
+
267
+ def test_cut_spec_by_ssn_band(self, mock_loader_data):
268
+ """Test cut_spec_by_ssn_band method."""
269
+ from solarwindpy.solar_activity.base import ID
270
+ with patch.object(SIDC, "_init_logger"):
271
+ sidc = SIDC.__new__(SIDC)
272
+ sidc._id = Mock(spec=ID) # Add missing _id attribute
273
+ sidc._loader = Mock()
274
+ sidc._loader.data = mock_loader_data.copy()
275
+
276
+ # Create mock interpolated data
277
+ sidc._interpolated = mock_loader_data[["ssn"]].copy()
278
+
279
+ # Test the method
280
+ result = sidc.cut_spec_by_ssn_band(key="ssn", dssn=10.0)
281
+
282
+ # Verify result
283
+ assert isinstance(result, pd.Series)
284
+ assert result.name == "ssn_band"
285
+ assert hasattr(sidc, "_spec_by_ssn_band")
286
+ assert hasattr(sidc, "_ssn_band_intervals")
287
+
288
+ def test_cut_spec_by_ssn_band_normalized_validation(self, mock_loader_data):
289
+ """Test that cut_spec_by_ssn_band validates dssn for normalized data."""
290
+ from solarwindpy.solar_activity.base import ID
291
+ with patch.object(SIDC, "_init_logger"):
292
+ sidc = SIDC.__new__(SIDC)
293
+ sidc._id = Mock(spec=ID) # Add missing _id attribute
294
+ sidc._loader = Mock()
295
+ sidc._loader.data = mock_loader_data.copy()
296
+ sidc._loader.data["nssn"] = sidc._loader.data["ssn"] / 100 # Normalized
297
+
298
+ # Create mock interpolated data
299
+ sidc._interpolated = sidc._loader.data[["nssn"]].copy()
300
+
301
+ # Should raise error for dssn >= 1 with normalized data
302
+ with pytest.raises(
303
+ ValueError, match="Normalized SSN requires that dssn < 1"
304
+ ):
305
+ sidc.cut_spec_by_ssn_band(key="nssn", dssn=1.5)
306
+
307
+ def test_interpolate_data(self, mock_loader_data):
308
+ """Test interpolate_data method."""
309
+ with patch.object(SIDC, "_init_logger"):
310
+ sidc = SIDC.__new__(SIDC)
311
+ sidc._loader = Mock()
312
+ sidc._loader.data = mock_loader_data.copy()
313
+
314
+ # Create target index for interpolation
315
+ target_index = pd.date_range("2010-01-01", "2015-12-31", freq="D")
316
+
317
+ # Mock parent interpolate_data method
318
+ expected_result = pd.Series(
319
+ np.random.uniform(10, 100, len(target_index)),
320
+ index=target_index,
321
+ name="ssn",
322
+ )
323
+
324
+ with patch.object(
325
+ SIDC.__bases__[0], "interpolate_data", return_value=expected_result
326
+ ):
327
+ result = sidc.interpolate_data(target_index, key="ssn")
328
+
329
+ # Verify result
330
+ assert isinstance(result, pd.Series)
331
+ assert len(result) == len(target_index)
332
+ assert hasattr(sidc, "_interpolated")
333
+
334
+ def test_properties_access(self, mock_loader_data, mock_extrema_data):
335
+ """Test property accessors."""
336
+ with patch.object(SIDC, "_init_logger"):
337
+ sidc = SIDC.__new__(SIDC)
338
+ sidc._loader = Mock()
339
+ sidc._loader.data = mock_loader_data.copy()
340
+ sidc._extrema = Mock()
341
+ sidc._extrema.data = mock_extrema_data.copy()
342
+
343
+ # Set up some internal state
344
+ sidc._spec_by_ssn_band = pd.Series([1, 2, 3])
345
+ sidc._ssn_band_intervals = pd.IntervalIndex([pd.Interval(0, 10)])
346
+
347
+ # Test properties
348
+ assert hasattr(sidc, "spec_by_ssn_band")
349
+ assert hasattr(sidc, "ssn_band_intervals")
350
+
351
+ assert sidc.spec_by_ssn_band is not None
352
+ assert sidc.ssn_band_intervals is not None
353
+
354
+ def test_inheritance_from_activity_indicator(self):
355
+ """Test that SIDC inherits from ActivityIndicator."""
356
+ from solarwindpy.solar_activity.base import ActivityIndicator
357
+
358
+ with (
359
+ patch.object(SIDC, "_init_logger"),
360
+ patch.object(SIDC, "load_data"),
361
+ patch.object(SIDC, "set_extrema"),
362
+ patch.object(SIDC, "calculate_extrema_kind"),
363
+ patch.object(SIDC, "calculate_edge"),
364
+ ):
365
+
366
+ sidc = SIDC("m")
367
+ assert isinstance(sidc, ActivityIndicator)
368
+
369
+
370
+ class TestSIDCEdgeCases:
371
+ """Test edge cases and error conditions for SIDC."""
372
+
373
+ def test_normalized_property_without_nssn_column(self, mock_loader_data):
374
+ """Test normalized property when nssn column doesn't exist."""
375
+ from solarwindpy.solar_activity.base import ID
376
+ with patch.object(SIDC, "_init_logger"):
377
+ sidc = SIDC.__new__(SIDC)
378
+ sidc._id = Mock(spec=ID) # Add missing _id attribute
379
+ sidc._loader = Mock()
380
+ sidc._loader.data = mock_loader_data.copy() # No 'nssn' column
381
+
382
+ # Mock normalize_ssn method
383
+ expected_normalized = pd.Series(
384
+ np.random.uniform(0, 1, len(mock_loader_data)),
385
+ index=mock_loader_data.index,
386
+ name="nssn",
387
+ )
388
+
389
+ with patch.object(sidc, "run_normalization", return_value=expected_normalized):
390
+ result = sidc.normalized
391
+
392
+ # Should call run_normalization when nssn column doesn't exist
393
+ sidc.run_normalization.assert_called_once()
394
+ assert isinstance(result, pd.Series)
395
+
396
+ def test_normalized_property_with_existing_nssn(self, mock_loader_data):
397
+ """Test normalized property when nssn column exists."""
398
+ with patch.object(SIDC, "_init_logger"):
399
+ sidc = SIDC.__new__(SIDC)
400
+ sidc._loader = Mock()
401
+ test_data = mock_loader_data.copy()
402
+ test_data["nssn"] = test_data["ssn"] / 100 # Add normalized column
403
+ sidc._loader.data = test_data
404
+
405
+ result = sidc.normalized
406
+
407
+ # Should return existing nssn column
408
+ assert isinstance(result, pd.Series)
409
+ assert result.name == "nssn"
410
+ pd.testing.assert_series_equal(result, test_data["nssn"])
411
+
412
+ def test_data_property_access(self, mock_loader_data):
413
+ """Test that data property returns loader data."""
414
+ with patch.object(SIDC, "_init_logger"):
415
+ sidc = SIDC.__new__(SIDC)
416
+ sidc._loader = Mock()
417
+ sidc._loader.data = mock_loader_data.copy()
418
+
419
+ result = sidc.data
420
+
421
+ assert isinstance(result, pd.DataFrame)
422
+ pd.testing.assert_frame_equal(result, mock_loader_data)
423
+
424
+ def test_calculate_extrema_kind_empty_data(self):
425
+ """Test calculate_extrema_kind with empty data."""
426
+ with patch.object(SIDC, "_init_logger"):
427
+ sidc = SIDC.__new__(SIDC)
428
+ sidc._loader = Mock()
429
+ sidc._loader.data = pd.DataFrame(columns=["cycle", "ssn"])
430
+ sidc._extrema = Mock()
431
+ sidc._extrema.data = pd.DataFrame(columns=["Min", "Max"])
432
+
433
+ # Should handle empty data gracefully
434
+ sidc.calculate_extrema_kind()
435
+
436
+ assert "extremum" in sidc._loader.data.columns
437
+
438
+ def test_calculate_edge_empty_data(self):
439
+ """Test calculate_edge with empty data."""
440
+ with patch.object(SIDC, "_init_logger"):
441
+ sidc = SIDC.__new__(SIDC)
442
+ sidc._loader = Mock()
443
+ sidc._loader.data = pd.DataFrame(columns=["cycle", "ssn"])
444
+ sidc._extrema = Mock()
445
+ sidc._extrema.data = pd.DataFrame(columns=["Min", "Max"])
446
+
447
+ # Should handle empty data gracefully
448
+ sidc.calculate_edge()
449
+
450
+ assert "edge" in sidc._loader.data.columns
451
+
452
+ def test_plot_on_colorbar_method_exists(self):
453
+ """Test that plot_on_colorbar method exists and is callable."""
454
+ with (
455
+ patch.object(SIDC, "_init_logger"),
456
+ patch.object(SIDC, "load_data"),
457
+ patch.object(SIDC, "set_extrema"),
458
+ patch.object(SIDC, "calculate_extrema_kind"),
459
+ patch.object(SIDC, "calculate_edge"),
460
+ ):
461
+
462
+ sidc = SIDC("m")
463
+
464
+ assert hasattr(sidc, "plot_on_colorbar")
465
+ assert callable(sidc.plot_on_colorbar)
@@ -0,0 +1,223 @@
1
+ #!/usr/bin/env python
2
+ """Test SIDC_ID class.
3
+
4
+ This module tests the SIDC_ID class from solar_activity.sunspot_number.sidc:
5
+ - URL mapping and key validation
6
+ - Valid and invalid key handling
7
+ - URL construction for SIDC endpoints
8
+ """
9
+
10
+ import pytest
11
+ from unittest.mock import Mock, patch
12
+
13
+ from solarwindpy.solar_activity.sunspot_number.sidc import SIDC_ID
14
+
15
+
16
+ class TestSIDC_ID:
17
+ """Test the SIDC_ID class for URL mapping and key validation."""
18
+
19
+ def test_valid_key_initialization(self):
20
+ """Test SIDC_ID initialization with valid keys."""
21
+ valid_keys = ["d", "m", "m13", "y", "hd", "hm", "hm13"]
22
+
23
+ for key in valid_keys:
24
+ sidc_id = SIDC_ID(key)
25
+ assert sidc_id.key == key
26
+
27
+ def test_url_base_property(self):
28
+ """Test that _url_base returns the correct SIDC base URL."""
29
+ sidc_id = SIDC_ID("d")
30
+ expected_url_base = "http://www.sidc.be/silso/INFO/"
31
+ assert sidc_id._url_base == expected_url_base
32
+
33
+ def test_trans_url_mapping(self):
34
+ """Test the _trans_url property provides correct URL mappings."""
35
+ sidc_id = SIDC_ID("d")
36
+ trans_url_dict = sidc_id._trans_url
37
+
38
+ expected_mappings = {
39
+ "d": "sndtotcsv.php",
40
+ "m": "snmtotcsv.php",
41
+ "m13": "snmstotcsv.php",
42
+ "y": "snytotcsv.php",
43
+ "hd": "sndhemcsv.php",
44
+ "hm": "snmhemcsv.php",
45
+ "hm13": "snmshemcsv.php",
46
+ }
47
+
48
+ for key, expected_filename in expected_mappings.items():
49
+ assert trans_url_dict[key] == expected_filename
50
+
51
+ def test_url_construction_valid_keys(self):
52
+ """Test URL construction for valid SIDC keys."""
53
+ test_cases = [
54
+ ("d", "http://www.sidc.be/silso/INFO/sndtotcsv.php"),
55
+ ("m", "http://www.sidc.be/silso/INFO/snmtotcsv.php"),
56
+ ("m13", "http://www.sidc.be/silso/INFO/snmstotcsv.php"),
57
+ ("y", "http://www.sidc.be/silso/INFO/snytotcsv.php"),
58
+ ("hd", "http://www.sidc.be/silso/INFO/sndhemcsv.php"),
59
+ ("hm", "http://www.sidc.be/silso/INFO/snmhemcsv.php"),
60
+ ("hm13", "http://www.sidc.be/silso/INFO/snmshemcsv.php"),
61
+ ]
62
+
63
+ for key, expected_url in test_cases:
64
+ sidc_id = SIDC_ID(key)
65
+ assert sidc_id.url == expected_url
66
+
67
+ def test_invalid_key_error_handling(self):
68
+ """Test that invalid keys raise appropriate errors."""
69
+ invalid_key = "invalid_key_not_in_mapping"
70
+
71
+ # SIDC_ID raises NotImplementedError during initialization for invalid keys
72
+ with pytest.raises(NotImplementedError, match="key unavailable"):
73
+ SIDC_ID(invalid_key)
74
+
75
+ def test_inheritance_from_id_base_class(self):
76
+ """Test that SIDC_ID inherits from ID base class."""
77
+ from solarwindpy.solar_activity.base import ID
78
+
79
+ sidc_id = SIDC_ID("d")
80
+ assert isinstance(sidc_id, ID)
81
+
82
+ # Test that it has the expected inherited properties
83
+ assert hasattr(sidc_id, "key")
84
+ assert hasattr(sidc_id, "url")
85
+
86
+ def test_key_case_sensitivity(self):
87
+ """Test that keys are case-sensitive."""
88
+ # Valid key
89
+ valid_id = SIDC_ID("m")
90
+ assert valid_id.key == "m"
91
+
92
+ # Case variations should raise NotImplementedError during init
93
+ case_variant_key = "M" # uppercase
94
+
95
+ with pytest.raises(NotImplementedError, match="key unavailable"):
96
+ SIDC_ID(case_variant_key)
97
+
98
+ def test_url_property_consistency(self):
99
+ """Test that url property is consistent and repeatable."""
100
+ sidc_id = SIDC_ID("m")
101
+ url1 = sidc_id.url
102
+ url2 = sidc_id.url
103
+
104
+ # URL should be consistent across multiple accesses
105
+ assert url1 == url2
106
+ assert url1 is not None
107
+ assert isinstance(url1, str)
108
+ assert url1.startswith("http://")
109
+
110
+ def test_all_mapped_keys_produce_valid_urls(self):
111
+ """Test that all keys in the mapping produce valid URL strings."""
112
+ # Get all mapped keys by creating an instance and accessing _trans_url
113
+ sample_id = SIDC_ID("d")
114
+ all_mapped_keys = sample_id._trans_url.keys()
115
+
116
+ for key in all_mapped_keys:
117
+ sidc_id = SIDC_ID(key)
118
+ url = sidc_id.url
119
+
120
+ # Basic URL validation
121
+ assert isinstance(url, str)
122
+ assert url.startswith("http://www.sidc.be/silso/INFO/")
123
+ assert url.endswith(".php")
124
+ assert len(url) > len(sidc_id._url_base)
125
+
126
+
127
+ class TestSIDC_IDEdgeCases:
128
+ """Test edge cases and error conditions for SIDC_ID."""
129
+
130
+ def test_empty_key_handling(self):
131
+ """Test behavior with empty or None keys."""
132
+ # Empty string key should raise NotImplementedError during init
133
+ with pytest.raises(NotImplementedError, match="key unavailable"):
134
+ SIDC_ID("")
135
+
136
+ # None key also raises NotImplementedError during init
137
+ with pytest.raises(NotImplementedError, match="key unavailable"):
138
+ SIDC_ID(None)
139
+
140
+ def test_whitespace_key_handling(self):
141
+ """Test behavior with whitespace in keys."""
142
+ whitespace_key = " m "
143
+
144
+ # Should not match the valid mapping due to whitespace, raises during init
145
+ with pytest.raises(NotImplementedError, match="key unavailable"):
146
+ SIDC_ID(whitespace_key)
147
+
148
+ def test_numeric_key_handling(self):
149
+ """Test behavior with numeric keys."""
150
+ # String numeric key should raise NotImplementedError during init
151
+ with pytest.raises(NotImplementedError, match="key unavailable"):
152
+ SIDC_ID("13")
153
+
154
+ # Integer key also raises NotImplementedError during init
155
+ with pytest.raises(NotImplementedError, match="key unavailable"):
156
+ SIDC_ID(13)
157
+
158
+ def test_special_characters_in_key(self):
159
+ """Test behavior with special characters in keys."""
160
+ special_key = "m13-special!@#$%"
161
+
162
+ # Should not match any valid mapping, raises during init
163
+ with pytest.raises(NotImplementedError, match="key unavailable"):
164
+ SIDC_ID(special_key)
165
+
166
+ def test_url_construction_consistency(self):
167
+ """Test that URL construction is deterministic and correct."""
168
+ key = "hm13"
169
+ id1 = SIDC_ID(key)
170
+ id2 = SIDC_ID(key)
171
+
172
+ # Both instances should produce the same URL
173
+ assert id1.url == id2.url
174
+
175
+ # URL should match expected pattern
176
+ expected = id1._url_base + id1._trans_url[key]
177
+ assert id1.url == expected
178
+
179
+ def test_key_length_variations(self):
180
+ """Test that key length variations are handled properly."""
181
+ # Valid keys of different lengths
182
+ short_key = "d" # 1 character
183
+ medium_key = "m13" # 3 characters
184
+ long_key = "hm13" # 4 characters
185
+
186
+ short_id = SIDC_ID(short_key)
187
+ medium_id = SIDC_ID(medium_key)
188
+ long_id = SIDC_ID(long_key)
189
+
190
+ assert short_id.key == short_key
191
+ assert medium_id.key == medium_key
192
+ assert long_id.key == long_key
193
+
194
+ # Invalid keys of various lengths
195
+ with pytest.raises(NotImplementedError):
196
+ SIDC_ID("abc") # 3 characters but invalid
197
+
198
+ with pytest.raises(NotImplementedError):
199
+ SIDC_ID("toolong") # longer than any valid key
200
+
201
+ def test_similar_valid_keys(self):
202
+ """Test that similar but distinct valid keys work correctly."""
203
+ # These keys are similar but should map to different URLs
204
+ monthly = SIDC_ID("m")
205
+ monthly_smoothed = SIDC_ID("m13")
206
+ hemispheric_monthly = SIDC_ID("hm")
207
+ hemispheric_monthly_smoothed = SIDC_ID("hm13")
208
+
209
+ # Should all be different URLs
210
+ urls = [
211
+ monthly.url,
212
+ monthly_smoothed.url,
213
+ hemispheric_monthly.url,
214
+ hemispheric_monthly_smoothed.url,
215
+ ]
216
+
217
+ assert len(set(urls)) == 4 # All URLs should be unique
218
+
219
+ # Check specific mappings
220
+ assert "snmtotcsv.php" in monthly.url
221
+ assert "snmstotcsv.php" in monthly_smoothed.url
222
+ assert "snmhemcsv.php" in hemispheric_monthly.url
223
+ assert "snmshemcsv.php" in hemispheric_monthly_smoothed.url