Hi Troels, For the Jacobian matrix which has the dimensions NxM, where N is the number of model parameters and M is the number of input data points (R2eff/R1rho/R1), you will have to construct it differently. Then scaling via a dot product with the scaling matrix will just work.
Regards, Edward On 2 September 2014 10:29, <[email protected]> wrote: > Author: tlinnet > Date: Tue Sep 2 10:29:50 2014 > New Revision: 25531 > > URL: http://svn.gna.org/viewcvs/relax?rev=25531&view=rev > Log: > To target function, added function which will calculate the Jacobian and its > corresponding unit conversion matrix and return them. > > task #7824(https://gna.org/task/index.php?7824): Model parameter ERROR > estimation from Jacobian and Co-variance matrix of dispersion models. > > Modified: > branches/est_par_error/target_functions/relax_disp.py > > Modified: branches/est_par_error/target_functions/relax_disp.py > URL: > http://svn.gna.org/viewcvs/relax/branches/est_par_error/target_functions/relax_disp.py?rev=25531&r1=25530&r2=25531&view=diff > ============================================================================== > --- branches/est_par_error/target_functions/relax_disp.py (original) > +++ branches/est_par_error/target_functions/relax_disp.py Tue Sep 2 > 10:29:50 2014 > @@ -26,7 +26,7 @@ > > # Python module imports. > from copy import deepcopy > -from numpy import all, arctan2, cos, dot, float64, int16, isfinite, max, > multiply, ones, rollaxis, pi, sin, sum, version, zeros > +from numpy import all, arctan2, array, cos, divide, dot, float64, int16, > isfinite, max, multiply, ones, rollaxis, pi, sin, sum, transpose, version, > zeros > from numpy.ma import masked_equal > > # relax module imports. > @@ -497,10 +497,18 @@ > # Transpose M0, to prepare for dot operation. Roll the last axis > one back, corresponds to a transpose for the outer two axis. > self.M0_T = rollaxis(self.M0, 6, 5) > > + # Set up parameters related to the Jacobian. > + # Set Jacobian function to None as standard. > + self.func_jacobian = None > + > + # Structure of data arrays for calculation in Jacobian function. > + # This is for speed, since it minimises the creation of array > structures for each function call. > + # Creating new structures is a safety measure, where a minimisation > could possible call both > + # the function and the Jacobian, and overwrite each other. Even > though they should be the same. > + self.r20a_struct_jac = deepcopy(self.r20a_struct) > + self.dw_struct_jac = deepcopy(self.dw_struct) > + > # Set up the model. > - # Set Jacobian to None as standard. > - self.jacobian = None > - > if model == MODEL_NOREX: > # FIXME: Handle mixed experiment types here - probably by > merging target functions. > if self.exp_types[0] in EXP_TYPE_LIST_CPMG: > @@ -522,7 +530,7 @@ > self.func = self.func_IT99 > if model == MODEL_TSMFK01: > self.func = self.func_TSMFK01 > - self.jacobian = self.func_TSMFK01_jacobian > + self.func_jacobian = self.func_TSMFK01_jacobian > if model == MODEL_B14: > self.func = self.func_B14 > if model == MODEL_B14_FULL: > @@ -2193,40 +2201,33 @@ > k_AB = params[self.end_index[1]] > > # Convert dw from ppm to rad/s. Use the out argument, to pass > directly to structure. > - multiply( multiply.outer( dw.reshape(1, self.NS), self.nm_no_nd_ones > ), self.frqs, out=self.dw_struct ) > + multiply( multiply.outer( dw.reshape(1, self.NS), self.nm_no_nd_ones > ), self.frqs, out=self.dw_struct_jac ) > > # Reshape R20A and R20B to per experiment, spin and frequency. > - self.r20a_struct[:] = multiply.outer( R20A.reshape(self.NE, self.NS, > self.NM), self.no_nd_ones ) > - > - # Get the Jacobian. > - jacobian = r2eff_TSMFK01_jacobian(r20a=self.r20a_struct, > dw=self.dw_struct, k_AB=k_AB, tcp=self.tau_cpmg) > - > - # Insert checks. > - if True: > - from lib.dispersion.tsmfk01 import d_f_d_r20a, d_f_d_dw, > d_f_d_k_AB > - from numpy import transpose, array, all > - NJ, NE, NS, NM, NO, ND = jacobian.shape > - for ei in range(NE): > - for si in range(NS): > - for mi in range(NM): > - for oi in range(NO): > - print ei, si, mi, oi > - cur_jacobian = jacobian[0:NJ:1, ei, si, mi, oi] > - > - r20a_t = self.r20a_struct[ei, si, mi, oi] > - dw_t = self.dw_struct[ei, si, mi, oi] > - k_AB_t = k_AB > - tcp_t = self.tau_cpmg[ei, si, mi, oi] > - > - get_d_f_d_r20a = d_f_d_r20a(r20a=r20a_t, > dw=dw_t, k_AB=k_AB_t, tcp=tcp_t) > - get_d_f_d_dw = d_f_d_dw(r20a=r20a_t, dw=dw_t, > k_AB=k_AB_t, tcp=tcp_t) > - get_d_f_d_k_AB = d_f_d_k_AB(r20a=r20a_t, > dw=dw_t, k_AB=k_AB_t, tcp=tcp_t) > - > - jac_t = transpose(array( [get_d_f_d_r20a , > get_d_f_d_dw , get_d_f_d_k_AB] ) ) > - > - #print cur_jacobian > - #print jac_t > - print jac_t == cur_jacobian > + self.r20a_struct_jac[:] = multiply.outer( R20A.reshape(self.NE, > self.NS, self.NM), self.no_nd_ones ) > + > + # Get the Jacobian as list of derivatives. > + d_f_d_r20a , d_f_d_dw, d_f_d_k_AB = > r2eff_TSMFK01_jacobian(r20a=self.r20a_struct_jac, dw=self.dw_struct_jac, > k_AB=k_AB, tcp=self.tau_cpmg) > + > + # Convert it to normal representation, where each column is the > derivative. > + jacobian = transpose(array( [d_f_d_r20a, d_f_d_dw, d_f_d_k_AB] ) ) > + > + # If get_jacobian is set to True, calculate a scale back matrix for > the Jacobian from rad/s to corresponding units in relax, and then store in > class. > + # This adds a overhead for the function. > + if self.get_jacobian: > + # Store in class, which will be extracted from function. > + self.jacobian = jacobian > + > + # Define scaling matrix, which will convert the units. > + d_f_d_r20a_scale = ones(d_f_d_r20a.shape) > + > + # Scale from rad/s to ppm. > + d_f_d_dw_scale = divide(ones(d_f_d_dw.shape), self.frqs) > + > + d_f_d_k_AB_scale = ones(d_f_d_k_AB.shape) > + > + # Collect the scaling matrix. > + self.jacobian_scale_mat = transpose(array( > [d_f_d_r20a_scale, d_f_d_dw_scale, d_f_d_k_AB_scale] ) ) > > # Return the Jacobian. > return jacobian > @@ -2255,3 +2256,23 @@ > > return back_calc_return > > + > + def get_jacobian_scaled(self, params): > + """Class function to return Jacobian in scaled units for relax. > + > + @param params: The vector of parameter values. > + @type params: numpy rank-1 float array > + @return: The Jacobian matrix for the current model, scaled > back to relax units. > + @rtype: list of numpy multidimensional array > + """ > + > + # A flag which if True will initialise the calculation to scale back > the jacobian from rad/s to units in relax and store it. > + self.get_jacobian = True > + > + # Make a single call, to store the scaled Jacobian. > + self.func_jacobian(params) > + > + # Now return list with first Jacobian, and scaling matrix to convert > to units in relax. > + # These have been stored in the Class. > + > + return [self.jacobian, self.jacobian_scale_mat] > > > _______________________________________________ > relax (http://www.nmr-relax.com) > > This is the relax-commits mailing list > [email protected] > > To unsubscribe from this list, get a password > reminder, or change your subscription options, > visit the list information page at > https://mail.gna.org/listinfo/relax-commits _______________________________________________ relax (http://www.nmr-relax.com) This is the relax-devel mailing list [email protected] To unsubscribe from this list, get a password reminder, or change your subscription options, visit the list information page at https://mail.gna.org/listinfo/relax-devel

