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,243 @@
1
+ """Tests for :mod:`solarwindpy.plotting.labels.chemistry` constants."""
2
+
3
+ from pathlib import Path
4
+
5
+ import pytest
6
+
7
+ from solarwindpy.plotting.labels import chemistry
8
+ from solarwindpy.plotting.labels.special import ManualLabel
9
+
10
+
11
+ @pytest.mark.parametrize(
12
+ "label, expected_tex, expected_unit, expected_path",
13
+ [
14
+ (
15
+ chemistry.mass_per_charge,
16
+ r"\mathrm{M/Q}",
17
+ r"\mathrm{AMU \, e^{-1}}",
18
+ Path("M-OV-Q"),
19
+ ),
20
+ (
21
+ chemistry.fip,
22
+ r"\mathrm{FIP}",
23
+ r"\mathrm{eV}",
24
+ Path("FIP"),
25
+ ),
26
+ (
27
+ chemistry.charge,
28
+ r"\mathrm{Q}",
29
+ r"\mathrm{e}",
30
+ Path("IonCharge"),
31
+ ),
32
+ (
33
+ chemistry.mass,
34
+ r"\mathrm{M}",
35
+ r"\mathrm{AMU}",
36
+ Path("IonMass"),
37
+ ),
38
+ ],
39
+ )
40
+ def test_manual_label_attributes(label, expected_tex, expected_unit, expected_path):
41
+ """Ensure each ``ManualLabel`` exposes the correct values."""
42
+
43
+ assert label.tex == expected_tex
44
+ assert label.unit == expected_unit
45
+ assert label.path == expected_path
46
+
47
+
48
+ class TestChemistryLabels:
49
+ """Test chemistry label constants comprehensively."""
50
+
51
+ def test_all_labels_are_manual_labels(self):
52
+ """Test that all chemistry labels are ManualLabel instances."""
53
+ labels = [
54
+ chemistry.mass_per_charge,
55
+ chemistry.fip,
56
+ chemistry.charge,
57
+ chemistry.mass,
58
+ ]
59
+
60
+ for label in labels:
61
+ assert isinstance(label, ManualLabel)
62
+
63
+ def test_mass_per_charge_properties(self):
64
+ """Test mass per charge label properties."""
65
+ label = chemistry.mass_per_charge
66
+ assert "M/Q" in label.tex
67
+ assert "AMU" in label.unit
68
+ assert "e^{-1}" in label.unit
69
+ assert str(label.path) == "M-OV-Q"
70
+
71
+ def test_fip_properties(self):
72
+ """Test First Ionization Potential label properties."""
73
+ label = chemistry.fip
74
+ assert "FIP" in label.tex
75
+ assert "eV" in label.unit
76
+ assert str(label.path) == "FIP"
77
+
78
+ def test_charge_properties(self):
79
+ """Test ion charge label properties."""
80
+ label = chemistry.charge
81
+ assert "Q" in label.tex
82
+ assert "e" in label.unit
83
+ assert str(label.path) == "IonCharge"
84
+
85
+ def test_mass_properties(self):
86
+ """Test ion mass label properties."""
87
+ label = chemistry.mass
88
+ assert "M" in label.tex
89
+ assert "AMU" in label.unit
90
+ assert str(label.path) == "IonMass"
91
+
92
+ def test_string_representation(self):
93
+ """Test string representations of chemistry labels."""
94
+ labels = [
95
+ chemistry.mass_per_charge,
96
+ chemistry.fip,
97
+ chemistry.charge,
98
+ chemistry.mass,
99
+ ]
100
+
101
+ for label in labels:
102
+ str_repr = str(label)
103
+ assert str_repr.startswith("$")
104
+ assert str_repr.endswith("$")
105
+ assert "[" in str_repr # Units are included
106
+ assert "]" in str_repr
107
+
108
+ def test_label_uniqueness(self):
109
+ """Test that all labels have unique tex, units, and paths."""
110
+ labels = [
111
+ chemistry.mass_per_charge,
112
+ chemistry.fip,
113
+ chemistry.charge,
114
+ chemistry.mass,
115
+ ]
116
+
117
+ # Test unique tex
118
+ tex_values = [label.tex for label in labels]
119
+ assert len(tex_values) == len(set(tex_values))
120
+
121
+ # Test unique units
122
+ unit_values = [label.unit for label in labels]
123
+ assert len(unit_values) == len(set(unit_values))
124
+
125
+ # Test unique paths
126
+ path_values = [str(label.path) for label in labels]
127
+ assert len(path_values) == len(set(path_values))
128
+
129
+ def test_label_inheritance(self):
130
+ """Test that labels inherit from base classes correctly."""
131
+ from solarwindpy.plotting.labels.base import Base
132
+
133
+ labels = [
134
+ chemistry.mass_per_charge,
135
+ chemistry.fip,
136
+ chemistry.charge,
137
+ chemistry.mass,
138
+ ]
139
+
140
+ for label in labels:
141
+ assert isinstance(label, Base) # Should inherit from Base
142
+ assert hasattr(label, "logger") # Should have logger from Base
143
+
144
+ def test_tex_formatting(self):
145
+ """Test TeX formatting is correct."""
146
+ # Test that math mode indicators are properly stripped from tex
147
+ assert chemistry.mass_per_charge.tex == r"\mathrm{M/Q}"
148
+ assert chemistry.fip.tex == r"\mathrm{FIP}"
149
+ assert chemistry.charge.tex == r"\mathrm{Q}"
150
+ assert chemistry.mass.tex == r"\mathrm{M}"
151
+
152
+ def test_unit_formatting(self):
153
+ """Test unit formatting is correct."""
154
+ # Test specific unit formatting
155
+ assert chemistry.mass_per_charge.unit == r"\mathrm{AMU \, e^{-1}}"
156
+ assert chemistry.fip.unit == r"\mathrm{eV}"
157
+ assert chemistry.charge.unit == r"\mathrm{e}"
158
+ assert chemistry.mass.unit == r"\mathrm{AMU}"
159
+
160
+ def test_path_types(self):
161
+ """Test that all paths are Path objects."""
162
+ labels = [
163
+ chemistry.mass_per_charge,
164
+ chemistry.fip,
165
+ chemistry.charge,
166
+ chemistry.mass,
167
+ ]
168
+
169
+ for label in labels:
170
+ assert isinstance(label.path, Path)
171
+
172
+ def test_label_comparison(self):
173
+ """Test label comparison based on string representation."""
174
+ # Labels should be comparable
175
+ labels = [
176
+ chemistry.mass_per_charge,
177
+ chemistry.fip,
178
+ chemistry.charge,
179
+ chemistry.mass,
180
+ ]
181
+
182
+ # Test equality (should be equal to themselves)
183
+ for label in labels:
184
+ assert label == label
185
+
186
+ # Test inequality (different labels should not be equal)
187
+ for i, label1 in enumerate(labels):
188
+ for j, label2 in enumerate(labels):
189
+ if i != j:
190
+ assert label1 != label2
191
+
192
+ def test_label_hashing(self):
193
+ """Test that labels can be hashed."""
194
+ labels = [
195
+ chemistry.mass_per_charge,
196
+ chemistry.fip,
197
+ chemistry.charge,
198
+ chemistry.mass,
199
+ ]
200
+
201
+ # Should be able to create a set (requires hashing)
202
+ label_set = set(labels)
203
+ assert len(label_set) == len(labels)
204
+
205
+ # Should be able to use as dictionary keys
206
+ label_dict = {label: str(label) for label in labels}
207
+ assert len(label_dict) == len(labels)
208
+
209
+ def test_module_attributes(self):
210
+ """Test that the chemistry module has all expected attributes."""
211
+ expected_attrs = ["mass_per_charge", "fip", "charge", "mass"]
212
+
213
+ for attr in expected_attrs:
214
+ assert hasattr(chemistry, attr)
215
+ label = getattr(chemistry, attr)
216
+ assert isinstance(label, ManualLabel)
217
+
218
+ def test_label_immutability(self):
219
+ """Test that label properties are effectively immutable."""
220
+ original_tex = chemistry.mass.tex
221
+ original_unit = chemistry.mass.unit
222
+ original_path = chemistry.mass.path
223
+
224
+ # These properties should be read-only
225
+ # (We can't directly test immutability, but we can test they return consistent values)
226
+ assert chemistry.mass.tex == original_tex
227
+ assert chemistry.mass.unit == original_unit
228
+ assert chemistry.mass.path == original_path
229
+
230
+ def test_scientific_accuracy(self):
231
+ """Test that labels represent scientifically accurate concepts."""
232
+ # Mass per charge should use atomic mass units per elementary charge
233
+ assert "AMU" in chemistry.mass_per_charge.unit
234
+ assert "e^{-1}" in chemistry.mass_per_charge.unit
235
+
236
+ # FIP should use electron volts
237
+ assert "eV" in chemistry.fip.unit
238
+
239
+ # Charge should use elementary charge units
240
+ assert "e" in chemistry.charge.unit
241
+
242
+ # Mass should use atomic mass units
243
+ assert "AMU" in chemistry.mass.unit
@@ -0,0 +1,345 @@
1
+ import logging
2
+ import pytest
3
+ from pathlib import Path
4
+
5
+ from solarwindpy.plotting.labels import composition
6
+ from solarwindpy.plotting.labels.base import Base
7
+
8
+
9
+ class IonWithUnits(composition.Ion):
10
+ """Ion subclass that allows overriding units."""
11
+
12
+ def __init__(self, species, charge, units):
13
+ super().__init__(species, charge)
14
+ self._units_override = units
15
+
16
+ @property
17
+ def units(self):
18
+ return self._units_override
19
+
20
+
21
+ def test_set_species_charge_known_species(caplog):
22
+ """Check that a known species does not trigger a warning.
23
+
24
+ Parameters
25
+ ----------
26
+ caplog : pytest.LogCaptureFixture
27
+ Logging capture fixture.
28
+ """
29
+ with caplog.at_level(logging.WARNING):
30
+ ion = composition.Ion("Fe", "2")
31
+ assert ion.species == "Fe"
32
+ assert ion.charge == "2"
33
+ assert "Unknown species" not in caplog.text
34
+
35
+
36
+ def test_set_species_charge_unknown_species(caplog):
37
+ """Check that an unknown species logs a warning.
38
+
39
+ Parameters
40
+ ----------
41
+ caplog : pytest.LogCaptureFixture
42
+ Logging capture fixture.
43
+ """
44
+ with caplog.at_level(logging.WARNING):
45
+ composition.Ion("Xe", "2")
46
+ assert "Unknown species (Xe)" in caplog.text
47
+
48
+
49
+ def test_set_species_charge_invalid_charge():
50
+ """Ensure invalid charge raises ``ValueError``."""
51
+ with pytest.raises(ValueError):
52
+ composition.Ion("Fe", "a")
53
+
54
+
55
+ def test_charge_state_units_equal():
56
+ """``ChargeState`` has ``#`` units when ion units match."""
57
+ cs = composition.ChargeState(("O", "2"), ("Fe", "3"))
58
+ assert cs.units == r"\#"
59
+
60
+
61
+ def test_charge_state_units_different():
62
+ """``ChargeState`` units combine when ion units differ."""
63
+ ion_a = IonWithUnits("O", "2", "cm-3")
64
+ ion_b = IonWithUnits("Fe", "3", "km/s")
65
+ cs = composition.ChargeState(ion_a, ion_b)
66
+ assert cs.units == "cm-3/km/s"
67
+
68
+
69
+ class TestIon:
70
+ """Test Ion class functionality."""
71
+
72
+ def test_ion_initialization(self):
73
+ """Test basic Ion initialization."""
74
+ ion = composition.Ion("Fe", "2")
75
+ assert ion.species == "Fe"
76
+ assert ion.charge == "2"
77
+
78
+ def test_ion_inheritance(self):
79
+ """Test that Ion inherits from Base."""
80
+ ion = composition.Ion("O", "6")
81
+ assert isinstance(ion, Base)
82
+ assert hasattr(ion, "logger")
83
+
84
+ def test_species_title_case(self):
85
+ """Test that species is converted to title case."""
86
+ ion = composition.Ion("fe", "2")
87
+ assert ion.species == "Fe"
88
+
89
+ ion2 = composition.Ion("FE", "3")
90
+ assert ion2.species == "Fe"
91
+
92
+ def test_tex_property(self):
93
+ """Test TeX representation of ion."""
94
+ ion = composition.Ion("Fe", "2")
95
+ assert ion.tex == "{Fe}^{2}"
96
+
97
+ # Test with different charge formats
98
+ ion_plus = composition.Ion("O", "6")
99
+ assert ion_plus.tex == "{O}^{6}"
100
+
101
+ def test_units_property(self):
102
+ """Test ion units property."""
103
+ ion = composition.Ion("Ne", "8")
104
+ assert ion.units == "\\#"
105
+
106
+ def test_path_property(self):
107
+ """Test path generation for ions."""
108
+ ion = composition.Ion("Si", "4")
109
+ assert isinstance(ion.path, Path)
110
+ assert str(ion.path) == "Si_4"
111
+
112
+ def test_path_with_valid_charges(self):
113
+ """Test path generation with various valid charges."""
114
+ # Test basic numeric charges
115
+ ion1 = composition.Ion("Fe", "2")
116
+ assert str(ion1.path) == "Fe_2"
117
+
118
+ # Test special charges
119
+ ion_i = composition.Ion("Fe", "i")
120
+ expected_path = "Fe_i"
121
+ assert str(ion_i.path) == expected_path
122
+
123
+ ion_j = composition.Ion("O", "j")
124
+ expected_path = "O_j"
125
+ assert str(ion_j.path) == expected_path
126
+
127
+ def test_known_species_list(self):
128
+ """Test the known species list."""
129
+ expected_species = ("C", "Fe", "He", "Mg", "Ne", "N", "O", "Si", "S")
130
+ assert composition.known_species == expected_species
131
+
132
+ def test_all_known_species_no_warning(self, caplog):
133
+ """Test that all known species don't trigger warnings."""
134
+ with caplog.at_level(logging.WARNING):
135
+ for species in composition.known_species:
136
+ composition.Ion(species, "2")
137
+ assert "Unknown species" not in caplog.text
138
+
139
+ def test_valid_charges(self):
140
+ """Test various valid charge formats."""
141
+ valid_charges = ["1", "2", "3", "10", "i", "j"]
142
+
143
+ for charge in valid_charges:
144
+ ion = composition.Ion("O", charge)
145
+ assert ion.charge == charge
146
+
147
+ def test_invalid_charges(self):
148
+ """Test invalid charge formats raise ValueError."""
149
+ invalid_charges = ["a", "x", "1.5", "+", "-", ""]
150
+
151
+ for charge in invalid_charges:
152
+ with pytest.raises(ValueError, match="Invalid charge"):
153
+ composition.Ion("O", charge)
154
+
155
+ def test_string_representation(self):
156
+ """Test string representations through base class."""
157
+ ion = composition.Ion("Fe", "2")
158
+ # Ion inherits from Base, so it should have with_units property
159
+ str_repr = str(ion)
160
+ assert isinstance(str_repr, str)
161
+
162
+ def test_ion_comparison(self):
163
+ """Test ion comparison functionality."""
164
+ ion1 = composition.Ion("Fe", "2")
165
+ ion2 = composition.Ion("Fe", "2")
166
+ ion3 = composition.Ion("O", "6")
167
+
168
+ # Same ions should be equal
169
+ assert ion1 == ion2
170
+
171
+ # Different ions should not be equal
172
+ assert ion1 != ion3
173
+
174
+ def test_ion_hashing(self):
175
+ """Test that ions can be hashed."""
176
+ ion1 = composition.Ion("Fe", "2")
177
+ ion2 = composition.Ion("O", "6")
178
+
179
+ # Should be able to create a set
180
+ ion_set = {ion1, ion2}
181
+ assert len(ion_set) == 2
182
+
183
+ # Should be able to use as dictionary keys
184
+ ion_dict = {ion1: "iron", ion2: "oxygen"}
185
+ assert len(ion_dict) == 2
186
+
187
+
188
+ class TestChargeState:
189
+ """Test ChargeState class functionality."""
190
+
191
+ def test_charge_state_initialization_with_tuples(self):
192
+ """Test ChargeState initialization with tuples."""
193
+ cs = composition.ChargeState(("O", "6"), ("O", "7"))
194
+ assert cs.ionA.species == "O"
195
+ assert cs.ionA.charge == "6"
196
+ assert cs.ionB.species == "O"
197
+ assert cs.ionB.charge == "7"
198
+
199
+ def test_charge_state_initialization_with_ions(self):
200
+ """Test ChargeState initialization with Ion objects."""
201
+ ion_a = composition.Ion("Fe", "10")
202
+ ion_b = composition.Ion("Fe", "11")
203
+ cs = composition.ChargeState(ion_a, ion_b)
204
+ assert cs.ionA == ion_a
205
+ assert cs.ionB == ion_b
206
+
207
+ def test_charge_state_inheritance(self):
208
+ """Test that ChargeState inherits from Base."""
209
+ cs = composition.ChargeState(("O", "6"), ("O", "7"))
210
+ assert isinstance(cs, Base)
211
+ assert hasattr(cs, "logger")
212
+
213
+ def test_charge_state_tex(self):
214
+ """Test TeX representation of charge state."""
215
+ cs = composition.ChargeState(("O", "6"), ("O", "7"))
216
+ assert cs.tex == "{O}^{6}/{O}^{7}"
217
+
218
+ def test_charge_state_path(self):
219
+ """Test path generation for charge state."""
220
+ cs = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
221
+ assert isinstance(cs.path, Path)
222
+ expected_path = "Fe_10-OV-Fe_11"
223
+ assert str(cs.path) == expected_path
224
+
225
+ def test_charge_state_same_units(self):
226
+ """Test charge state units when both ions have same units."""
227
+ # Default Ion units are "\#"
228
+ cs = composition.ChargeState(("O", "6"), ("O", "7"))
229
+ assert cs.units == r"\#"
230
+
231
+ def test_charge_state_different_units(self):
232
+ """Test charge state units when ions have different units."""
233
+ ion_a = IonWithUnits("O", "6", "cm^-3")
234
+ ion_b = IonWithUnits("O", "7", "km/s")
235
+ cs = composition.ChargeState(ion_a, ion_b)
236
+ assert cs.units == "cm^-3/km/s"
237
+
238
+ def test_charge_state_mixed_initialization(self):
239
+ """Test ChargeState with mix of Ion and tuple."""
240
+ ion_a = composition.Ion("Fe", "2")
241
+ cs = composition.ChargeState(ion_a, ("O", "6"))
242
+ assert cs.ionA == ion_a
243
+ assert cs.ionB.species == "O"
244
+ assert cs.ionB.charge == "6"
245
+
246
+ def test_charge_state_comparison(self):
247
+ """Test charge state comparison functionality."""
248
+ cs1 = composition.ChargeState(("O", "6"), ("O", "7"))
249
+ cs2 = composition.ChargeState(("O", "6"), ("O", "7"))
250
+ cs3 = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
251
+
252
+ # Same charge states should be equal
253
+ assert cs1 == cs2
254
+
255
+ # Different charge states should not be equal
256
+ assert cs1 != cs3
257
+
258
+ def test_charge_state_hashing(self):
259
+ """Test that charge states can be hashed."""
260
+ cs1 = composition.ChargeState(("O", "6"), ("O", "7"))
261
+ cs2 = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
262
+
263
+ # Should be able to create a set
264
+ cs_set = {cs1, cs2}
265
+ assert len(cs_set) == 2
266
+
267
+ # Should be able to use as dictionary keys
268
+ cs_dict = {cs1: "oxygen", cs2: "iron"}
269
+ assert len(cs_dict) == 2
270
+
271
+ def test_charge_state_string_representation(self):
272
+ """Test string representation of charge state."""
273
+ cs = composition.ChargeState(("O", "6"), ("O", "7"))
274
+ str_repr = str(cs)
275
+ assert isinstance(str_repr, str)
276
+
277
+
278
+ class TestCompositionModule:
279
+ """Test module-level functionality."""
280
+
281
+ def test_module_all(self):
282
+ """Test module __all__ exports."""
283
+ assert composition.__all__ == ["Ion", "ChargeState"]
284
+
285
+ def test_module_attributes(self):
286
+ """Test module has expected attributes."""
287
+ assert hasattr(composition, "Ion")
288
+ assert hasattr(composition, "ChargeState")
289
+ assert hasattr(composition, "known_species")
290
+
291
+ def test_known_species_completeness(self):
292
+ """Test that known_species covers common solar wind ions."""
293
+ expected_common_ions = ["C", "Fe", "He", "Mg", "Ne", "N", "O", "Si", "S"]
294
+ for ion in expected_common_ions:
295
+ assert ion in composition.known_species
296
+
297
+ def test_scientific_accuracy(self):
298
+ """Test that composition labels represent scientifically accurate concepts."""
299
+ # Test common solar wind charge states
300
+ o6_o7 = composition.ChargeState(("O", "6"), ("O", "7"))
301
+ assert "O" in o6_o7.tex
302
+ assert "6" in o6_o7.tex
303
+ assert "7" in o6_o7.tex
304
+
305
+ # Test iron charge states
306
+ fe10_fe11 = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
307
+ assert "Fe" in fe10_fe11.tex
308
+ assert "10" in fe10_fe11.tex
309
+ assert "11" in fe10_fe11.tex
310
+
311
+
312
+ class TestCompositionIntegration:
313
+ """Test integration between Ion and ChargeState classes."""
314
+
315
+ def test_ion_in_charge_state_roundtrip(self):
316
+ """Test creating ions and using them in charge states."""
317
+ # Create ions
318
+ o6 = composition.Ion("O", "6")
319
+ o7 = composition.Ion("O", "7")
320
+
321
+ # Use in charge state
322
+ cs = composition.ChargeState(o6, o7)
323
+
324
+ # Verify roundtrip
325
+ assert cs.ionA.species == "O"
326
+ assert cs.ionA.charge == "6"
327
+ assert cs.ionB.species == "O"
328
+ assert cs.ionB.charge == "7"
329
+
330
+ def test_complex_charge_state_ratios(self):
331
+ """Test complex charge state ratios with different species."""
332
+ # O6+ / Fe10+ ratio
333
+ cs = composition.ChargeState(("O", "6"), ("Fe", "10"))
334
+ assert "O" in cs.tex
335
+ assert "Fe" in cs.tex
336
+ assert "{O}^{6}/{Fe}^{10}" == cs.tex
337
+
338
+ def test_charge_state_path_uniqueness(self):
339
+ """Test that different charge states have unique paths."""
340
+ cs1 = composition.ChargeState(("O", "6"), ("O", "7"))
341
+ cs2 = composition.ChargeState(("Fe", "10"), ("Fe", "11"))
342
+ cs3 = composition.ChargeState(("O", "7"), ("O", "6")) # Reversed
343
+
344
+ paths = [str(cs1.path), str(cs2.path), str(cs3.path)]
345
+ assert len(paths) == len(set(paths)) # All unique