Source code for sciunit.scores.collections_m2m

"""Score collections for direct comparison of models against other models."""

import warnings

import pandas as pd

from sciunit.models import Model
from sciunit.tests import Test


[docs]class ScoreArrayM2M(pd.Series): """ Represents an array of scores derived from TestM2M. Extends the pandas Series such that items are either models subject to a test or the test itself. """
[docs] def __init__(self, test, models, scores): items = models if not test.observation else [test]+models super(ScoreArrayM2M, self).__init__(data=scores, index=items)
[docs] def __getitem__(self, item): if isinstance(item, str): result = self.get_by_name(item) else: result = super(ScoreArrayM2M, self).__getitem__(item) return result
[docs] def __getattr__(self, name): if name in ['score', 'norm_scores', 'related_data']: attr = self.apply(lambda x: getattr(x, name)) else: attr = super(ScoreArrayM2M,self).__getattribute__(name) return attr
[docs] def get_by_name(self, name): for entry in self.index: if entry.name == name or name.lower() == "observation": return self.__getitem__(entry) raise KeyError(("Doesn't match test, 'observation' or " "any model: '%s'") % name)
@property def norm_scores(self): return self.map(lambda x: x.norm_score)
[docs]class ScoreMatrixM2M(pd.DataFrame): """ Represents a matrix of scores derived from TestM2M. Extends the pandas DataFrame such that models/observation are both columns and the index. """
[docs] def __init__(self, test, models, scores): if not test.observation: items = models else: # better to have header as "observation" than test.name # only affects pandas.DataFrame; not test.name in individual scores test.name = "observation" items = [test]+models super(ScoreMatrixM2M, self).__init__(data=scores, index=items, columns=items) with warnings.catch_warnings(): warnings.filterwarnings("ignore", message=(".*Pandas doesn't allow columns " "to be created via a new ")) self.test = test self.models = models
[docs] def __getitem__(self, item): if isinstance(item, (Test, Model)): result = ScoreArrayM2M(self.test, self.models, scores=self.loc[item, :]) elif isinstance(item, str): result = self.get_by_name(item) elif isinstance(item, (list, tuple)) and len(item) == 2: result = self.get_group(item) else: raise TypeError(("Expected test/'observation'; model; " "test/'observation',model; " "model,test/'observation'; or model,model")) return result
[docs] def get_by_name(self, name): for model in self.models: if model.name == name: return self.__getitem__(model) if self.test.name == name or name.lower() == "observation": return self.__getitem__(self.test) raise KeyError(("Doesn't match test, 'observation' or " "any model: '%s'") % name)
[docs] def get_group(self, x): if isinstance(x[0], (Test, Model)) and isinstance(x[1], (Test, Model)): return self.loc[x[0], x[1]] elif isinstance(x[0], str): return self.__getitem__(x[0]).__getitem__(x[1]) raise TypeError("Expected test/model pair")
[docs] def __getattr__(self, name): if name in ['score', 'norm_score', 'related_data']: attr = self.applymap(lambda x: getattr(x, name)) else: attr = super(ScoreMatrixM2M, self).__getattribute__(name) return attr
@property def norm_scores(self): return self.applymap(lambda x: x.norm_score)