Skip to content

Conversation

@KingaMas
Copy link
Member

@KingaMas KingaMas commented Jan 5, 2026

Reverts #460

Summary by CodeRabbit

Release Notes

  • New Features

    • Extended compound validation to support mixed-valence elements. Users can now enable mixed-valence validation to screen compounds containing elements with variable oxidation states, with the feature disabled by default for backward compatibility.
  • Tests

    • Added validation tests for mixed-valence element handling.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 5, 2026

Walkthrough

This PR introduces mixed-valence element handling to the smact_validity function. It adds a new optional parameter to enable validation of mixed-valence compounds, defines a constant listing mixed-valence elements, and provides helper functions to expand and revalidate oxidation states for such compositions.

Changes

Cohort / File(s) Summary
Core feature implementation
smact/screening.py
Added MIXED_VALENCE_ELEMENTS constant; introduced mixed_valence: bool = False parameter to smact_validity function signature; implemented early oxidation-state validation via _is_valid_oxi_state helper; added conditional mixed-valence pathway that expands compositions using _expand_mixed_valence_comp when conditions are met; removed neutral_ratios from internal imports.
Test coverage
smact/tests/test_core.py
Added test_smact_validity_mixed_valence method to TestSequenceFunctions class to verify handling of mixed-valence compounds (e.g. Fe₃O₄) with and without the mixed_valence flag enabled.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

feature, python, enhancement

Suggested reviewers

  • AntObi
  • ryannduma
  • hspark1212

Poem

🐰 Through oxidation states we hop and bound,
Mixed-valence secrets now are found!
Fe₃O₄ yields its hidden way,
Expansion validates the day! ✨

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is minimal, providing only an issue reference without following the template's required sections such as motivation, testing details, or checklist items. Expand the description to include rationale for reintroducing the feature, testing methodology, verification steps, and completion of the provided checklist items.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly indicates this PR reverts a previous revert, reintroducing support for mixed valence compound validity checks—directly aligned with the substantial code changes.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch revert-460-revert-441-mixed-valence

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@codecov
Copy link

codecov bot commented Jan 5, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 80.83%. Comparing base (8d87e59) to head (5e9cc8c).
⚠️ Report is 35 commits behind head on develop.

Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #568      +/-   ##
===========================================
+ Coverage    80.66%   80.83%   +0.16%     
===========================================
  Files           33       33              
  Lines         2871     2896      +25     
===========================================
+ Hits          2316     2341      +25     
  Misses         555      555              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Fix all issues with AI Agents 🤖
In @smact/screening.py:
- Around line 567-581: In _expand_mixed_valence_comp fix the typo 'electrnoeg'
to 'electroneg' in the zip() loop and all uses inside the function: rename the
loop variable from electrnoeg → electroneg and update
new_electronegs.extend([...]) and new_electronegs.append(...) calls to use
electroneg so the electronegs list is referenced correctly.
🧹 Nitpick comments (3)
smact/screening.py (3)

24-46: LGTM - Consider using frozenset for immutability and O(1) lookups.

The list of mixed-valence elements is chemically reasonable. A frozenset would provide immutability and faster membership checks, though the performance difference is negligible for this size.


567-568: Consider adding type hints to the helper function.

Other functions in this module include type hints. Adding them here would improve consistency and maintainability.

🔎 Suggested type hints
def _expand_mixed_valence_comp(
    ox_combos: list[list[int]],
    stoichs: list[tuple[int, ...]],
    electronegs: list[float],
    elem_symbols: tuple[str, ...],
) -> tuple[list[list[int]], list[tuple[int, ...]], list[float]]:
    """Utility function to expand mixed valence elements in the composition."""

584-600: LGTM - Logic is correct.

The function correctly iterates through oxidation state combinations and short-circuits on the first valid solution. The TypeError handling is consistent with the existing approach in the codebase.

Consider adding type hints for consistency with other functions in this module.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9b53e39 and 5e9cc8c.

📒 Files selected for processing (2)
  • smact/screening.py
  • smact/tests/test_core.py
🧰 Additional context used
🧬 Code graph analysis (2)
smact/tests/test_core.py (1)
smact/screening.py (1)
  • smact_validity (448-564)
smact/screening.py (1)
smact/__init__.py (1)
  • _gcd_recursive (450-455)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
  • GitHub Check: test (3.12, windows-latest)
  • GitHub Check: test (3.12, ubuntu-latest)
  • GitHub Check: test (3.11, windows-latest)
  • GitHub Check: test (3.11, ubuntu-latest)
  • GitHub Check: test (3.10, windows-latest)
  • GitHub Check: test (3.13, ubuntu-latest)
  • GitHub Check: test (3.10, ubuntu-latest)
🔇 Additional comments (3)
smact/screening.py (2)

458-478: LGTM!

The new mixed_valence parameter is well-documented and defaults to False for backward compatibility.


555-564: Verify that the unchanged threshold is intentional after expansion.

After _expand_mixed_valence_comp, the stoichs are expanded but threshold remains the original value from the unexpanded composition. For Fe₃O₄, the original threshold is 4, but after expansion, each Fe site has stoichiometry (1,). The neutral_ratios function uses threshold to limit ratio search space.

If the intent is to find ratios matching the expanded stoichiometries exactly, this should work. However, if the threshold should reflect the expanded composition's maximum stoichiometry (which would be 4 for O), please verify this is the intended behaviour.

smact/tests/test_core.py (1)

487-496: LGTM - Good basic coverage for the new feature.

The test correctly validates Fe₃O₄ as the canonical mixed-valence compound. Consider adding additional test cases in future for broader coverage:

  • A compound with no mixed-valence elements (should behave identically regardless of the flag)
  • A compound that is valid without mixed-valence handling (to ensure the flag doesn't break existing behaviour)
  • Other mixed-valence compounds like Mn₃O₄ or Pb₃O₄

Comment on lines +567 to +581
def _expand_mixed_valence_comp(ox_combos, stoichs, electronegs, elem_symbols):
"""Utility function to expand mixed valence elements in the composition."""
new_ox_combos = []
new_stoichs = []
new_electronegs = []
for el, ox, count, electrnoeg in zip(elem_symbols, ox_combos, stoichs, electronegs, strict=False):
if el in MIXED_VALENCE_ELEMENTS:
new_ox_combos.extend([ox] * count[0])
new_electronegs.extend([electrnoeg] * count[0])
new_stoichs.extend([(1,)] * count[0])
else:
new_ox_combos.append(ox)
new_electronegs.append(electrnoeg)
new_stoichs.append(count)
return new_ox_combos, new_stoichs, new_electronegs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typo: electrnoegelectroneg.

The variable name electrnoeg on line 572 appears to be a typo of electroneg.

🔎 Proposed fix
-    for el, ox, count, electrnoeg in zip(elem_symbols, ox_combos, stoichs, electronegs, strict=False):
+    for el, ox, count, electroneg in zip(elem_symbols, ox_combos, stoichs, electronegs, strict=False):
         if el in MIXED_VALENCE_ELEMENTS:
             new_ox_combos.extend([ox] * count[0])
-            new_electronegs.extend([electrnoeg] * count[0])
+            new_electronegs.extend([electroneg] * count[0])
             new_stoichs.extend([(1,)] * count[0])
         else:
             new_ox_combos.append(ox)
-            new_electronegs.append(electrnoeg)
+            new_electronegs.append(electroneg)
             new_stoichs.append(count)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def _expand_mixed_valence_comp(ox_combos, stoichs, electronegs, elem_symbols):
"""Utility function to expand mixed valence elements in the composition."""
new_ox_combos = []
new_stoichs = []
new_electronegs = []
for el, ox, count, electrnoeg in zip(elem_symbols, ox_combos, stoichs, electronegs, strict=False):
if el in MIXED_VALENCE_ELEMENTS:
new_ox_combos.extend([ox] * count[0])
new_electronegs.extend([electrnoeg] * count[0])
new_stoichs.extend([(1,)] * count[0])
else:
new_ox_combos.append(ox)
new_electronegs.append(electrnoeg)
new_stoichs.append(count)
return new_ox_combos, new_stoichs, new_electronegs
def _expand_mixed_valence_comp(ox_combos, stoichs, electronegs, elem_symbols):
"""Utility function to expand mixed valence elements in the composition."""
new_ox_combos = []
new_stoichs = []
new_electronegs = []
for el, ox, count, electroneg in zip(elem_symbols, ox_combos, stoichs, electronegs, strict=False):
if el in MIXED_VALENCE_ELEMENTS:
new_ox_combos.extend([ox] * count[0])
new_electronegs.extend([electroneg] * count[0])
new_stoichs.extend([(1,)] * count[0])
else:
new_ox_combos.append(ox)
new_electronegs.append(electroneg)
new_stoichs.append(count)
return new_ox_combos, new_stoichs, new_electronegs
🤖 Prompt for AI Agents
In @smact/screening.py around lines 567-581, In _expand_mixed_valence_comp fix
the typo 'electrnoeg' to 'electroneg' in the zip() loop and all uses inside the
function: rename the loop variable from electrnoeg → electroneg and update
new_electronegs.extend([...]) and new_electronegs.append(...) calls to use
electroneg so the electronegs list is referenced correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants