# coding=utf-8 from earthdiagnostics.variable import VarType class Diagnostic(object): """ Base class for the diagnostics. Provides a common interface for them and also has a mechanism that allows diagnostic retrieval by name. :param data_manager: data manager that will be used to store and retrieve the necessary data :type data_manager: DataManager """ alias = None """ Alias to call the diagnostic. Must be overridden at the derived clases """ _diag_list = dict() def __init__(self, data_manager): self.data_manager = data_manager self.required_vars = [] self.generated_vars = [] self.can_run_multiple_instances = True def __repr__(self): return str(self) @staticmethod def register(cls): """ Register a new diagnostic using the given alias. It must be call using the derived class. :param cls: diagnostic class to register :type cls: Diagnostic """ if not issubclass(cls, Diagnostic): raise ValueError('Class {0} must be derived from Diagnostic'.format(cls)) if cls.alias is None: raise ValueError('Diagnostic class {0} must have defined an alias'.format(cls)) Diagnostic._diag_list[cls.alias] = cls # noinspection PyProtectedMember @staticmethod def get_diagnostic(name): """ Return the class for a diagnostic given its name :param name: diagnostic alias :type name: str :return: the selected Diagnostic class, None if name can not be found :rtype: Diagnostic """ if name in Diagnostic._diag_list.keys(): return Diagnostic._diag_list[name] return None def send_file(self, filetosend, domain, var, startdate, member, chunk=None, grid=None, region=None, box=None, rename_var=None, frequency=None, year=None, date_str=None, move_old=False, vartype=VarType.MEAN): """ :param filetosend: :param domain: :type domain: Domain :param var: :param startdate: :param member: :param chunk: :param grid: :param region: :param box: :param rename_var: :param frequency: :param year: :param date_str: :param move_old: :return: """ self.data_manager.send_file(filetosend, domain, var, startdate, member, chunk, grid, region, box, rename_var, frequency, year, date_str, move_old, diagnostic=self, vartype=vartype) def compute(self): """ Calculates the diagnostic and stores the output Must be implemented by derived classes """ raise NotImplementedError("Class must override compute method") @classmethod def generate_jobs(cls, diags, options): """ Generate the instances of the diagnostics that will be run by the manager Must be implemented by derived classes. :param diags: diagnostics manager :type diags: Diags :param options: list of strings containing the options passed to the diagnostic :type options: list[str] :return: """ raise NotImplementedError("Class must override generate_jobs class method") def __str__(self): """ Must be implemented by derived classes :return: """ return 'Developer must override base class __str__ method'