Skip to content

Commit

Permalink
[ENH] Add atomic scattering factors (#174)
Browse files Browse the repository at this point in the history
* bump jupyterlab

* add atomic screening factors

* add atomic number

* add property metadata

* add docs
  • Loading branch information
lmmentel authored Aug 17, 2024
1 parent e287062 commit dfe91eb
Show file tree
Hide file tree
Showing 7 changed files with 362 additions and 23 deletions.
31 changes: 31 additions & 0 deletions alembic/versions/68c046f6983b_add_scattering_factors_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""add scattering factors table
Revision ID: 68c046f6983b
Revises: 7d745d77a7c1
Create Date: 2024-08-15 20:21:40.641912
"""

# revision identifiers, used by Alembic.
revision = '68c046f6983b'
down_revision = '7d745d77a7c1'
branch_labels = None
depends_on = None

from alembic import op
import sqlalchemy as sa


def upgrade():
op.create_table(
"scattering_factors",
sa.Column("id", sa.Integer, primary_key=True),
sa.Column("atomic_number", sa.Integer),
sa.Column("energy", sa.Float),
sa.Column("f1", sa.Float),
sa.Column("f2", sa.Float),
)


def downgrade():
op.drop_table("scattering_factors")
16 changes: 16 additions & 0 deletions docs/source/data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,22 @@ for compatibility. The table below provides explanations of the symbols.
| 24Ne | 24Ne | heavy cluster emission |
+---------+----------------------------+------------------------------------------------------------+


Atomic Scattering Factors
=========================

+-------------------+----------------------------------------------+------+--------------+-------------------------------------------------+
| Attribute name | Description | Unit | Value origin | Citation keys |
+===================+==============================================+======+==============+=================================================+
| ``atomic_number`` | Atomic number | | stored | :cite:`atomic_scattering_factors,henke1993xray` |
+-------------------+----------------------------------------------+------+--------------+-------------------------------------------------+
| ``energy`` | Energy of the incident photon | eV | stored | :cite:`atomic_scattering_factors,henke1993xray` |
+-------------------+----------------------------------------------+------+--------------+-------------------------------------------------+
| ``f1`` | Scattering factor f1 | | stored | :cite:`atomic_scattering_factors,henke1993xray` |
+-------------------+----------------------------------------------+------+--------------+-------------------------------------------------+
| ``f2`` | Scattering factor f2 | | stored | :cite:`atomic_scattering_factors,henke1993xray` |
+-------------------+----------------------------------------------+------+--------------+-------------------------------------------------+

.. rubric:: Data Footnotes

.. [#f_atomic_weight] **Atomic Weights**
Expand Down
17 changes: 17 additions & 0 deletions docs/source/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -857,3 +857,20 @@ @article{ParrPearson1983
url = {https://doi.org/10.1021/ja00364a005},
eprint = {https://doi.org/10.1021/ja00364a005}
}
@misc{atomic_scattering_factors,
title = {The atomic scattering factors (data files)},
author = {Henke, B.L},
howpublished = {\url{https://henke.lbl.gov/optical_constants/asf.html}},
note = {Accessed: 2024-08-15}
}
@article{henke1993xray,
title = {X-ray interactions: photoabsorption, scattering, transmission, and reflection at E=50-30000 eV, Z=1-92},
author = {Henke, B.L. and Gullikson, E.M. and Davis, J.C.},
journal = {Atomic Data and Nuclear Data Tables},
volume = {54},
number = {2},
pages = {181--342},
year = {1993},
month = {July},
publisher = {Elsevier}
}
Binary file modified mendeleev/elements.db
Binary file not shown.
27 changes: 27 additions & 0 deletions mendeleev/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,7 @@ class Element(Base):
ionic_radii = relationship("IonicRadius", lazy="subquery")
isotopes = relationship("Isotope", lazy="subquery", back_populates="element")
phase_transitions = relationship("PhaseTransition", lazy="subquery")
scattering_factors = relationship("ScatteringFactor", lazy="subquery")
screening_constants = relationship("ScreeningConstant", lazy="subquery")

@reconstructor
Expand Down Expand Up @@ -711,6 +712,7 @@ def __hash__(self) -> int:
"isotopes",
"screening_constants",
"phase_transitions",
"scattering_factors",
]
hashable = [(k, v) for k, v in self.__dict__.items() if k not in to_drop]
return hash(tuple(sorted(hashable)))
Expand Down Expand Up @@ -1181,3 +1183,28 @@ def __str__(self) -> str:

def __repr__(self) -> str:
return str(self)


class ScatteringFactor(Base):
"""Atomic scattering factors
Args:
atomic_number (int): Atomic number
energy (float): Energy in eV
f1 (float): Energy in eV
f1 (float): Energy in eV
"""

__tablename__ = "scattering_factors"

id = Column(Integer, primary_key=True)
atomic_number = Column(Integer, ForeignKey("elements.atomic_number"))
energy = Column(Float)
f1 = Column(Float)
f2 = Column(Float)

def __str__(self):
return f"Z={self.atomic_number} E={self.energy} f1={self.f1} f2={self.f2}"

def __repr__(self):
return str(self)
258 changes: 258 additions & 0 deletions notebooks/atomic-scattering-factors.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "1e1ca7ca-264b-429e-b7a9-ee31bd1e6e2e",
"metadata": {},
"source": [
"## Aromic scattering factors\n",
"\n",
"source: https://henke.lbl.gov/optical_constants/asf.html"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "eb146023-9199-4927-b15a-53aedc19902a",
"metadata": {},
"outputs": [],
"source": [
"from pathlib import Path\n",
"import pandas as pd\n",
"from mendeleev import element\n",
"from mendeleev.db import get_session\n",
"from mendeleev.models import ScatteringFactor, PropertyMetadata, ValueOrigin"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "8e3f5828-3b08-4947-bcf7-6ceefd97c8dd",
"metadata": {},
"outputs": [],
"source": [
"root = Path(\"../data/atomic-scattering-factors/\")"
]
},
{
"cell_type": "markdown",
"id": "6a7ca7c6-317e-488e-a566-f6cea3954531",
"metadata": {},
"source": [
"## Preprocess the files\n",
"\n",
"- some rows have traling tabs \"\\t\" that break parsing\n",
"- a few file start with a comment or non standard header - manually correct"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2f4a618d-364f-4e1b-9dc2-f24a54ac13cf",
"metadata": {},
"outputs": [],
"source": [
"proc = root.joinpath(\"preprocessed\")\n",
"proc.mkdir(exist_ok=True)\n",
"\n",
"for file in root.glob(\"*.nff\"):\n",
"\n",
" with file.open(\"r\") as fo:\n",
" lines = fo.readlines()\n",
" \n",
" with proc.joinpath(file.name).open(\"w\") as fo:\n",
" for line in lines:\n",
" fo.write(line.strip() + \"\\n\")"
]
},
{
"cell_type": "markdown",
"id": "810be02e-d7bd-4d51-947f-549f3e270a1d",
"metadata": {},
"source": [
"## Load the data into the db"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cbb5401d-7c1b-476e-aae0-d8381d3dad53",
"metadata": {},
"outputs": [],
"source": [
"session = get_session(read_only=False)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "27b8c7ec-7943-446c-ab63-17d3f418cfe5",
"metadata": {},
"outputs": [],
"source": [
"for file in proc.glob(\"*.nff\"):\n",
" e = element(file.stem.capitalize())\n",
" print(file.stem.capitalize(), e.atomic_number)\n",
" df = pd.read_csv(file, sep=\"\\t\", header=0, engine=\"python\", comment=\"#\")\n",
" print(df.columns)\n",
" for index, row in df.iterrows():\n",
" scattering_factor = ScatteringFactor(\n",
" atomic_number=e.atomic_number,\n",
" energy=row['E(eV)'],\n",
" f1=row['f1'],\n",
" f2=row['f2']\n",
" )\n",
" session.add(scattering_factor)\n",
" session.commit()"
]
},
{
"cell_type": "markdown",
"id": "89a898e9-e2ae-4eef-88c3-dab163a5dc7d",
"metadata": {},
"source": [
"## Test if the numbers of rows in the Scattering Factors table are the same as rows in the DF"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7c041915-a112-4880-832d-998ed2ad1cea",
"metadata": {},
"outputs": [],
"source": [
"for file in proc.glob(\"*.nff\"):\n",
" e = element(file.stem.capitalize())\n",
" print(file.stem.capitalize(), e.atomic_number)\n",
" df = pd.read_csv(file, sep=\"\\t\", header=0, engine=\"python\", comment=\"#\")\n",
" db_rows = session.query(ScatteringFactor).filter_by(atomic_number=e.atomic_number).count()\n",
" \n",
" if db_rows == df.shape[0]:\n",
" print(\"OK\")\n",
" else:\n",
" print(f\"ERROR {db_rows=} {df.shape[0]=}\")"
]
},
{
"cell_type": "markdown",
"id": "45576c65-5042-42a2-8890-48c34ecae2af",
"metadata": {},
"source": [
"## Create PropertyMetdata records"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "6a08f783-a63f-4ffe-b49c-1c26c21c7d04",
"metadata": {},
"outputs": [],
"source": [
"z = PropertyMetadata(\n",
" annotations=None,\n",
" attribute_name=\"atomic_number\",\n",
" category=\"electric and optical properties\",\n",
" citation_keys=\"atomic_scattering_factors,henke1993xray\",\n",
" table_name=\"scattering_factors\",\n",
" class_name=\"ScatteringFactor\",\n",
" column_name=\"atomic_number\",\n",
" description=\"Atomic number\",\n",
" unit=None,\n",
" value_origin=ValueOrigin.STORED,\n",
")\n",
"session.add(z)\n",
"session.commit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "dfb62a0f-65e6-4bd7-b459-87a8e252d130",
"metadata": {},
"outputs": [],
"source": [
"energy = PropertyMetadata(\n",
" annotations=\"specific data references available at cited data source\",\n",
" attribute_name=\"energy\",\n",
" category=\"electric and optical properties\",\n",
" citation_keys=\"atomic_scattering_factors,henke1993xray\",\n",
" table_name=\"scattering_factors\",\n",
" class_name=\"ScatteringFactor\",\n",
" column_name=\"energy\",\n",
" description=\"Energy of the incident photon\",\n",
" unit=\"eV\",\n",
" value_origin=ValueOrigin.STORED,\n",
")\n",
"session.add(energy)\n",
"session.commit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "af7a8a3a-cbca-4f62-a961-0d34ad729ce3",
"metadata": {},
"outputs": [],
"source": [
"f1 = PropertyMetadata(\n",
" annotations=\"specific data references available at cited data source\",\n",
" attribute_name=\"f1\",\n",
" category=\"electric and optical properties\",\n",
" citation_keys=\"atomic_scattering_factors,henke1993xray\",\n",
" table_name=\"scattering_factors\",\n",
" class_name=\"ScatteringFactor\",\n",
" column_name=\"f1\",\n",
" description=\"Scattering factor f1\",\n",
" unit=None,\n",
" value_origin=ValueOrigin.STORED,\n",
")\n",
"session.add(f1)\n",
"session.commit()"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ab8d29db-2bf8-4ea3-bf33-5ee81b55f3c8",
"metadata": {},
"outputs": [],
"source": [
"f2 = PropertyMetadata(\n",
" annotations=\"specific data references available at cited data source\",\n",
" attribute_name=\"f2\",\n",
" category=\"electric and optical properties\",\n",
" citation_keys=\"atomic_scattering_factors,henke1993xray\",\n",
" table_name=\"scattering_factors\",\n",
" class_name=\"ScatteringFactor\",\n",
" column_name=\"f2\",\n",
" description=\"Scattering factor f2\",\n",
" unit=None,\n",
" value_origin=ValueOrigin.STORED,\n",
")\n",
"session.add(f2)\n",
"session.commit()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3 (ipykernel)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Loading

0 comments on commit dfe91eb

Please sign in to comment.