Author: bugman Date: Thu Sep 5 15:23:54 2013 New Revision: 20849 URL: http://svn.gna.org/viewcvs/relax?rev=20849&view=rev Log: Changes so that the target function will handle multiple experiment types. This follows from http://thread.gmane.org/gmane.science.nmr.relax.devel/4530, the thread about supporting multiple data types such as SQ+MQ data simultaneously. The data structures from return_r2eff_arrays() now have an additional dimension. The new first dimension is that of the experiment type. This affects the values, errors, and missing data structures. This dimension is stripped in the dispersion target function class for the single experiment type models, but will be preserved for the combined models to be added in the future. Modified: branches/relax_disp/specific_analyses/relax_disp/api.py branches/relax_disp/specific_analyses/relax_disp/disp_data.py branches/relax_disp/target_functions/relax_disp.py Modified: branches/relax_disp/specific_analyses/relax_disp/api.py URL: http://svn.gna.org/viewcvs/relax/branches/relax_disp/specific_analyses/relax_disp/api.py?rev=20849&r1=20848&r2=20849&view=diff ============================================================================== --- branches/relax_disp/specific_analyses/relax_disp/api.py (original) +++ branches/relax_disp/specific_analyses/relax_disp/api.py Thu Sep 5 15:23:54 2013 @@ -47,7 +47,7 @@ from specific_analyses.api_base import API_base from specific_analyses.api_common import API_common from specific_analyses.relax_disp.checks import check_c_modules, check_disp_points, check_exp_type, check_exp_type_fixed_time, check_model_type, check_pipe_type -from specific_analyses.relax_disp.disp_data import average_intensity, find_intensity_keys, get_curve_type, has_exponential_exp_type, loop_cluster, loop_exp_frq, loop_exp_frq_point, loop_exp_frq_point_time, loop_frq, loop_frq_point, loop_frq_point_key, loop_frq_point_time, loop_point, loop_time, relax_time, return_cpmg_frqs, return_index_from_disp_point, return_index_from_frq, return_key_from_disp_point_index, return_offset_data, return_param_key_from_data, return_r1_data, return_r2eff_arrays, return_spin_lock_nu1, return_value_from_frq_index, spin_ids_to_containers +from specific_analyses.relax_disp.disp_data import average_intensity, find_intensity_keys, get_curve_type, has_exponential_exp_type, loop_cluster, loop_exp_frq, loop_exp_frq_point, loop_exp_frq_point_time, loop_frq, loop_frq_point, loop_frq_point_key, loop_frq_point_time, loop_point, loop_time, relax_time, return_cpmg_frqs, return_index_from_disp_point, return_index_from_exp_type, return_index_from_frq, return_key_from_disp_point_index, return_offset_data, return_param_key_from_data, return_r1_data, return_r2eff_arrays, return_spin_lock_nu1, return_value_from_frq_index, spin_ids_to_containers from specific_analyses.relax_disp.parameters import assemble_param_vector, assemble_scaling_matrix, disassemble_param_vector, linear_constraints, loop_parameters, param_conversion, param_index_to_param_info, param_num from specific_analyses.relax_disp.variables import EXP_TYPE_LIST_FIXED_TIME, EXP_TYPE_LIST_VAR_TIME, MODEL_LIST_FULL, MODEL_LM63, MODEL_LM63_3SITE, MODEL_CR72, MODEL_CR72_FULL, MODEL_DPL94, MODEL_IT99, MODEL_M61, MODEL_M61B, MODEL_NOREX, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_R1RHO_2SITE, MODEL_R2EFF, MODEL_TP02, MODEL_TSMFK01 from target_functions.relax_disp import Dispersion @@ -128,7 +128,7 @@ field_count = cdp.spectrometer_frq_count # Initialise the data structures for the target function. - values, errors, missing, frqs = return_r2eff_arrays(spins=[spin], spin_ids=[spin_id], fields=fields, field_count=field_count) + values, errors, missing, frqs, exp_types = return_r2eff_arrays(spins=[spin], spin_ids=[spin_id], fields=fields, field_count=field_count) # The offset and R1 data for R1rho off-resonance models. chemical_shifts, offsets, tilt_angles, r1 = None, None, None, None @@ -137,7 +137,7 @@ r1 = return_r1_data(spins=[spin], spin_ids=[spin_id], fields=fields, field_count=field_count) # Initialise the relaxation dispersion fit functions. - model = Dispersion(model=spin.model, num_params=param_num(spins=[spin]), num_spins=1, num_frq=field_count, num_disp_points=cdp.dispersion_points, values=values, errors=errors, missing=missing, frqs=frqs, cpmg_frqs=return_cpmg_frqs(ref_flag=False), spin_lock_nu1=return_spin_lock_nu1(ref_flag=False), chemical_shifts=chemical_shifts, spin_lock_offsets=offsets, tilt_angles=tilt_angles, r1=r1, relax_time=cdp.relax_time_list[0], scaling_matrix=scaling_matrix) + model = Dispersion(model=spin.model, num_params=param_num(spins=[spin]), num_spins=1, num_frq=field_count, num_disp_points=cdp.dispersion_points, exp_types=exp_types, values=values, errors=errors, missing=missing, frqs=frqs, cpmg_frqs=return_cpmg_frqs(ref_flag=False), spin_lock_nu1=return_spin_lock_nu1(ref_flag=False), chemical_shifts=chemical_shifts, spin_lock_offsets=offsets, tilt_angles=tilt_angles, r1=r1, relax_time=cdp.relax_time_list[0], scaling_matrix=scaling_matrix) # Make a single function call. This will cause back calculation and the data will be stored in the class instance. model.func(param_vector) @@ -146,6 +146,7 @@ results = {} for exp_type, frq, point in loop_exp_frq_point(): # The indices. + exp_type_index = return_index_from_exp_type(exp_type=exp_type) frq_index = return_index_from_frq(frq) point_index = return_index_from_disp_point(point, exp_type=exp_type) @@ -153,7 +154,7 @@ param_key = return_param_key_from_data(frq=frq, point=point) # Skip missing data. - if missing[0, frq_index, point_index]: + if missing[exp_type_index, 0, frq_index, point_index]: continue # Store the result. @@ -1110,7 +1111,7 @@ raise RelaxError("The spectrometer frequency information has not been specified.") # The R2eff/R1rho data. - values, errors, missing, frqs = return_r2eff_arrays(spins=spins, spin_ids=spin_ids, fields=fields, field_count=field_count, sim_index=sim_index) + values, errors, missing, frqs, exp_types = return_r2eff_arrays(spins=spins, spin_ids=spin_ids, fields=fields, field_count=field_count, sim_index=sim_index) # The offset and R1 data for R1rho off-resonance models. chemical_shifts, offsets, tilt_angles, r1 = None, None, None, None @@ -1149,7 +1150,7 @@ print("Unconstrained grid search size: %s (constraints may decrease this size).\n" % grid_size) # Initialise the function to minimise. - model = Dispersion(model=spins[0].model, num_params=param_num(spins=spins), num_spins=len(spins), num_frq=field_count, num_disp_points=cdp.dispersion_points, values=values, errors=errors, missing=missing, frqs=frqs, cpmg_frqs=return_cpmg_frqs(ref_flag=False), spin_lock_nu1=return_spin_lock_nu1(ref_flag=False), chemical_shifts=chemical_shifts, spin_lock_offsets=offsets, tilt_angles=tilt_angles, r1=r1, relax_time=cdp.relax_time_list[0], scaling_matrix=scaling_matrix) + model = Dispersion(model=spins[0].model, num_params=param_num(spins=spins), num_spins=len(spins), num_frq=field_count, num_disp_points=cdp.dispersion_points, exp_types=exp_types, values=values, errors=errors, missing=missing, frqs=frqs, cpmg_frqs=return_cpmg_frqs(ref_flag=False), spin_lock_nu1=return_spin_lock_nu1(ref_flag=False), chemical_shifts=chemical_shifts, spin_lock_offsets=offsets, tilt_angles=tilt_angles, r1=r1, relax_time=cdp.relax_time_list[0], scaling_matrix=scaling_matrix) # Grid search. if search('^[Gg]rid', min_algor): @@ -1237,11 +1238,12 @@ # Loop over the R2eff data. for exp_type, frq, point in loop_exp_frq_point(): # The indices. + exp_type_index = return_index_from_exp_type(exp_type=exp_type) disp_pt_index = return_index_from_disp_point(point, exp_type=exp_type) frq_index = return_index_from_frq(frq) # Missing data. - if missing[spin_index, frq_index, disp_pt_index]: + if missing[exp_type_index, spin_index, frq_index, disp_pt_index]: continue # The R2eff key. Modified: branches/relax_disp/specific_analyses/relax_disp/disp_data.py URL: http://svn.gna.org/viewcvs/relax/branches/relax_disp/specific_analyses/relax_disp/disp_data.py?rev=20849&r1=20848&r2=20849&view=diff ============================================================================== --- branches/relax_disp/specific_analyses/relax_disp/disp_data.py (original) +++ branches/relax_disp/specific_analyses/relax_disp/disp_data.py Thu Sep 5 15:23:54 2013 @@ -982,6 +982,23 @@ return index +def return_index_from_exp_type(exp_type=None): + """Convert the experiment type into the corresponding index. + + @keyword exp_type: The experiment type. + @type exp_type: str + @return: The corresponding index. + @rtype: int + """ + + # Check. + if exp_type == None: + raise RelaxError("The experiment type has not been supplied.") + + # Return the index. + return cdp.exp_type_list.index(exp_type) + + def return_index_from_frq(value): """Convert the dispersion point data into the corresponding index. @@ -1287,12 +1304,13 @@ """ # The counts. + exp_num = num_exp_types() spin_num = len(spins) # Initialise the data structures for the target function (errors are set to one to avoid divide by zero for missing data in the chi-squared function). - values = zeros((spin_num, field_count, cdp.dispersion_points), float64) - errors = ones((spin_num, field_count, cdp.dispersion_points), float64) - missing = ones((spin_num, field_count, cdp.dispersion_points), int32) + values = zeros((exp_num, spin_num, field_count, cdp.dispersion_points), float64) + errors = ones((exp_num, spin_num, field_count, cdp.dispersion_points), float64) + missing = ones((exp_num, spin_num, field_count, cdp.dispersion_points), int32) frqs = zeros((spin_num, field_count), float64) # Pack the R2eff/R1rho data. @@ -1313,6 +1331,7 @@ # Loop over the R2eff data. for exp_type, frq, point in loop_exp_frq_point(): # The indices. + exp_type_index = return_index_from_exp_type(exp_type=exp_type) disp_pt_index = return_index_from_disp_point(point, exp_type=exp_type) frq_index = return_index_from_frq(frq) @@ -1329,22 +1348,25 @@ # The values. if sim_index == None: - values[spin_index, frq_index, disp_pt_index] = spin.r2eff[key] + values[exp_type_index, spin_index, frq_index, disp_pt_index] = spin.r2eff[key] else: - values[spin_index, frq_index, disp_pt_index] = spin.r2eff_sim[sim_index][key] + values[exp_type_index, spin_index, frq_index, disp_pt_index] = spin.r2eff_sim[sim_index][key] # The errors. - errors[spin_index, frq_index, disp_pt_index] = spin.r2eff_err[key] + errors[exp_type_index, spin_index, frq_index, disp_pt_index] = spin.r2eff_err[key] # Flip the missing flag to off. - missing[spin_index, frq_index, disp_pt_index] = 0 + missing[exp_type_index, spin_index, frq_index, disp_pt_index] = 0 # No R2eff/R1rho data for the spin cluster. if not data_flag: raise RelaxError("No R2eff/R1rho data could be found for the spin cluster %s." % spin_ids) + # The experiment types. + exp_types = cdp.exp_type_list + # Return the structures. - return values, errors, missing, frqs + return values, errors, missing, frqs, exp_types def return_spin_lock_nu1(ref_flag=True): Modified: branches/relax_disp/target_functions/relax_disp.py URL: http://svn.gna.org/viewcvs/relax/branches/relax_disp/target_functions/relax_disp.py?rev=20849&r1=20848&r2=20849&view=diff ============================================================================== --- branches/relax_disp/target_functions/relax_disp.py (original) +++ branches/relax_disp/target_functions/relax_disp.py Thu Sep 5 15:23:54 2013 @@ -43,11 +43,11 @@ from lib.dispersion.tsmfk01 import r2eff_TSMFK01 from lib.errors import RelaxError from target_functions.chi2 import chi2 -from specific_analyses.relax_disp.variables import MODEL_CR72, MODEL_CR72_FULL, MODEL_DPL94, MODEL_IT99, MODEL_LIST_FULL, MODEL_LM63, MODEL_LM63_3SITE, MODEL_M61, MODEL_M61B, MODEL_NOREX, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_R1RHO_2SITE, MODEL_R2EFF, MODEL_TP02, MODEL_TSMFK01 +from specific_analyses.relax_disp.variables import MODEL_CR72, MODEL_CR72_FULL, MODEL_DPL94, MODEL_IT99, MODEL_LIST_CPMG, MODEL_LIST_FULL, MODEL_LIST_R1RHO, MODEL_LM63, MODEL_LM63_3SITE, MODEL_M61, MODEL_M61B, MODEL_NOREX, MODEL_NS_CPMG_2SITE_3D, MODEL_NS_CPMG_2SITE_3D_FULL, MODEL_NS_CPMG_2SITE_EXPANDED, MODEL_NS_CPMG_2SITE_STAR, MODEL_NS_CPMG_2SITE_STAR_FULL, MODEL_NS_R1RHO_2SITE, MODEL_R2EFF, MODEL_TP02, MODEL_TSMFK01 class Dispersion: - def __init__(self, model=None, num_params=None, num_spins=None, num_frq=None, num_disp_points=None, values=None, errors=None, missing=None, frqs=None, cpmg_frqs=None, spin_lock_nu1=None, chemical_shifts=None, spin_lock_offsets=None, tilt_angles=None, r1=None, relax_time=None, scaling_matrix=None): + def __init__(self, model=None, num_params=None, num_spins=None, num_frq=None, num_disp_points=None, exp_types=None, values=None, errors=None, missing=None, frqs=None, cpmg_frqs=None, spin_lock_nu1=None, chemical_shifts=None, spin_lock_offsets=None, tilt_angles=None, r1=None, relax_time=None, scaling_matrix=None): """Relaxation dispersion target functions for optimisation. Models @@ -86,12 +86,14 @@ @type num_frq: int @keyword num_disp_points: The number of points on the dispersion curve. @type num_disp_points: int - @keyword values: The R2eff/R1rho values. The first dimension is that of the spin cluster (each element corresponds to a different spin in the block), the second dimension is the spectrometer field strength, and the third is the dispersion points. - @type values: numpy rank-3 float array - @keyword errors: The R2eff/R1rho errors. The three dimensions must correspond to those of the values argument. - @type errors: numpy rank-3 float array - @keyword missing: The data structure indicating missing R2eff/R1rho data. The three dimensions must correspond to those of the values argument. - @type missing: numpy rank-3 int array + @keyword exp_types: The list of experiment types. + @type exp_types: list of str + @keyword values: The R2eff/R1rho values. The dimensions are: the experiment type; the spin cluster (each element corresponds to a different spin in the block); the spectrometer field strength; and the dispersion points. + @type values: numpy rank-4 float array + @keyword errors: The R2eff/R1rho errors. The dimensions must correspond to those of the values argument. + @type errors: numpy rank-4 float array + @keyword missing: The data structure indicating missing R2eff/R1rho data. The dimensions must correspond to those of the values argument. + @type missing: numpy rank-4 int array @keyword frqs: The spin Larmor frequencies (in MHz*2pi to speed up the ppm to rad/s conversion). The dimensions correspond to the first two of the value, error and missing structures. @type frqs: numpy rank-2 float array @keyword cpmg_frqs: The CPMG frequencies in Hertz for each separate dispersion point. This will be ignored for R1rho experiments. @@ -128,6 +130,7 @@ raise RelaxError("R1 relaxation rates must be supplied for the '%s' R1rho off-resonance dispersion model." % model) # Store the arguments. + self.model = model self.num_params = num_params self.num_spins = num_spins self.num_frq = num_frq @@ -144,6 +147,9 @@ self.r1 = r1 self.relax_time = relax_time self.scaling_matrix = scaling_matrix + + # Check the experiment types, simplifying the data structures as needed. + self.experiment_type_setup() # Scaling initialisation. self.scaling_flag = False @@ -402,6 +408,19 @@ return chi2_sum + def experiment_type_setup(self): + """Check the experiment types and simplify data structures. + + For the single experiment type models, the first dimension of the values, errors, and missing data structures will be removed to simplify the target functions. + """ + + # The CPMG and R1rho single models. + if self.model in MODEL_LIST_CPMG + MODEL_LIST_R1RHO: + self.values = self.values[0] + self.errors = self.errors[0] + self.missing = self.missing[0] + + def func_CR72(self, params): """Target function for the reduced Carver and Richards (1972) 2-site exchange model on all time scales.