optimize.py 6.77 KB
Newer Older
1
"""
2
3
Created on 12/15/16 10:08 AM
@author: Numan Laanait
4
5
"""

6
from __future__ import division, print_function, absolute_import, unicode_literals
7
8
9
10
11
from warnings import warn
import numpy as np
import sys
import multiprocessing as mp
from .guess_methods import GuessMethods
12
13
from .fit_methods import Fit_Methods
import scipy
14

Somnath, Suhas's avatar
Somnath, Suhas committed
15

16
def targetFuncGuess(args, **kwargs):
17
    """
Somnath, Suhas's avatar
Somnath, Suhas committed
18
    This is just creates mappable function for multiprocessing guess
19
20
21
22
    :param args:
    :param kwargs:
    :return:
    """
Chris Smith's avatar
Chris Smith committed
23
24
    opt = args[-1]
    func = opt._guessFunc()
25
26
27
    results = func(args[0])
    return results

Somnath, Suhas's avatar
Somnath, Suhas committed
28

29
30
31
32
33
34
35
def targetFuncFit(args, **kwargs):
    """
    Needed to create mappable function for multiprocessing
    :param args:
    :param kwargs:
    :return:
    """
Chris Smith's avatar
Chris Smith committed
36
37
    opt = args[-1]
    solver, solver_options, func = opt._initiateSolverAndObjFunc()
38
39
40
    results = solver(func, args[1], args=[args[0]])
    return results

Somnath, Suhas's avatar
Somnath, Suhas committed
41

42
43
44
45
46
class Optimize(object):
    """
    In charge of all optimization and computation and is used within the Model Class.
    """

47
    def __init__(self, data=np.array([]), guess=np.array([]), parallel=True):
48
49
50
51
52
53
        """

        :param data:
        """
        if isinstance(data, np.ndarray):
            self.data = data
54
55
        if isinstance(guess, np.ndarray):
            self.guess = guess
56
        else:
57
            warn('Error: data and guess must be numpy.ndarray. Exiting...')
58
59
60
61
62
63
64
65
66
            sys.exit()
        self._parallel = parallel

    def _guessFunc(self):
        gm = GuessMethods()
        if self.strategy in gm.methods:
            func = gm.__getattribute__(self.strategy)(**self.options)
            return func
        else:
67
            warn('Error: %s is not implemented in pycroscopy.analysis.GuessMethods to find guesses' % self.strategy)
68

Somnath, Suhas's avatar
Somnath, Suhas committed
69
70
    def computeGuess(self, processors=1, strategy='wavelet_peaks',
                     options={"peak_widths": np.array([10, 200]), "peak_step": 20}, **kwargs):
71
        """
Somnath, Suhas's avatar
Somnath, Suhas committed
72
        Computes the guess function using numerous cores
73
74
75

        Parameters
        ----------
Somnath, Suhas's avatar
Somnath, Suhas committed
76
77
        processors : unsigned int
            Number of logical cores to use for computing
78
79
        strategy: string
            Default is 'Wavelet_Peaks'.
Unknown's avatar
Unknown committed
80
81
            Can be one of ['wavelet_peaks', 'relative_maximum', 'gaussian_processes']. For updated list,
            run GuessMethods.methods
82
83
84
85
86
87
88
89
90
91
        options: dict
            Default: Options for wavelet_peaks{"peaks_widths": np.array([10,200]), "peak_step":20}.
            Dictionary of options passed to strategy. For more info see GuessMethods documentation.

        kwargs:
            processors: int
                number of processors to use. Default all processors on the system except for 1.

        Returns
        -------
Somnath, Suhas's avatar
Somnath, Suhas committed
92
93
        results : unknown
            unknown
94
95
96
97
98
99
100
101
102
103
104
105
        """
        self.strategy = strategy
        self.options = options
        gm = GuessMethods()
        if strategy in gm.methods:
            # func = gm.__getattribute__(strategy)(**options)
            results = list()
            if self._parallel:
                # start pool of workers
                print('Computing Jobs In parallel ... launching %i kernels...' % processors)
                pool = mp.Pool(processors)
                # Vectorize tasks
Chris Smith's avatar
Chris Smith committed
106
                tasks = [(vector, self) for vector in self.data]
107
108
                chunk = int(self.data.shape[0] / processors)
                # Map them across processors
109
                jobs = pool.imap(targetFuncGuess, tasks, chunksize=chunk)
110
111
112
113
114
115
                # get Results from different processes
                results = [j for j in jobs]
                print('Extracted Results...')
                # Finished reading the entire data set
                print('closing %i kernels...' % processors)
                pool.close()
116
117
                return results

118
119
            else:
                print("Computing Guesses In Serial ...")
Chris Smith's avatar
Chris Smith committed
120
                results = [targetFuncGuess((vector, self)) for vector in self.data]
121
122
123
                return results
        else:
            warn('Error: %s is not implemented in pycroscopy.analysis.GuessMethods to find guesses' % strategy)
124
125
126
127
128
129
130

    def _initiateSolverAndObjFunc(self):
        if self.solver_type in scipy.optimize.__dict__.keys():
            solver = scipy.optimize.__dict__[self.solver_type]
        if self.obj_func is None:
            fm = Fit_Methods()
            func = fm.__getattribute__(self.obj_func_name)(self.obj_func_xvals)
131
        return solver, self.solver_options, func
132

Somnath, Suhas's avatar
Somnath, Suhas committed
133
134
    def computeFit(self, processors=1, solver_type='least_squares', solver_options={},
                   obj_func={'class': 'Fit_Methods', 'obj_func': 'SHO', 'xvals': np.array([])}):
135
136
137
138
        """

        Parameters
        ----------
Somnath, Suhas's avatar
Somnath, Suhas committed
139
140
        processors : unsigned int
            Number of logical cores to use for computing
141
142
143
144
145
146
147
        solver_type : string
            Optimization solver to use (minimize,least_sq, etc...). For additional info see scipy.optimize
        solver_options: dict()
            Default: dict()
            Dictionary of options passed to solver. For additional info see scipy.optimize
        obj_func: dict()
            Default is 'SHO'.
Somnath, Suhas's avatar
Somnath, Suhas committed
148
149
            Can be one of ['wavelet_peaks', 'relative_maximum', 'gaussian_processes'].
            For updated list, run GuessMethods.methods
150
151
152

        Returns
        -------
Somnath, Suhas's avatar
Somnath, Suhas committed
153
154
        results : unknown
            unknown
155
156
157
158
        """
        self.solver_type = solver_type
        self.solver_options = solver_options
        if self.solver_type not in scipy.optimize.__dict__.keys():
Unknown's avatar
Unknown committed
159
            warn('Solver %s does not exist!. For additional info see scipy.optimize' % solver_type)
160
161
162
163
164
165
166
167
168
169
170
171
172
173
            sys.exit()
        if obj_func['class'] is None:
            self.obj_func = obj_func['obj_func']
        else:
            self.obj_func_xvals = obj_func['xvals']
            self.obj_func = None
            self.obj_func_name = obj_func['obj_func']
            self.obj_func_class = obj_func['class']

        if self._parallel:
            # start pool of workers
            print('Computing Jobs In parallel ... launching %i kernels...' % processors)
            pool = mp.Pool(processors)
            # Vectorize tasks
Chris Smith's avatar
Chris Smith committed
174
            tasks = [(vector, guess, self) for vector, guess in zip(self.data, self.guess)]
175
176
177
178
179
180
181
182
183
184
185
186
            chunk = int(self.data.shape[0] / processors)
            # Map them across processors
            jobs = pool.imap(targetFuncFit, tasks, chunksize=chunk)
            # get Results from different processes
            results = [j for j in jobs]
            # Finished reading the entire data set
            print('closing %i kernels...' % processors)
            pool.close()
            return results

        else:
            print("Computing Fits In Serial ...")
Chris Smith's avatar
Chris Smith committed
187
            tasks = [(vector, guess, self) for vector, guess in zip(self.data, self.guess)]
188
            results = [targetFuncFit(task) for task in tasks]
Somnath, Suhas's avatar
Somnath, Suhas committed
189
            return results