Developer Reference
First off, please make sure you have read and understood our code of conduct. We expect everybody to adhere to it. You can find this project’s code of condact here.
To get started with developing, fork the github repository and clone it into a local directory. If this is your first time contributing to an open-source project, have a look at these general guidelines.
We are trying to make it as easy as possible to contribute to this project. The project itself is set up using rye. This makes everything very smooth.
Development workflow
Fork the repository and clone it to your computer. If you have rye installed, simply run:
rye sync
and all dependencies will be installed and you are ready to go. We use rye to manage format and lint. To format and lint, run:
rye fmt
rye lint
We also strive for 100% test coverage. So if you fix a bug, please write a test first that fails, then fix the bug, then make sure all tests still pass, including the new one. To run the tests, use:
rye test
If you add a new feature, please also add a test for it. In addition, please add a docstring to the new feature that includes an example. This will automatically be included in the documentation. To test all the docstrings, run:
rye run test_doc
Pre-commit hooks
Personally, I like the pre-commit framework a lot as it helps me commit clean code upon every commit.
If you want to set up pre-commit hooks, go to the folder and run the following command (after installing pre-commit using pip or pipx):
$ pre-commit install
This will install the hooks that are defined in .pre-commit-config.yaml into your git repository.
Structure of the data tables
All data lives in the data
subfolder
underneath the main package.
Aside from the nist.py
file,
all databases contain 2 dictionaries,
one for elements and one for isotopes.
Missing values must be denotes as np.nan
.
ele_dict
Element dictionary
The element dictionary ele_dict
is shaped in the following structure:
ele_dict = {
'Symb':
[
sol_abu_ele,
[a1, ..., an],
[rel_abu1, ..., rel_abun],
[sol_abu1, ..., sol_abun]
],
...
}
Here, Symb
is the element symbol,
e.g., H
for hydrogen.
This is the dictionary key.
The entry is followed by a list.
The entry sol_abu_ele
is the
solar abundance of the element in number fractions
normalized such that the solar abundance of Si is 1e6.
a1
to an
are the atomic mass numbers
of the isotopes of this element.
rel_abu1
to rel_abun
and sol_abu1
to sol_abun
are these isotopes relative abundances and solar abundance,
respectively.
Note that the relative abundances
must be normed such that their sum is unity.
iso_dict
Isotope dictionary
The isotope dictionary iso_dict
is shaped in the following structure:
iso_dict = {
'Symb-A':
[
rel_abu,
sol_abu
],
...
}
Here, Symb-A is the key of the dictionary
and is composed of the element symbol Symb
and the isotope’s atomic number A
.
A dash separates the two entries.
The dictionary entries are rel_abu
and sol_abu
,
which are the isotopes relative and
solar abundance, respectively.
The same normalization rules apply as discussed above.
Adding a database
Parser files for individual databases
that have already been added
were put into the dev
folder in the repository.
Every database added has their datafile in some format
and a parser living there.
The parser creates automatically the python file.
Have a look at some of these parsers,
especially the write method.
Here, the headers,
imports, etc. are written.
Then the dictionaries are dumped out using json.dump()
.
While this results in a really ugly format for the python file,
running black
over the generated file
will properly format everything.
This python file must then be moved to the iniabu/data
folder.
Adjust the iniabu/data/__init__.py
file
to contain imports for the two new dictionaries.
Extend the database_selector()
function
with an additional elif
statement
to contain the new database.
Finally, new tests for this database must be added.
All tests live in the test
folder,
which has the same structure as the iniabu
folder
that contains the package source code.
One good way to write a test is to use an existing test
file for a dataset.
Then adjust the subroutines and associated asserts.
At least make sure that tests exist for:
Data integrity
Solar abundance of Si is 106
Relative abundances of all isotopes sum to unity
Finally, add a new test in test_main.py
to ensure that the database loads correctly.
You should add a consistency check for the new database.
This ensures that code
coverage stays at 100%.