__init__.py 4.74 KB
Newer Older
1
# -*- coding: utf-8 -*-
2 3
# Copyright (C) 2014 Laboratoire d'Astrophysique de Marseille, AMU
# Copyright (C) 2012, 2014 Centre de données Astrophysiques de Marseille
4
# Licensed under the CeCILL-v2 licence - see Licence_CeCILL_V2-en.txt
5
# Author: Yannick Roehlly & Denis Burgarella
6

7
from datetime import datetime
8
from importlib import import_module
9 10
import os
import shutil
11

12 13 14 15 16

class AnalysisModule(object):
    """Abstract class, the pCigale analysis modules are based on.
    """

17
    # parameter_list is a dictionary containing all the parameters
18 19 20 21 22
    # used by the module. Each parameter name is associate to a tuple
    # (variable type, description [string], default value). Each module must
    # define its parameter list, unless it does not use any parameter. Using
    # None means that there is no description, unit or default value. If None
    # should be the default value, use the 'None' string instead.
23
    parameter_list = dict()
24 25 26 27 28 29 30 31 32 33

    def __init__(self, **kwargs):
        """Instantiate a analysis module

        The module parameters values can be passed as keyword parameters.
        """
        # parameters is a dictionary containing the actual values for each
        # module parameter.
        self.parameters = kwargs

34
    def _process(self, configuration):
35 36 37 38 39 40 41
        """Do the actual analysis

        This method is responsible for the fitting / analysis process
        and must be implemented by each real module.

        Parameters
        ----------
42 43
        configuration: dictionary
            Configuration file
44 45 46 47 48 49 50 51

        Returns
        -------
        The process results are saved to disk by the analysis module.

        """
        raise NotImplementedError()

52
    def prepare_dirs(self):
53
        # Create a new out/ directory and move existing one if needed
54
        if os.path.exists('out/'):
55
            name = datetime.now().strftime("%Y-%m-%d_%H:%M:%S") + '_out/'
56 57 58 59 60 61
            os.rename('out/', name)
            print("The out/ directory was renamed to {}".format(name))

        os.mkdir('out/')
        shutil.copy('pcigale.ini', 'out/')
        shutil.copy('pcigale.ini.spec', 'out/')
62

63
    def process(self, configuration):
64 65 66 67 68 69 70 71 72
        """Process with the analysis

        This method is responsible for checking the module parameters before
        doing the actual processing (_process method). If a parameter is not
        given but exists in the parameter_list with a default value, this
        value is used.

        Parameters
        ----------
73 74
        configuration: dictionary
            Contents of pcigale.ini in the form of a dictionary
75 76 77 78 79 80 81

        Returns
        -------
        The process results are saved to disk by the analysis module

        Raises
        ------
82
        KeyError: when not all the needed parameters are given.
83 84

        """
85
        parameters = configuration['analysis_params']
86 87 88 89
        # For parameters that are present on the parameter_list with a default
        # value and that are not in the parameters dictionary, we add them
        # with their default value.
        for key in self.parameter_list:
Médéric Boquien's avatar
Médéric Boquien committed
90
            if (key not in parameters) and (
91 92 93 94 95 96 97
                    self.parameter_list[key][2] is not None):
                parameters[key] = self.parameter_list[key][2]

        # If the keys of the parameters dictionary are different from the one
        # of the parameter_list dictionary, we raises a KeyError. That means
        # that a parameter is missing (and has no default value) or that an
        # unexpected one was given.
98 99
        if not set(parameters) == set(self.parameter_list):
            missing_parameters = (set(self.parameter_list) - set(parameters))
Médéric Boquien's avatar
Médéric Boquien committed
100 101
            unexpected_parameters = (set(parameters) -
                                     set(self.parameter_list))
102 103 104 105 106 107 108 109 110 111 112 113
            message = ""
            if missing_parameters:
                message += ("Missing parameters: " +
                            ", ".join(missing_parameters) +
                            ".")
            if unexpected_parameters:
                message += ("Unexpected parameters: " +
                            ", ".join(unexpected_parameters) +
                            ".")
            raise KeyError("The parameters passed are different from the "
                           "expected one." + message)

Médéric Boquien's avatar
Médéric Boquien committed
114
        # We do the actual processing
115
        self._process(configuration)
116 117 118 119 120 121 122


def get_module(module_name):
    """Return the main class of the module provided

    Parameters
    ----------
123
    module_name: string
124 125 126 127
        The name of the module we want to get the class.

    Returns
    -------
128
    module_class: class
129 130 131 132 133 134 135 136
    """

    try:
        module = import_module('.' + module_name, 'pcigale.analysis_modules')
        return module.Module()
    except ImportError:
        print('Module ' + module_name + ' does not exists!')
        raise