use – Inject parsing results into free functions

This module extends the functionalities provided by use to the commonplace task of parsing Tripoli-4 output files. The decorators defined by this module, using_parse_result and using_browser, can be used to remove boilerplate code that parses and accesses the Tripoli-4 results. At the same time, they simplify the integration of user-defined post-processing (tests) into the valjean workflow.

We will need to set up a few things to show an example of how to use the decorators. We don’t want to build and run Tripoli-4 for the purpose of this documentation, but we can mock a Tripoli-4 run by writing an existing Tripoli-4 output to a file. Here is the sample output:

>>> example = """BATCH 10
... initialization time (s): 7
...  batch number : 10
... *********************************************************
...  RESULTS ARE GIVEN FOR SOURCE INTENSITY : 8.111452e+04
... *********************************************************
...
...
...  Mean weight leakage = 7.929746e+00      sigma = 7.929746e+00    sigma% = 1.000000e+02
...
...
...  Edition after batch number : 10
...
...
...
... ******************************************************************************
... RESPONSE FUNCTION : FLUX
... RESPONSE NAME :
... ENERGY DECOUPAGE NAME : DEC_SPECTRE
...
...
...  PARTICULE : NEUTRON
... ******************************************************************************
...
...          scoring mode : SCORE_SURF
...          scoring zone :          Frontier        volumes : 14,27
...
...
...          SPECTRUM RESULTS
...          number of first discarded batches : 0
...
...          group                   score           sigma_%         score/lethargy
... Units:   MeV                     neut.s^-1       %               neut.s^-1
...
... 2.000000e+01 - 1.000000e-11     1.307419e+00    8.719708e+01    1.046074e+01
...
...          ENERGY INTEGRATED RESULTS
...
...          number of first discarded batches : 0
...
... number of batches used: 10      1.307419e+00    8.719708e+01
...
...
...
...  simulation time (s) : 20
...
...
...  Type and parameters of random generator at the end of simulation:
...          DRAND48_RANDOM 13531 45249 20024  COUNTER      2062560
...
...
...  simulation time (s): 20
...
...
... =====================================================================
...         NORMAL COMPLETION
... =====================================================================
... """

We construct a RunTaskFactory that simply echoes any text passed as an argument:

>>> from valjean.cosette.run import RunTaskFactory
>>> echo_factory = RunTaskFactory.from_executable('/bin/echo', name='echo',
...                                               default_args=['{text}'])

In the real world, the RunTaskFactory would actually generate tasks to run a Tripoli-4 executable.

Injecting the raw parse results

Now we can construct the decorator that parses the Tripoli-4 results and apply it to a Python function:

>>> from valjean.eponine.tripoli4 import use
>>> using_last_parse_result = use.using_last_parse_result(echo_factory)
>>> @using_last_parse_result(text=example)
... def source(results):
...     return results.res['batch_data']['source_intensity']

If we inspect source, we can see that it is a Use object:

>>> type(source)
<class 'valjean.cosette.use.Use'>

If you are not sure what Use does, this is a good moment to go and read its documentation. Don’t worry, I’ll wait.

(time passes)

valjean can inspect this object and convert it into a Task:

>>> source_task = source.get_task()
>>> type(source_task)
<class 'valjean.cosette.pythontask.PythonTask'>
>>> source_task.name
'....source'

The task has explicit dependencies, which means that it will be correctly integrated in the valjean dependency graph. In particular, this task depends on a task that actually does the parsing:

>>> source_task.depends_on
{Task('....parse_batch_index')}
>>> parse_task = next(iter(source_task.depends_on))

It depends on the make_parser_task, that scans the file and build the parser

>>> parse_task.depends_on
{Task('....make_parser')}
>>> make_parser_task = next(iter(parse_task.depends_on))

and make_parser_task in turn depends on the RunTask that was generated by echo_factory:

>>> make_parser_task.depends_on
{Task('....echo')}
>>> run_task = next(iter(make_parser_task.depends_on))

We manually execute the tasks in the correct order and we check that we recover the right result at the end:

>>> from valjean.cosette.env import Env
>>> env = Env()
>>> for task in [run_task, make_parser_task, parse_task, source_task]:
...     env_up, _ = task.do(env=env, config=config)
...     env.apply(env_up)
>>> print(env[source_task.name]['result'])
81114.52

Using a Browser

The raw parse results are useful in some situations, but most of the time you probably want to work with a higher-level representation of the calculation result, such as a Browser. This module provides a function to construct a decorator that automatically creates the RunTask from the RunTaskFactory, runs the task, parses the resulting output and wraps the parse results in an Browser:

>>> using_browser = use.using_browser(echo_factory, 10)
>>> @using_browser(text=example)
... def extract_simulation_time(browser):
...     return browser.globals['simulation_time']

We can again check that everything went as expected by manually unwrapping the sequence of tasks and running them:

>>> extract_task = extract_simulation_time.get_task()
>>> browse_task = next(iter(extract_task.depends_on))
>>> parse_task = next(iter(browse_task.depends_on))
>>> make_parser_task = next(iter(parse_task.depends_on))
>>> run_task = next(iter(make_parser_task.depends_on))
>>> env = Env()
>>> for task in [run_task, make_parser_task, parse_task,
...              browse_task, extract_task]:
...     env_up, _ = task.do(env=env, config=config)
...     env.apply(env_up)
>>> print(env[extract_task.name]['result'])
20

Module API

valjean.eponine.tripoli4.use.partial(func, *args, **kwargs)[source]

An improved version of functools.partial that calls functools.update_wrapper on the partially applied function in order to update its metadata (name, etc.).

valjean.eponine.tripoli4.use.make_parser(filename)[source]

Create a Parser object and scan a Tripoli-4 output file.

Parameters:
  • filename (str) – the name of the file to parse.

  • batch (int) – the number of the batch to parse; see __init__.

Raises:

ValueError – if parsing fails.

Returns:

the parser

Return type:

Parser

valjean.eponine.tripoli4.use.parse_batch_number(parser, *, batch_number)[source]

Parse a batch result from Tripoli-4.

Parameters:

batch_number (int) – batch number

Return type:

ParseResult

valjean.eponine.tripoli4.use.parse_batch_index(parser, *, batch_index=- 1)[source]

Parse a batch result from Tripoli-4.

Parameters:

batch_index (int) – index of the batch in the list of batches

Return type:

ParseResult

valjean.eponine.tripoli4.use.using_parser(factory)[source]

Construct a decorator that injects Tripoli-4 parser into a Python function.

Parameters:

factory (RunTaskFactory) – a factory producing Tripoli-4 runs.

Returns:

a decorator (see the module docstring for more information).

valjean.eponine.tripoli4.use.using_parse_result(factory, batch_number)[source]

Construct a decorator that injects the raw Tripoli-4 parse results into a Python function.

Parameters:
  • factory (RunTaskFactory) – a factory producing Tripoli-4 runs.

  • batch_number (int) – the number of the batch to parse; see __init__.

Returns:

a decorator (see the module docstring for more information).

valjean.eponine.tripoli4.use.using_last_parse_result(factory)[source]

Construct a decorator that injects the last raw Tripoli-4 parse results into a Python function.

Parameters:

factory (RunTaskFactory) – a factory producing Tripoli-4 runs.

Returns:

a decorator (see the module docstring for more information).

valjean.eponine.tripoli4.use.to_browser(result)[source]

Create a Browser from the parsing result.

Parameters:

result (ParseResult) – result from T4 parser

Returns:

the browser

Return type:

Browser

valjean.eponine.tripoli4.use.using_browser(factory, batch_number)[source]

Construct a decorator that injects an Browser to the Tripoli-4 parse results into a Python function.

Parameters:
  • factory (RunTaskFactory) – a factory producing Tripoli-4 runs.

  • batch_number (int) – the number of the required batch (will be parsed then transformed in Browser)

Returns:

a decorator (see the module docstring for more information).

valjean.eponine.tripoli4.use.using_last_browser(factory)[source]

Construct a decorator that injects a Browser to the Tripoli-4 last parse results into a Python function.

Parameters:

factory (RunTaskFactory) – a factory producing Tripoli-4 runs.

Returns:

a decorator (see the module docstring for more information).