|
| 1 | +"""Class MorphFuncx -- apply a user-supplied python function to the |
| 2 | +x-axis.""" |
| 3 | + |
| 4 | +from diffpy.morph.morphs.morph import LABEL_GR, LABEL_RA, Morph |
| 5 | + |
| 6 | + |
| 7 | +class MorphFuncx(Morph): |
| 8 | + """Apply a custom function to the x-axis (grid) of the morph |
| 9 | + function. |
| 10 | +
|
| 11 | + General morph function that applies a user-supplied function to the |
| 12 | + x-coordinates of morph data to make it align with a target. |
| 13 | +
|
| 14 | + Notice: the function provided must preserve the monotonic |
| 15 | + increase of the grid. |
| 16 | + I.e. the function f applied on the grid x must ensure for all |
| 17 | + indices i<j, f(x[i]) < f(x[j]). |
| 18 | +
|
| 19 | + Configuration Variables |
| 20 | + ----------------------- |
| 21 | + function: callable |
| 22 | + The user-supplied function that applies a transformation to the |
| 23 | + x-coordinates of the data. |
| 24 | +
|
| 25 | + parameters: dict |
| 26 | + A dictionary of parameters to pass to the function. |
| 27 | +
|
| 28 | + Returns |
| 29 | + ------- |
| 30 | + A tuple (x_morph_out, y_morph_out, x_target_out, y_target_out) |
| 31 | + where the target values remain the same and the morph data is |
| 32 | + transformed according to the user-specified function and parameters |
| 33 | + The morphed data is returned on the same grid as the unmorphed data |
| 34 | +
|
| 35 | + Example |
| 36 | + ------- |
| 37 | + Import the funcx morph function: |
| 38 | +
|
| 39 | + >>> from diffpy.morph.morphs.morphfuncx import MorphFuncx |
| 40 | +
|
| 41 | + Define or import the user-supplied transformation function: |
| 42 | +
|
| 43 | + >>> import numpy as np |
| 44 | + >>> def exp_function(x, y, scale, rate): |
| 45 | + >>> return abs(scale) * np.exp(rate * x) |
| 46 | +
|
| 47 | + Note that this transformation is monotonic increasing, so will preserve |
| 48 | + the monotonic increasing nature of the provided grid. |
| 49 | +
|
| 50 | + Provide initial guess for parameters: |
| 51 | +
|
| 52 | + >>> parameters = {'scale': 1, 'rate': 1} |
| 53 | +
|
| 54 | + Run the funcy morph given input morph array (x_morph, y_morph)and target |
| 55 | + array (x_target, y_target): |
| 56 | +
|
| 57 | + >>> morph = MorphFuncx() |
| 58 | + >>> morph.funcx_function = exp_function |
| 59 | + >>> morph.funcx = parameters |
| 60 | + >>> x_morph_out, y_morph_out, x_target_out, y_target_out = |
| 61 | + ... morph.morph(x_morph, y_morph, x_target, y_target) |
| 62 | +
|
| 63 | + To access parameters from the morph instance: |
| 64 | +
|
| 65 | + >>> x_morph_in = morph.x_morph_in |
| 66 | + >>> y_morph_in = morph.y_morph_in |
| 67 | + >>> x_target_in = morph.x_target_in |
| 68 | + >>> y_target_in = morph.y_target_in |
| 69 | + >>> parameters_out = morph.funcx |
| 70 | + """ |
| 71 | + |
| 72 | + # Define input output types |
| 73 | + summary = "Apply a Python function to the x-axis data" |
| 74 | + xinlabel = LABEL_RA |
| 75 | + yinlabel = LABEL_GR |
| 76 | + xoutlabel = LABEL_RA |
| 77 | + youtlabel = LABEL_GR |
| 78 | + parnames = ["funcx_function", "funcx"] |
| 79 | + |
| 80 | + def morph(self, x_morph, y_morph, x_target, y_target): |
| 81 | + """Apply the user-supplied Python function to the x-coordinates |
| 82 | + of the morph data.""" |
| 83 | + Morph.morph(self, x_morph, y_morph, x_target, y_target) |
| 84 | + self.x_morph_out = self.funcx_function( |
| 85 | + self.x_morph_in, self.y_morph_in, **self.funcx |
| 86 | + ) |
| 87 | + return self.xyallout |
0 commit comments