Find 1D, 2D, and 3D structures of the same material

Dear all,

I would like to know if there is a way to explore the Materials Project database to identify materials composed of only elements X and Y, for example, but exhibiting different structural Dimensionality (1D, 2D and 3D).

Regards,
Ballmer

Hey @Ballmer here’s an example of how you might do this for the Mo-S chemical system. This snippet will first find all materials in MP with the matching chemical system, then searches the robocrys collection of automated crystal descriptions to see if they are 1, 2 or 3D:

from mp_api.client import MPRester

chemsys = "Mo-S"
with MPRester("your_api_key") as mpr:

    mat_docs = mpr.materials.search(chemsys=chemsys,fields=["material_id","structure"])
    robo_docs = mpr.materials.robocrys.search_docs(material_ids=[doc.material_id for doc in mat_docs])

mpid_to_structure = {
    doc.material_id.string : doc.structure for doc in mat_docs
}

structures_by_dim = {f"{i}D": {} for i in range(1,4)}
int_to_word = {
    1 : "one",
    2 : "two"
}
for doc in robo_docs:
    for i in range(1,3):
        if f"{int_to_word[i]}-dimensional" in doc.description.lower():
            dim = i
            break
    else:
        dim = 3
    structures_by_dim[f"{dim}D"][doc.material_id.string] = {
        "structure": mpid_to_structure[doc.material_id.string],
        "description": doc.description,
    }
1 Like

Thank you @Aaron_Kaplan.
This is fantastic, I had suspected that my inquiry might be impossible to achieve. I’m new to the Materials Project and understand that this code snippet is meant to be used with the mp-API. Although I haven’t yet taken the time to learn and explore it myself, I would really appreciate it if you could point me in the right direction or share a quick resource on how to get started using this snippet.

Our documentation is a great place to start!

If you’re not familiar with coding in python (the snippet I sent), all of the robocrys descriptions are available on materials summary pages under the Description (Auto-generated) heading. But I’d recommend doing this programmatically

Dear @Aaron_Kaplan,

I managed to run and use the Python code you provided, thank you again, it’s working perfectly.

I have a follow-up question, if you don’t mind. Instead of starting with a specific chemical system like elements X and Y and then checking for their dimensionality (which often turns out to include only a 3D structure), I would like to search for materials that already have all three structural forms. For example, I’d like the script to return something like “Chemical system X-Y” which has known 1D, 2D, and 3D polymorphs.

Is there a way to perform such a query using the mp-api please?

Yes it’s possible, try to see if you can modify the code I sent you to do it? Some hints:

Associating reduced formulas / polymorph formula units with material IDs:

from collections import defaultdict

with MPRester() as mpr:
    mat_docs = mpr.materials.search(fields=['composition','material_id'])
formula_to_mpids = defaultdict(list)
for doc in mat_docs:
    formula_to_mpids[doc.composition.reduced_formula].append(doc.material_id.string)

Getting all robocrys docs:

with MPRester() as mpr:
    robo_docs = mpr.materials.robocrys.search_docs()
description_by_mpid = {
    doc.material_id.string : doc.description for doc in robo_docs
}
1 Like

Sorry for the late reply as I needed some time to modify and test the code before getting back to you. This is fantastic and incredibly powerful! Thank you very much, @Aaron_Kaplan, for your help and guidance.

It seems that there are 155 chemical systems with 1D, 2D, and “3D” polymorphs in the Materials Project database. I would appreciate it if you could confirm this number, just to ensure I haven’t made any mistakes.

However, as shown in the attached image, the number of Materials Project documents does not match the number of the description documents generated by Robocrystallographer. It appears that 197 descriptions are missing, which would otherwise be generated by Robocrystallographer.

We don’t generate robocrys descriptions for every material - sometimes robocrys can’t identify a prototype, or something goes wrong in determining nearest neighbors

Happy to look over code that you used to get those numbers

Sure, here is the code, and I appreciate any insights from you please.

from mp_api.client import MPRester
from collections import defaultdict


with MPRester("XXXXXXXXXXXXXXXXXX") as mpr:
    mat_docs = mpr.materials.search(fields=['composition', 'material_id'])
    robo_docs = mpr.materials.robocrys.search_docs()

description_by_mpid = {doc.material_id: doc.description for doc in robo_docs}
formula_to_mpids = defaultdict(list)
for doc in mat_docs:
    formula = doc.composition.reduced_formula
    mpid = doc.material_id
    formula_to_mpids[formula].append(mpid)


mpid_to_dim = {}
int_to_word = {1: "one", 2: "two"}

for mpid, desc in description_by_mpid.items():
    for i in range(1, 3):
        if f"{int_to_word[i]}-dimensional" in desc.lower():
            mpid_to_dim[mpid] = f"{i}D"
            break
    else:
        mpid_to_dim[mpid] = "Other"



results = {}
for formula, mpids in formula_to_mpids.items():
    dim_to_mpids = {"1D": [], "2D": [], "Other": []}
    for mpid in mpids:
        if mpid in mpid_to_dim:
            dim = mpid_to_dim[mpid]
            dim_to_mpids[dim].append(mpid)
    if all(dim_to_mpids[d] for d in ["1D", "2D", "Other"]):
        results[formula] = dim_to_mpids



for i, (formula, dims) in enumerate(results.items(), 1):
    print(f"{i}- Chemical system: {formula}")
    for dim in ["1D", "2D", "Other"]:
        mpids = dims[dim]
        print(f"   - {len(mpids)} {dim} structures:")
        for mpid in mpids:
            print(f"       - {mpid}")
    print()