Skip to content

Feature/sof-7954 Feat: Interfacial Energy WF#344

Merged
VsevolodX merged 12 commits into
mainfrom
feature/SOF-7954
Jul 23, 2026
Merged

Feature/sof-7954 Feat: Interfacial Energy WF#344
VsevolodX merged 12 commits into
mainfrom
feature/SOF-7954

Conversation

@VsevolodX

@VsevolodX VsevolodX commented Jul 13, 2026

Copy link
Copy Markdown
Member

Summary by CodeRabbit

  • Documentation
    • Updated the materials designer notebook index and renamed the Thermodynamics subsection to Interfacial Energy, with a link to the new notebook.
  • New Features
    • Added an end-to-end Interfacial Energy notebook for heterostructures, including workflow setup, job submission, and results reporting.
    • Enabled SCF k-grid configuration across relevant workflow substeps.
  • Bug Fixes
    • Improved bulk/interface resolution and fail-fast behavior when prerequisite bulk/total-energy data is missing.
  • Refactor
    • Streamlined bulk-energy resolution and simplified workflow output for energy notebooks.
  • Tests
    • Added unit coverage for SCF k-grid updates and bulk query resolution logic.

@review-notebook-app

Copy link
Copy Markdown

Check out this pull request on  ReviewNB

See visual diffs & provide feedback on Jupyter Notebooks.


Powered by ReviewNB

@coderabbitai

coderabbitai Bot commented Jul 13, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@VsevolodX, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 55 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4da02209-e66f-4992-aaf3-371c79f1e05f

📥 Commits

Reviewing files that changed from the base of the PR and between 7fe685d and e70b224.

📒 Files selected for processing (1)
  • other/materials_designer/workflows/Introduction.ipynb
📝 Walkthrough

Walkthrough

Adds an interfacial-energy workflow notebook and links it from the materials-designer documentation. Refactors shared bulk resolution, adds reusable SCF k-grid application, and updates the surface-energy notebook to use existing bulk total-energy properties and a previously loaded workflow.

Changes

Energy workflow updates

Layer / File(s) Summary
Shared material-resolution helpers
src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py, src/py/mat3ra/notebooks_utils/core/entity/material/api.py, src/py/mat3ra/notebooks_utils/core/entity/property/api.py
Adds slab bulk-crystal extraction, bulk-query resolution, owner-aware material lookup, and highest-precision total-energy retrieval.
Reusable SCF k-grid application
src/py/mat3ra/notebooks_utils/workflow.py, tests/py/unit/test_workflow_utils.py
Adds apply_scf_kgrid for updating pw_scf contexts and tests the resulting k-grid data.
Surface-energy bulk and workflow resolution
other/materials_designer/workflows/surface_energy.ipynb
Requires existing bulk total energy, reuses the loaded workflow, applies SCF settings, and simplifies job and result reporting.
Interfacial workflow setup and bulk resolution
other/materials_designer/workflows/interfacial_energy.ipynb
Adds interface loading and preparation, resolves substrate and film bulks with total-energy properties, and assembles the ordered three-material input.
Interfacial job execution and results
other/materials_designer/workflows/interfacial_energy.ipynb
Configures workflow and compute parameters, submits the job, waits for completion, and retrieves interfacial-energy results.
Workflow navigation documentation
README.md, other/materials_designer/workflows/Introduction.ipynb
Adds the Interfacial Energy notebook to workflow listings and replaces the placeholder entry with a link.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Notebook
  participant Mat3raAPI
  participant WorkflowStandata
  participant ComputeJob
  Notebook->>Mat3raAPI: authenticate and load interface and bulk materials
  Notebook->>WorkflowStandata: load and configure Interfacial Energy workflow
  Notebook->>ComputeJob: create and submit interfacial job
  ComputeJob-->>Notebook: completed energy properties
  Notebook->>Mat3raAPI: retrieve and visualize results
Loading

Possibly related PRs

Suggested reviewers: timurbazhirov

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 63.16% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly points to the main change: adding the Interfacial Energy workflow.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/SOF-7954

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (2)
other/materials_designer/workflows/interfacial_energy.ipynb (1)

354-381: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated bulk-resolution logic (substrate vs. film).

This cell is nearly identical to the substrate cell (Lines 318-343), differing only by part, the io-bulk-* unit name, and target variable names. The two TE-check cells (Lines 415-455 and 466-504) share the same duplication. Consider extracting a helper (e.g., resolve_bulk(part, io_unit_name) and check_bulk_total_energy(subworkflow, ids, ...)) to keep the query/projection extraction in one place and reduce drift.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@other/materials_designer/workflows/interfacial_energy.ipynb` around lines 354
- 381, Extract the duplicated substrate/film bulk-resolution flow into a shared
helper such as resolve_bulk(part, io_unit_name), covering interface crystal
lookup, query/projection extraction, material lookup, missing-result validation,
and response conversion. Update both bulk-resolution cells to call it with their
respective identifiers, and similarly consolidate the duplicated total-energy
checks through a shared check_bulk_total_energy helper while preserving existing
outputs and error behavior.
other/materials_designer/workflows/surface_energy.ipynb (1)

295-322: 🔒 Security & Privacy | 🔵 Trivial | ⚖️ Poor tradeoff

eval() on workflow-derived template strings is a fragile/insecure pattern.

Multiple eval(..., {"__builtins__": {}}, ...) calls (lines 301, 306, 309, 311, 322) evaluate template strings pulled from workflow subworkflow/unit definitions. Clearing __builtins__ is a commonly-bypassed mitigation (e.g. via object-graph traversal like ().__class__.__base__.__subclasses__()), not a real sandbox — flagged by Ruff as S307. Since these templates originate from platform-authored workflow definitions rather than end-user input, the immediate exploitability is lower, but this pattern still deserves scrutiny given it's now used repeatedly across the notebook (also at lines 404-405) as the sole templating mechanism for extracting query/projection data.

Consider having the workflow templates expose structured (non-eval'd) accessors, or restrict evaluation to a minimal safe-expression parser (e.g. ast.literal_eval won't work here since the templates reference variables like SLAB/BULK_ID, so a small allow-listed AST-based evaluator would be needed instead).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@other/materials_designer/workflows/surface_energy.ipynb` around lines 295 -
322, Replace the eval-based template handling in the workflow extraction block,
including the related calls around the later query/projection extraction, with
structured workflow accessors or a minimal allow-listed AST evaluator. Preserve
variable substitution for SLAB, BULK_ID, and LAST_BUILD_CRYSTAL while allowing
only the required expression forms and rejecting all other nodes; do not rely on
an empty __builtins__ dictionary as sandboxing.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@other/materials_designer/workflows/surface_energy.ipynb`:
- Around line 313-317: Update the ValueError message in the bulk_query
validation to accurately cover both ID-based and crystal-build-based lookup
failures, rather than asserting missing crystal scaledHash or hash. Preserve the
guidance to upload the bulk material and run total_energy.ipynb first.
- Around line 270-277: Replace the positional subworkflow lookups in the
surface_workflow setup with resolution by each subworkflow’s stable identifier,
or use a single helper that defines and validates the ordering contract. Ensure
resolve_bulk_by_id_subworkflow, resolve_bulk_by_build_subworkflow, and
get_bulk_energy_subworkflow remain bound to the correct named subworkflows if
the template order changes.

In `@src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py`:
- Around line 162-165: Update find_owned_material so it does not return an
unowned matches[0] as though it were an owned match; return an ownership
indicator or None for the fallback, and adjust get_bulk_material to distinguish
and log the owned-match and non-owned fallback paths correctly.

---

Nitpick comments:
In `@other/materials_designer/workflows/interfacial_energy.ipynb`:
- Around line 354-381: Extract the duplicated substrate/film bulk-resolution
flow into a shared helper such as resolve_bulk(part, io_unit_name), covering
interface crystal lookup, query/projection extraction, material lookup,
missing-result validation, and response conversion. Update both bulk-resolution
cells to call it with their respective identifiers, and similarly consolidate
the duplicated total-energy checks through a shared check_bulk_total_energy
helper while preserving existing outputs and error behavior.

In `@other/materials_designer/workflows/surface_energy.ipynb`:
- Around line 295-322: Replace the eval-based template handling in the workflow
extraction block, including the related calls around the later query/projection
extraction, with structured workflow accessors or a minimal allow-listed AST
evaluator. Preserve variable substitution for SLAB, BULK_ID, and
LAST_BUILD_CRYSTAL while allowing only the required expression forms and
rejecting all other nodes; do not rely on an empty __builtins__ dictionary as
sandboxing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bae0442b-9df5-4727-ab15-d026481480c7

📥 Commits

Reviewing files that changed from the base of the PR and between 871c7b9 and 31a2f8b.

📒 Files selected for processing (5)
  • README.md
  • other/materials_designer/workflows/Introduction.ipynb
  • other/materials_designer/workflows/interfacial_energy.ipynb
  • other/materials_designer/workflows/surface_energy.ipynb
  • src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py

Comment thread other/materials_designer/workflows/surface_energy.ipynb
Comment thread other/materials_designer/workflows/surface_energy.ipynb Outdated
Comment on lines +162 to +165
def find_owned_material(api_client: Any, bulk_query: dict, owner_id: str) -> Optional[Any]:
matches = api_client.materials.list(bulk_query)
owned = next((item for item in matches if item.get("owner", {}).get("_id") == owner_id), None)
return owned or (matches[0] if matches else None)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- analysis.py around find_owned_material and get_bulk_material ---'
nl -ba src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py | sed -n '120,210p'

echo
echo '--- usages of find_owned_material / get_bulk_material ---'
rg -n "find_owned_material|get_bulk_material" src/py -S

echo
echo '--- broader context for bulk/material ownership logic ---'
rg -n "owner_id|owner.*_id|owned material|bulk material|Found exact bulk material|bulk_query" src/py/mat3ra/notebooks_utils -S

Repository: mat3ra/api-examples

Length of output: 266


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- analysis.py around find_owned_material and get_bulk_material ---'
sed -n '120,210p' src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py

echo
echo '--- usages of find_owned_material / get_bulk_material ---'
rg -n "find_owned_material|get_bulk_material" src/py -S

echo
echo '--- broader context for bulk/material ownership logic ---'
rg -n "owner_id|owner.*_id|owned material|bulk material|Found exact bulk material|bulk_query" src/py/mat3ra/notebooks_utils -S

Repository: mat3ra/api-examples

Length of output: 6065


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- call sites of get_bulk_material ---'
rg -n "get_bulk_material\(" src/py -S

echo
echo '--- surrounding context at each call site ---'
python3 - <<'PY'
from pathlib import Path
import re

path = Path("src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py")
text = path.read_text().splitlines()
for i, line in enumerate(text, 1):
    if "get_bulk_material(" in line and "def " not in line:
        start = max(1, i-15)
        end = min(len(text), i+25)
        print(f"\n### {path}:{i}\n")
        for j in range(start, end+1):
            print(f"{j:4d}: {text[j-1]}")
PY

Repository: mat3ra/api-examples

Length of output: 391


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo '--- docs/comments mentioning shared/public bulk or material ownership ---'
rg -n "public|shared|owner|ownership|bulk material|bulkId|hash" src/py/mat3ra/notebooks_utils -S

echo
echo '--- material API helpers for owner-aware lookups ---'
sed -n '1,120p' src/py/mat3ra/notebooks_utils/core/entity/material/api.py

echo
echo '--- workflow API helper for comparison ---'
sed -n '1,120p' src/py/mat3ra/notebooks_utils/core/entity/workflow/api.py

Repository: mat3ra/api-examples

Length of output: 7855


Handle the non-owned fallback explicitly. find_owned_material returns matches[0] when no owned match exists, so get_bulk_material can log Found exact bulk material for a material owned by someone else. Return an ownership flag or None here so the caller can distinguish the fallback path.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py` around lines
162 - 165, Update find_owned_material so it does not return an unowned
matches[0] as though it were an owned match; return an ownership indicator or
None for the fallback, and adjust get_bulk_material to distinguish and log the
owned-match and non-owned fallback paths correctly.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@other/materials_designer/workflows/interfacial_energy.ipynb`:
- Around line 118-123: Validate N_INTERFACES before it is used to configure the
workflow, accepting only the documented integer values 1 or 2 and rejecting
zero, negative, fractional, or other values with a clear error. Preserve the
existing interface-count semantics for valid configurations.
- Around line 346-383: The bulk lookup in resolve_bulk_material must be
restricted to ACCOUNT_ID so it cannot select another account’s hash twin or
energy property. Reuse get_bulk_material with ACCOUNT_ID if available, or
constrain the materials.list query with owner._id equal to ACCOUNT_ID, while
preserving the existing selection of a candidate with finished Total Energy and
ensuring the returned bulk and property belong to that owner.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: ab6c5d67-6e42-4e9d-8afe-704d92d71394

📥 Commits

Reviewing files that changed from the base of the PR and between 31a2f8b and 7f6e6fd.

📒 Files selected for processing (3)
  • other/materials_designer/workflows/Introduction.ipynb
  • other/materials_designer/workflows/interfacial_energy.ipynb
  • other/materials_designer/workflows/surface_energy.ipynb

Comment thread other/materials_designer/workflows/interfacial_energy.ipynb
Comment thread other/materials_designer/workflows/interfacial_energy.ipynb Outdated
@@ -0,0 +1,683 @@
{

@timurbazhirov timurbazhirov Jul 17, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Line #18.    def find_bulk_with_total_energy(crystal, role, material_index):

These two should be reused across sufrace energy and interfacial energy nbs


Reply via ReviewNB

@@ -0,0 +1,683 @@
{

@timurbazhirov timurbazhirov Jul 17, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Line #5.    def apply_workflow_parameters(workflow: Workflow, scf_kgrid=None, n_interfaces=None) -> Workflow:

Is this reusable too?


Reply via ReviewNB

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
other/materials_designer/workflows/interfacial_energy.ipynb (1)

586-607: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

interface_te_data is fetched but never used.

Line 596-598 fetches the interface's total-energy property via an API call, but it's never passed to visualize_properties or referenced in the print statements below (only substrate/film energies are printed). This is either dead code (extra unnecessary API call) or an incomplete feature — the interface's own total energy should likely be surfaced alongside substrate/film energies for consistency.

♻️ Suggested fix: surface the fetched value
 print(f"Interface (material 0):     {saved_interface.name} ({saved_interface.id})")
+print(f"  total energy: {interface_te_data['data']['value']} eV")
 print(f"Substrate bulk (material 1): {substrate_bulk.name} ({substrate_bulk.id}), "
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@other/materials_designer/workflows/interfacial_energy.ipynb` around lines 586
- 607, Use the fetched interface_te_data in the interfacial energy workflow
instead of leaving it unused: surface the interface total-energy value alongside
the substrate and film energies in the output, reusing the existing interface
identity and value-access patterns.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/py/unit/test_workflow_utils.py`:
- Around line 52-60: Update test_apply_scf_kgrid_updates_pw_scf_context to
locate the context item named "kgrid" and assert that its "dimensions" value
equals SCF_KGRID directly. Remove the broad predicate that accepts any item
containing a "dimensions" key.

---

Nitpick comments:
In `@other/materials_designer/workflows/interfacial_energy.ipynb`:
- Around line 586-607: Use the fetched interface_te_data in the interfacial
energy workflow instead of leaving it unused: surface the interface total-energy
value alongside the substrate and film energies in the output, reusing the
existing interface identity and value-access patterns.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5e317c77-9dc7-4e7b-84fb-d71486adcb5e

📥 Commits

Reviewing files that changed from the base of the PR and between 7f6e6fd and 7b1a68e.

📒 Files selected for processing (4)
  • other/materials_designer/workflows/interfacial_energy.ipynb
  • other/materials_designer/workflows/surface_energy.ipynb
  • src/py/mat3ra/notebooks_utils/workflow.py
  • tests/py/unit/test_workflow_utils.py

Comment thread tests/py/unit/test_workflow_utils.py Outdated
return workflow
context = PointsGridDataProvider(dimensions=scf_kgrid, isEdited=True).get_context_item_data()
for subworkflow in workflow.subworkflows:
if "pw_scf" not in [unit.name for unit in subworkflow.units]:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems hardcoded

return np.linalg.norm(crossprod)


def get_slab_bulk_crystal(slab_material: Material) -> dict:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Docstring?? WTH?

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/py/unit/core/entity/test_material_analysis.py`:
- Line 7: Update the shared SILICON fixture and its uses in
resolve_bulk_query_from_crystal tests to copy the material data and remove
scaledHash, hash, and _id before merging extra_keys. Apply this sanitized
fixture consistently, including
test_resolve_bulk_query_computes_hash_when_none_present, so hash-only, _id-only,
and computed-hash fallback paths are exercised.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7bab1722-8574-4992-a39c-d80f1f14424a

📥 Commits

Reviewing files that changed from the base of the PR and between 7b1a68e and 7fe685d.

📒 Files selected for processing (8)
  • other/materials_designer/workflows/interfacial_energy.ipynb
  • other/materials_designer/workflows/surface_energy.ipynb
  • src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py
  • src/py/mat3ra/notebooks_utils/core/entity/material/api.py
  • src/py/mat3ra/notebooks_utils/core/entity/property/api.py
  • src/py/mat3ra/notebooks_utils/workflow.py
  • tests/py/unit/core/entity/test_material_analysis.py
  • tests/py/unit/test_workflow_utils.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/py/unit/test_workflow_utils.py
  • other/materials_designer/workflows/interfacial_energy.ipynb

from mat3ra.notebooks_utils.core.entity.material.analysis import resolve_bulk_query_from_crystal
from mat3ra.standata.materials import Materials

SILICON = Materials.get_by_name_first_match("Silicon")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
python - <<'PY'
from mat3ra.standata.materials import Materials

material = Materials.get_by_name_first_match("Silicon")
print({key: material.get(key) for key in ("scaledHash", "hash", "_id")})
PY

Repository: mat3ra/api-examples

Length of output: 276


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== file list candidate =="
git ls-files | rg 'test_material_analysis|materials|Material|materials' | head -200

echo "== test file =="
if [ -f tests/py/unit/core/entity/test_material_analysis.py ]; then
  cat -n tests/py/unit/core/entity/test_material_analysis.py
fi

echo "== resolve_bulk_query definitions =="
rg -n "resolve_bulk_query_from_crystal|class Materials|def get_by_name_first_match|scaledHash|hash|_id" -S . | head -300

Repository: mat3ra/api-examples

Length of output: 49602


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== resolution implementation =="
cat -n src/py/mat3ra/notebooks_utils/core/entity/material/analysis.py | sed -n '100,135p'

echo "== Materials source candidates =="
git ls-files '*materials*' | sed -n '1,120p'
rg -n "class Materials|def get_by_name_first_match|get_by_name_first_match|standata|materials" src tests other examples | sed -n '1,200p'

Repository: mat3ra/api-examples

Length of output: 41207


🌐 Web query:

mat3ra standata Materials Silicon get_by_name_first_match scaledHash hash _id

💡 Result:

In the context of the Mat3ra platform and its data standards, the terms provided relate to material structure identification and data retrieval within the platform's API and schema [1][2][3][4]. 1. scaledHash: This is a property of a material entity, represented as a string [3][4]. It acts as a hash used to identify structures that are identical even under different uniform pressure [3][4]. It is calculated by scaling all dimensions of the material's primitive unit cell by the lattice constant 'a' so that 'a' is set to 1.0 [3][4]. 2. hash: Often used alongside scaledHash to uniquely identify materials or structural configurations [4][5]. 3. _id: This typically refers to the unique identifier for an entity (such as a material, owner, or subworkflow) within the Mat3ra platform's database [4][5]. 4. get_by_name_first_match: While not a documented top-level API function for the Materials entity, similar naming patterns (e.g., resolve_bulk_material, get_bulk_material) are used in the platform's API-examples repository to resolve material or subworkflow entities by criteria such as identifiers, hashes, or names [5]. The ESSE (Essential Source of Schemas and Examples) Data Convention serves as the foundation for these structures, using JSON to organize entity properties [2][4]. For example, a material sample of Silicon would be represented with these properties to ensure consistent identification across the platform [1][4].

Citations:


🌐 Web query:

site:docs.mat3ra.com/materials/data Silicon scaledHash hash _id

💡 Result:

For the Silicon FCC example in Mat3ra docs, the material JSON shows:

  • _id: LCthJ6E2QabYCZqf3
  • hash: 4ac3fa057e3530628eb1295c77110eaa
  • scaledHash: 5bd4eb168e3530628eb1295d88221cbb (docs.mat3ra.com)

The docs define hash as the structure-based hash for the primitive standard representation, and scaledHash as the same idea after scaling the primitive cell so lattice vector a = 1.0, to identify the same structure under uniform pressure. (docs.mat3ra.com)

Citations:


Remove resolver identifiers from the shared Silicon fixture.

SILICON includes scaledHash, hash, and _id, and resolve_bulk_query_from_crystal() returns whichever of those fields is present. This masks the hash-only, _id-only, and computed-hash fallback paths; use a copy with those three keys removed before merging extra_keys, including the test_resolve_bulk_query_computes_hash_when_none_present case.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/py/unit/core/entity/test_material_analysis.py` at line 7, Update the
shared SILICON fixture and its uses in resolve_bulk_query_from_crystal tests to
copy the material data and remove scaledHash, hash, and _id before merging
extra_keys. Apply this sanitized fixture consistently, including
test_resolve_bulk_query_computes_hash_when_none_present, so hash-only, _id-only,
and computed-hash fallback paths are exercised.

@VsevolodX
VsevolodX merged commit fcc7bcf into main Jul 23, 2026
7 of 8 checks passed
@VsevolodX
VsevolodX deleted the feature/SOF-7954 branch July 23, 2026 03:33
@coderabbitai coderabbitai Bot mentioned this pull request Jul 23, 2026
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