def setup_data(self): """Function for setting up some data for the unit tests.""" # Get the data pipe. dp = pipes.get_pipe('orig') # Create the first residue and add some data to its spin container. create_residue(1, 'Ala') dp.mol[0].res[0].spin[0].num = 111 dp.mol[0].res[0].spin[0].x = 1 dp.mol[0].name = 'Old mol' # Create a second molecule. dp.mol.add_item('New mol') # Copy the residue to the new molecule. copy_residue(res_from=':1', res_to='#New mol') copy_residue(res_from='#Old mol:1', res_to='#New mol:5') # Change the first residue's data. dp.mol[0].res[0].spin[0].num = 222 dp.mol[0].res[0].spin[0].x = 2 # Update the metadata. metadata_update()
def test_copy_molecule_within_pipe(self): """Test the copying of the molecule data within a single data pipe. The function tested is both pipe_control.mol_res_spin.copy_molecule() and prompt.molecule.copy(). """ # Get the data pipe. dp = pipes.get_pipe('orig') # Create the first molecule and residue and add some data to its spin container. self.molecule_fns.create('Old mol') create_residue(1, 'Ala') dp.mol[0].res[0].spin[0].num = 111 dp.mol[0].res[0].spin[0].x = 1 # Update the metadata. metadata_update() # Copy the molecule a few times. self.molecule_fns.copy(mol_from='#Old mol', mol_to='#2') self.molecule_fns.copy(mol_from='#Old mol', pipe_to='orig', mol_to='#3') # Change the first molecule's data. dp.mol[0].res[0].spin[0].num = 222 dp.mol[0].res[0].spin[0].x = 2 # Update the metadata. metadata_update() # Copy the molecule once more. self.molecule_fns.copy(mol_from='#Old mol', mol_to='#4') # Test the original molecule. self.assertEqual(dp.mol[0].name, 'Old mol') self.assertEqual(dp.mol[0].res[0].num, 1) self.assertEqual(dp.mol[0].res[0].name, 'Ala') self.assertEqual(dp.mol[0].res[0].spin[0].num, 222) self.assertEqual(dp.mol[0].res[0].spin[0].x, 2) # Test the new molecule 2. self.assertEqual(dp.mol[1].name, '2') self.assertEqual(dp.mol[1].res[0].num, 1) self.assertEqual(dp.mol[1].res[0].name, 'Ala') self.assertEqual(dp.mol[1].res[0].spin[0].num, 111) self.assertEqual(dp.mol[1].res[0].spin[0].x, 1) # Test the new molecule 3. self.assertEqual(dp.mol[2].name, '3') self.assertEqual(dp.mol[2].res[0].num, 1) self.assertEqual(dp.mol[2].res[0].name, 'Ala') self.assertEqual(dp.mol[2].res[0].spin[0].num, 111) self.assertEqual(dp.mol[2].res[0].spin[0].x, 1) # Test the new molecule 4. self.assertEqual(dp.mol[3].name, '4') self.assertEqual(dp.mol[3].res[0].num, 1) self.assertEqual(dp.mol[3].res[0].name, 'Ala') self.assertEqual(dp.mol[3].res[0].spin[0].num, 222) self.assertEqual(dp.mol[3].res[0].spin[0].x, 2)
def test_copy_spin_between_pipes(self): """Test the copying of the spin data between different data pipes. The function tested is both pipe_control.mol_res_spin.copy_spin() and prompt.spin.copy(). """ # Copy the spin data. self.spin_fns.copy(spin_from='#Old mol:1@C8', pipe_to='test') # Get the data pipes. dp = pipes.get_pipe('orig') dp_test = pipes.get_pipe('test') # Change the first spin's data. dp.mol[0].res[0].spin[0].num = 222 dp.mol[0].res[0].spin[0].x = 2 # Update the metadata. metadata_update() # Test the original spin. self.assertEqual(dp.mol[0].res[0].spin[0].num, 222) self.assertEqual(dp.mol[0].res[0].spin[0].x, 2) # Test the new spin. self.assertEqual(dp_test.mol[0].res[0].spin[0].num, 111) self.assertEqual(dp_test.mol[0].res[0].spin[0].x, 1)
def test_copy_molecule_between_pipes(self): """Test the copying of the molecule data between different data pipes. The function tested is both pipe_control.mol_res_spin.copy_molecule() and prompt.molecule.copy(). """ # Get the data pipes. dp = pipes.get_pipe('orig') dp_test = pipes.get_pipe('test') # Create the first molecule and residue and add some data to its spin container. self.molecule_fns.create('Old mol') create_residue(1, 'Ala') dp.mol[0].res[0].spin[0].num = 111 dp.mol[0].res[0].spin[0].x = 1 # Update the metadata. metadata_update() # Copy the molecule to the second data pipe. self.molecule_fns.copy(mol_from='#Old mol', pipe_to='test') self.molecule_fns.copy(pipe_from='orig', mol_from='#Old mol', pipe_to='test', mol_to='#New mol') # Change the first molecule's data. dp.mol[0].res[0].spin[0].num = 222 dp.mol[0].res[0].spin[0].x = 2 # Update the metadata. metadata_update() # Test the original molecule. self.assertEqual(dp.mol[0].name, 'Old mol') self.assertEqual(dp.mol[0].res[0].num, 1) self.assertEqual(dp.mol[0].res[0].name, 'Ala') self.assertEqual(dp.mol[0].res[0].spin[0].num, 222) self.assertEqual(dp.mol[0].res[0].spin[0].x, 2) # Test the new molecule. self.assertEqual(dp_test.mol[0].name, 'Old mol') self.assertEqual(dp_test.mol[0].res[0].num, 1) self.assertEqual(dp_test.mol[0].res[0].name, 'Ala') self.assertEqual(dp_test.mol[0].res[0].spin[0].num, 111) self.assertEqual(dp_test.mol[0].res[0].spin[0].x, 1) # Test the second new molecule. self.assertEqual(dp_test.mol[1].name, 'New mol') self.assertEqual(dp_test.mol[1].res[0].num, 1) self.assertEqual(dp_test.mol[1].res[0].name, 'Ala') self.assertEqual(dp_test.mol[1].res[0].spin[0].num, 111) self.assertEqual(dp_test.mol[1].res[0].spin[0].x, 1)
def read(file='results', dir=None): """Function for reading the data out of a file.""" # Test if the current data pipe exists. check_pipe() # Make sure that the data pipe is empty. if not cdp.is_empty(): raise RelaxError("The current data pipe is not empty.") # Get the full file path, for later use. file_path = get_file_path(file_name=file, dir=dir) # Open the file. file = open_read_file(file_name=file_path) # Determine the format of the file. format = determine_format(file) # XML results. if format == 'xml': ds.from_xml(file, dir=dirname(file_path), pipe_to=pipes.cdp_name()) # Columnar results (for backwards compatibility with ancient relax results model-free files). elif format == 'columnar': # Extract the data from the file. file_data = extract_data(file=file) # Strip data. file_data = strip(file_data) # Do nothing if the file does not exist. if not file_data: raise RelaxFileEmptyError # Read the results. read_columnar_results(file_data) # Unknown results file. else: raise RelaxError("The format of the results file " + repr(file_path) + " cannot be determined.") # Update all of the required metadata structures. mol_res_spin.metadata_update() interatomic.metadata_update()
def setUp(self): """Set up some molecules, residues, and spins for testing.""" # Add a data pipe to the data store. ds.add(pipe_name='orig', pipe_type='mf') # Name the first molecule. cdp.mol[0].name = 'Ap4Aase' # Add a second molecule to the system. cdp.mol.add_item(mol_name='RNA') # Add two more residues to the first molecule (and set the residue number of the first). cdp.mol[0].res[0].num = 1 cdp.mol[0].res.add_item(res_num=2, res_name='Glu') cdp.mol[0].res.add_item(res_num=4, res_name='Pro') # Add some spin info to this molecule. cdp.mol[0].res[0].spin[0].name = 'NH' cdp.mol[0].res[0].spin[0].num = 60 cdp.mol[0].res[1].spin[0].name = 'NH' cdp.mol[0].res[1].spin[0].num = 63 # Add one more residue to the second molecule (and set the residue number of the first). cdp.mol[1].res[0].num = -5 cdp.mol[1].res.add_item(res_num=-4) # Add a second set of spins to the second molecule (naming the first set first). cdp.mol[1].res[0].spin[0].name = 'C8' cdp.mol[1].res[1].spin[0].name = 'C8' cdp.mol[1].res[0].spin.add_item(spin_name='N5') cdp.mol[1].res[1].spin.add_item(spin_name='N5') cdp.mol[1].res[1].spin.add_item(spin_name='2H', spin_num=132) # Deselect a number of spins. cdp.mol[0].res[0].spin[0].select = 0 cdp.mol[0].res[2].spin[0].select = 0 cdp.mol[1].res[0].spin[0].select = 0 cdp.mol[1].res[1].spin[1].select = 0 # Update the metadata. mol_res_spin.metadata_update()
def test_copy_molecule_between_pipes_fail_no_pipe(self): """Test the failure of copying of the molecule data between different data pipes. The function tested is both pipe_control.mol_res_spin.copy_molecule() and prompt.molecule.copy(). """ # Get the data pipe. dp = pipes.get_pipe('orig') # Create the first molecule and residue and add some data to its spin container. self.molecule_fns.create('Old mol') create_residue(1, 'Ala') dp.mol[0].res[0].spin[0].num = 111 dp.mol[0].res[0].spin[0].x = 1 # Update the metadata. metadata_update() # Copy the molecule to the second data pipe. self.assertRaises(RelaxNoPipeError, self.molecule_fns.copy, mol_from='#Old mol', pipe_to='test2')
def load_state(state=None, dir=None, verbosity=1, force=False): """Function for loading a saved program state. @keyword state: The saved state file. @type state: str @keyword dir: The path of the state file. @type dir: str @keyword verbosity: The verbosity level. @type verbosity: int @keyword force: If True, the relax data store will be reset prior to state loading. @type force: bool """ # Open the file for reading. file = open_read_file(file_name=state, dir=dir, verbosity=verbosity) # Reset. if force: reset() # Make sure that the data store is empty. if not ds.is_empty(): raise RelaxError("The relax data store is not empty.") # Restore from the XML. ds.from_xml(file) # Update all of the required metadata structures. for pipe, pipe_name in pipes.pipe_loop(name=True): mol_res_spin.metadata_update(pipe=pipe_name) interatomic.metadata_update(pipe=pipe_name) # Signal a change in the current data pipe. status.observers.pipe_alteration.notify() # Signal the state loading status.observers.state_load.notify()
def setUp(self): """Set up for all the spin unit tests. The data contained within the 'orig' data pipe is: ID Molecule Res number Res name Spin number Spin name 0,0,0 Old mol 1 Ala 111 C8 0,0,1 Old mol 1 Ala 6 C19 0,0,2 Old mol 1 Ala 7 C21 0,0,3 Old mol 1 Ala 8 C24 0,0,4 Old mol 1 Ala 9 C26 0,1,0 Old mol 2 Arg 78 NH 1,0,0 New mol 5 Lys 239 NH 1,1,0 New mol 6 Thr None None 1,1,1 New mol 6 Thr 3239 NH The IDs correspond to the molecule, residue and spin indices. """ # Add a data pipe to the data store. ds.add(pipe_name='orig', pipe_type='mf') # Add a second data pipe for copying tests. ds.add(pipe_name='test', pipe_type='mf') # Set the current data pipe to 'orig'. pipes.switch('orig') # Name the first molecule. cdp.mol[0].name = 'Old mol' # Create the first residue and add some data to its spin container. cdp.mol[0].res[0].num = 1 cdp.mol[0].res[0].name = 'Ala' cdp.mol[0].res[0].spin[0].num = 111 cdp.mol[0].res[0].spin[0].name = 'C8' cdp.mol[0].res[0].spin[0].x = 1 # Add some more spins. cdp.mol[0].res[0].spin.add_item('C19', 6) cdp.mol[0].res[0].spin.add_item('C21', 7) cdp.mol[0].res[0].spin.add_item('C24', 8) cdp.mol[0].res[0].spin.add_item('C26', 9) # Create a second residue. cdp.mol[0].res.add_item('Arg', 2) cdp.mol[0].res[1].spin[0].num = 78 cdp.mol[0].res[1].spin[0].name = 'NH' # Create a second molecule. cdp.mol.add_item('New mol') # Create the first and second residue of the second molecule and add some data to its spin container. cdp.mol[1].res[0].num = 5 cdp.mol[1].res[0].name = 'Lys' cdp.mol[1].res[0].spin[0].num = 239 cdp.mol[1].res[0].spin[0].name = 'NH' cdp.mol[1].res.add_item('Thr', 6) cdp.mol[1].res[1].spin.add_item(None, 1433) cdp.mol[1].res[1].spin.add_item('NH', 3239) # Create a third molecule. cdp.mol.add_item('3rd') # Create the first residue of the 3rd molecule and add some data to its spin container. cdp.mol[2].res[0].num = 13 cdp.mol[2].res[0].name = 'Gly' cdp.mol[2].res[0].spin[0].x = 'hello' # Update the metadata. metadata_update()
def test_sim_init_values(self): """Test the specific_analyses.relax_disp.api.sim_init_values() function for a cluster of 2 spins.""" # Test parameter values. fixed_values = { 'r1': 2.2, 'r2eff': 10.0, 'r2': 15.0, 'r2a': 12.0, 'r2b': 18.0, 'pA': 0.80, 'pB': 0.15, 'k_AB': 0.001, 'k_BA': 0.003, 'kex': 0.01, 'kex_AB': 0.015, 'kex_BC': 0.017, 'kex_AC': 0.016, 'kB': 0.005, 'kC': 0.004, 'tex': 50.0, 'dw': 1.0, 'dw_AB': 1.02, 'dw_BC': 1.03, 'dwH': 0.1, 'dwH_AB': 0.12, 'dwH_BC': 0.13, 'phi_ex': 0.5, 'phi_ex_B': 0.4, 'phi_ex_C': 0.3, } # Loop over all models. print( "Checking the parameter conversion and setting for a cluster of 2 spins." ) for model in MODEL_LIST_FULL: # Printout. print(" Model '%s'." % model) # Set up the data store. ds.add(pipe_name=model, pipe_type='relax_disp') if model == MODEL_R2EFF: cdp.model_type = 'R2eff' else: cdp.model_type = 'disp' cdp.exp_type_list = [self.exp_type[model]] cdp.spectrometer_frq_list = [1e6] cdp.sim_number = 2 # Set up the spin systems. cdp.mol.add_item(mol_name="sim test") cdp.mol[0].res[0].num = 1 cdp.mol[0].res.add_item(res_num=2) mol_res_spin.metadata_update() spins = [cdp.mol[0].res[0].spin[0], cdp.mol[0].res[1].spin[0]] for spin in spins: spin.model = model if model == MODEL_R2EFF: spin.params = ['r2eff'] else: spin.params = deepcopy(MODEL_PARAMS[model]) spin.chi2 = 1000.0 spin.iter = 20 spin.f_count = 300 spin.g_count = 200 spin.h_count = 100 spin.warning = None spin.isotope = '15N' # Set the ordinary parameter values, as these are copied into the simulation structures. for name, param_index, spin_index, R20_key in loop_parameters( spins): # R1/R2 parameters. if name in ['r1', 'r2', 'r2a', 'r2b']: key = "%s - %.8f MHz" % (cdp.exp_type_list[0], cdp.spectrometer_frq_list[0] / 1e6) print(" Setting spin %i parameter %s['%s'] to %s." % (spin_index, name, key, fixed_values[name])) setattr(spins[spin_index], name, {key: fixed_values[name]}) # Global parameters. elif spin_index == None: print(" Setting global parameter %s to %s." % (name, fixed_values[name])) setattr(spins[0], name, fixed_values[name]) setattr(spins[1], name, fixed_values[name]) # Spin parameters. else: print(" Setting spin %i parameter %s to %s." % (spin_index, name, fixed_values[name])) setattr(spins[spin_index], name, fixed_values[name]) # MC simulation setup. api = Relax_disp() api.sim_init_values() # Checks. for i in range(cdp.sim_number): print(" Simulation %i." % i) # Check the probabilities. if 'pB' in MODEL_PARAMS[model]: print(" Checking parameter pC.") self.assertAlmostEqual(spins[0].pC_sim[i], 0.05) self.assertAlmostEqual(spins[1].pC_sim[i], 0.05) elif 'pA' in MODEL_PARAMS[model]: print(" Checking parameter pB.") self.assertAlmostEqual(spins[0].pB_sim[i], 0.20) self.assertAlmostEqual(spins[1].pB_sim[i], 0.20) # Check the kex-tex pair. if 'kex' in MODEL_PARAMS[model]: print(" Checking parameter tex.") self.assertAlmostEqual(spins[0].tex_sim[i], 100.0) self.assertAlmostEqual(spins[1].tex_sim[i], 100.0) elif 'tex' in MODEL_PARAMS[model]: print(" Checking parameter kex.") self.assertAlmostEqual(spins[0].kex_sim[i], 0.02) self.assertAlmostEqual(spins[1].kex_sim[i], 0.02) # Check the rates. if 'kex' in MODEL_PARAMS[model] and 'pA' in MODEL_PARAMS[model]: print(" Checking parameter k_AB.") self.assertAlmostEqual(spins[0].k_AB_sim[i], 0.002) self.assertAlmostEqual(spins[1].k_AB_sim[i], 0.002) print(" Checking parameter k_BA.") self.assertAlmostEqual(spins[0].k_BA_sim[i], 0.008) self.assertAlmostEqual(spins[1].k_BA_sim[i], 0.008)
def select(method=None, modsel_pipe=None, bundle=None, pipes=None): """Model selection function. @keyword method: The model selection method. This can currently be one of: - 'AIC', Akaike's Information Criteria. - 'AICc', Small sample size corrected AIC. - 'BIC', Bayesian or Schwarz Information Criteria. - 'CV', Single-item-out cross-validation. None of the other model selection techniques are currently supported. @type method: str @keyword modsel_pipe: The name of the new data pipe to be created by copying of the selected data pipe. @type modsel_pipe: str @keyword bundle: The optional data pipe bundle to associate the newly created pipe with. @type bundle: str or None @keyword pipes: A list of the data pipes to use in the model selection. @type pipes: list of str """ # Test if the pipe already exists. if has_pipe(modsel_pipe): raise RelaxPipeError(modsel_pipe) # Use all pipes. if pipes == None: # Get all data pipe names from the relax data store. pipes = pipe_names() # Select the model selection technique. if method == 'AIC': print("AIC model selection.") formula = aic elif method == 'AICc': print("AICc model selection.") formula = aicc elif method == 'BIC': print("BIC model selection.") formula = bic elif method == 'CV': print("CV model selection.") raise RelaxError("The model selection technique " + repr(method) + " is not currently supported.") else: raise RelaxError("The model selection technique " + repr(method) + " is not currently supported.") # No pipes. if len(pipes) == 0: raise RelaxError("No data pipes are available for use in model selection.") # Initialise. function_type = {} model_loop = {} model_type = {} duplicate_data = {} model_statistics = {} skip_function = {} modsel_pipe_exists = False # Cross validation setup. if isinstance(pipes[0], list): # No pipes. if len(pipes[0]) == 0: raise RelaxError("No pipes are available for use in model selection in the array " + repr(pipes[0]) + ".") # Loop over the data pipes. for i in range(len(pipes)): for j in range(len(pipes[i])): # The specific analysis API object. api = return_api(pipe_name=pipes[i][j]) # Store the specific functions. model_loop[pipes[i][j]] = api.model_loop model_type[pipes[i][j]] = api.model_type duplicate_data[pipes[i][j]] = api.duplicate_data model_statistics[pipes[i][j]] = api.model_statistics skip_function[pipes[i][j]] = api.skip_function # The model loop should be the same for all data pipes! for i in range(len(pipes)): for j in range(len(pipes[i])): if model_loop[pipes[0][j]] != model_loop[pipes[i][j]]: raise RelaxError("The models for each data pipes should be the same.") # Alias some function from the specific API of the first data pipe. api = return_api(pipe_name=pipes[0][0]) model_loop = api.model_loop model_desc = api.model_desc # Global vs. local models. global_flag = False for i in range(len(pipes)): for j in range(len(pipes[i])): if model_type[pipes[i][j]]() == 'global': global_flag = True # All other model selection setup. else: # Loop over the data pipes. for i in range(len(pipes)): # The specific analysis API object. api = return_api() # Store the specific functions. model_loop[pipes[i]] = api.model_loop model_type[pipes[i]] = api.model_type duplicate_data[pipes[i]] = api.duplicate_data model_statistics[pipes[i]] = api.model_statistics skip_function[pipes[i]] = api.skip_function # Alias some function from the specific API of the first data pipe. api = return_api(pipe_name=pipes[0]) model_loop = api.model_loop model_desc = api.model_desc # Global vs. local models. global_flag = False for j in range(len(pipes)): if model_type[pipes[j]]() == 'global': global_flag = True # Loop over the base models. for model_info in model_loop(): # Print out. print("\n") desc = model_desc(model_info) if desc: print(desc) # Initial model. best_model = None best_crit = 1e300 data = [] # Loop over the pipes. for j in range(len(pipes)): # Single-item-out cross validation. if method == 'CV': # Sum of chi-squared values. sum_crit = 0.0 # Loop over the validation samples and sum the chi-squared values. for k in range(len(pipes[j])): # Alias the data pipe name. pipe = pipes[j][k] # Switch to this pipe. switch(pipe) # Skip function. if skip_function[pipe](model_info): continue # Get the model statistics. k, n, chi2 = model_statistics[pipe](model_info) # Missing data sets. if k == None or n == None or chi2 == None: continue # Chi2 sum. sum_crit = sum_crit + chi2 # Cross-validation criterion (average chi-squared value). crit = sum_crit / float(len(pipes[j])) # Other model selection methods. else: # Reassign the pipe. pipe = pipes[j] # Switch to this pipe. switch(pipe) # Skip function. if skip_function[pipe](model_info): continue # Get the model statistics. k, n, chi2 = model_statistics[pipe](model_info, global_stats=global_flag) # Missing data sets. if k == None or n == None or chi2 == None: continue # Calculate the criterion value. crit = formula(chi2, float(k), float(n)) # Store the values for a later printout. data.append([pipe, repr(k), repr(n), "%.5f" % chi2, "%.5f" % crit]) # Select model. if crit < best_crit: best_model = pipe best_crit = crit # Write out the table. write_data(out=sys.stdout, headings=["Data pipe", "Num_params_(k)", "Num_data_sets_(n)", "Chi2", "Criterion"], data=data) # Duplicate the data from the 'best_model' to the model selection data pipe. if best_model != None: # Print out of selected model. print("The model from the data pipe " + repr(best_model) + " has been selected.") # Switch to the selected data pipe. switch(best_model) # Duplicate. duplicate_data[best_model](best_model, modsel_pipe, model_info, global_stats=global_flag, verbose=False) # Model selection pipe now exists. modsel_pipe_exists = True # No model selected. else: # Print out of selected model. print("No model has been selected.") # Switch to the model selection pipe. if modsel_pipe_exists: switch(modsel_pipe) # Bundle the data pipe. if bundle: pipe_control.pipes.bundle(bundle=bundle, pipe=modsel_pipe) # Update all of the required metadata structures. mol_res_spin.metadata_update() interatomic.metadata_update()