SMACT 2.5.2__tar.gz → 2.5.4__tar.gz

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.
Files changed (56) hide show
  1. {SMACT-2.5.2 → SMACT-2.5.4}/PKG-INFO +22 -2
  2. SMACT-2.5.2/SMACT.egg-info/PKG-INFO → SMACT-2.5.4/README.md +13 -25
  3. SMACT-2.5.2/README.md → SMACT-2.5.4/SMACT.egg-info/PKG-INFO +45 -1
  4. {SMACT-2.5.2 → SMACT-2.5.4}/setup.py +3 -2
  5. {SMACT-2.5.2 → SMACT-2.5.4}/smact/__init__.py +38 -4
  6. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/element_data.txt +1 -1
  7. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data_loader.py +56 -9
  8. SMACT-2.5.4/smact/dopant_prediction/doper.py +212 -0
  9. {SMACT-2.5.2 → SMACT-2.5.4}/smact/screening.py +8 -2
  10. {SMACT-2.5.2 → SMACT-2.5.4}/smact/structure_prediction/database.py +1 -3
  11. {SMACT-2.5.2 → SMACT-2.5.4}/smact/structure_prediction/mutation.py +1 -2
  12. {SMACT-2.5.2 → SMACT-2.5.4}/smact/structure_prediction/prediction.py +1 -2
  13. {SMACT-2.5.2 → SMACT-2.5.4}/smact/structure_prediction/structure.py +5 -5
  14. {SMACT-2.5.2 → SMACT-2.5.4}/smact/tests/test_core.py +15 -5
  15. {SMACT-2.5.2 → SMACT-2.5.4}/smact/tests/test_structure.py +1 -3
  16. SMACT-2.5.2/smact/dopant_prediction/doper.py +0 -186
  17. {SMACT-2.5.2 → SMACT-2.5.4}/LICENSE +0 -0
  18. {SMACT-2.5.2 → SMACT-2.5.4}/MANIFEST.in +0 -0
  19. {SMACT-2.5.2 → SMACT-2.5.4}/SMACT.egg-info/SOURCES.txt +0 -0
  20. {SMACT-2.5.2 → SMACT-2.5.4}/SMACT.egg-info/dependency_links.txt +0 -0
  21. {SMACT-2.5.2 → SMACT-2.5.4}/SMACT.egg-info/not-zip-safe +0 -0
  22. {SMACT-2.5.2 → SMACT-2.5.4}/SMACT.egg-info/requires.txt +0 -0
  23. {SMACT-2.5.2 → SMACT-2.5.4}/SMACT.egg-info/top_level.txt +0 -0
  24. {SMACT-2.5.2 → SMACT-2.5.4}/pyproject.toml +0 -0
  25. {SMACT-2.5.2 → SMACT-2.5.4}/setup.cfg +0 -0
  26. {SMACT-2.5.2 → SMACT-2.5.4}/smact/builder.py +0 -0
  27. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/Covalent_radii.csv +0 -0
  28. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/HHIs.txt +0 -0
  29. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/SSE.csv +0 -0
  30. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/SSE_2015.csv +0 -0
  31. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/SSE_Pauling.csv +0 -0
  32. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/ionic_radii.csv +0 -0
  33. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/ordered_periodic.txt +0 -0
  34. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/oxidation_state_probability_table.json +0 -0
  35. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/oxidation_states.txt +0 -0
  36. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/oxidation_states_SP.txt +0 -0
  37. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/oxidation_states_icsd.txt +0 -0
  38. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/oxidation_states_pmg.txt +0 -0
  39. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/oxidation_states_wiki.txt +0 -0
  40. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/oxidationstates.data +0 -0
  41. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/shannon_radii.csv +0 -0
  42. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/shannon_radii_ML_extended.csv +0 -0
  43. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/solid_properties.txt +0 -0
  44. {SMACT-2.5.2 → SMACT-2.5.4}/smact/data/solid_properties.xlsx +0 -0
  45. {SMACT-2.5.2 → SMACT-2.5.4}/smact/distorter.py +0 -0
  46. {SMACT-2.5.2 → SMACT-2.5.4}/smact/dopant_prediction/__init__.py +0 -0
  47. {SMACT-2.5.2 → SMACT-2.5.4}/smact/lattice.py +0 -0
  48. {SMACT-2.5.2 → SMACT-2.5.4}/smact/lattice_parameters.py +0 -0
  49. {SMACT-2.5.2 → SMACT-2.5.4}/smact/mainpage.py +0 -0
  50. {SMACT-2.5.2 → SMACT-2.5.4}/smact/oxidation_states.py +0 -0
  51. {SMACT-2.5.2 → SMACT-2.5.4}/smact/properties.py +0 -0
  52. {SMACT-2.5.2 → SMACT-2.5.4}/smact/structure_prediction/__init__.py +0 -0
  53. {SMACT-2.5.2 → SMACT-2.5.4}/smact/structure_prediction/probability_models.py +0 -0
  54. {SMACT-2.5.2 → SMACT-2.5.4}/smact/structure_prediction/utilities.py +0 -0
  55. {SMACT-2.5.2 → SMACT-2.5.4}/smact/tests/__init__.py +0 -0
  56. {SMACT-2.5.2 → SMACT-2.5.4}/smact/tests/test_doper.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: SMACT
3
- Version: 2.5.2
3
+ Version: 2.5.4
4
4
  Summary: Semiconducting Materials by Analogy and Chemical Theory
5
5
  Home-page: https://github.com/WMD-group/SMACT
6
6
  Author: Daniel W. Davies
@@ -12,6 +12,7 @@ Classifier: Programming Language :: Python :: 3
12
12
  Classifier: Programming Language :: Python :: 3.8
13
13
  Classifier: Programming Language :: Python :: 3.9
14
14
  Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
15
16
  Classifier: Development Status :: 5 - Production/Stable
16
17
  Classifier: Intended Audience :: Science/Research
17
18
  Classifier: Operating System :: OS Independent
@@ -21,6 +22,13 @@ Classifier: Topic :: Scientific/Engineering :: Chemistry
21
22
  Requires-Python: >=3.8
22
23
  Description-Content-Type: text/markdown
23
24
  License-File: LICENSE
25
+ Requires-Dist: scipy
26
+ Requires-Dist: numpy
27
+ Requires-Dist: spglib
28
+ Requires-Dist: pymatgen
29
+ Requires-Dist: ase
30
+ Requires-Dist: pandas
31
+ Requires-Dist: pathos
24
32
 
25
33
  [![DOI](http://joss.theoj.org/papers/10.21105/joss.01361/status.svg)](https://doi.org/10.21105/joss.01361)
26
34
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5553202.svg)](https://doi.org/10.5281/zenodo.5553202)
@@ -29,6 +37,7 @@ License-File: LICENSE
29
37
  ![python version](https://img.shields.io/pypi/pyversions/smact)
30
38
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
31
39
  [![PyPi](https://img.shields.io/pypi/v/smact)](https://pypi.org/project/SMACT/)
40
+ [![Conda](https://anaconda.org/conda-forge/smact/badges/version.svg)](https://anaconda.org/conda-forge/smact)
32
41
  [![GitHub issues](https://img.shields.io/github/issues-raw/WMD-Group/SMACT)](https://github.com/WMD-group/SMACT/issues)
33
42
  ![dependencies](https://img.shields.io/librariesio/release/pypi/smact)
34
43
  [![CI Status](https://github.com/WMD-group/SMACT/actions/workflows/ci.yml/badge.svg)](https://github.com/WMD-group/SMACT/actions/workflows/ci.yml)
@@ -83,7 +92,9 @@ Code features
83
92
  - The code also has some tools for manipulating common crystal lattice types:
84
93
  - Common crystal structure types can be built using the [builder module](https://smact.readthedocs.io/en/latest/smact.builder.html)
85
94
  - Lattice parameters can be quickly estimated using ionic radii of the elements for various common crystal structure types using the [lattice_parameters module](https://smact.readthedocs.io/en/latest/smact.lattice_parameters.html).
86
- - The [lattice module](https://smact.readthedocs.io/en/latest/smact.lattice.html) and [distorter module](https://smact.readthedocs.io/en/latest/smact.distorter.html) rely on the [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) and can be used to generate unique atomic substitutions on a given crystal structure.
95
+ - The [lattice module](https://smact.readthedocs.io/en/latest/smact.lattice.html) and [distorter module](https://smact.readthedocs.io/en/latest/smact.distorter.html) rely on the [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) and can be used to generate unique atomic substitutions on a given crystal structure.
96
+ - The [structure prediction](https://smact.readthedocs.io/en/latest/smact.structure_prediction.html) module can be used to predict the structure of hypothetical compositions using species similarity measures.
97
+ - The [dopant prediction](https://smact.readthedocs.io/en/latest/smact.dopant_prediction.html) module can be used to facilitate high-throughput predictions of p-type and n-type dopants of multicomponent solids.
87
98
 
88
99
  List of modules
89
100
  -------
@@ -101,6 +112,9 @@ List of modules
101
112
  * **lattice_parameters.py** Estimation of lattice parameters for various lattice types using covalent/ionic radii.
102
113
  * **distorter.py** A collection of functions for enumerating and then
103
114
  substituting on inequivalent sites of a sub-lattice.
115
+ * **oxidation_states.py**: Used for predicting the likelihood of species coexisting in a compound based on a statistical model.
116
+ * **structure_prediction**: A submodule which contains a collection of tools for facilitating crystal structure predictions via ionic substitutions
117
+ * **dopant_prediction**: A submodule which contains a collections of tools for predicting n-type and p-type dopants.
104
118
 
105
119
  Requirements
106
120
  ------------
@@ -115,6 +129,12 @@ The latest stable release of SMACT can be installed via pip which will automatic
115
129
 
116
130
  pip install smact
117
131
 
132
+ SMACT is also available via conda through the conda-forge channel on Anaconda Cloud:
133
+
134
+ ```
135
+ conda install -c conda-forge smact
136
+ ```
137
+
118
138
  Alternatively, the very latest version can be installed using:
119
139
 
120
140
  pip install git+git://github.com/WMD-group/SMACT.git
@@ -1,27 +1,3 @@
1
- Metadata-Version: 2.1
2
- Name: SMACT
3
- Version: 2.5.2
4
- Summary: Semiconducting Materials by Analogy and Chemical Theory
5
- Home-page: https://github.com/WMD-group/SMACT
6
- Author: Daniel W. Davies
7
- Author-email: d.w.davies@imperial.ac.uk
8
- Maintainer: Anthony O. Onwuli
9
- Maintainer-email: anthony.onwuli16@imperial.ac.uk
10
- License: MIT
11
- Classifier: Programming Language :: Python :: 3
12
- Classifier: Programming Language :: Python :: 3.8
13
- Classifier: Programming Language :: Python :: 3.9
14
- Classifier: Programming Language :: Python :: 3.10
15
- Classifier: Development Status :: 5 - Production/Stable
16
- Classifier: Intended Audience :: Science/Research
17
- Classifier: Operating System :: OS Independent
18
- Classifier: License :: OSI Approved :: MIT License
19
- Classifier: Topic :: Scientific/Engineering
20
- Classifier: Topic :: Scientific/Engineering :: Chemistry
21
- Requires-Python: >=3.8
22
- Description-Content-Type: text/markdown
23
- License-File: LICENSE
24
-
25
1
  [![DOI](http://joss.theoj.org/papers/10.21105/joss.01361/status.svg)](https://doi.org/10.21105/joss.01361)
26
2
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5553202.svg)](https://doi.org/10.5281/zenodo.5553202)
27
3
  [![Documentation Status](https://readthedocs.org/projects/smact/badge/?version=latest)](http://smact.readthedocs.org/en/latest/?badge=latest)
@@ -29,6 +5,7 @@ License-File: LICENSE
29
5
  ![python version](https://img.shields.io/pypi/pyversions/smact)
30
6
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
31
7
  [![PyPi](https://img.shields.io/pypi/v/smact)](https://pypi.org/project/SMACT/)
8
+ [![Conda](https://anaconda.org/conda-forge/smact/badges/version.svg)](https://anaconda.org/conda-forge/smact)
32
9
  [![GitHub issues](https://img.shields.io/github/issues-raw/WMD-Group/SMACT)](https://github.com/WMD-group/SMACT/issues)
33
10
  ![dependencies](https://img.shields.io/librariesio/release/pypi/smact)
34
11
  [![CI Status](https://github.com/WMD-group/SMACT/actions/workflows/ci.yml/badge.svg)](https://github.com/WMD-group/SMACT/actions/workflows/ci.yml)
@@ -83,7 +60,9 @@ Code features
83
60
  - The code also has some tools for manipulating common crystal lattice types:
84
61
  - Common crystal structure types can be built using the [builder module](https://smact.readthedocs.io/en/latest/smact.builder.html)
85
62
  - Lattice parameters can be quickly estimated using ionic radii of the elements for various common crystal structure types using the [lattice_parameters module](https://smact.readthedocs.io/en/latest/smact.lattice_parameters.html).
86
- - The [lattice module](https://smact.readthedocs.io/en/latest/smact.lattice.html) and [distorter module](https://smact.readthedocs.io/en/latest/smact.distorter.html) rely on the [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) and can be used to generate unique atomic substitutions on a given crystal structure.
63
+ - The [lattice module](https://smact.readthedocs.io/en/latest/smact.lattice.html) and [distorter module](https://smact.readthedocs.io/en/latest/smact.distorter.html) rely on the [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) and can be used to generate unique atomic substitutions on a given crystal structure.
64
+ - The [structure prediction](https://smact.readthedocs.io/en/latest/smact.structure_prediction.html) module can be used to predict the structure of hypothetical compositions using species similarity measures.
65
+ - The [dopant prediction](https://smact.readthedocs.io/en/latest/smact.dopant_prediction.html) module can be used to facilitate high-throughput predictions of p-type and n-type dopants of multicomponent solids.
87
66
 
88
67
  List of modules
89
68
  -------
@@ -101,6 +80,9 @@ List of modules
101
80
  * **lattice_parameters.py** Estimation of lattice parameters for various lattice types using covalent/ionic radii.
102
81
  * **distorter.py** A collection of functions for enumerating and then
103
82
  substituting on inequivalent sites of a sub-lattice.
83
+ * **oxidation_states.py**: Used for predicting the likelihood of species coexisting in a compound based on a statistical model.
84
+ * **structure_prediction**: A submodule which contains a collection of tools for facilitating crystal structure predictions via ionic substitutions
85
+ * **dopant_prediction**: A submodule which contains a collections of tools for predicting n-type and p-type dopants.
104
86
 
105
87
  Requirements
106
88
  ------------
@@ -115,6 +97,12 @@ The latest stable release of SMACT can be installed via pip which will automatic
115
97
 
116
98
  pip install smact
117
99
 
100
+ SMACT is also available via conda through the conda-forge channel on Anaconda Cloud:
101
+
102
+ ```
103
+ conda install -c conda-forge smact
104
+ ```
105
+
118
106
  Alternatively, the very latest version can be installed using:
119
107
 
120
108
  pip install git+git://github.com/WMD-group/SMACT.git
@@ -1,3 +1,35 @@
1
+ Metadata-Version: 2.1
2
+ Name: SMACT
3
+ Version: 2.5.4
4
+ Summary: Semiconducting Materials by Analogy and Chemical Theory
5
+ Home-page: https://github.com/WMD-group/SMACT
6
+ Author: Daniel W. Davies
7
+ Author-email: d.w.davies@imperial.ac.uk
8
+ Maintainer: Anthony O. Onwuli
9
+ Maintainer-email: anthony.onwuli16@imperial.ac.uk
10
+ License: MIT
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.8
13
+ Classifier: Programming Language :: Python :: 3.9
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Development Status :: 5 - Production/Stable
17
+ Classifier: Intended Audience :: Science/Research
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: License :: OSI Approved :: MIT License
20
+ Classifier: Topic :: Scientific/Engineering
21
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
22
+ Requires-Python: >=3.8
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: scipy
26
+ Requires-Dist: numpy
27
+ Requires-Dist: spglib
28
+ Requires-Dist: pymatgen
29
+ Requires-Dist: ase
30
+ Requires-Dist: pandas
31
+ Requires-Dist: pathos
32
+
1
33
  [![DOI](http://joss.theoj.org/papers/10.21105/joss.01361/status.svg)](https://doi.org/10.21105/joss.01361)
2
34
  [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.5553202.svg)](https://doi.org/10.5281/zenodo.5553202)
3
35
  [![Documentation Status](https://readthedocs.org/projects/smact/badge/?version=latest)](http://smact.readthedocs.org/en/latest/?badge=latest)
@@ -5,6 +37,7 @@
5
37
  ![python version](https://img.shields.io/pypi/pyversions/smact)
6
38
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
7
39
  [![PyPi](https://img.shields.io/pypi/v/smact)](https://pypi.org/project/SMACT/)
40
+ [![Conda](https://anaconda.org/conda-forge/smact/badges/version.svg)](https://anaconda.org/conda-forge/smact)
8
41
  [![GitHub issues](https://img.shields.io/github/issues-raw/WMD-Group/SMACT)](https://github.com/WMD-group/SMACT/issues)
9
42
  ![dependencies](https://img.shields.io/librariesio/release/pypi/smact)
10
43
  [![CI Status](https://github.com/WMD-group/SMACT/actions/workflows/ci.yml/badge.svg)](https://github.com/WMD-group/SMACT/actions/workflows/ci.yml)
@@ -59,7 +92,9 @@ Code features
59
92
  - The code also has some tools for manipulating common crystal lattice types:
60
93
  - Common crystal structure types can be built using the [builder module](https://smact.readthedocs.io/en/latest/smact.builder.html)
61
94
  - Lattice parameters can be quickly estimated using ionic radii of the elements for various common crystal structure types using the [lattice_parameters module](https://smact.readthedocs.io/en/latest/smact.lattice_parameters.html).
62
- - The [lattice module](https://smact.readthedocs.io/en/latest/smact.lattice.html) and [distorter module](https://smact.readthedocs.io/en/latest/smact.distorter.html) rely on the [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) and can be used to generate unique atomic substitutions on a given crystal structure.
95
+ - The [lattice module](https://smact.readthedocs.io/en/latest/smact.lattice.html) and [distorter module](https://smact.readthedocs.io/en/latest/smact.distorter.html) rely on the [Atomic Simulation Environment](https://wiki.fysik.dtu.dk/ase/) and can be used to generate unique atomic substitutions on a given crystal structure.
96
+ - The [structure prediction](https://smact.readthedocs.io/en/latest/smact.structure_prediction.html) module can be used to predict the structure of hypothetical compositions using species similarity measures.
97
+ - The [dopant prediction](https://smact.readthedocs.io/en/latest/smact.dopant_prediction.html) module can be used to facilitate high-throughput predictions of p-type and n-type dopants of multicomponent solids.
63
98
 
64
99
  List of modules
65
100
  -------
@@ -77,6 +112,9 @@ List of modules
77
112
  * **lattice_parameters.py** Estimation of lattice parameters for various lattice types using covalent/ionic radii.
78
113
  * **distorter.py** A collection of functions for enumerating and then
79
114
  substituting on inequivalent sites of a sub-lattice.
115
+ * **oxidation_states.py**: Used for predicting the likelihood of species coexisting in a compound based on a statistical model.
116
+ * **structure_prediction**: A submodule which contains a collection of tools for facilitating crystal structure predictions via ionic substitutions
117
+ * **dopant_prediction**: A submodule which contains a collections of tools for predicting n-type and p-type dopants.
80
118
 
81
119
  Requirements
82
120
  ------------
@@ -91,6 +129,12 @@ The latest stable release of SMACT can be installed via pip which will automatic
91
129
 
92
130
  pip install smact
93
131
 
132
+ SMACT is also available via conda through the conda-forge channel on Anaconda Cloud:
133
+
134
+ ```
135
+ conda install -c conda-forge smact
136
+ ```
137
+
94
138
  Alternatively, the very latest version can be installed using:
95
139
 
96
140
  pip install git+git://github.com/WMD-group/SMACT.git
@@ -5,10 +5,10 @@ __author_email__ = "d.w.davies@imperial.ac.uk"
5
5
  __copyright__ = (
6
6
  "Copyright Daniel W. Davies, Adam J. Jackson, Keith T. Butler (2019)"
7
7
  )
8
- __version__ = "2.5.2"
8
+ __version__ = "2.5.4"
9
9
  __maintainer__ = "Anthony O. Onwuli"
10
10
  __maintaier_email__ = "anthony.onwuli16@imperial.ac.uk"
11
- __date__ = "July 13 2023"
11
+ __date__ = "November 30 2023"
12
12
 
13
13
  import os
14
14
  import unittest
@@ -61,6 +61,7 @@ if __name__ == "__main__":
61
61
  "Programming Language :: Python :: 3.8",
62
62
  "Programming Language :: Python :: 3.9",
63
63
  "Programming Language :: Python :: 3.10",
64
+ "Programming Language :: Python :: 3.11",
64
65
  "Development Status :: 5 - Production/Stable",
65
66
  "Intended Audience :: Science/Research",
66
67
  "Operating System :: OS Independent",
@@ -59,6 +59,8 @@ class Element:
59
59
 
60
60
  Element.oxidation_states_wiki (list): List of oxidation states that appear wikipedia (https://en.wikipedia.org/wiki/Template:List_of_oxidation_states_of_the_elements) Data retrieved: 2022-09-22
61
61
 
62
+ Element.oxidation_states_custom (list | None ): List of oxidation states that appear in the custom data file supplied (if any)
63
+
62
64
  Element.coord_envs (list): The allowed coordination enviroments for the ion
63
65
 
64
66
  Element.covalent_radius (float) : Covalent radius of the element
@@ -77,15 +79,35 @@ class Element:
77
79
 
78
80
  """
79
81
 
80
- def __init__(self, symbol: str):
82
+ def __init__(
83
+ self, symbol: str, oxi_states_custom_filepath: Optional[str] = None
84
+ ):
81
85
  """Initialise Element class
82
86
 
83
87
  Args:
84
88
  symbol (str): Chemical element symbol (e.g. 'Fe')
89
+ oxi_states_custom_filepath (str): Path to custom oxidation states file
85
90
 
86
91
  """
92
+ # Get the oxidation states from the custom file if it exists
93
+ if oxi_states_custom_filepath:
94
+ try:
95
+ self._oxidation_states_custom = (
96
+ data_loader.lookup_element_oxidation_states_custom(
97
+ symbol, oxi_states_custom_filepath
98
+ )
99
+ )
100
+ self.oxidation_states_custom = self._oxidation_states_custom
101
+ except TypeError:
102
+ warnings.warn(
103
+ "Custom oxidation states file not found. Please check the file path."
104
+ )
105
+ self.oxidation_states_custom = None
106
+ else:
107
+ self.oxidation_states_custom = None
108
+ self.symbol = symbol
87
109
 
88
- dataset = data_loader.lookup_element_data(symbol, copy=False)
110
+ dataset = data_loader.lookup_element_data(self.symbol, copy=False)
89
111
 
90
112
  if dataset == None:
91
113
  raise NameError(f"Elemental data for {symbol} not found.")
@@ -307,7 +329,10 @@ def ordered_elements(x: int, y: int) -> List[str]:
307
329
  return ordered_elements
308
330
 
309
331
 
310
- def element_dictionary(elements: Optional[Iterable[str]] = None):
332
+ def element_dictionary(
333
+ elements: Optional[Iterable[str]] = None,
334
+ oxi_states_custom_filepath: Optional[str] = None,
335
+ ):
311
336
  """
312
337
  Create a dictionary of initialised smact.Element objects
313
338
 
@@ -317,13 +342,22 @@ def element_dictionary(elements: Optional[Iterable[str]] = None):
317
342
  Args:
318
343
  elements (iterable of strings) : Elements to include. If None,
319
344
  use all elements up to 103.
345
+ oxi_states_custom_filepath (str): Path to custom oxidation states file
346
+
347
+
320
348
  Returns:
321
349
  dict: Dictionary with element symbols as keys and smact.Element
322
350
  objects as data
323
351
  """
324
352
  if elements == None:
325
353
  elements = ordered_elements(1, 103)
326
- return {symbol: Element(symbol) for symbol in elements}
354
+ if oxi_states_custom_filepath:
355
+ return {
356
+ symbol: Element(symbol, oxi_states_custom_filepath)
357
+ for symbol in elements
358
+ }
359
+ else:
360
+ return {symbol: Element(symbol) for symbol in elements}
327
361
 
328
362
 
329
363
  def are_eq(A: list, B: list, tolerance: float = 1e-4):
@@ -97,7 +97,7 @@ Kr Krypton 36 83.7980000000 1.16 None -13.00 -26.50 1
97
97
  Rb Rubidium 37 85.4678000000 2.20 0.485916 None -3.94 9.00e+01 0.82 4.177128 316.20
98
98
  Sr Strontium 38 87.6200000000 1.95 0.05206 None -5.00 3.70e+02 0.95 5.69486720 190.82
99
99
  Y Yttrium 39 88.9058400000 1.90 0.307 None -5.53 3.30e+01 1.22 6.21726 153.00
100
- Zr Zirconium 40 91.2240000000 1.75 0.426 None None 1.65e+02 0.33 6.63390 121.00
100
+ Zr Zirconium 40 91.2240000000 1.75 0.426 None None 1.65e+02 1.33 6.63390 121.00
101
101
  Nb Niobium 41 92.9063700000 1.64 0.893 None None 2.20e+02 1.6 6.75885 106.00
102
102
  Mo Molybdenum 42 95.9500000000 1.54 0.7472 None None 1.20e+00 2.16 7.09243 72.50
103
103
  Tc Technetium 43 98.0000000000 1.47 0.55 None None None 2.10 7.11938 80.40
@@ -269,6 +269,59 @@ def lookup_element_oxidation_states_wiki(symbol, copy=True):
269
269
  return None
270
270
 
271
271
 
272
+ _el_ox_states_custom = None
273
+
274
+
275
+ def lookup_element_oxidation_states_custom(symbol, filepath, copy=True):
276
+ """
277
+ Retrieve a list of known oxidation states for an element.
278
+ The oxidation states list is specified by the user in a text file.
279
+
280
+ Args:
281
+ symbol (str) : the atomic symbol of the element to look up.
282
+ copy (Optional(bool)): if True (default), return a copy of the
283
+ oxidation-state list, rather than a reference to the cached
284
+ data -- only use copy=False in performance-sensitive code
285
+ and where the list will not be modified!
286
+
287
+ Returns:
288
+ list: List of known oxidation states for the element.
289
+
290
+ Return None if oxidation states for the Element were not
291
+ found in the external data.
292
+ """
293
+
294
+ global _el_ox_states_custom
295
+
296
+ if _el_ox_states_custom is None:
297
+ _el_ox_states_custom = {}
298
+
299
+ for items in _get_data_rows(filepath):
300
+ _el_ox_states_custom[items[0]] = [
301
+ int(oxidationState) for oxidationState in items[1:]
302
+ ]
303
+
304
+ if symbol in _el_ox_states_custom:
305
+ if copy:
306
+ # _el_ox_states_custom stores lists -> if copy is set, make an implicit
307
+ # deep copy. The elements of the lists are integers, which are
308
+ # "value types" in Python.
309
+
310
+ return [
311
+ oxidationState
312
+ for oxidationState in _el_ox_states_custom[symbol]
313
+ ]
314
+ else:
315
+ return _el_ox_states_custom[symbol]
316
+ else:
317
+ if _print_warnings:
318
+ print(
319
+ "WARNING: Oxidation states for element {} "
320
+ "not found.".format(symbol)
321
+ )
322
+ return None
323
+
324
+
272
325
  # Loader and cache for the element HHI scores.
273
326
 
274
327
  _element_hhis = None
@@ -367,9 +420,7 @@ def lookup_element_data(symbol, copy=True):
367
420
  # or, if not clearly a number, to None
368
421
  clean_items = items[0:2] + list(map(float_or_None, items[2:]))
369
422
 
370
- _element_data.update(
371
- {items[0]: dict(list(zip(keys, clean_items)))}
372
- )
423
+ _element_data.update({items[0]: dict(list(zip(keys, clean_items)))})
373
424
 
374
425
  if symbol in _element_data:
375
426
  if copy:
@@ -384,9 +435,7 @@ def lookup_element_data(symbol, copy=True):
384
435
  return _element_data[symbol]
385
436
  else:
386
437
  if _print_warnings:
387
- print(
388
- "WARNING: Elemental data for {}" " not found.".format(symbol)
389
- )
438
+ print("WARNING: Elemental data for {}" " not found.".format(symbol))
390
439
  print(_element_data)
391
440
  return None
392
441
 
@@ -471,9 +520,7 @@ def lookup_element_shannon_radius_data(symbol, copy=True):
471
520
  # function on each element.
472
521
  # The dictionary values are all Python "value types", so
473
522
  # nothing further is required to make a deep copy.
474
- return [
475
- item.copy() for item in _element_shannon_radii_data[symbol]
476
- ]
523
+ return [item.copy() for item in _element_shannon_radii_data[symbol]]
477
524
  else:
478
525
  return _element_shannon_radii_data[symbol]
479
526
  else:
@@ -0,0 +1,212 @@
1
+ from typing import List, Tuple
2
+
3
+ from pymatgen.util import plotting
4
+
5
+ import smact
6
+ from smact.structure_prediction import mutation, utilities
7
+
8
+
9
+ class Doper:
10
+ """
11
+ A class to search for n & p type dopants
12
+ Methods: get_dopants, plot_dopants
13
+
14
+ Attributes:
15
+ _original_species: A tuple which describes the constituent species of a material. For example:
16
+
17
+ >>> test= Doper(("Zn2+","S2-"))
18
+ >>> test.original_species
19
+ ('Zn2+','S2-')
20
+
21
+ """
22
+
23
+ def __init__(
24
+ self, _original_species: Tuple[str, ...], filepath: str = None
25
+ ):
26
+ """
27
+ Intialise the `Doper` class with a tuple of species
28
+
29
+ Args:
30
+ _original_species: See :class:`~.Doper`.
31
+ filepath (str): lambda table json file
32
+
33
+ """
34
+ self._original_species = _original_species
35
+ self._filepath = filepath
36
+
37
+ @property
38
+ def original_species(self):
39
+ return self._original_species
40
+
41
+ @original_species.setter
42
+ def original_species(self, original_species):
43
+ self._original_species = original_species
44
+
45
+ @property
46
+ def filepath(self):
47
+ return self._filepath
48
+
49
+ @filepath.setter
50
+ def filepath(self, filepath):
51
+ self._filepath = filepath
52
+
53
+ def _get_cation_dopants(
54
+ self, element_objects: List[smact.Element], cations: List[str]
55
+ ):
56
+ poss_n_type_cat = set()
57
+ poss_p_type_cat = set()
58
+
59
+ for element in element_objects:
60
+ # [-2, -1, 0, +1, +2]
61
+ oxi_state = element.oxidation_states
62
+ el_symbol = element.symbol
63
+ for state in oxi_state:
64
+ for cation in cations:
65
+ ele = utilities.unparse_spec((el_symbol, state))
66
+ _, charge = utilities.parse_spec(cation)
67
+ if state > charge:
68
+ poss_n_type_cat.add(ele)
69
+ elif state < charge and state > 0:
70
+ poss_p_type_cat.add(ele)
71
+
72
+ return list(poss_n_type_cat), list(poss_p_type_cat)
73
+
74
+ def _get_anion_dopants(
75
+ self, element_objects: List[smact.Element], anions: List[str]
76
+ ):
77
+ poss_n_type_an = set()
78
+ poss_p_type_an = set()
79
+
80
+ for element in element_objects:
81
+ oxi_state = element.oxidation_states
82
+ el_symbol = element.symbol
83
+ for state in oxi_state:
84
+ for anion in anions:
85
+ ele = utilities.unparse_spec((el_symbol, state))
86
+ _, charge = utilities.parse_spec(anion)
87
+ if state > charge and state < 0:
88
+ poss_n_type_an.add(ele)
89
+ elif state < charge:
90
+ poss_p_type_an.add(ele)
91
+ return list(poss_n_type_an), list(poss_p_type_an)
92
+
93
+ def get_dopants(
94
+ self,
95
+ num_dopants: int = 5,
96
+ ) -> dict:
97
+ """
98
+ Args:
99
+ num_dopants (int): The number of suggestions to return for n- and p-type dopants.
100
+ Returns:
101
+ (dict): Dopant suggestions, given as a dictionary with keys
102
+ "n_type_cation", "p_type_cation", "n_type_anion", "p_type_anion".
103
+
104
+ Examples:
105
+ >>> test = Doper(('Ti4+','O2-'))
106
+ >>> print(test.get_dopants(num_dopants=2))
107
+ {'n-type cation substitutions': [('Ta5+', 8.790371775858281e-05),
108
+ ('Nb5+', 7.830035204694342e-05)],
109
+ 'p-type cation substitutions': [('Na1+', 0.00010060400812977031),
110
+ ('Zn2+', 8.56373996146833e-05)],
111
+ 'n-type anion substitutions': [('F1-', 0.01508116810515677),
112
+ ('Cl1-', 0.004737202729901607)],
113
+ 'p-type anion substitutions': [('N3-', 0.0014663800608945628),
114
+ ('C4-', 9.31310255126729e-08)]}
115
+ """
116
+
117
+ cations = []
118
+ anions = []
119
+ try:
120
+ for ion in self._original_species:
121
+ _, charge = utilities.parse_spec(ion)
122
+ if charge > 0:
123
+ cations.append(ion)
124
+ elif charge < 0:
125
+ anions.append(ion)
126
+ except Exception as e:
127
+ print(f"{e}: charge is not defined for {ion}!")
128
+
129
+ CM = mutation.CationMutator.from_json(self._filepath)
130
+
131
+ # call all elements
132
+ element_objects = list(smact.element_dictionary().values())
133
+
134
+ poss_n_type_cat, poss_p_type_cat = self._get_cation_dopants(
135
+ element_objects, cations
136
+ )
137
+ poss_n_type_an, poss_p_type_an = self._get_anion_dopants(
138
+ element_objects, anions
139
+ )
140
+
141
+ n_type_cat, p_type_cat, n_type_an, p_type_an = [], [], [], []
142
+ for cation in cations:
143
+ cation_charge = utilities.parse_spec(cation)[1]
144
+ for n_specie in poss_n_type_cat:
145
+ n_specie_charge = utilities.parse_spec(n_specie)[1]
146
+ if cation_charge >= n_specie_charge:
147
+ continue
148
+ n_type_cat.append(
149
+ (n_specie, cation, CM.sub_prob(cation, n_specie))
150
+ )
151
+ for p_specie in poss_p_type_cat:
152
+ p_specie_charge = utilities.parse_spec(p_specie)[1]
153
+ if cation_charge <= p_specie_charge:
154
+ continue
155
+ p_type_cat.append(
156
+ (p_specie, cation, CM.sub_prob(cation, p_specie))
157
+ )
158
+
159
+ for anion in anions:
160
+ anion_charge = utilities.parse_spec(anion)[1]
161
+ for n_specie in poss_n_type_an:
162
+ n_specie_charge = utilities.parse_spec(n_specie)[1]
163
+ if anion == n_specie or anion_charge >= n_specie_charge:
164
+ continue
165
+ n_type_an.append(
166
+ (n_specie, anion, CM.sub_prob(anion, n_specie))
167
+ )
168
+ for p_specie in poss_p_type_an:
169
+ p_specie_charge = utilities.parse_spec(p_specie)[1]
170
+ if anion == p_specie or anion_charge <= p_specie_charge:
171
+ continue
172
+ p_type_an.append(
173
+ (p_specie, anion, CM.sub_prob(anion, p_specie))
174
+ )
175
+
176
+ # [('B3+', 0.003), ('C4+', 0.001), (), (), ...] : list(tuple(str, float))
177
+ # sort by probability
178
+ n_type_cat.sort(key=lambda x: x[-1], reverse=True)
179
+ p_type_cat.sort(key=lambda x: x[-1], reverse=True)
180
+ n_type_an.sort(key=lambda x: x[-1], reverse=True)
181
+ p_type_an.sort(key=lambda x: x[-1], reverse=True)
182
+
183
+ self.results = {
184
+ "n-type cation substitutions": n_type_cat[:num_dopants],
185
+ "p-type cation substitutions": p_type_cat[:num_dopants],
186
+ "n-type anion substitutions": n_type_an[:num_dopants],
187
+ "p-type anion substitutions": p_type_an[:num_dopants],
188
+ }
189
+ # return the top (num_dopants) results for each case
190
+ return self.results
191
+
192
+ def plot_dopants(self) -> None:
193
+ """
194
+ Uses pymatgen plotting utilities to plot the results of doping search
195
+ Args:
196
+ None
197
+ Returns:
198
+ None
199
+ """
200
+ try:
201
+ for val in self.results.values():
202
+ dict_results = {
203
+ utilities.parse_spec(x)[0]: y for x, _, y in val
204
+ }
205
+ plotting.periodic_table_heatmap(
206
+ elemental_data=dict_results,
207
+ cmap="rainbow",
208
+ blank_color="gainsboro",
209
+ edge_color="white",
210
+ )
211
+ except AttributeError as e:
212
+ print(f"Dopants are not calculated. Run get_dopants first.")
@@ -1,10 +1,14 @@
1
1
  import itertools
2
+ import os
2
3
  import warnings
3
4
  from collections import namedtuple
4
5
  from itertools import combinations
5
6
  from typing import Iterable, List, Optional, Tuple, Union
6
7
 
7
8
  from smact import Element, neutral_ratios
9
+ from smact.data_loader import (
10
+ lookup_element_oxidation_states_custom as oxi_custom,
11
+ )
8
12
 
9
13
  # Use named tuple to improve readability of smact_filter outputs
10
14
  _allowed_compositions = namedtuple(
@@ -324,7 +328,7 @@ def smact_filter(
324
328
  threshold (int): Threshold for stoichiometry limit, default = 8
325
329
  stoichs (list[int]): A selection of valid stoichiometric ratios for each site.
326
330
  species_unique (bool): Whether or not to consider elements in different oxidation states as unique in the results.
327
- oxidation_states_set (string): A string to choose which set of oxidation states should be chosen. Options are 'default', 'icsd', 'pymatgen' and 'wiki' for the default, icsd, pymatgen structure predictor and Wikipedia (https://en.wikipedia.org/wiki/Template:List_of_oxidation_states_of_the_elements) oxidation states respectively.
331
+ oxidation_states_set (string): A string to choose which set of oxidation states should be chosen. Options are 'default', 'icsd', 'pymatgen' and 'wiki' for the default, icsd, pymatgen structure predictor and Wikipedia (https://en.wikipedia.org/wiki/Template:List_of_oxidation_states_of_the_elements) oxidation states respectively. A filepath to an oxidation states text file can also be supplied as well.
328
332
  comp_tuple (bool): Whether or not to return the results as a named tuple of elements and stoichiometries (True) or as a normal tuple of elements and stoichiometries (False).
329
333
  Returns:
330
334
  allowed_comps (list): Allowed compositions for that chemical system
@@ -371,10 +375,12 @@ def smact_filter(
371
375
  }
372
376
  if oxidation_states_set in oxi_set:
373
377
  ox_combos = oxi_set[oxidation_states_set]
378
+ elif os.path.exists(oxidation_states_set):
379
+ ox_combos = [oxi_custom(e.symbol, oxidation_states_set) for e in els]
374
380
  else:
375
381
  raise (
376
382
  Exception(
377
- f'{oxidation_states_set} is not valid. Enter either "default", "icsd", "pymatgen" or "wiki" for oxidation_states_set.'
383
+ f'{oxidation_states_set} is not valid. Enter either "default", "icsd", "pymatgen","wiki" or a filepath to a textfile of oxidation states.'
378
384
  )
379
385
  )
380
386
  if oxidation_states_set == "wiki":
@@ -202,9 +202,7 @@ class StructureDB:
202
202
 
203
203
  return num
204
204
 
205
- def get_structs(
206
- self, composition: str, table: str
207
- ) -> List[SmactStructure]:
205
+ def get_structs(self, composition: str, table: str) -> List[SmactStructure]:
208
206
  """Get SmactStructures for a given composition.
209
207
 
210
208
  Args:
@@ -373,8 +373,7 @@ class CationMutator:
373
373
  def cond_sub_prob(self, s1: str, s2: str) -> float:
374
374
  """Calculate the probability of substitution of one species with another."""
375
375
  return (
376
- np.exp(self.get_lambda(s1, s2))
377
- / np.exp(self.get_lambdas(s2)).sum()
376
+ np.exp(self.get_lambda(s1, s2)) / np.exp(self.get_lambdas(s2)).sum()
378
377
  )
379
378
 
380
379
  def cond_sub_probs(self, s1: str) -> pd.Series:
@@ -183,8 +183,7 @@ class StructurePredictor:
183
183
  sub_species = list(map(list, sub_species))
184
184
 
185
185
  potential_nary_parents: List[List[SmactStructure]] = list(
186
- self.db.get_with_species(specs, self.table)
187
- for specs in sub_species
186
+ self.db.get_with_species(specs, self.table) for specs in sub_species
188
187
  )
189
188
 
190
189
  for spec_idx, parents in enumerate(potential_nary_parents):
@@ -274,9 +274,12 @@ class SmactStructure:
274
274
  )
275
275
  struct = oxi_transform.apply_transformation(structure)
276
276
  print("Oxidation states assigned based on ICSD statistics")
277
+ elif determine_oxi == "predecorated":
278
+ struct = structure
279
+
277
280
  else:
278
281
  raise ValueError(
279
- f"Argument for 'determine_oxi', <{determine_oxi}> is not valid. Choose either 'BV','comp_ICSD' or 'both'."
282
+ f"Argument for 'determine_oxi', <{determine_oxi}> is not valid. Choose either 'BV','comp_ICSD','both' or 'predecorated'."
280
283
  )
281
284
 
282
285
  sites, species = SmactStructure.__parse_py_sites(struct)
@@ -433,10 +436,7 @@ class SmactStructure:
433
436
  lattice_param = float(lines[1])
434
437
 
435
438
  lattice = np.array(
436
- [
437
- [float(point) for point in line.split(" ")]
438
- for line in lines[2:5]
439
- ]
439
+ [[float(point) for point in line.split(" ")] for line in lines[2:5]]
440
440
  )
441
441
 
442
442
  sites = defaultdict(list)
@@ -15,12 +15,17 @@ from smact import Species
15
15
  from smact.builder import wurtzite
16
16
  from smact.properties import band_gap_Harrison, compound_electroneg
17
17
 
18
+ files_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), "files")
19
+ TEST_OX_STATES = os.path.join(files_dir, "test_oxidation_states.txt")
20
+
18
21
 
19
22
  class TestSequenceFunctions(unittest.TestCase):
20
23
  # ---------------- TOP-LEVEL ----------------
21
24
 
22
25
  def test_Element_class_Pt(self):
23
- Pt = smact.Element("Pt")
26
+ Pt = smact.Element(
27
+ "Pt",
28
+ )
24
29
  self.assertEqual(Pt.name, "Platinum")
25
30
  self.assertEqual(Pt.ionpot, 8.95883)
26
31
  self.assertEqual(Pt.number, 78)
@@ -34,9 +39,10 @@ class TestSequenceFunctions(unittest.TestCase):
34
39
 
35
40
  def test_element_dictionary(self):
36
41
  newlist = ["O", "Rb", "W"]
37
- dictionary = smact.element_dictionary(newlist)
42
+ dictionary = smact.element_dictionary(newlist, TEST_OX_STATES)
38
43
  self.assertEqual(dictionary["O"].crustal_abundance, 461000.0)
39
44
  self.assertEqual(dictionary["Rb"].oxidation_states, [-1, 1])
45
+ self.assertEqual(dictionary["Rb"].oxidation_states_custom, [-1, 1])
40
46
  self.assertEqual(dictionary["W"].name, "Tungsten")
41
47
  self.assertTrue("Rn" in smact.element_dictionary())
42
48
 
@@ -46,9 +52,7 @@ class TestSequenceFunctions(unittest.TestCase):
46
52
  [1.00, 2.00, 3.00], [1.001, 1.999, 3.00], tolerance=1e-2
47
53
  )
48
54
  )
49
- self.assertFalse(
50
- smact.are_eq([1.00, 2.00, 3.00], [1.001, 1.999, 3.00])
51
- )
55
+ self.assertFalse(smact.are_eq([1.00, 2.00, 3.00], [1.001, 1.999, 3.00]))
52
56
 
53
57
  def test_gcd_recursive(self):
54
58
  self.assertEqual(smact._gcd_recursive(4, 12, 10, 32), 2)
@@ -346,6 +350,12 @@ class TestSequenceFunctions(unittest.TestCase):
346
350
  (("Na", "Fe", "Cl"), (1, 1, -1), (1, 1, 2)),
347
351
  ],
348
352
  )
353
+ self.assertEqual(
354
+ result,
355
+ smact.screening.smact_filter(
356
+ [Na, Fe, Cl], threshold=2, oxidation_states_set=TEST_OX_STATES
357
+ ),
358
+ )
349
359
  result_comp_tuple = smact.screening.smact_filter(
350
360
  [Na, Fe, Cl], threshold=2, comp_tuple=True
351
361
  )
@@ -363,9 +363,7 @@ class CationMutatorTest(unittest.TestCase):
363
363
  """Set up the test initial structure and mutator."""
364
364
  cls.test_struct = SmactStructure.from_file(TEST_POSCAR)
365
365
 
366
- cls.test_mutator = CationMutator.from_json(
367
- lambda_json=TEST_LAMBDA_JSON
368
- )
366
+ cls.test_mutator = CationMutator.from_json(lambda_json=TEST_LAMBDA_JSON)
369
367
  cls.test_pymatgen_mutator = CationMutator.from_json(
370
368
  lambda_json=None, alpha=lambda x, y: -5
371
369
  )
@@ -1,186 +0,0 @@
1
- ### This Jupyter notebook creates ntype ptype possiblie dopants for input species
2
- ### using SMACT structure prediction
3
- ### Working with Kieth from SCIML and Anthony
4
-
5
- ###Doper ver 2
6
-
7
- # Now 'Doper' can generate possible n-type p-type dopants for multicomponent materials (i.e. Ternary, Quaternary etc).
8
- # Can plot the result of doping search within a single step
9
- # """ex) test= Doper(('Cu1+','Zn2+','Ge4+','S2-'))
10
- # test.get_dopants(num_dopants = 10, plot_heatmap = True)"""
11
-
12
-
13
- from typing import List, Tuple
14
-
15
- from pymatgen.util import plotting
16
-
17
- import smact
18
- from smact.structure_prediction import mutation, utilities
19
-
20
-
21
- class Doper:
22
- """
23
- A class to search for n & p type dopants
24
- Methods: get_dopants, plot_dopants
25
-
26
- Attributes:
27
- original_species: A tuple which describes the constituent species of a material. For example:
28
-
29
- >>> test= Doper(('Cu1+','Zn2+','Ge4+','S2-'))
30
- >>> test.original_species
31
- ('Cu1+','Zn2+','Ge4+','S2-')
32
-
33
- """
34
-
35
- def __init__(self, original_species: Tuple[str, ...]):
36
- """
37
- Intialise the `Doper` class with a tuple of species
38
-
39
- Args:
40
- original_species: See :class:`~.Doper`.
41
-
42
- """
43
- self.original_species = original_species
44
-
45
- def _get_cation_dopants(
46
- self, element_objects: List[smact.Element], cations: List[str]
47
- ):
48
- poss_n_type_cat = []
49
- poss_p_type_cat = []
50
-
51
- for element in element_objects:
52
- # [-2, -1, 0, +1, +2]
53
- oxi_state = element.oxidation_states
54
- el_symbol = element.symbol
55
- for state in oxi_state:
56
- for cation in cations:
57
- _, charge = utilities.parse_spec(cation)
58
- if state > charge:
59
- poss_n_type_cat.append(
60
- utilities.unparse_spec((el_symbol, state))
61
- )
62
- elif state < charge and state > 0:
63
- poss_p_type_cat.append(
64
- utilities.unparse_spec((el_symbol, state))
65
- )
66
-
67
- return poss_n_type_cat, poss_p_type_cat
68
-
69
- def _get_anion_dopants(
70
- self, element_objects: List[smact.Element], anions: List[str]
71
- ):
72
- poss_n_type_an = []
73
- poss_p_type_an = []
74
-
75
- for element in element_objects:
76
- oxi_state = element.oxidation_states
77
- el_symbol = element.symbol
78
- for state in oxi_state:
79
- for anion in anions:
80
- _, charge = utilities.parse_spec(anion)
81
- if state > charge and state < 0:
82
- poss_n_type_an.append(
83
- utilities.unparse_spec((el_symbol, state))
84
- )
85
- elif state < charge:
86
- poss_p_type_an.append(
87
- utilities.unparse_spec((el_symbol, state))
88
- )
89
- return poss_n_type_an, poss_p_type_an
90
-
91
- def _plot_dopants(self, results: dict):
92
- """
93
- Uses pymatgen plotting utilities to plot the results of doping search
94
- """
95
- for key, val in results.items():
96
- dict_results = {utilities.parse_spec(x)[0]: y for x, y in val}
97
- plotting.periodic_table_heatmap(
98
- elemental_data=dict_results,
99
- cmap="rainbow",
100
- blank_color="gainsboro",
101
- edge_color="white",
102
- )
103
-
104
- def get_dopants(
105
- self,
106
- num_dopants: int = 5,
107
- plot_heatmap: bool = False,
108
- ) -> dict:
109
- """
110
- Args:
111
- num_dopants (int): The number of suggestions to return for n- and p-type dopants.
112
- plot_heatmap (bool): If True, the results of the doping search are plotted as heatmaps
113
-
114
- Returns:
115
- (dict): Dopant suggestions, given as a dictionary with keys
116
- "n_type_cation", "p_type_cation", "n_type_anion", "p_type_anion".
117
-
118
- Examples:
119
- >>> test = Doper(('Ti4+','O2-'))
120
- >>> print(test.get_dopants(num_dopants=2))
121
- {'n-type cation substitutions': [('Ta5+', 8.790371775858281e-05),
122
- ('Nb5+', 7.830035204694342e-05)],
123
- 'p-type cation substitutions': [('Na1+', 0.00010060400812977031),
124
- ('Zn2+', 8.56373996146833e-05)],
125
- 'n-type anion substitutions': [('F1-', 0.01508116810515677),
126
- ('Cl1-', 0.004737202729901607)],
127
- 'p-type anion substitutions': [('N3-', 0.0014663800608945628),
128
- ('C4-', 9.31310255126729e-08)]}
129
- """
130
-
131
- cations = []
132
- anions = []
133
- try:
134
- for ion in self.original_species:
135
- _, charge = utilities.parse_spec(ion)
136
- if charge > 0:
137
- cations.append(ion)
138
- elif charge < 0:
139
- anions.append(ion)
140
- except Exception as e:
141
- print(e, "charge is not defined")
142
-
143
- CM = mutation.CationMutator.from_json()
144
-
145
- # call all elements
146
- element_objects = list(smact.element_dictionary().values())
147
-
148
- poss_n_type_cat, poss_p_type_cat = self._get_cation_dopants(
149
- element_objects, cations
150
- )
151
- poss_n_type_an, poss_p_type_an = self._get_anion_dopants(
152
- element_objects, anions
153
- )
154
-
155
- n_type_cat, p_type_cat, n_type_an, p_type_an = [], [], [], []
156
- for cation in cations:
157
- for n_specie, p_specie in zip(poss_n_type_cat, poss_p_type_cat):
158
- n_type_cat.append((n_specie, CM.sub_prob(cation, n_specie)))
159
- p_type_cat.append((p_specie, CM.sub_prob(cation, p_specie)))
160
-
161
- for anion in anions:
162
- for n_specie, p_specie in zip(poss_n_type_an, poss_p_type_an):
163
- n_type_an.append((n_specie, CM.sub_prob(anion, n_specie)))
164
- p_type_an.append((p_specie, CM.sub_prob(anion, p_specie)))
165
-
166
- # [('B3+', 0.003), ('C4+', 0.001), (), (), ...] : list(tuple(str, float))
167
- # sort by probability
168
- n_type_cat.sort(key=lambda x: x[1], reverse=True)
169
- p_type_cat.sort(key=lambda x: x[1], reverse=True)
170
- n_type_an.sort(key=lambda x: x[1], reverse=True)
171
- p_type_an.sort(key=lambda x: x[1], reverse=True)
172
-
173
- results = {
174
- "n-type cation substitutions": n_type_cat[:num_dopants],
175
- "p-type cation substitutions": p_type_cat[:num_dopants],
176
- "n-type anion substitutions": n_type_an[:num_dopants],
177
- "p-type anion substitutions": p_type_an[:num_dopants],
178
- }
179
-
180
- # plot heatmap
181
-
182
- if plot_heatmap:
183
- self._plot_dopants(results)
184
-
185
- # return the top (num_dopants) results for each case
186
- return results
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes