-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Rastislav Turanyi
committed
Jan 17, 2025
1 parent
29a3ce6
commit a244706
Showing
7 changed files
with
484 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
How-To Guides | ||
============= | ||
|
||
This section contains How-To guides, goal-oriented directions that will | ||
hopefully help you achieve anything you might want to do with ResINS. If there | ||
are any problems you are trying to solve with ResINS that we do not have a | ||
How-To guide for, or if any of the existing How-To guides are not clear, please | ||
do open an issue on | ||
`our GitHub <https://github.com/pace-neutrons/resolution_functions/issues>`_. | ||
|
||
Though, do note that these guides are provided as instructions to solve common | ||
problems - for learning how to use ResINS, please see our | ||
:doc:`Tutorials<tutorials>` section. The following How-To guides are currently | ||
provided: | ||
|
||
|
||
.. toctree:: | ||
:maxdepth: 1 | ||
:glob: | ||
|
||
howtos/* |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
How To Add an Instrument | ||
======================== | ||
|
||
ResINS strives to model all :term:`INS` :term:`instruments<instrument>` past, | ||
present, and future, but it is inevitable that some will not be natively | ||
supported *yet*. Fortunately, ResINS was designed to make adding new instruments | ||
relatively straightforward. Though, there are two ways of doing this: | ||
|
||
.. contents:: | ||
:backlinks: entry | ||
:depth: 2 | ||
:local: | ||
|
||
.. _add-personal-instrument: | ||
|
||
How To Add an Instrument for Personal Use | ||
----------------------------------------- | ||
|
||
It is possible to add an :term:`instrument` only locally, outside the ResINS | ||
ecosystem. Technically, all that is required is a dictionary, but the most | ||
readable way is to construct a YAML file with the instrument details. This file | ||
**must** follow the :doc:`data file spec<../dev/yaml_spec>` and include all the | ||
necessary information. Then, ResINS can be leveraged to do the rest without | ||
additional code: | ||
|
||
>>> from resolution_functions import Instrument | ||
>>> new_instrument_path = '~/instrument/instrument.yaml' | ||
>>> version = 'version' # If the created YAML file contains multiple versions | ||
>>> new_instrument = Instrument.from_file(new_instrument_path, version) | ||
>>> new_instrument.name | ||
'new_instrument' | ||
>>> new_instrument.version | ||
'version' | ||
|
||
Given that the YAML file specifies a model already implemented in ResINS, and | ||
that its parameters have been all included, the resolution function can be | ||
computed: | ||
|
||
>>> model = new_instrument.get_resolution_function('PyChop_fit', chopper_package='A', e_init=100, chopper_frequency=300) | ||
>>> print(model) | ||
PyChopModelFermi(citation=['']) | ||
|
||
However, if a new model was created for the new instrument, more work will be | ||
required, see :doc:`add_model`. | ||
|
||
How to register an instrument with ResINS | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
?????????????????? | ||
|
||
How to add an instrument without creating a yaml file | ||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||
|
||
For personal use, it is possible to also specify an instrument without creating | ||
a YAML data file for it. All that is required is a Python dictionary, though the | ||
dictionary still **must** follow the :doc:`data file spec<../dev/yaml_spec>` | ||
(though only the dict inside :ref:`models: key<spec-models>`): | ||
|
||
>>> from resolution_functions import Instrument | ||
>>> new_instrument_name = 'name' | ||
>>> new_instrument_version = 'v1' | ||
>>> new_instrument_default_model = 'AbINS' | ||
>>> new_instrument_data = {'AbINS': {'function': 'polynomial_1d', 'citation': [''], 'parameters': [0, 2], 'settings': {}}} | ||
>>> new_instrument = Instrument(new_instrument_name, new_instrument_version, new_instrument_data, new_instrument_default_model) | ||
>>> print(new_instrument) | ||
Instrument(name=name, version=v1) | ||
>>> model = new_instrument.get_resolution_function() | ||
>>> print(model) | ||
PolynomialModel1D(citation=['']) | ||
>>> model(100) | ||
200.0 | ||
|
||
How To Add an Instrument to ResINS | ||
---------------------------------- | ||
|
||
If you would like to contribute a new :term:`instrument` to ResINS (which we do | ||
appreciate!), do open an issue on | ||
`our GitHub <https://github.com/pace-neutrons/resolution_functions>`_ | ||
so that we can help. Otherwise, the process will start out similar to when you | ||
would :ref:`create an instrument for personal use<add-personal-instrument>` in | ||
that you will need to create a new YAML file for the instrument, following the | ||
:doc:`spec<../dev/yaml_spec>`. Then, the file will have to be placed in | ||
``resolution_functions/src/resolution_functions/instrument_data`` (of course | ||
working on a new branch of your own fork, see Contributing Guidelines). Lastly, | ||
to be able to use the new instrument with | ||
:py:meth:`~resolution_functions.instrument.Instrument.from_default`, | ||
it has to be added to | ||
:py:data:`resolution_functions.instrument.INSTRUMENT_MAP`; | ||
create a new entry in the dictionary with the format:: | ||
|
||
INSTRUMENT_MAP = { | ||
'instrument_name': ('yaml_file_name', None) | ||
} | ||
|
||
where `instrument_name` is the official name of the instrument that you would | ||
like users to use when creating the instrument, and `yaml_file_name` is the | ||
name of the YAML file without the `.yaml` extension, e.g. `arcs`. | ||
|
||
.. note:: | ||
|
||
The `None` in the example above is used for creating an alias and represents | ||
a version name for one of the versions in the `yaml_file_name.yaml` file. | ||
For example, the TFXA instrument is an alias for the TFXA :term:`version` of | ||
the TOSCA :term:`instrument` and is specified as | ||
`'TFXA': ('tosca', 'TFXA')`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
How To Add A New Model | ||
====================== | ||
|
||
.. contents:: | ||
:backlinks: entry | ||
:depth: 2 | ||
:local: | ||
|
||
How to add a new model for personal use | ||
--------------------------------------- | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
How To Add a Version To an Instrument | ||
===================================== | ||
|
||
ResINS strives to model all :term:`versions<version>` of any given :term:`INS` | ||
:term:`instrument` - old, new, and planned - but it is inevitable that some will | ||
not be natively supported *yet*. Fortunately, while not as straightforward as | ||
:doc:`creating a new instrument<add_instrument>`, ResINS aims to make adding | ||
new :term:`versions<version>` as simple as possible: | ||
|
||
.. contents:: | ||
:backlinks: entry | ||
:depth: 2 | ||
:local: | ||
|
||
|
||
How to add a version for personal use | ||
------------------------------------- | ||
|
||
Adding a :term:`version` to an :term:`instrument` only locally (without | ||
:ref:`submitting to ResINS<howto-version-resins>`) is the more difficult task | ||
since ResINS does not have an extension/add-ons mechanism. Therefore, to create | ||
a version, it is necessary to resort to either creating an entire instrument or | ||
working with Python dictionaries instead of YAML files: | ||
|
||
Using YAML files | ||
^^^^^^^^^^^^^^^^ | ||
|
||
To add a :term:`version` to an existing :term:`instrument` | ||
|
||
|
||
.. _howto-version-resins: | ||
|
||
How to add a version to ResINS | ||
------------------------------ | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
How To Get the Resolution Function | ||
================================== | ||
|
||
The short answer for getting the :term:`resolution function` of a particular | ||
:term:`version` of a given :term:`instrument` is to use the | ||
:py:meth:`resolution_functions.instrument.Instrument.get_resolution_function` | ||
method, e.g.: | ||
|
||
>>> from resolution_functions import Instrument | ||
>>> tosca = Instrument('TOSCA') | ||
>>> book = tosca.get_resolution_function('book', detector_bank='Forward') | ||
>>> print(book) | ||
ToscaBookModel(citation="") | ||
|
||
However, this is a shared interface, and so the | ||
:term:`configurations<configuration>` and :term:`settings<setting>` that need to | ||
be provided differ between :term:`instruments<instrument>`, | ||
:term:`versions<version>`, and :term:`models<model>`. Of course, the information | ||
required can be gathered from the documentation, and the :term:`configuration` | ||
details can be found via :doc:`programmatic means<programmatic_query>`, but the | ||
only way of obtaining all the information simultaneously is getting the model | ||
signature: | ||
|
||
How To Get the Model Signature | ||
------------------------------ | ||
|
||
The | ||
:py:meth:`resolution_functions.instrument.Instrument.get_model_signature` | ||
method returns a :py:class:`~inspect.Signature` (from the `inspect` module) that | ||
contains all the information for calling the | ||
:py:meth:`resolution_functions.instrument.Instrument.get_resolution_function` | ||
method: | ||
|
||
* All arguments available for the :term:`model` & :term:`version` & | ||
:term:`instrument` | ||
* The type annotation for that argument | ||
* The default value for that argument | ||
* The restrictions on that argument | ||
|
||
This method does not distinguish between :term:`configurations<configuration>` | ||
and :term:`settings<setting>`; it only considers | ||
:py:meth:`resolution_functions.instrument.Instrument.get_resolution_function` | ||
and its call signature: | ||
|
||
>>> from resolution_functions import Instrument | ||
>>> maps = Instrument.from_default('MAPS') | ||
>>> sig = maps.get_model_signature() | ||
>>> sig | ||
<Signature (model_name: Optional[str] = 'PyChop_fit', *, chopper_package: Literal['A', 'B', 'S'] = 'A', e_init: Annotated[ForwardRef('Optional[float]'), 'restriction=[0, 2000]'] = 500, chopper_frequency: Annotated[ForwardRef('Optional[int]'), 'restriction=[50, 601, 50]'] = 400, fitting_order: 'int' = 4, _) -> resolution_functions.models.pychop.PyChopModelFermi> | ||
|
||
The returned :py:class:`inspect.Signature` object can be then be queried using | ||
the full capabilities afforded by this standard library implementation. For | ||
example, the return annotation and the arguments can be queried separately: | ||
|
||
>>> sig.return_annotation | ||
<class 'resolution_functions.models.pychop.PyChopModelFermi'> | ||
>>> sig.parameters | ||
mappingproxy(OrderedDict([('model_name', <Parameter "model_name: Optional[str] = 'PyChop_fit'">), ('chopper_package', <Parameter "chopper_package: Literal['A', 'B', 'S'] = 'A'">), ('e_init', <Parameter "e_init: Annotated[ForwardRef('Optional[float]'), 'restriction=[0, 2000]'] = 500">), ('chopper_frequency', <Parameter "chopper_frequency: Annotated[ForwardRef('Optional[int]'), 'restriction=[50, 601, 50]'] = 400">), ('fitting_order', <Parameter "fitting_order: 'int' = 4">), ('_', <Parameter "_">)])) | ||
|
||
Where the latter can then be investigated in much more detail via the | ||
:py:class:`inspect.Parameter` interface: | ||
|
||
>>> sig.parameters['e_init'] | ||
<Parameter "e_init: Annotated[ForwardRef('Optional[float]'), 'restriction=[0, 2000]'] = 500"> | ||
>>> sig.parameters['e_init'].name | ||
'e_init' | ||
>>> sig.parameters['e_init'].default | ||
500 | ||
>>> sig.parameters['e_init'].annotation | ||
typing.Annotated[ForwardRef('Optional[float]'), 'restriction=[0, 2000]'] | ||
>>> sig.parameters['e_init'].kind | ||
<_ParameterKind.KEYWORD_ONLY: 3> |
Oops, something went wrong.