Source code for valjean.gavroche.diagnostics.metadata
# Copyright French Alternative Energies and Atomic Energy Commission
# Contributors: valjean developers
# valjean-support@cea.fr
#
# This software is a computer program whose purpose is to analyze and
# post-process numerical simulation results.
#
# This software is governed by the CeCILL license under French law and abiding
# by the rules of distribution of free software. You can use, modify and/ or
# redistribute the software under the terms of the CeCILL license as circulated
# by CEA, CNRS and INRIA at the following URL: http://www.cecill.info.
#
# As a counterpart to the access to the source code and rights to copy, modify
# and redistribute granted by the license, users are provided only with a
# limited warranty and the software's author, the holder of the economic
# rights, and the successive licensors have only limited liability.
#
# In this respect, the user's attention is drawn to the risks associated with
# loading, using, modifying and/or developing or reproducing the software by
# the user in light of its specific status of free software, that may mean that
# it is complicated to manipulate, and that also therefore means that it is
# reserved for developers and experienced professionals having in-depth
# computer knowledge. Users are therefore encouraged to load and test the
# software's suitability as regards their requirements in conditions enabling
# the security of their systems and/or data to be ensured and, more generally,
# to use and operate it in the same conditions as regards security.
#
# The fact that you are presently reading this means that you have had
# knowledge of the CeCILL license and that you accept its terms.
'''This module define tests for metadata.'''
from ..test import Test, TestResult
MISSING = Missing()
[docs]class TestResultMetadata(TestResult):
'''Results of metadata comparisons.'''
[docs] def __init__(self, test, dict_res):
'''Initialisation of TestResultMetadata.'''
super().__init__(test)
self.dict_res = dict_res
def __bool__(self):
# aitem = [all(val.values()) for val in self.dict_res.values()]
# return all(aitem)
return all(v for val in self.dict_res.values() for v in val.values())
[docs] def per_key(self):
'''Test result sorted by key.'''
ditem = {key: all(val.values()) for key, val in self.dict_res.items()}
return ditem
[docs] def only_failed_comparisons(self):
'''Return only the failed comparisons. Structure is the same as the
``dict_res``.'''
ditem = {key: self.test.all_md[key]
for key, val in self.dict_res.items()
if not all(val.values())}
return ditem
[docs]class TestMetadata(Test):
'''A test that compares metadata.
.. todo::
Document the parameters...
'''
[docs] def __init__(self, dict_md, name, description='', labels=None,
exclude=('results', 'index', 'score_index', 'response_index',
'response_type')):
'''Initialisation of :class:`TestMetadata`.
:param str name: local name of the test
:param str description: specific description of the test
:param dict labels: labels to be used for test classification in
reports, for example category, input file name, type of result, ...
:param tuple exclude: a tuple of keys that will not be considered as
metadata. Default: ``('results', 'index', 'score_index',
'response_index', 'response_type')``
'''
super().__init__(name=name, description=description, labels=labels)
if not isinstance(dict_md, dict):
raise TypeError('Metadata should be given as a dictionary '
'name: dict of metadata')
self.dmd = dict_md
self.exclude = exclude
self.all_md = self.build_metadata_dict()
[docs] def build_metadata_dict(self):
'''Build the dictionary of metadata.
Contains all the metadata for all samples.
'''
all_keys = (set(key for md in self.dmd.values() for key in md)
.difference(self.exclude))
# we could write the whole following loop as a nested dict
# comprehension, but let's not
cdict = {}
for key in all_keys:
cdict[key] = {name: tmd[key] if key in tmd else MISSING
for name, tmd in self.dmd.items()}
return cdict
[docs] def compare_metadata(self):
'''Metadata are compared with respect to the first one.'''
bdict = {}
t0name = sorted(self.dmd)[0]
for key, kdict in self.all_md.items():
bdict[key] = {n: v == kdict[t0name] for n, v in kdict.items()}
return bdict
[docs] def evaluate(self):
'''Evaluate this test and turn it into a :class:`TestResultMetadata`.
'''
return TestResultMetadata(self, self.compare_metadata())
[docs] def data(self):
'''Generator yielding objects supporting the buffer protocol that (as a
whole) represent a serialized version of `self`.'''
yield from super().data()
yield self.__class__.__name__.encode('utf-8')
for key, tmd in self.dmd.items():
yield key.encode('utf-8')
for mdkey, mdval in tmd.items():
yield mdkey.encode('utf-8')
yield str(mdval).encode('utf-8')
for key in self.exclude:
yield key.encode('utf-8')