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

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

Potentially problematic release.


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

Files changed (412) hide show
  1. plans/.velocity/metrics.json +96 -0
  2. plans/0-overview-template.md +268 -0
  3. plans/N-phase-template.md +106 -0
  4. plans/PLAN_AUDIT_SUMMARY.md +173 -0
  5. plans/TEMPLATE-USAGE-GUIDE.md +198 -0
  6. plans/__init__.py +1 -0
  7. plans/abandoned/compaction-agent-system/0-Overview.md +123 -0
  8. plans/abandoned/compaction-agent-system/agents-index-update-plan.md +109 -0
  9. plans/abandoned/compaction-agent-system/compacted_state.md +85 -0
  10. plans/abandoned/compaction-agent-system/implementation-plan.md +107 -0
  11. plans/abandoned/compaction-agent-system/system-validation-report.md +159 -0
  12. plans/abandoned/compaction-agent-system/usage-guide.md +210 -0
  13. plans/abandoned/hook-system-enhancement/0-Overview.md +214 -0
  14. plans/abandoned/hook-system-enhancement/1-Phase1-Core-Infrastructure.md +313 -0
  15. plans/abandoned/hook-system-enhancement/2-Phase2-Intelligent-Testing.md +385 -0
  16. plans/abandoned/hook-system-enhancement/3-Phase3-Physics-Validation.md +444 -0
  17. plans/abandoned/hook-system-enhancement/4-Phase4-Performance-Monitoring.md +458 -0
  18. plans/abandoned/hook-system-enhancement/5-Phase5-Developer-Experience.md +532 -0
  19. plans/abandoned/hook-system-enhancement/6-Implementation-Timeline.md +274 -0
  20. plans/abandoned/hook-system-enhancement/7-Risk-Management.md +376 -0
  21. plans/abandoned/hook-system-enhancement/8-Testing-Strategy.md +579 -0
  22. plans/abandoned/readthedocs-automation/0-Overview.md +247 -0
  23. plans/abandoned/readthedocs-automation/1-Emergency-Documentation-Fixes.md +270 -0
  24. plans/abandoned/readthedocs-automation/2-Template-System-Enhancement.md +811 -0
  25. plans/abandoned/readthedocs-automation/3-Quality-Audit-ReadTheDocs-Integration.md +844 -0
  26. plans/abandoned/readthedocs-automation/4-Plan-Consolidation-Cleanup.md +632 -0
  27. plans/abandoned/readthedocs-automation/9-Closeout.md +207 -0
  28. plans/abandoned/readthedocs-automation/ABANDONMENT_REASON.md +72 -0
  29. plans/cicd-architecture-redesign/0-Overview.md +193 -0
  30. plans/cicd-architecture-redesign/1-Workflow-Creation.md +103 -0
  31. plans/cicd-architecture-redesign/2-Version-Detection.md +123 -0
  32. plans/cicd-architecture-redesign/3-Deployment-Gates.md +169 -0
  33. plans/cicd-architecture-redesign/4-RC-Testing.md +194 -0
  34. plans/cicd-architecture-redesign/5-TestPyPI-Validation.md +264 -0
  35. plans/cicd-architecture-redesign/6-Production-Release.md +263 -0
  36. plans/cicd-architecture-redesign/7-Cleanup.md +243 -0
  37. plans/cicd-architecture-redesign/8-Documentation.md +285 -0
  38. plans/cicd-architecture-redesign/Closeout.md +225 -0
  39. plans/closeout-template.md +259 -0
  40. plans/completed/circular-import-audit/0-Overview.md +152 -0
  41. plans/completed/circular-import-audit/1-Static-Dependency-Analysis.md +62 -0
  42. plans/completed/circular-import-audit/2-Dynamic-Import-Testing.md +56 -0
  43. plans/completed/circular-import-audit/3-Performance-Impact-Assessment.md +56 -0
  44. plans/completed/circular-import-audit/4-Issue-Remediation.md +78 -0
  45. plans/completed/circular-import-audit/5-Preventive-Infrastructure.md +89 -0
  46. plans/completed/claude-settings-ecosystem-alignment/0-Overview.md +162 -0
  47. plans/completed/claude-settings-ecosystem-alignment/1-Security-Foundation.md +148 -0
  48. plans/completed/claude-settings-ecosystem-alignment/2-Hook-Integration.md +158 -0
  49. plans/completed/claude-settings-ecosystem-alignment/3-Agent-System-Integration.md +177 -0
  50. plans/completed/claude-settings-ecosystem-alignment/4-Enhanced-Workflow-Automation.md +159 -0
  51. plans/completed/claude-settings-ecosystem-alignment/5-Validation-Monitoring.md +181 -0
  52. plans/completed/claude-settings-ecosystem-alignment/compacted_session_state.md +290 -0
  53. plans/completed/combined_plan_with_checklist_documentation/1-Overview-and-Goals.md +51 -0
  54. plans/completed/combined_plan_with_checklist_documentation/2-Toolchain-and-Hosting.md +69 -0
  55. plans/completed/combined_plan_with_checklist_documentation/3-Repository-Structure.md +61 -0
  56. plans/completed/combined_plan_with_checklist_documentation/4-Configuration-and-Standards.md +70 -0
  57. plans/completed/combined_plan_with_checklist_documentation/5-Documentation-Content.md +62 -0
  58. plans/completed/combined_plan_with_checklist_documentation/6-CI-CD-and-Validation.md +58 -0
  59. plans/completed/combined_plan_with_checklist_documentation/7-Maintenance.md +55 -0
  60. plans/completed/combined_test_plan_with_checklist_fitfunctions/0-Overview.md +135 -0
  61. plans/completed/combined_test_plan_with_checklist_fitfunctions/1-Common-fixtures.md +59 -0
  62. plans/completed/combined_test_plan_with_checklist_fitfunctions/10-power_laws.md +56 -0
  63. plans/completed/combined_test_plan_with_checklist_fitfunctions/2-core.py-FitFunction.md +118 -0
  64. plans/completed/combined_test_plan_with_checklist_fitfunctions/3-gaussians.py-Gaussian-GaussianNormalized-GaussianLn.md +69 -0
  65. plans/completed/combined_test_plan_with_checklist_fitfunctions/4-trend_fits.py-TrendFit.md +99 -0
  66. plans/completed/combined_test_plan_with_checklist_fitfunctions/5-plots.py-FFPlot.md +98 -0
  67. plans/completed/combined_test_plan_with_checklist_fitfunctions/6-tex_info.py-TeXinfo.md +79 -0
  68. plans/completed/combined_test_plan_with_checklist_fitfunctions/7-Justification.md +49 -0
  69. plans/completed/combined_test_plan_with_checklist_fitfunctions/8-exponentials.md +64 -0
  70. plans/completed/combined_test_plan_with_checklist_fitfunctions/9-lines.md +58 -0
  71. plans/completed/combined_test_plan_with_checklist_plotting/0-Overview.md +142 -0
  72. plans/completed/combined_test_plan_with_checklist_plotting/1-base.py.md +90 -0
  73. plans/completed/combined_test_plan_with_checklist_plotting/10-labels-special.py.md +102 -0
  74. plans/completed/combined_test_plan_with_checklist_plotting/11-labels-chemistry.py.md +212 -0
  75. plans/completed/combined_test_plan_with_checklist_plotting/12-labels-composition.py.md +242 -0
  76. plans/completed/combined_test_plan_with_checklist_plotting/13-labels-datetime.py.md +247 -0
  77. plans/completed/combined_test_plan_with_checklist_plotting/14-labels-elemental_abundance.py.md +274 -0
  78. plans/completed/combined_test_plan_with_checklist_plotting/15-visual-validation.md +256 -0
  79. plans/completed/combined_test_plan_with_checklist_plotting/16-integration-testing.md +266 -0
  80. plans/completed/combined_test_plan_with_checklist_plotting/17-performance-benchmarks.md +267 -0
  81. plans/completed/combined_test_plan_with_checklist_plotting/18-Fixtures-and-Utilities.md +86 -0
  82. plans/completed/combined_test_plan_with_checklist_plotting/2-agg_plot.py.md +90 -0
  83. plans/completed/combined_test_plan_with_checklist_plotting/3-histograms.py.md +201 -0
  84. plans/completed/combined_test_plan_with_checklist_plotting/4-scatter.py.md +167 -0
  85. plans/completed/combined_test_plan_with_checklist_plotting/5-spiral.py.md +216 -0
  86. plans/completed/combined_test_plan_with_checklist_plotting/6-orbits.py.md +108 -0
  87. plans/completed/combined_test_plan_with_checklist_plotting/7-tools.py.md +86 -0
  88. plans/completed/combined_test_plan_with_checklist_plotting/8-select_data_from_figure.py.md +97 -0
  89. plans/completed/combined_test_plan_with_checklist_plotting/9-labels-base.py.md +88 -0
  90. plans/completed/combined_test_plan_with_checklist_solar_activity/.gitkeep +0 -0
  91. plans/completed/combined_test_plan_with_checklist_solar_activity/0-Overview.md +170 -0
  92. plans/completed/combined_test_plan_with_checklist_solar_activity/1-Package-Entry-Point-__init__.py.md +121 -0
  93. plans/completed/combined_test_plan_with_checklist_solar_activity/2-Core-Base-Classes-base.py.md +142 -0
  94. plans/completed/combined_test_plan_with_checklist_solar_activity/3-Plotting-Helpers-plots.py.md +123 -0
  95. plans/completed/combined_test_plan_with_checklist_solar_activity/4-LISIRD-Sub-package.md +119 -0
  96. plans/completed/combined_test_plan_with_checklist_solar_activity/5-Extrema-Calculator.md +103 -0
  97. plans/completed/combined_test_plan_with_checklist_solar_activity/6-Sunspot-Number-Sub-package.md +163 -0
  98. plans/completed/combined_test_plan_with_checklist_solar_activity/7-Sunspot-Number-Init.py.md +217 -0
  99. plans/completed/combined_test_plan_with_checklist_solar_activity/compacted_state.md +52 -0
  100. plans/completed/compaction-agent-modernization/0-Overview.md +156 -0
  101. plans/completed/compaction-agent-modernization/1-Architecture-Audit-Gap-Analysis.md +132 -0
  102. plans/completed/compaction-agent-modernization/2-Token-Baseline-Recalibration.md +153 -0
  103. plans/completed/compaction-agent-modernization/3-Agent-Reference-Updates.md +184 -0
  104. plans/completed/compaction-agent-modernization/4-Compression-Algorithm-Modernization.md +238 -0
  105. plans/completed/compaction-agent-modernization/5-Workflow-Integration-Streamlining.md +252 -0
  106. plans/completed/compaction-agent-modernization/6-Template-Structure-Optimization.md +240 -0
  107. plans/completed/compaction-agent-modernization/7-Integration-Testing-Validation.md +292 -0
  108. plans/completed/compaction-hook-enhancement/0-Overview.md +150 -0
  109. plans/completed/compaction-hook-enhancement/1-Token-Estimation-Enhancement.md +179 -0
  110. plans/completed/compaction-hook-enhancement/2-Compression-Intelligence.md +294 -0
  111. plans/completed/compaction-hook-enhancement/3-Git-Integration-Metadata.md +310 -0
  112. plans/completed/compaction-hook-enhancement/4-Session-Continuity-Features.md +358 -0
  113. plans/completed/compaction-hook-enhancement/5-Testing-Strategy.md +404 -0
  114. plans/completed/compaction-hook-enhancement/6-Integration-Roadmap.md +319 -0
  115. plans/completed/compaction-hook-enhancement/compacted_state.md +142 -0
  116. plans/completed/docstring-audit-enhancement/0-Overview.md +274 -0
  117. plans/completed/docstring-audit-enhancement/1-Infrastructure-Setup-and-Validation-Tools.md +206 -0
  118. plans/completed/docstring-audit-enhancement/2-Core-Physics-Modules-Enhancement.md +237 -0
  119. plans/completed/docstring-audit-enhancement/3-Fitfunctions-Mathematical-Modules-Enhancement.md +188 -0
  120. plans/completed/docstring-audit-enhancement/4-Plotting-Visualization-Modules-Enhancement.md +243 -0
  121. plans/completed/docstring-audit-enhancement/5-Specialized-Modules-Enhancement.md +216 -0
  122. plans/completed/docstring-audit-enhancement/6-Validation-and-Integration.md +216 -0
  123. plans/completed/fitfunctions-testing-implementation/0-Overview.md +130 -0
  124. plans/completed/fitfunctions-testing-implementation/1-Test-Infrastructure-Setup.md +79 -0
  125. plans/completed/fitfunctions-testing-implementation/2-Common-Fixtures-Test-Utilities.md +104 -0
  126. plans/completed/fitfunctions-testing-implementation/3-Core-FitFunction-Testing.md +168 -0
  127. plans/completed/fitfunctions-testing-implementation/4-Specialized-Function-Classes.md +210 -0
  128. plans/completed/fitfunctions-testing-implementation/5-Advanced-Classes-Testing.md +214 -0
  129. plans/completed/fitfunctions-testing-implementation/6-Plotting-Integration-Testing.md +231 -0
  130. plans/completed/fitfunctions-testing-implementation/7-Extended-Coverage-BONUS.md +184 -0
  131. plans/completed/numpy-docstring-conversion-plan/numpy-docstring-conversion-plan.md +118 -0
  132. plans/completed/pr-review-remediation/0-Overview.md +138 -0
  133. plans/completed/pr-review-remediation/1-Critical-Safety-Improvements.md +179 -0
  134. plans/completed/pr-review-remediation/2-Smart-Timeouts-Validation.md +399 -0
  135. plans/completed/pr-review-remediation/3-Enhanced-GitHub-Integration.md +258 -0
  136. plans/completed/pr-review-remediation/compacted_state.md +66 -0
  137. plans/completed/python-310-migration/0-Overview.md +390 -0
  138. plans/completed/python-310-migration/1-Planning-Setup.md +164 -0
  139. plans/completed/python-310-migration/2-Implementation.md +256 -0
  140. plans/completed/python-310-migration/3-Testing-Validation.md +335 -0
  141. plans/completed/python-310-migration/4-Documentation-Release.md +274 -0
  142. plans/completed/python-310-migration/5-Closeout.md +252 -0
  143. plans/completed/requirements-management-consolidation/0-Overview.md +118 -0
  144. plans/completed/requirements-management-consolidation/1-Documentation-Validation-Environment-Setup.md +116 -0
  145. plans/completed/requirements-management-consolidation/2-Requirements-Consolidation.md +161 -0
  146. plans/completed/requirements-management-consolidation/3-Workflow-Automation-Final-Integration.md +196 -0
  147. plans/completed/single-ecosystem-plan-implementation/0-Overview.md +83 -0
  148. plans/completed/single-ecosystem-plan-implementation/1-Plan-Preservation-Session-Management.md +38 -0
  149. plans/completed/single-ecosystem-plan-implementation/2-File-Structure-Optimization.md +43 -0
  150. plans/completed/single-ecosystem-plan-implementation/3-Plan-Migration-Archive-Setup.md +82 -0
  151. plans/completed/single-ecosystem-plan-implementation/4-Agent-System-Transformation.md +108 -0
  152. plans/completed/single-ecosystem-plan-implementation/5-Template-System-Enhancement.md +131 -0
  153. plans/completed/single-ecosystem-plan-implementation/6-Final-Validation-Testing.md +120 -0
  154. plans/completed/test-directory-consolidation/0-Overview.md +51 -0
  155. plans/completed/test-directory-consolidation/1-Structure-Preparation.md +82 -0
  156. plans/completed/test-directory-consolidation/2-File-Migration.md +100 -0
  157. plans/completed/test-directory-consolidation/3-Import-Transformation.md +117 -0
  158. plans/completed/test-directory-consolidation/4-Configuration-Consolidation.md +140 -0
  159. plans/completed/test-directory-consolidation/5-Validation.md +152 -0
  160. plans/completed/test-directory-consolidation/6-Cleanup.md +156 -0
  161. plans/completed/test-planning-agents-architecture/0-Overview.md +79 -0
  162. plans/completed/test-planning-agents-architecture/1-Branch-Isolation-Testing.md +49 -0
  163. plans/completed/test-planning-agents-architecture/2-Cross-Branch-Coordination.md +51 -0
  164. plans/completed/test-planning-agents-architecture/3-Merge-Workflow-Testing.md +48 -0
  165. plans/deployment-semver-pypi-rtd/0-Overview.md +463 -0
  166. plans/deployment-semver-pypi-rtd/1-Semantic-Versioning-Foundation.md +136 -0
  167. plans/deployment-semver-pypi-rtd/2-PyPI-Deployment-Infrastructure.md +168 -0
  168. plans/deployment-semver-pypi-rtd/3-Release-Automation.md +214 -0
  169. plans/deployment-semver-pypi-rtd/4-Plan-Closeout.md +543 -0
  170. plans/deployment-semver-pypi-rtd/compacted_session_state.md +172 -0
  171. plans/deployment-semver-pypi-rtd/compacted_state.md +131 -0
  172. plans/documentation-code-audit/0-Overview.md +393 -0
  173. plans/documentation-code-audit/1-Discovery-Inventory.md +183 -0
  174. plans/documentation-code-audit/2-Execution-Environment-Setup.md +263 -0
  175. plans/documentation-code-audit/3-Systematic-Validation.md +322 -0
  176. plans/documentation-code-audit/4-Code-Example-Remediation.md +358 -0
  177. plans/documentation-code-audit/5-Physics-MultiIndex-Compliance.md +464 -0
  178. plans/documentation-code-audit/6-Doctest-Integration.md +523 -0
  179. plans/documentation-code-audit/7-Reporting-Documentation.md +498 -0
  180. plans/documentation-code-audit/8-Closeout.md +456 -0
  181. plans/documentation-rebuild-session/compacted_state.md +109 -0
  182. plans/documentation-rendering-fixes/0-Overview.md +104 -0
  183. plans/documentation-rendering-fixes/1-Sphinx-Build-Diagnostics-Warning-Audit.md +101 -0
  184. plans/documentation-rendering-fixes/2-Configuration-Infrastructure-Fixes.md +113 -0
  185. plans/documentation-rendering-fixes/3-Docstring-Syntax-Audit-Repair.md +131 -0
  186. plans/documentation-rendering-fixes/4-HTML-Page-Rendering-Verification.md +113 -0
  187. plans/documentation-rendering-fixes/5-Advanced-Documentation-Quality-Assurance.md +119 -0
  188. plans/documentation-rendering-fixes/6-Documentation-Build-Optimization-Testing.md +129 -0
  189. plans/documentation-rendering-fixes/compacted_state.md +132 -0
  190. plans/documentation-template-fix/0-Overview.md +197 -0
  191. plans/documentation-template-fix/1-Template-System-Analysis.md +269 -0
  192. plans/documentation-template-fix/2-Template-Modification.md +609 -0
  193. plans/documentation-template-fix/3-Build-System-Integration.md +766 -0
  194. plans/documentation-template-fix/4-Testing-Validation.md +1399 -0
  195. plans/documentation-template-fix/5-Documentation-Training.md +602 -0
  196. plans/documentation-workflow-fix/0-Overview.md +222 -0
  197. plans/documentation-workflow-fix/1-Immediate-Fixes.md +238 -0
  198. plans/documentation-workflow-fix/2-Configuration-Setup.md +298 -0
  199. plans/documentation-workflow-fix/3-Pre-commit-Integration.md +382 -0
  200. plans/documentation-workflow-fix/4-Workflow-Improvements.md +446 -0
  201. plans/documentation-workflow-fix/5-Documentation-and-Training.md +527 -0
  202. plans/duplicate-object-warnings-fix-plan.md +130 -0
  203. plans/github-issues-migration/0-Overview.md +510 -0
  204. plans/github-issues-migration/1-Foundation-Label-System.md +180 -0
  205. plans/github-issues-migration/2-Migration-Tool-Rewrite.md +235 -0
  206. plans/github-issues-migration/3-CLI-Integration-Automation.md +169 -0
  207. plans/github-issues-migration/4-Validated-Migration.md +252 -0
  208. plans/github-issues-migration/5-Documentation-Training.md +171 -0
  209. plans/github-issues-migration/6-Closeout.md +179 -0
  210. plans/github-workflows-repair/repair-plan.md +299 -0
  211. plans/issues_from_plans.py +342 -0
  212. plans/pr-270-doc-validation-fixes/0-Overview.md +354 -0
  213. plans/pr-270-doc-validation-fixes/1-Critical-PR-Fixes.md +117 -0
  214. plans/pr-270-doc-validation-fixes/2-Framework-Right-Sizing.md +129 -0
  215. plans/pr-270-doc-validation-fixes/3-Sustainable-Documentation.md +126 -0
  216. plans/pr-270-doc-validation-fixes/4-Closeout-Migration.md +143 -0
  217. plans/pr-270-doc-validation-fixes/PLAN_COMPLETED.md +149 -0
  218. plans/python-310-migration/0-Overview.md +390 -0
  219. plans/python-310-migration/1-Planning-Setup.md +164 -0
  220. plans/python-310-migration/2-Implementation.md +256 -0
  221. plans/python-310-migration/3-Testing-Validation.md +335 -0
  222. plans/python-310-migration/4-Documentation-Release.md +274 -0
  223. plans/python-310-migration/5-Closeout.md +252 -0
  224. plans/readthedocs-simplified/0-Overview.md +243 -0
  225. plans/readthedocs-simplified/1-Immediate-Fixes.md +216 -0
  226. plans/readthedocs-simplified/2-Template-Simplification.md +278 -0
  227. plans/readthedocs-simplified/3-ReadTheDocs-Setup.md +298 -0
  228. plans/readthedocs-simplified/4-Testing-Validation.md +328 -0
  229. plans/readthedocs-simplified/5-Closeout.md +231 -0
  230. plans/readthedocs-simplified/compacted_state.md +127 -0
  231. plans/session-compaction-2025-08-12/compacted_state.md +114 -0
  232. plans/session-compaction-2025-08-13/compacted_state.md +145 -0
  233. plans/session-continuity-protocol/0-Overview.md +35 -0
  234. plans/session-continuity-protocol/1-Core-Principles-Framework.md +40 -0
  235. plans/session-continuity-protocol/2-Pre-Session-Validation-System.md +79 -0
  236. plans/session-continuity-protocol/3-Context-Switching-Prevention.md +87 -0
  237. plans/session-continuity-protocol/4-Progress-Tracking-Recovery.md +100 -0
  238. plans/sphinx-warnings-analysis.md +222 -0
  239. plans/systemprompt-optimization/0-Overview.md +447 -0
  240. plans/systemprompt-optimization/1-Deploy-SystemPrompt.md +114 -0
  241. plans/systemprompt-optimization/2-Documentation-Alignment.md +198 -0
  242. plans/systemprompt-optimization/3-Monitoring-Infrastructure.md +396 -0
  243. plans/systemprompt-optimization/4-Implementation-Script.md +450 -0
  244. plans/systemprompt-optimization/9-Closeout.md +165 -0
  245. plans/systemprompt-optimization/compacted_state.md +143 -0
  246. plans/template-value-propositions/0-Overview.md +357 -0
  247. plans/template-value-propositions/1-Value-Proposition-Framework-Design.md +144 -0
  248. plans/template-value-propositions/2-Plan-Template-Enhancement.md +178 -0
  249. plans/template-value-propositions/3-Value-Generator-Hook-Implementation.md +291 -0
  250. plans/template-value-propositions/4-Value-Validator-Hook-Implementation.md +274 -0
  251. plans/template-value-propositions/5-Documentation-Agent-Updates.md +219 -0
  252. plans/template-value-propositions/6-Integration-Testing-Validation.md +247 -0
  253. plans/tests-audit/0-Overview.md +410 -0
  254. plans/tests-audit/1-Discovery-Inventory.md +170 -0
  255. plans/tests-audit/2-Physics-Validation-Audit.md +195 -0
  256. plans/tests-audit/3-Architecture-Compliance.md +195 -0
  257. plans/tests-audit/4-Numerical-Stability-Analysis.md +203 -0
  258. plans/tests-audit/5-Documentation-Enhancement.md +220 -0
  259. plans/tests-audit/6-Audit-Deliverables.md +220 -0
  260. plans/tests-audit/7-Closeout.md +252 -0
  261. plans/tests-audit/artifacts/ARCHITECTURE_COMPLIANCE_REPORT.md +315 -0
  262. plans/tests-audit/artifacts/ARCHITECTURE_RECOMMENDATIONS.md +943 -0
  263. plans/tests-audit/artifacts/COMPREHENSIVE_AUDIT_REPORT.md +356 -0
  264. plans/tests-audit/artifacts/CONTRIBUTING_ENHANCED_TEMPLATE.md +419 -0
  265. plans/tests-audit/artifacts/COVERAGE_GAP_ANALYSIS.md +152 -0
  266. plans/tests-audit/artifacts/DOCUMENTATION_ENHANCEMENT_REPORT.md +502 -0
  267. plans/tests-audit/artifacts/EXECUTIVE_AUDIT_SUMMARY.md +129 -0
  268. plans/tests-audit/artifacts/IMPLEMENTATION_ROADMAP.md +647 -0
  269. plans/tests-audit/artifacts/NUMERICAL_RECOMMENDATIONS.md +739 -0
  270. plans/tests-audit/artifacts/NUMERICAL_STABILITY_GUIDE_TEMPLATE.rst +451 -0
  271. plans/tests-audit/artifacts/NUMERICAL_STABILITY_REPORT.md +301 -0
  272. plans/tests-audit/artifacts/PHASE_3_SUMMARY.md +280 -0
  273. plans/tests-audit/artifacts/PHASE_4_SUMMARY.md +229 -0
  274. plans/tests-audit/artifacts/PHASE_5_SUMMARY.md +292 -0
  275. plans/tests-audit/artifacts/PHASE_6_CLOSEOUT.md +278 -0
  276. plans/tests-audit/artifacts/PHYSICS_GUIDE_TEMPLATE.rst +268 -0
  277. plans/tests-audit/artifacts/PHYSICS_VALIDATION_REPORT.md +235 -0
  278. plans/tests-audit/artifacts/TECHNICAL_DELIVERABLES_PACKAGE.md +2502 -0
  279. plans/tests-audit/artifacts/TEST_INVENTORY.csv +1204 -0
  280. plans/tests-audit/artifacts/TEST_INVENTORY.md +135 -0
  281. plans/tests-audit/artifacts/test_discovery_analysis.py +231 -0
  282. plans/tests-audit/artifacts/test_parser.py +395 -0
  283. solarwindpy/README.md +3 -0
  284. solarwindpy/Untitled.ipynb +54 -0
  285. solarwindpy/__init__.py +74 -0
  286. solarwindpy/core/__init__.py +23 -0
  287. solarwindpy/core/alfvenic_turbulence.py +804 -0
  288. solarwindpy/core/base.py +267 -0
  289. solarwindpy/core/ions.py +309 -0
  290. solarwindpy/core/plasma.py +2133 -0
  291. solarwindpy/core/spacecraft.py +256 -0
  292. solarwindpy/core/tensor.py +90 -0
  293. solarwindpy/core/units_constants.py +199 -0
  294. solarwindpy/core/vector.py +328 -0
  295. solarwindpy/fitfunctions/__init__.py +20 -0
  296. solarwindpy/fitfunctions/core.py +734 -0
  297. solarwindpy/fitfunctions/exponentials.py +188 -0
  298. solarwindpy/fitfunctions/gaussians.py +264 -0
  299. solarwindpy/fitfunctions/lines.py +116 -0
  300. solarwindpy/fitfunctions/moyal.py +71 -0
  301. solarwindpy/fitfunctions/plots.py +751 -0
  302. solarwindpy/fitfunctions/power_laws.py +209 -0
  303. solarwindpy/fitfunctions/tex_info.py +568 -0
  304. solarwindpy/fitfunctions/trend_fits.py +482 -0
  305. solarwindpy/instabilities/__init__.py +16 -0
  306. solarwindpy/instabilities/beta_ani.py +82 -0
  307. solarwindpy/instabilities/verscharen2016.py +631 -0
  308. solarwindpy/plotting/__init__.py +33 -0
  309. solarwindpy/plotting/agg_plot.py +489 -0
  310. solarwindpy/plotting/base.py +465 -0
  311. solarwindpy/plotting/hist1d.py +405 -0
  312. solarwindpy/plotting/hist2d.py +1035 -0
  313. solarwindpy/plotting/histograms.py +1845 -0
  314. solarwindpy/plotting/labels/__init__.py +104 -0
  315. solarwindpy/plotting/labels/base.py +686 -0
  316. solarwindpy/plotting/labels/chemistry.py +19 -0
  317. solarwindpy/plotting/labels/composition.py +100 -0
  318. solarwindpy/plotting/labels/datetime.py +235 -0
  319. solarwindpy/plotting/labels/elemental_abundance.py +73 -0
  320. solarwindpy/plotting/labels/special.py +794 -0
  321. solarwindpy/plotting/orbits.py +515 -0
  322. solarwindpy/plotting/scatter.py +99 -0
  323. solarwindpy/plotting/select_data_from_figure.py +329 -0
  324. solarwindpy/plotting/spiral.py +980 -0
  325. solarwindpy/plotting/tools.py +434 -0
  326. solarwindpy/scripts/__init__.py +1 -0
  327. solarwindpy/scripts/logs/.gitignore +1 -0
  328. solarwindpy/solar_activity/__init__.py +53 -0
  329. solarwindpy/solar_activity/base.py +605 -0
  330. solarwindpy/solar_activity/lisird/__init__.py +3 -0
  331. solarwindpy/solar_activity/lisird/extrema_calculator.py +394 -0
  332. solarwindpy/solar_activity/lisird/lisird.py +319 -0
  333. solarwindpy/solar_activity/plots.py +116 -0
  334. solarwindpy/solar_activity/sunspot_number/.DS_Store +0 -0
  335. solarwindpy/solar_activity/sunspot_number/__init__.py +3 -0
  336. solarwindpy/solar_activity/sunspot_number/sidc.py +556 -0
  337. solarwindpy/solar_activity/sunspot_number/ssn_extrema.csv +72 -0
  338. solarwindpy/solar_activity/sunspot_number/ssn_extrema.csv.silso +72 -0
  339. solarwindpy/tools/__init__.py +162 -0
  340. solarwindpy-0.1.0.dist-info/METADATA +181 -0
  341. solarwindpy-0.1.0.dist-info/RECORD +409 -0
  342. {solarwindpy-0.0.1.dev0.dist-info → solarwindpy-0.1.0.dist-info}/WHEEL +1 -1
  343. solarwindpy-0.1.0.dist-info/licenses/LICENSE.rst +32 -0
  344. solarwindpy-0.1.0.dist-info/top_level.txt +3 -0
  345. tests/__init__.py +1 -0
  346. tests/conftest.py +10 -0
  347. tests/core/__init__.py +1 -0
  348. tests/core/test_alfvenic_turbulence.py +544 -0
  349. tests/core/test_base.py +112 -0
  350. tests/core/test_base_head_tail.py +29 -0
  351. tests/core/test_base_mi_tuples.py +11 -0
  352. tests/core/test_core_verify_datetimeindex.py +32 -0
  353. tests/core/test_ions.py +325 -0
  354. tests/core/test_plasma.py +2581 -0
  355. tests/core/test_plasma_io.py +12 -0
  356. tests/core/test_quantities.py +507 -0
  357. tests/core/test_spacecraft.py +210 -0
  358. tests/core/test_units_constants.py +22 -0
  359. tests/data/epoch.csv +4 -0
  360. tests/data/plasma.csv +4 -0
  361. tests/data/spacecraft.csv +4 -0
  362. tests/fitfunctions/conftest.py +60 -0
  363. tests/fitfunctions/test_core.py +193 -0
  364. tests/fitfunctions/test_exponentials.py +342 -0
  365. tests/fitfunctions/test_gaussians.py +142 -0
  366. tests/fitfunctions/test_lines.py +349 -0
  367. tests/fitfunctions/test_moyal.py +258 -0
  368. tests/fitfunctions/test_plots.py +258 -0
  369. tests/fitfunctions/test_power_laws.py +365 -0
  370. tests/fitfunctions/test_tex_info.py +183 -0
  371. tests/fitfunctions/test_trend_fit_properties.py +31 -0
  372. tests/fitfunctions/test_trend_fits.py +244 -0
  373. tests/plotting/__init__.py +1 -0
  374. tests/plotting/labels/__init__.py +1 -0
  375. tests/plotting/labels/test_chemistry.py +243 -0
  376. tests/plotting/labels/test_composition.py +345 -0
  377. tests/plotting/labels/test_datetime.py +445 -0
  378. tests/plotting/labels/test_elemental_abundance.py +366 -0
  379. tests/plotting/labels/test_init.py +66 -0
  380. tests/plotting/labels/test_labels_base.py +347 -0
  381. tests/plotting/labels/test_special.py +550 -0
  382. tests/plotting/test_agg_plot.py +602 -0
  383. tests/plotting/test_base.py +752 -0
  384. tests/plotting/test_fixtures_utilities.py +775 -0
  385. tests/plotting/test_histograms.py +546 -0
  386. tests/plotting/test_integration.py +675 -0
  387. tests/plotting/test_orbits.py +435 -0
  388. tests/plotting/test_performance.py +708 -0
  389. tests/plotting/test_scatter.py +752 -0
  390. tests/plotting/test_select_data_from_figure.py +1209 -0
  391. tests/plotting/test_spiral.py +573 -0
  392. tests/plotting/test_tools.py +607 -0
  393. tests/plotting/test_visual_validation.py +465 -0
  394. tests/solar_activity/__init__.py +1 -0
  395. tests/solar_activity/lisird/__init__.py +1 -0
  396. tests/solar_activity/lisird/test_extrema_calculator.py +593 -0
  397. tests/solar_activity/lisird/test_lisird_id.py +187 -0
  398. tests/solar_activity/sunspot_number/__init__.py +1 -0
  399. tests/solar_activity/sunspot_number/test_init.py +399 -0
  400. tests/solar_activity/sunspot_number/test_sidc.py +465 -0
  401. tests/solar_activity/sunspot_number/test_sidc_id.py +223 -0
  402. tests/solar_activity/sunspot_number/test_sidc_loader.py +275 -0
  403. tests/solar_activity/sunspot_number/test_ssn_extrema.py +406 -0
  404. tests/solar_activity/test_base.py +656 -0
  405. tests/solar_activity/test_init.py +396 -0
  406. tests/solar_activity/test_plots.py +371 -0
  407. tests/test_circular_imports.py +408 -0
  408. tests/test_issue_titles.py +25 -0
  409. tests/test_statusline.py +298 -0
  410. solarwindpy-0.0.1.dev0.dist-info/METADATA +0 -14
  411. solarwindpy-0.0.1.dev0.dist-info/RECORD +0 -4
  412. solarwindpy-0.0.1.dev0.dist-info/top_level.txt +0 -1
@@ -0,0 +1,752 @@
1
+ #!/usr/bin/env python
2
+ """Tests for solarwindpy.plotting.base module.
3
+
4
+ This module provides comprehensive test coverage for the abstract base classes and
5
+ helper classes used throughout the plotting package.
6
+ """
7
+
8
+ import pytest
9
+ import logging
10
+ import pandas as pd
11
+ import numpy as np
12
+ from pathlib import Path
13
+ from unittest.mock import patch, MagicMock
14
+
15
+ from solarwindpy.plotting.base import (
16
+ Base,
17
+ LogAxes,
18
+ AxesLabels,
19
+ RangeLimits,
20
+ DataLimFormatter,
21
+ CbarMaker,
22
+ PlotWithZdata,
23
+ )
24
+
25
+
26
+ class ConcreteBase(Base):
27
+ """Concrete implementation of Base for testing abstract functionality."""
28
+
29
+ def __init__(self):
30
+ super().__init__()
31
+ self._data = None
32
+ self._clip = False
33
+
34
+ def set_data(self, data=None):
35
+ """Minimal implementation for testing."""
36
+ if data is None:
37
+ self._data = pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]})
38
+ else:
39
+ self._data = data
40
+
41
+ def make_plot(self):
42
+ """Minimal implementation for testing."""
43
+ return "plot_created"
44
+
45
+ def set_path(self, new, add_scale=False):
46
+ """Concrete implementation of set_path for testing."""
47
+ path, x, y, z, scale_info = super().set_path(new, add_scale)
48
+ self._path = path
49
+ return path, x, y, z, scale_info
50
+
51
+
52
+ class ConcretePlotWithZdata(PlotWithZdata):
53
+ """Concrete implementation of PlotWithZdata for testing."""
54
+
55
+ def __init__(self):
56
+ super().__init__()
57
+
58
+ def make_plot(self):
59
+ """Minimal implementation for testing."""
60
+ return "plot_with_z_created"
61
+
62
+
63
+ class TestNamedTuples:
64
+ """Test the named tuple definitions."""
65
+
66
+ def test_log_axes_creation(self):
67
+ """Test LogAxes namedtuple with defaults."""
68
+ # LogAxes defaults=(False,) only provides default for y, x is required
69
+ log_axes = LogAxes(x=True)
70
+ assert log_axes.x is True
71
+ assert log_axes.y is False # default
72
+
73
+ log_axes = LogAxes(True, True)
74
+ assert log_axes.x is True
75
+ assert log_axes.y is True
76
+
77
+ def test_axes_labels_creation(self):
78
+ """Test AxesLabels namedtuple with defaults."""
79
+ # AxesLabels defaults=(None,) only provides default for z, x and y are required
80
+ labels = AxesLabels("X-axis", "Y-axis")
81
+ assert labels.x == "X-axis"
82
+ assert labels.y == "Y-axis"
83
+ assert labels.z is None # default
84
+
85
+ labels = AxesLabels("X-axis", "Y-axis", "Z-axis")
86
+ assert labels.x == "X-axis"
87
+ assert labels.y == "Y-axis"
88
+ assert labels.z == "Z-axis"
89
+
90
+ def test_range_limits_creation(self):
91
+ """Test RangeLimits namedtuple with defaults."""
92
+ # RangeLimits requires at least the 'lower' parameter
93
+ limits = RangeLimits(None)
94
+ assert limits.lower is None
95
+ assert limits.upper is None
96
+
97
+ limits = RangeLimits(0, 100)
98
+ assert limits.lower == 0
99
+ assert limits.upper == 100
100
+
101
+
102
+ class TestBaseAbstractClass:
103
+ """Test the Base abstract class functionality."""
104
+
105
+ def test_base_instantiation_via_subclass(self):
106
+ """Test that Base can be instantiated via subclass with proper
107
+ initialization."""
108
+ concrete = ConcreteBase()
109
+
110
+ # Verify initialization occurred
111
+ assert hasattr(concrete, "_logger")
112
+ assert hasattr(concrete, "_labels")
113
+ assert hasattr(concrete, "_log")
114
+ assert hasattr(concrete, "_path")
115
+
116
+ # Verify types and defaults
117
+ assert isinstance(concrete._labels, tuple) # AxesLabels is a namedtuple
118
+ assert isinstance(concrete._log, tuple) # LogAxes is a namedtuple
119
+ assert concrete._labels.x == "x"
120
+ assert concrete._labels.y == "y"
121
+ assert concrete._log.x is False
122
+ assert concrete._log.y is False
123
+
124
+ def test_base_cannot_be_instantiated_directly(self):
125
+ """Test that Base cannot be instantiated directly."""
126
+ with pytest.raises(TypeError):
127
+ Base()
128
+
129
+ def test_str_returns_class_name(self):
130
+ """Test that __str__ returns the class name."""
131
+ concrete = ConcreteBase()
132
+ assert str(concrete) == "ConcreteBase"
133
+
134
+ def test_logger_initialization(self):
135
+ """Test that logger is properly initialized."""
136
+ concrete = ConcreteBase()
137
+ logger = concrete.logger
138
+ assert isinstance(logger, logging.Logger)
139
+ assert logger.name.endswith("ConcreteBase")
140
+
141
+ def test_data_property(self):
142
+ """Test that data property returns internal _data."""
143
+ concrete = ConcreteBase()
144
+ test_data = pd.DataFrame({"a": [1, 2], "b": [3, 4]})
145
+ concrete._data = test_data
146
+ assert concrete.data is test_data
147
+
148
+ def test_clip_property(self):
149
+ """Test that clip property returns internal _clip."""
150
+ concrete = ConcreteBase()
151
+ concrete._clip = True
152
+ assert concrete.clip is True
153
+
154
+ concrete._clip = False
155
+ assert concrete.clip is False
156
+
157
+ def test_log_property(self):
158
+ """Test that log property returns internal _log."""
159
+ concrete = ConcreteBase()
160
+ assert concrete.log == concrete._log
161
+ assert concrete.log.x is False
162
+ assert concrete.log.y is False
163
+
164
+ def test_labels_property(self):
165
+ """Test that labels property returns internal _labels."""
166
+ concrete = ConcreteBase()
167
+ assert concrete.labels == concrete._labels
168
+ assert concrete.labels.x == "x"
169
+ assert concrete.labels.y == "y"
170
+
171
+ def test_path_property(self):
172
+ """Test that path property returns internal _path."""
173
+ concrete = ConcreteBase()
174
+ # Path should be set during initialization
175
+ assert hasattr(concrete, "_path")
176
+ assert concrete.path == concrete._path
177
+
178
+
179
+ class TestBaseLogMethods:
180
+ """Test log scaling functionality in Base class."""
181
+
182
+ def test_set_log_defaults(self):
183
+ """Test set_log() with defaults toggles log.x and log.y appropriately."""
184
+ concrete = ConcreteBase()
185
+
186
+ # Initial state
187
+ assert concrete.log.x is False
188
+ assert concrete.log.y is False
189
+
190
+ # Call with no arguments should use current values
191
+ concrete.set_log()
192
+ assert concrete.log.x is False
193
+ assert concrete.log.y is False
194
+
195
+ def test_set_log_explicit_values(self):
196
+ """Test set_log(x=True, y=False) correctly updates log axes."""
197
+ concrete = ConcreteBase()
198
+
199
+ concrete.set_log(x=True, y=False)
200
+ assert concrete.log.x is True
201
+ assert concrete.log.y is False
202
+
203
+ concrete.set_log(x=False, y=True)
204
+ assert concrete.log.x is False
205
+ assert concrete.log.y is True
206
+
207
+ concrete.set_log(x=True, y=True)
208
+ assert concrete.log.x is True
209
+ assert concrete.log.y is True
210
+
211
+ def test_set_log_partial_specification(self):
212
+ """Test set_log with only x or y specified."""
213
+ concrete = ConcreteBase()
214
+
215
+ # Set initial state
216
+ concrete.set_log(x=True, y=True)
217
+
218
+ # Change only x
219
+ concrete.set_log(x=False)
220
+ assert concrete.log.x is False
221
+ assert concrete.log.y is True # Should remain unchanged
222
+
223
+ # Change only y
224
+ concrete.set_log(y=False)
225
+ assert concrete.log.x is False # Should remain unchanged
226
+ assert concrete.log.y is False
227
+
228
+ def test_set_log_type_coercion(self):
229
+ """Test that set_log converts values to bool."""
230
+ concrete = ConcreteBase()
231
+
232
+ # Test truthy/falsy values
233
+ concrete.set_log(x=1, y=0)
234
+ assert concrete.log.x is True
235
+ assert concrete.log.y is False
236
+
237
+ concrete.set_log(x="true", y="")
238
+ assert concrete.log.x is True
239
+ assert concrete.log.y is False
240
+
241
+
242
+ class TestBaseLabelMethods:
243
+ """Test label management functionality in Base class."""
244
+
245
+ def test_set_labels_updates_labels_and_regenerates_path(self):
246
+ """Test set_labels() updates labels and regenerates path."""
247
+ concrete = ConcreteBase()
248
+ original_path = concrete.path
249
+
250
+ concrete.set_labels(x="New X", y="New Y")
251
+
252
+ assert concrete.labels.x == "New X"
253
+ assert concrete.labels.y == "New Y"
254
+ # Path should have been regenerated (different from original)
255
+ # Note: exact path comparison depends on implementation details
256
+ assert hasattr(concrete, "_path")
257
+
258
+ def test_set_labels_partial_update(self):
259
+ """Test setting only some labels preserves others."""
260
+ concrete = ConcreteBase()
261
+
262
+ # Set initial labels
263
+ concrete.set_labels(x="X1", y="Y1", z="Z1")
264
+
265
+ # Update only x
266
+ concrete.set_labels(x="X2")
267
+ assert concrete.labels.x == "X2"
268
+ assert concrete.labels.y == "Y1" # Should remain unchanged
269
+ assert concrete.labels.z == "Z1" # Should remain unchanged
270
+
271
+ def test_set_labels_auto_update_path_false(self):
272
+ """Test set_labels with auto_update_path=False."""
273
+ concrete = ConcreteBase()
274
+ original_path = concrete.path
275
+
276
+ # This should not trigger path update
277
+ concrete.set_labels(x="New X", auto_update_path=False)
278
+
279
+ assert concrete.labels.x == "New X"
280
+ # Path should remain the same (though this is implementation dependent)
281
+ # The main point is that set_path("auto") was not called
282
+
283
+ def test_set_labels_unexpected_kwarg_raises_keyerror(self):
284
+ """Test that set_labels(unexpected=...) raises KeyError."""
285
+ concrete = ConcreteBase()
286
+
287
+ with pytest.raises(KeyError, match="Unexpected kwarg"):
288
+ concrete.set_labels(unexpected="value")
289
+
290
+ with pytest.raises(KeyError, match="Unexpected kwarg"):
291
+ concrete.set_labels(x="valid", invalid="invalid")
292
+
293
+ def test_set_labels_multiple_unexpected_kwargs(self):
294
+ """Test error message with multiple unexpected kwargs."""
295
+ concrete = ConcreteBase()
296
+
297
+ with pytest.raises(KeyError) as exc_info:
298
+ concrete.set_labels(bad1="value1", bad2="value2")
299
+
300
+ # Should mention both unexpected kwargs
301
+ error_message = str(exc_info.value)
302
+ assert "bad1" in error_message
303
+ assert "bad2" in error_message
304
+
305
+
306
+ class TestBasePathMethods:
307
+ """Test path management functionality in Base class."""
308
+
309
+ def test_set_path_auto_mode(self):
310
+ """Test set_path with 'auto' mode."""
311
+ concrete = ConcreteBase()
312
+
313
+ # Set some labels first
314
+ concrete.set_labels(x="density", y="velocity", z="temperature")
315
+
316
+ # Test auto path generation
317
+ path, x, y, z, scale_info = concrete.set_path("auto")
318
+
319
+ assert isinstance(path, Path)
320
+ assert path.name == "ConcreteBase" # Should use class name
321
+ assert x == "density"
322
+ assert y == "velocity"
323
+ assert z == "temperature"
324
+ assert scale_info is None # add_scale defaults to False
325
+
326
+ def test_set_path_auto_mode_with_scale(self):
327
+ """Test set_path with 'auto' mode and add_scale=True."""
328
+ concrete = ConcreteBase()
329
+ concrete.set_log(x=True, y=False)
330
+
331
+ path, x, y, z, scale_info = concrete.set_path("auto", add_scale=True)
332
+
333
+ assert scale_info == ["logX", "linY"]
334
+
335
+ def test_set_path_explicit_path(self):
336
+ """Test set_path with explicit path."""
337
+ concrete = ConcreteBase()
338
+
339
+ path, x, y, z, scale_info = concrete.set_path("/custom/path")
340
+
341
+ assert path == Path("/custom/path")
342
+ assert x is None
343
+ assert y is None
344
+ assert z is None
345
+ assert scale_info is None
346
+
347
+ def test_set_path_none(self):
348
+ """Test set_path with None."""
349
+ concrete = ConcreteBase()
350
+
351
+ path, x, y, z, scale_info = concrete.set_path(None)
352
+
353
+ assert path == Path("")
354
+ assert x is None
355
+ assert y is None
356
+ assert z is None
357
+ assert scale_info is None
358
+
359
+ def test_set_path_label_attribute_handling(self):
360
+ """Test set_path handles labels with .path attributes."""
361
+ concrete = ConcreteBase()
362
+
363
+ # Mock labels with .path attributes
364
+ mock_label = MagicMock()
365
+ mock_label.path = "custom-path"
366
+ concrete._labels = AxesLabels(x=mock_label, y="normal-label", z=None)
367
+
368
+ path, x, y, z, scale_info = concrete.set_path("auto")
369
+
370
+ assert x == "custom-path"
371
+ assert y == "normal-label"
372
+ assert z == "z" # Default when None
373
+
374
+ def test_set_path_string_sanitization(self):
375
+ """Test that set_path sanitizes string labels."""
376
+ concrete = ConcreteBase()
377
+ concrete._labels = AxesLabels(x="Label With Spaces", y="normal", z="None")
378
+
379
+ path, x, y, z, scale_info = concrete.set_path("auto")
380
+
381
+ assert x == "Label-With-Spaces" # Spaces replaced with hyphens
382
+ assert y == "normal"
383
+ assert z == "z" # "None" string converted to default
384
+
385
+
386
+ class TestBaseAxisFormatting:
387
+ """Test axis formatting methods in Base class."""
388
+
389
+ @patch("matplotlib.pyplot")
390
+ def test_add_axis_labels(self, mock_plt):
391
+ """Test _add_axis_labels method."""
392
+ concrete = ConcreteBase()
393
+ concrete.set_labels(x="X Label", y="Y Label")
394
+
395
+ mock_ax = MagicMock()
396
+ concrete._add_axis_labels(mock_ax)
397
+
398
+ mock_ax.set_xlabel.assert_called_once_with("X Label")
399
+ mock_ax.set_ylabel.assert_called_once_with("Y Label")
400
+
401
+ @patch("matplotlib.pyplot")
402
+ def test_add_axis_labels_transpose(self, mock_plt):
403
+ """Test _add_axis_labels with transpose_axes=True."""
404
+ concrete = ConcreteBase()
405
+ concrete.set_labels(x="X Label", y="Y Label")
406
+
407
+ mock_ax = MagicMock()
408
+ concrete._add_axis_labels(mock_ax, transpose_axes=True)
409
+
410
+ # Labels should be swapped
411
+ mock_ax.set_xlabel.assert_called_once_with("Y Label")
412
+ mock_ax.set_ylabel.assert_called_once_with("X Label")
413
+
414
+ @patch("matplotlib.pyplot")
415
+ def test_add_axis_labels_none_handling(self, mock_plt):
416
+ """Test _add_axis_labels with None labels."""
417
+ concrete = ConcreteBase()
418
+ concrete.set_labels(x=None, y="Y Label")
419
+
420
+ mock_ax = MagicMock()
421
+ concrete._add_axis_labels(mock_ax)
422
+
423
+ mock_ax.set_xlabel.assert_not_called()
424
+ mock_ax.set_ylabel.assert_called_once_with("Y Label")
425
+
426
+ @patch("matplotlib.pyplot")
427
+ def test_set_axis_scale(self, mock_plt):
428
+ """Test _set_axis_scale method."""
429
+ concrete = ConcreteBase()
430
+ concrete.set_log(x=True, y=False)
431
+
432
+ mock_ax = MagicMock()
433
+ concrete._set_axis_scale(mock_ax)
434
+
435
+ mock_ax.set_xscale.assert_called_once_with("log")
436
+ mock_ax.set_yscale.assert_not_called()
437
+
438
+ @patch("matplotlib.pyplot")
439
+ def test_set_axis_scale_transpose(self, mock_plt):
440
+ """Test _set_axis_scale with transpose_axes=True."""
441
+ concrete = ConcreteBase()
442
+ concrete.set_log(x=True, y=False)
443
+
444
+ mock_ax = MagicMock()
445
+ concrete._set_axis_scale(mock_ax, transpose_axes=True)
446
+
447
+ # Scales should be swapped
448
+ mock_ax.set_xscale.assert_not_called()
449
+ mock_ax.set_yscale.assert_called_once_with("log")
450
+
451
+ @patch("matplotlib.pyplot")
452
+ def test_format_axis_complete(self, mock_plt):
453
+ """Test _format_axis method calls all formatting functions."""
454
+ concrete = ConcreteBase()
455
+ concrete.set_labels(x="X", y="Y")
456
+ concrete.set_log(x=True, y=True)
457
+
458
+ mock_ax = MagicMock()
459
+ concrete._format_axis(mock_ax)
460
+
461
+ # Check that all formatting was applied
462
+ mock_ax.set_xlabel.assert_called_once_with("X")
463
+ mock_ax.set_ylabel.assert_called_once_with("Y")
464
+ mock_ax.set_xscale.assert_called_once_with("log")
465
+ mock_ax.set_yscale.assert_called_once_with("log")
466
+ mock_ax.grid.assert_called_once_with(True, which="major", axis="both")
467
+ mock_ax.tick_params.assert_called_once_with(
468
+ axis="both", which="both", direction="inout"
469
+ )
470
+
471
+
472
+ class TestPlotWithZdata:
473
+ """Test the PlotWithZdata class functionality."""
474
+
475
+ def test_set_data_basic(self):
476
+ """Test basic set_data functionality."""
477
+ plot = ConcretePlotWithZdata()
478
+
479
+ x = np.array([1, 2, 3])
480
+ y = np.array([4, 5, 6])
481
+ z = np.array([7, 8, 9])
482
+
483
+ plot.set_data(x, y, z)
484
+
485
+ assert isinstance(plot.data, pd.DataFrame)
486
+ assert list(plot.data.columns) == ["x", "y", "z"]
487
+ assert len(plot.data) == 3
488
+ assert plot.clip is False
489
+
490
+ def test_set_data_without_z(self):
491
+ """Test set_data without z parameter creates default z=1."""
492
+ plot = ConcretePlotWithZdata()
493
+
494
+ x = np.array([1, 2, 3])
495
+ y = np.array([4, 5, 6])
496
+
497
+ plot.set_data(x, y)
498
+
499
+ assert "z" in plot.data.columns
500
+ assert all(plot.data["z"] == 1)
501
+
502
+ def test_set_data_with_clip(self):
503
+ """Test set_data with clip_data=True."""
504
+ plot = ConcretePlotWithZdata()
505
+
506
+ x = np.array([1, 2, 3])
507
+ y = np.array([4, 5, 6])
508
+
509
+ plot.set_data(x, y, clip_data=True)
510
+
511
+ assert plot.clip is True
512
+
513
+ def test_set_data_drops_nan(self):
514
+ """Test that set_data drops NaN values."""
515
+ plot = ConcretePlotWithZdata()
516
+
517
+ x = np.array([1, np.nan, 3])
518
+ y = np.array([4, 5, np.nan])
519
+ z = np.array([7, 8, 9])
520
+
521
+ plot.set_data(x, y, z)
522
+
523
+ # Should have dropped rows with NaN
524
+ assert len(plot.data) == 1 # Only first row is complete
525
+ assert plot.data.iloc[0]["x"] == 1
526
+ assert plot.data.iloc[0]["y"] == 4
527
+ assert plot.data.iloc[0]["z"] == 7
528
+
529
+ def test_set_data_all_nan_raises_error(self):
530
+ """Test that set_data raises ValueError when all data is NaN."""
531
+ plot = ConcretePlotWithZdata()
532
+
533
+ x = np.array([np.nan, np.nan])
534
+ y = np.array([np.nan, np.nan])
535
+
536
+ with pytest.raises(ValueError, match="exclusively NaNs"):
537
+ plot.set_data(x, y)
538
+
539
+ def test_set_path_auto_with_scale(self):
540
+ """Test set_path auto mode with add_scale=True (default)."""
541
+ plot = ConcretePlotWithZdata()
542
+ plot.set_labels(x="X", y="Y", z="Z")
543
+ plot.set_log(x=True, y=False)
544
+
545
+ plot.set_path("auto")
546
+
547
+ # Check that path was constructed properly
548
+ assert isinstance(plot.path, Path)
549
+ # Should include scale information by default
550
+
551
+ def test_set_path_explicit(self):
552
+ """Test set_path with explicit path."""
553
+ plot = ConcretePlotWithZdata()
554
+
555
+ plot.set_path("/custom/path", add_scale=False)
556
+
557
+ assert plot.path == Path("/custom/path")
558
+
559
+ def test_set_labels_preserves_z(self):
560
+ """Test that set_labels properly handles z label."""
561
+ plot = ConcretePlotWithZdata()
562
+ plot.set_labels(x="X", y="Y", z="Z")
563
+
564
+ # Update only x and y
565
+ plot.set_labels(x="New X", y="New Y")
566
+
567
+ assert plot.labels.x == "New X"
568
+ assert plot.labels.y == "New Y"
569
+ assert plot.labels.z == "Z" # Should be preserved
570
+
571
+
572
+ class TestDataLimFormatter:
573
+ """Test the DataLimFormatter mixin class."""
574
+
575
+ def test_format_axis_calls_super_and_sets_limits(self):
576
+ """Test that _format_axis calls super and sets data limits."""
577
+ # This is a mixin, so we need to test it with a concrete class
578
+ # that also inherits from Base
579
+
580
+ class ConcreteDataLimFormatter(DataLimFormatter, ConcreteBase):
581
+ def __init__(self):
582
+ super().__init__()
583
+ self.set_data(pd.DataFrame({"x": [1, 2, 3], "y": [4, 5, 6]}))
584
+
585
+ formatter = ConcreteDataLimFormatter()
586
+
587
+ mock_ax = MagicMock()
588
+ mock_collection = MagicMock()
589
+ mock_collection.sticky_edges.x = []
590
+ mock_collection.sticky_edges.y = []
591
+
592
+ formatter._format_axis(mock_ax, mock_collection)
593
+
594
+ # Should have called grid and tick_params from super()
595
+ mock_ax.grid.assert_called_once()
596
+ mock_ax.tick_params.assert_called_once()
597
+
598
+ # Should have set sticky edges
599
+ assert mock_collection.sticky_edges.x == [1, 3] # min, max of x
600
+ assert mock_collection.sticky_edges.y == [4, 6] # min, max of y
601
+
602
+ # Should have updated data limits
603
+ mock_ax.update_datalim.assert_called_once()
604
+ mock_ax.autoscale_view.assert_called_once()
605
+
606
+
607
+ class TestCbarMaker:
608
+ """Test the CbarMaker mixin class."""
609
+
610
+ @patch("matplotlib.pyplot")
611
+ def test_make_cbar_with_ax(self, mock_plt):
612
+ """Test _make_cbar with ax parameter."""
613
+
614
+ class ConcreteCbarMaker(CbarMaker, ConcreteBase):
615
+ pass
616
+
617
+ maker = ConcreteCbarMaker()
618
+ maker.set_labels(z="Z Label")
619
+
620
+ mock_ax = MagicMock()
621
+ mock_fig = MagicMock()
622
+ mock_ax.figure = mock_fig
623
+ mock_mappable = MagicMock()
624
+
625
+ result = maker._make_cbar(mock_mappable, ax=mock_ax)
626
+
627
+ mock_fig.colorbar.assert_called_once_with(
628
+ mock_mappable, label="Z Label", ax=mock_ax, cax=None
629
+ )
630
+ assert result == mock_fig.colorbar.return_value
631
+
632
+ @patch("matplotlib.pyplot")
633
+ def test_make_cbar_with_cax(self, mock_plt):
634
+ """Test _make_cbar with cax parameter."""
635
+
636
+ class ConcreteCbarMaker(CbarMaker, ConcreteBase):
637
+ pass
638
+
639
+ maker = ConcreteCbarMaker()
640
+ maker.set_labels(z="Z Label")
641
+
642
+ mock_cax = MagicMock()
643
+ mock_fig = MagicMock()
644
+ mock_cax.figure = mock_fig
645
+ mock_mappable = MagicMock()
646
+
647
+ result = maker._make_cbar(mock_mappable, cax=mock_cax)
648
+
649
+ mock_fig.colorbar.assert_called_once_with(
650
+ mock_mappable, label="Z Label", ax=None, cax=mock_cax
651
+ )
652
+
653
+ def test_make_cbar_ax_and_cax_error(self):
654
+ """Test that passing both ax and cax raises ValueError."""
655
+
656
+ class ConcreteCbarMaker(CbarMaker, ConcreteBase):
657
+ pass
658
+
659
+ maker = ConcreteCbarMaker()
660
+ mock_ax = MagicMock()
661
+ mock_cax = MagicMock()
662
+ mock_mappable = MagicMock()
663
+
664
+ with pytest.raises(ValueError, match="Can't pass ax and cax"):
665
+ maker._make_cbar(mock_mappable, ax=mock_ax, cax=mock_cax)
666
+
667
+ def test_make_cbar_no_ax_or_cax_error(self):
668
+ """Test that not passing ax or cax raises ValueError."""
669
+
670
+ class ConcreteCbarMaker(CbarMaker, ConcreteBase):
671
+ pass
672
+
673
+ maker = ConcreteCbarMaker()
674
+ mock_mappable = MagicMock()
675
+
676
+ with pytest.raises(ValueError, match="You must pass `ax` or `cax`"):
677
+ maker._make_cbar(mock_mappable)
678
+
679
+ @patch("matplotlib.pyplot")
680
+ def test_make_cbar_custom_label(self, mock_plt):
681
+ """Test _make_cbar with custom label parameter."""
682
+
683
+ class ConcreteCbarMaker(CbarMaker, ConcreteBase):
684
+ pass
685
+
686
+ maker = ConcreteCbarMaker()
687
+
688
+ mock_ax = MagicMock()
689
+ mock_fig = MagicMock()
690
+ mock_ax.figure = mock_fig
691
+ mock_mappable = MagicMock()
692
+
693
+ maker._make_cbar(mock_mappable, ax=mock_ax, label="Custom Label")
694
+
695
+ mock_fig.colorbar.assert_called_once_with(
696
+ mock_mappable, label="Custom Label", ax=mock_ax, cax=None
697
+ )
698
+
699
+
700
+ class TestBaseEdgeCases:
701
+ """Test edge cases and error conditions."""
702
+
703
+ def test_abstract_methods_not_implemented(self):
704
+ """Test that abstract methods raise NotImplementedError if not implemented."""
705
+
706
+ class IncompleteBase(Base):
707
+ def __init__(self):
708
+ super().__init__()
709
+
710
+ # Missing set_data and make_plot implementations
711
+
712
+ with pytest.raises(TypeError):
713
+ IncompleteBase()
714
+
715
+ def test_logger_name_format(self):
716
+ """Test that logger name includes module and class name."""
717
+ concrete = ConcreteBase()
718
+ logger_name = concrete.logger.name
719
+
720
+ assert "base" in logger_name # module name
721
+ assert "ConcreteBase" in logger_name # class name
722
+
723
+ def test_multiple_label_updates(self):
724
+ """Test multiple sequential label updates."""
725
+ concrete = ConcreteBase()
726
+
727
+ concrete.set_labels(x="X1", y="Y1")
728
+ assert concrete.labels.x == "X1"
729
+
730
+ concrete.set_labels(x="X2")
731
+ assert concrete.labels.x == "X2"
732
+ assert concrete.labels.y == "Y1" # Should be preserved
733
+
734
+ concrete.set_labels(y="Y2", z="Z2")
735
+ assert concrete.labels.x == "X2" # Should be preserved
736
+ assert concrete.labels.y == "Y2"
737
+ assert concrete.labels.z == "Z2"
738
+
739
+ def test_log_scale_persistence(self):
740
+ """Test that log scale settings persist across operations."""
741
+ concrete = ConcreteBase()
742
+
743
+ concrete.set_log(x=True, y=True)
744
+ concrete.set_labels(x="New X") # This might trigger path update
745
+
746
+ # Log settings should remain unchanged
747
+ assert concrete.log.x is True
748
+ assert concrete.log.y is True
749
+
750
+
751
+ if __name__ == "__main__":
752
+ pytest.main([__file__])