Basics

There are some common rules when developing new components for TauREx 3. These apply to the majority of components in the TauREx pipeline. The only major exception is the Opacity related classes that have a different system in place.

Automatic Input Arguments

In TauREx, when loading in a class, it will dynamically parse all __init__ arguments and make them accessible in the input file. If you build a new temperature class:

from taurex.temperature import TemperatureProfile
import numpy as np

class MyNewTemperatureProfile(TemperatureProfile):

    def __init__(self, mykeyword=[1,2,3], another_keyword='A string'):
        super().__init__(name=self.__class__.__name__)
        print('A: ',mykeyword)
        print('B: ',another_keyword)

    @property
    def profile(self):
        T = np.random.rand(self.nlayers)*1000 + 1
        return T

    @classmethod
    def input_keywords(cls):
        return ['myprofile']

Then the keyword arguments mykeyword and another_keyword become arguments in the input file:

[Temperature]
profile_type = myprofile
my_keyword = 5,6,7,
another_keyword = "Another string"

Which when run will produce:

A: [5, 6, 7]
B: Another string

We recommend defining all __init__ arguments as keywords if you intend for your components to be used through the input file. The input file only supports arguments that accept:

  • scalars or strings

  • lists of scalars and/or strings
    • i.e my_arg = 1, 3.14, hello-world!

Input keywords

Most classes in TauREx include the class method input_keywords. This function returns a list of words used to identify the component in the input file. Under most headers in the input file there is a selection keyword (i.e [Optimizer] has optimizer, [Chemistry] has chemistry_type etc.) used to select the correct class for the job. This selection is made by searching for the values input_keywords from all components of that type until a match is found. So, for example, if we have a new sampler:

from taurex.optimizer import Optimizer
class MyOptimizer(Optimizer):
    #....
    @classmethod
    def input_keywords(cls):
        return ['myoptimizer', ]

We can select it in the input file as:

[Optimizer]
optimizer = myoptimizer

You can also alias the class by including multiple words:

from taurex.optimizer import Optimizer
class MyOptimizer(Optimizer):
#....
    @classmethod
    def input_keywords(cls):
        return ['myoptimizer', 'my-optimizer',
        'hello-optimizer']

We can select the class using one of the three values:

[Optimizer]
optimizer = myoptimizer # Valid
optimizer = my-optimizer # Also Valid
optimizer = hello-optimizer # Valid as well

Developers implementing this must follow a few rules:

  • The values must be lowercase only

  • Commas are not allowed

  • They must be unique; if two components have the same values, then one may never be selected

Tip

This is only necessary if you intend to have your component usable from the input file. If you only indent for it to work when used in a python script, you can omit this.

Logging

Every component has access to info() warning(), debug() error() and critical() methods:

from taurex.chemistry import Chemistry
class MyChemistry(Chemistry):

    def do_things(self):
        self.info('I am info')
        self.warning('I am warning!!')
        self.error("I am error!!!")

Calling do_things will output:

taurex.MyChemistry - INFO - I am info
taurex.MyChemistry - WARNING - I am warning!!
taurex.MyChemistry - ERROR - In: do_things()/line:7 - I am error!!!

While you can use your own printing methods. We recommend using these built in methods for logging as:

  • They can be automatically hidden during retrievals

  • They will only output once under MPI

  • They automatically include the class, function and line number for debug(), error() and critical().

Bibliography

New in version 3.1.

It is important to recognise the works involved in each component during a TauREx run. TauREx includes a basic bibliography system that will collect and parse bibtex entries embedded in each component.

Embedding bibliographic information for most cases only requires defining the BIBTEX_ENTRIES class variable as a list of bibtex entries:

from taurex.temperature import TemperatureProfile
import numpy as np

class MyNewTemperatureProfile(TemperatureProfile):

    def __init__(self, mykeyword=[1,2,3], another_keyword='A string'):
        super().__init__(name=self.__class__.__name__)
        print('A: ',mykeyword)
        print('B: ',another_keyword)

    @property
    def profile(self):
        T = np.random.rand(self.nlayers)*1000 + 1
        return T

    @classmethod
    def input_keywords(cls):
        return ['myprofile']

    BIBTEX_ENTRIES = [
        """
        @article{myprof,
            url = {https://vixra.org/abs/1512.0013},
            year = 2015,
            month = {dec},
            volume = {1512},
            number = {0013},
            author = {Ben S. Dover, Micheal T Hunt, Christopher S Peacock},
            title = {A New Addition to the Stellar Metamorphsis. the Merlin Hypothesis},
            journal = {vixra},
        }
        """,
        """
        @misc{vale2014bayesian,
            title={Bayesian Prediction for The Winds of Winter},
            author={Richard Vale},
            year={2014},
            eprint={1409.5830},
            archivePrefix={arXiv},
            primaryClass={stat.AP}
        }
        """

    ]

Warning

If your BibTeX entry includes non-Unicode characters, then Python will refuse to run, or your plugin may not be able to load into the TauREx pipeline.

Running TauREx, on program end, we get:

A New Addition to the Stellar Metamorphsis. the Merlin Hypothesis
Ben S. Dover, Micheal T Hunt, Christopher S Peacock
vixra, 1512, dec, 2015

Bayesian Prediction for The Winds of Winter
Vale, Richard
arXiv, 1409.5830, 2014

Additionally, running taurex with --bibtex mybib.bib will export the citation as a .bib file:

@misc{cad6f055,
    author = "Al-Refaie, Ahmed F. and Changeat, Quentin and Waldmann, Ingo P. and Tinetti, Giovanna",
    title = "TauREx III: A fast, dynamic and extendable framework for retrievals",
    year = "2019",
    eprint = "1912.07759",
    archivePrefix = "arXiv",
    primaryClass = "astro-ph.IM"
}

@article{6720c2d1,
    author = "Ben S. Dover, Micheal T Hunt, Christopher S Peacock",
    url = "https://vixra.org/abs/1512.0013",
    year = "2015",
    month = "dec",
    volume = "1512",
    number = "0013",
    title = "A New Addition to the Stellar Metamorphsis. the Merlin Hypothesis",
    journal = "vixra"
}

@misc{f55ed081,
    author = "Vale, Richard",
    title = "Bayesian Prediction for The Winds of Winter",
    year = "2014",
    eprint = "1409.5830",
    archivePrefix = "arXiv",
    primaryClass = "stat.AP"
}

Bibliographies are additive as well; if we decided to build on top of this class we do not need to redefine the older bibliographic information as all parent bibliographic information is also inherited:

class AnotherProfile(MyNewTemperatureProfile):
# ...

    BIBTEX_ENTRIES = [
        """
        @misc{scott2015farewell,
            title={A Farewell to Falsifiability},
            author={Douglas Scott and Ali Frolop and Ali Narimani and Andrei Frolov},
            year={2015},
            eprint={1504.00108},
            archivePrefix={arXiv},
            primaryClass={astro-ph.CO}
            }
        ]

Will yield:

A Farewell to Falsifiability
Douglas Scott, Ali Frolop, Ali Narimani, Andrei Frolov
arXiv, 1504.00108, 2015

A New Addition to the Stellar Metamorphsis. the Merlin Hypothesis
Ben S. Dover, Micheal T Hunt, Christopher S Peacock
vixra, 1512, dec, 2015

Bayesian Prediction for The Winds of Winter
Vale, Richard
arXiv, 1409.5830, 2014

You can get citations from each object through the citations() method which will output a list of parsed bibtex entries:

>>> t = MyNewTemperatureProfile()
>>> t.citations()
[Entry('article',
fields=[
('url', 'https://vixra.org/abs/1512.0013'),
('year', '2015'),
('month', 'dec'),
('volume', '1512'),
('number', '0013'),
('title', 'A New Addi.....etc

A printable string can also be generated using the nice_citation() method:

>>> print(t.nice_citation())
A New Addition to the Stellar Metamorphsis. the Merlin Hypothesis
Ben S. Dover, Micheal T Hunt, Christopher S Peacock
vixra, 1512, dec, 2015

Bayesian Prediction for The Winds of Winter
Vale, Richard
arXiv, 1409.5830, 2014

If you’re developing a ForwardModel then citations() should include its own BIBTEX_ENTRIES as well as every component in the model itself (i.e Temperature, Contributions etc.) we have a nice recipe to accomplish this:

def citations(self):

    all_citiations = [
        super().citations(),
        self.tp.citations(),
        self.chem.citations(),
        # Other components
        # ...etc...
    ]

    return unique_citiations_only(
    sum(all_citiations,[])

Here self.tp and self.chem are temperature and chemistry components used in our implementation of a forward model. unique_citations_only() will remove any repeat bibliography information and sum(all_citiations,[]) combines all citation lists into a single list.