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

from warnings import warn
import numpy as np
import sys
import multiprocessing as mp
from .guess_methods import GuessMethods
11
12
from .fit_methods import Fit_Methods
import scipy
13

14
def targetFuncGuess(args, **kwargs):
15
16
17
18
19
20
21
22
23
24
    """
    Needed to create mappable function for multiprocessing
    :param args:
    :param kwargs:
    :return:
    """
    func = Optimize._guessFunc(args[-1])
    results = func(args[0])
    return results

25
26
27
28
29
30
31
def targetFuncFit(args, **kwargs):
    """
    Needed to create mappable function for multiprocessing
    :param args:
    :param kwargs:
    :return:
    """
32
    solver, solver_options, func = Optimize._initiateSolverAndObjFunc(args[-1])
33
34
35
    results = solver(func, args[1], args=[args[0]])
    return results

36
37
38
39
40
class Optimize(object):
    """
    In charge of all optimization and computation and is used within the Model Class.
    """

41
    def __init__(self, data=np.array([]), guess=np.array([]), parallel=True):
42
43
44
45
46
47
        """

        :param data:
        """
        if isinstance(data, np.ndarray):
            self.data = data
48
49
        if isinstance(guess, np.ndarray):
            self.guess = guess
50
        else:
51
            warn('Error: data and guess must be numpy.ndarray. Exiting...')
52
53
54
55
56
57
58
59
60
61
            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:
62
            warn('Error: %s is not implemented in pycroscopy.analysis.GuessMethods to find guesses' % self.strategy)
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99



    def computeGuess(self, processors = 1, strategy='wavelet_peaks',
                     options={"peak_widths": np.array([10,200]),"peak_step":20}, **kwargs):
        """

        Parameters
        ----------
        data
        strategy: string
            Default is 'Wavelet_Peaks'.
            Can be one of ['wavelet_peaks', 'relative_maximum', 'gaussian_processes']. For updated list, run GuessMethods.methods
        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
        -------

        """
        self.strategy = strategy
        self.options = options
        processors = processors
        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
100
                tasks = [(vector, self) for vector in self.data]
101
102
                chunk = int(self.data.shape[0] / processors)
                # Map them across processors
103
                jobs = pool.imap(targetFuncGuess, tasks, chunksize=chunk)
104
105
106
107
108
109
                # 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()
110
111
                return results

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

    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)
125
        return solver, self.solver_options, func
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164

    def computeFit(self, processors = 1, solver_type='least_squares', solver_options={},
                   obj_func={'class':'Fit_Methods','obj_func':'SHO','xvals':np.array([])}):
        """

        Parameters
        ----------
        data
        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'.
            Can be one of ['wavelet_peaks', 'relative_maximum', 'gaussian_processes']. For updated list, run GuessMethods.methods

        Returns
        -------

        """
        self.solver_type = solver_type
        self.solver_options = solver_options
        if self.solver_type not in scipy.optimize.__dict__.keys():
            warn('Solver %s does not exist!. For additional info see scipy.optimize' % (solver_type))
            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
165
            tasks = [(vector, guess, self) for vector, guess in zip(self.data, self.guess)]
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
            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 ...")
            solver, solver_options, func = self._initiateSolverAndObjFunc()
            results = [solver(func, guess, args=[vector]) for vector, guess in zip(self.data, self.guess)]
            return results