예제 #1
0
    def run(self, processor, completed):
        """Set up and perform the optimisation."""

        # Print out.
        if self.verbosity >= 1:
            # Individual spin block section.
            top = 2
            if self.verbosity >= 2:
                top += 2
            subsection(file=sys.stdout, text="Fitting to the spin block %s"%self.spin_ids, prespace=top)

            # Grid search printout.
            if search('^[Gg]rid', self.min_algor):
                result = 1
                for x in self.inc:
                    result = mul(result, x)
                print("Unconstrained grid search size: %s (constraints may decrease this size).\n" % result)

        # Initialise the function to minimise.
        model = Dispersion(model=self.spins[0].model, num_params=self.param_num, num_spins=count_spins(self.spins), num_frq=len(self.fields), exp_types=self.exp_types, values=self.values, errors=self.errors, missing=self.missing, frqs=self.frqs, frqs_H=self.frqs_H, cpmg_frqs=self.cpmg_frqs, spin_lock_nu1=self.spin_lock_nu1, chemical_shifts=self.chemical_shifts, offset=self.offsets, tilt_angles=self.tilt_angles, r1=self.r1, relax_times=self.relax_times, scaling_matrix=self.scaling_matrix, r1_fit=self.r1_fit)

        # Grid search.
        if search('^[Gg]rid', self.min_algor):
            results = grid(func=model.func, args=(), num_incs=self.inc, lower=self.lower, upper=self.upper, A=self.A, b=self.b, verbosity=self.verbosity)

            # Unpack the results.
            param_vector, chi2, iter_count, warning = results
            f_count = iter_count
            g_count = 0.0
            h_count = 0.0

        # Minimisation.
        else:
            results = generic_minimise(func=model.func, args=(), x0=self.param_vector, min_algor=self.min_algor, min_options=self.min_options, func_tol=self.func_tol, grad_tol=self.grad_tol, maxiter=self.max_iterations, A=self.A, b=self.b, full_output=True, print_flag=self.verbosity)

            # Unpack the results.
            if results == None:
                return
            param_vector, chi2, iter_count, f_count, g_count, h_count, warning = results

        # Optimisation printout.
        if self.verbosity:
            print("\nOptimised parameter values:")
            for i in range(len(param_vector)):
                print("%-20s %25.15f" % (self.param_names[i], param_vector[i]*self.scaling_matrix[i, i]))

        # Create the result command object to send back to the master.
        processor.return_object(Disp_result_command(processor=processor, memo_id=self.memo_id, param_vector=param_vector, chi2=chi2, iter_count=iter_count, f_count=f_count, g_count=g_count, h_count=h_count, warning=warning, missing=self.missing, back_calc=model.get_back_calc(), completed=False))
예제 #2
0
    def __init__(self,
                 exp_type=None,
                 num_spins=1,
                 model=None,
                 r2=None,
                 r2a=None,
                 r2b=None,
                 phi_ex=None,
                 phi_ex_B=None,
                 phi_ex_C=None,
                 dw=None,
                 dw_AB=None,
                 dw_BC=None,
                 dwH=None,
                 dwH_AB=None,
                 dwH_BC=None,
                 pA=None,
                 pB=None,
                 kex=None,
                 kex_AB=None,
                 kex_BC=None,
                 kex_AC=None,
                 kB=None,
                 kC=None,
                 k_AB=None,
                 tex=None,
                 spins_params=None):
        """Special method __init__() is called first (acts as Constructor).

        It brings in data from outside the class like the variable num_spins (in this case num_spins is also set to a default value of 1).  The first parameter of any method/function in the class is always self, the name self is used by convention.  Assigning num_spins to self.num_spins allows it to be passed to all methods within the class.  Think of self as a carrier, or if you want impress folks call it target instance object.

        @keyword exp_type:      The list of experiment types.
        @type exp_type:         list of str
        @keyword num_spins:     Number of spins in the cluster.
        @type num_spins:        integer
        @keyword model:         The dispersion model to instantiate the Dispersion class with.
        @type model:            string
        @keyword r2:            The transversal relaxation rate.
        @type r2:               float
        @keyword r2a:           The transversal relaxation rate for state A in the absence of exchange.
        @type r2a:              float
        @keyword r2b:           The transversal relaxation rate for state B in the absence of exchange.
        @type r2b:              float
        @keyword phi_ex:        The phi_ex = pA.pB.dw**2 value (ppm^2)
        @type phi_ex:           float
        @keyword phi_ex_B:      The fast exchange factor between sites A and B (ppm^2)
        @type phi_ex_B:         float
        @keyword phi_ex_C:      The fast exchange factor between sites A and C (ppm^2)
        @type phi_ex_C:         float
        @keyword dw:            The chemical exchange difference between states A and B in ppm.
        @type dw:               float
        @keyword pA:            The population of state A.
        @type pA:               float
        @keyword kex:           The rate of exchange.
        @type kex:              float
        @keyword kB :           The rate of exchange.
        @type kB:               float
        @keyword kC:            The rate of exchange.
        @type kC:               float
        @keyword k_AB:          The exchange rate from state A to state B
        @type k_AB:             float
        @keyword tex:           The exchange time.
        @type tex:              float
        @keyword spins_params:  List of parameter strings used in dispersion model.
        @type spins_params:     array of strings
        """

        # Define parameters
        self.exp_type = exp_type
        self.model = model
        self.num_spins = num_spins
        #self.fields = array([800. * 1E6])
        #self.fields = array([600. * 1E6, 800. * 1E6])
        self.fields = array([600. * 1E6, 800. * 1E6, 900. * 1E6])

        # Set The spin-lock field strength, nu1, in Hz
        self.spin_lock_fields = [431.0, 651.2, 800.5, 984.0, 1341.11]

        # Required data structures.
        self.relax_times = self.fields / (100 * 100. * 1E6)
        self.ncycs = []
        self.points = []
        self.value = []
        self.error = []
        for i in range(len(self.fields)):
            ncyc = arange(2, 1000. * self.relax_times[i], 4)
            #ncyc = arange(2, 42, 2)
            self.ncycs.append(ncyc)
            print("sfrq: ", self.fields[i], "number of cpmg frq", len(ncyc),
                  ncyc)

            # CPMG data.
            if EXP_TYPE_CPMG_SQ in self.exp_type or EXP_TYPE_CPMG_MQ in self.exp_type:
                cpmg_point = ncyc / self.relax_times[i]

                self.points.append(list(cpmg_point))
                self.value.append([2.0] * len(cpmg_point))
                self.error.append([1.0] * len(cpmg_point))

            # R1rho data.
            else:
                points = self.spin_lock_fields

                self.points.append(list(points))
                self.value.append([2.0] * len(self.spin_lock_fields))
                self.error.append([1.0] * len(self.spin_lock_fields))

        # Spin lock offsets in ppm.
        if EXP_TYPE_CPMG_SQ in self.exp_type or EXP_TYPE_CPMG_MQ in self.exp_type:
            self.offsets = [0]
        else:
            self.offsets = list(range(10))

        # Chemical shift in ppm.
        self.chemical_shift = 1.0

        # Assemble param vector.
        self.params = self.assemble_param_vector(r2=r2,
                                                 r2a=r2a,
                                                 r2b=r2b,
                                                 phi_ex=phi_ex,
                                                 phi_ex_B=phi_ex_B,
                                                 phi_ex_C=phi_ex_C,
                                                 dw=dw,
                                                 dw_AB=dw_AB,
                                                 dw_BC=dw_BC,
                                                 dwH=dwH,
                                                 dwH_AB=dwH_AB,
                                                 dwH_BC=dwH_BC,
                                                 pA=pA,
                                                 pB=pB,
                                                 kex=kex,
                                                 kex_AB=kex_AB,
                                                 kex_BC=kex_BC,
                                                 kex_AC=kex_AC,
                                                 kB=kB,
                                                 kC=kC,
                                                 k_AB=k_AB,
                                                 tex=tex,
                                                 spins_params=spins_params)

        # Make nested list arrays of data. And return them.
        values, errors, cpmg_frqs, missing, frqs, frqs_H, exp_types, relax_times, offsets, spin_lock_nu1 = self.return_r2eff_arrays(
        )

        # The offset and R1 data.
        chemical_shifts, offsets, tilt_angles, Delta_omega, w_eff = self.return_offset_data(
        )
        r1 = ones([self.num_spins, self.fields.shape[0]])

        # relax version compatibility.
        self.relax_times_compat = relax_times
        if version == 'repository checkout' or version_comparison(
                version, '3.2.3') == 1:
            self.relax_times_compat = []
            for ei in range(len(self.exp_type)):
                self.relax_times_compat.append([])
                for mi in range(len(self.fields)):
                    self.relax_times_compat[ei].append([])
                    for oi in range(len(self.offsets)):
                        self.relax_times_compat[ei][mi].append([])
                        for di in range(len(self.points[mi])):
                            self.relax_times_compat[ei][mi][oi].append(
                                self.relax_times.tolist())

        # Init the Dispersion class.
        self.model = Dispersion(model=self.model,
                                num_params=None,
                                num_spins=self.num_spins,
                                num_frq=len(self.fields),
                                exp_types=exp_types,
                                values=values,
                                errors=errors,
                                missing=missing,
                                frqs=frqs,
                                frqs_H=frqs_H,
                                cpmg_frqs=cpmg_frqs,
                                spin_lock_nu1=spin_lock_nu1,
                                chemical_shifts=chemical_shifts,
                                offset=offsets,
                                tilt_angles=tilt_angles,
                                r1=r1,
                                relax_times=self.relax_times_compat,
                                scaling_matrix=None)
예제 #3
0
def back_calc_r2eff(spins=None, spin_ids=None, cpmg_frqs=None, spin_lock_offset=None, spin_lock_nu1=None, relax_times_new=None, store_chi2=False):
    """Back-calculation of R2eff/R1rho values for the given spin.

    @keyword spins:             The list of specific spin data container for cluster.
    @type spins:                List of SpinContainer instances
    @keyword spin_ids:          The list of spin ID strings for the spin containers in cluster.
    @type spin_ids:             list of str
    @keyword cpmg_frqs:         The CPMG frequencies to use instead of the user loaded values - to enable interpolation.
    @type cpmg_frqs:            list of lists of numpy rank-1 float arrays
    @keyword spin_lock_offset:  The spin-lock offsets to use instead of the user loaded values - to enable interpolation.
    @type spin_lock_offset:     list of lists of numpy rank-1 float arrays
    @keyword spin_lock_nu1:     The spin-lock field strengths to use instead of the user loaded values - to enable interpolation.
    @type spin_lock_nu1:        list of lists of numpy rank-1 float arrays
    @keyword relax_times_new:   The interpolated experiment specific fixed time period for relaxation (in seconds).  The dimensions are {Ei, Mi, Oi, Di, Ti}.
    @type relax_times_new:      rank-4 list of floats
    @keyword store_chi2:        A flag which if True will cause the spin specific chi-squared value to be stored in the spin container.
    @type store_chi2:           bool
    @return:                    The back-calculated R2eff/R1rho value for the given spin.
    @rtype:                     numpy rank-1 float array
    """

    # Create the initial parameter vector.
    param_vector = assemble_param_vector(spins=spins)

    # Number of spectrometer fields.
    fields = [None]
    field_count = 1
    if hasattr(cdp, 'spectrometer_frq_count'):
        fields = cdp.spectrometer_frq_list
        field_count = cdp.spectrometer_frq_count

    # Initialise the data structures for the target function.
    values, errors, missing, frqs, frqs_H, exp_types, relax_times = return_r2eff_arrays(spins=spins, spin_ids=spin_ids, fields=fields, field_count=field_count)

    # The offset and R1 data.
    r1_setup()
    offsets, spin_lock_fields_inter, chemical_shifts, tilt_angles, Delta_omega, w_eff = return_offset_data(spins=spins, spin_ids=spin_ids, field_count=field_count, spin_lock_offset=spin_lock_offset, fields=spin_lock_nu1)
    r1 = return_r1_data(spins=spins, spin_ids=spin_ids, field_count=field_count)
    r1_fit = is_r1_optimised(spins[0].model)

    # The relaxation times.
    if relax_times_new != None:
        relax_times = relax_times_new

    # The dispersion data.
    recalc_tau = True
    if cpmg_frqs == None and spin_lock_nu1 == None and spin_lock_offset == None:
        cpmg_frqs = return_cpmg_frqs(ref_flag=False)
        spin_lock_nu1 = return_spin_lock_nu1(ref_flag=False)

    # Reset the cpmg_frqs if interpolating R1rho models.
    elif cpmg_frqs == None and spin_lock_offset != None:
        cpmg_frqs = None
        spin_lock_nu1 = spin_lock_fields_inter

        recalc_tau = False
        values = []
        errors = []
        missing = []
        for exp_type, ei in loop_exp(return_indices=True):
            values.append([])
            errors.append([])
            missing.append([])
            for si in range(len(spins)):
                values[ei].append([])
                errors[ei].append([])
                missing[ei].append([])
                for frq, mi in loop_frq(return_indices=True):
                    values[ei][si].append([])
                    errors[ei][si].append([])
                    missing[ei][si].append([])
                    for oi, offset in enumerate(offsets[ei][si][mi]):
                        num = len(spin_lock_nu1[ei][mi][oi])

                        values[ei][si][mi].append(zeros(num, float64))
                        errors[ei][si][mi].append(ones(num, float64))
                        missing[ei][si][mi].append(zeros(num, int32))

    # Reconstruct the structures for interpolation.
    else:
        recalc_tau = False
        values = []
        errors = []
        missing = []
        for exp_type, ei in loop_exp(return_indices=True):
            values.append([])
            errors.append([])
            missing.append([])
            for si in range(len(spins)):
                values[ei].append([])
                errors[ei].append([])
                missing[ei].append([])
                for frq, mi in loop_frq(return_indices=True):
                    values[ei][si].append([])
                    errors[ei][si].append([])
                    missing[ei][si].append([])
                    for offset, oi in loop_offset(exp_type=exp_type, frq=frq, return_indices=True):
                        if exp_type in EXP_TYPE_LIST_CPMG:
                            num = len(cpmg_frqs[ei][mi][oi])
                        else:
                            num = len(spin_lock_nu1[ei][mi][oi])
                        values[ei][si][mi].append(zeros(num, float64))
                        errors[ei][si][mi].append(ones(num, float64))
                        missing[ei][si][mi].append(zeros(num, int32))

    # Initialise the relaxation dispersion fit functions.
    model = Dispersion(model=spins[0].model, num_params=param_num(spins=spins), num_spins=len(spins), num_frq=field_count, exp_types=exp_types, values=values, errors=errors, missing=missing, frqs=frqs, frqs_H=frqs_H, cpmg_frqs=cpmg_frqs, spin_lock_nu1=spin_lock_nu1, chemical_shifts=chemical_shifts, offset=offsets, tilt_angles=tilt_angles, r1=r1, relax_times=relax_times, recalc_tau=recalc_tau, r1_fit=r1_fit)

    # Make a single function call.  This will cause back calculation and the data will be stored in the class instance.
    chi2 = model.func(param_vector)

    # Store the chi-squared value.
    if store_chi2:
        for spin in spins:
            spin.chi2 = chi2

    # Return the structure.
    return model.get_back_calc()