from ..core import Fittable
from ..core import Citable
from ..parameter.factory import log
# Try and create __init_mixin__
[docs]def mixed_init(self, **kwargs):
import inspect
new_class = self.__class__
base_class = self.__class__.__bases__[-1]
args = inspect.getfullargspec(base_class.__init__).args[1:]
new_kwargs = {}
for k, v in kwargs.items():
if k in args:
new_kwargs[k] = v
super(new_class, self).__init__(**new_kwargs)
new_kwargs = {}
for klass in reversed(new_class.__bases__[:-1]):
args = inspect.getfullargspec(klass.__init_mixin__).args[1:]
new_kwargs = {}
for k, v in kwargs.items():
if k in args:
new_kwargs[k] = v
klass.__init_mixin__(self, **new_kwargs)
[docs]class Mixin(Fittable, Citable):
def __init__(self, **kwargs):
old_fitting_parameters = {}
old_derived_parameters = {}
if hasattr(self, '_param_dict'):
old_fitting_parameters = self._param_dict
old_derived_parameters = self._derived_dict
super().__init__(**kwargs)
self._param_dict.update(old_fitting_parameters)
self._derived_dict.update(old_derived_parameters)
def __init__mixin(self):
pass
[docs]class StarMixin(Mixin):
"""
A mixin that enhances :class:`~taurex.data.stellar.star.Star`
"""
pass
[docs]class TemperatureMixin(Mixin):
pass
[docs]class PlanetMixin(Mixin):
pass
[docs]class ContributionMixin(Mixin):
pass
[docs]class ChemistryMixin(Mixin):
pass
[docs]class PressureMixin(Mixin):
pass
[docs]class ForwardModelMixin(Mixin):
pass
[docs]class ObservationMixin(Mixin):
pass
[docs]class OptimizerMixin(Mixin):
pass
[docs]class GasMixin(Mixin):
pass
[docs]class InstrumentMixin(Mixin):
pass
[docs]def determine_mixin_args(klasses):
import inspect
all_kwargs = []
defaults = []
for klass in klasses:
argspec = inspect.getfullargspec(klass.__init__)
if issubclass(klass, Mixin):
argspec = inspect.getfullargspec(klass.__init_mixin__)
if not argspec.defaults:
continue
args = argspec.args
defaults.extend(argspec.defaults)
num_defaults = len(argspec.defaults)
all_kwargs.extend(args[-num_defaults:])
all_kwargs = {k: v for k, v in zip(all_kwargs, defaults)}
return all_kwargs
[docs]def build_new_mixed_class(base_klass, mixins):
if not hasattr(mixins, '__len__'):
mixins = [mixins]
all_classes = tuple(mixins) + tuple([base_klass])
new_name = '+'.join([x.__name__[:10] for x in all_classes])
new_klass = type(new_name, all_classes, {'__init__': mixed_init})
return new_klass
[docs]def enhance_class(base_klass, mixins, **kwargs):
new_klass = build_new_mixed_class(base_klass, mixins)
all_kwargs = determine_mixin_args(new_klass.__bases__)
for k in kwargs:
if k not in all_kwargs:
log.error('Object {} does not have '
'parameter {}'.format(new_klass, k))
log.error('Available parameters are %s', all_kwargs)
raise KeyError(f'Object {new_klass} does not have parameter {k}')
return new_klass(**kwargs)