Package test_suite :: Package gui_tests :: Module model_free
[hide private]
[frames] | no frames]

Source Code for Module test_suite.gui_tests.model_free

  1  ############################################################################### 
  2  #                                                                             # 
  3  # Copyright (C) 2006-2013 Edward d'Auvergne                                   # 
  4  #                                                                             # 
  5  # This file is part of the program relax (http://www.nmr-relax.com).          # 
  6  #                                                                             # 
  7  # This program is free software: you can redistribute it and/or modify        # 
  8  # it under the terms of the GNU General Public License as published by        # 
  9  # the Free Software Foundation, either version 3 of the License, or           # 
 10  # (at your option) any later version.                                         # 
 11  #                                                                             # 
 12  # This program is distributed in the hope that it will be useful,             # 
 13  # but WITHOUT ANY WARRANTY; without even the implied warranty of              # 
 14  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               # 
 15  # GNU General Public License for more details.                                # 
 16  #                                                                             # 
 17  # You should have received a copy of the GNU General Public License           # 
 18  # along with this program.  If not, see <http://www.gnu.org/licenses/>.       # 
 19  #                                                                             # 
 20  ############################################################################### 
 21   
 22  # Python module imports. 
 23  import numpy 
 24  from os import F_OK, access, sep 
 25  from tempfile import mkdtemp 
 26  import wx 
 27   
 28  # relax module imports. 
 29  from data import Relax_data_store; ds = Relax_data_store() 
 30  from generic_fns.interatomic import interatomic_loop 
 31  from generic_fns.mol_res_spin import spin_loop 
 32  from generic_fns.pipes import cdp_name 
 33  from status import Status; status = Status() 
 34  from test_suite.gui_tests.base_classes import GuiTestCase 
 35   
 36  # relax GUI imports. 
 37  from gui.analyses import auto_model_free 
 38  from gui.interpreter import Interpreter; interpreter = Interpreter() 
 39  from gui.string_conv import float_to_gui, str_to_gui 
 40  from gui.uf_objects import Uf_storage; uf_store = Uf_storage() 
 41  from gui.wizard import Wiz_window 
 42   
 43   
44 -class Mf(GuiTestCase):
45 """Class for testing various aspects specific to the model-free auto-analysis.""" 46
48 """Catch U{bug #20479<https://web.archive.org/web/https://gna.org/bugs/?20479>}, the failure to load a relax state in the GUI. 49 50 This was reported by U{Stanislava Panova<https://web.archive.org/web/https://gna.org/users/stacy>}. 51 """ 52 53 # Simulate the new analysis wizard. 54 self.app.gui.analysis.menu_new(None) 55 page = self.app.gui.analysis.new_wizard.wizard.get_page(0) 56 page.select_mf(None) 57 page.analysis_name.SetValue(str_to_gui("Model-free test")) 58 self.app.gui.analysis.new_wizard.wizard._go_next(None) 59 page = self.app.gui.analysis.new_wizard.wizard.get_page(1) 60 self.app.gui.analysis.new_wizard.wizard._go_next(None) 61 62 # Get the data. 63 analysis_type, analysis_name, pipe_name, pipe_bundle = self.app.gui.analysis.new_wizard.get_data() 64 65 # Set up the analysis. 66 self.app.gui.analysis.new_analysis(analysis_type=analysis_type, analysis_name=analysis_name, pipe_name=pipe_name, pipe_bundle=pipe_bundle) 67 68 # Alias the analysis. 69 analysis = self.app.gui.analysis.get_page_from_name("Model-free test") 70 71 # Change the results directory. 72 analysis.field_results_dir.SetValue(str_to_gui(ds.tmpdir)) 73 74 # The data path. 75 data_path = status.install_path + sep + 'test_suite' + sep + 'shared_data' + sep + 'model_free' + sep + 'bug_20479_gui_final_pipe' + sep 76 77 # Launch the spin viewer window. 78 self.app.gui.show_tree() 79 80 # Spin loading wizard: Initialisation. 81 self.app.gui.spin_viewer.load_spins_wizard() 82 83 # Spin loading wizard: The NOE data file. 84 page = self.app.gui.spin_viewer.wizard.get_page(0) 85 page.selection = 'sequence' 86 self.app.gui.spin_viewer.wizard._go_next() 87 page = self.app.gui.spin_viewer.wizard.get_page(self.app.gui.spin_viewer.wizard._current_page) 88 page.uf_args['file'].SetValue(str_to_gui(data_path + 'NoeRelN')) 89 self.app.gui.spin_viewer.wizard._go_next() 90 interpreter.flush() # Required because of the asynchronous uf call. 91 92 # Spin loading wizard: The spin loading. 93 self.app.gui.spin_viewer.wizard._go_next() 94 interpreter.flush() # Required because of the asynchronous uf call. 95 96 # Close the spin viewer window. 97 self.app.gui.spin_viewer.handler_close() 98 99 # Flush the interpreter in preparation for the synchronous user functions of the peak list wizard. 100 interpreter.flush() 101 102 # Set the element type. 103 self._execute_uf(uf_name='spin.element', element='N') 104 105 # Load the relaxation data. 106 data = [ 107 ['NoeRelN', 'noe_800', 'NOE', 800000031.0], 108 ['R1850', 'r1_800', 'R1', 800000031.0], 109 ['R2863', 'r2_800', 'R2', 800000031.0], 110 ['R2604', 'r2_600', 'R2', 599999000.0] 111 ] 112 for i in range(len(data)): 113 self._execute_uf(uf_name='relax_data.read', file=data_path+data[i][0], ri_id=data[i][1], ri_type=data[i][2], frq=data[i][3], mol_name_col=1, res_num_col=2, res_name_col=3, spin_num_col=4, spin_name_col=5, data_col=6, error_col=7) 114 115 # Attach the protons. 116 self._execute_uf(uf_name='sequence.attach_protons') 117 118 # Dipole-dipole interaction wizard. 119 analysis.setup_dipole_pair() # Initialisation. 120 analysis.dipole_wizard._skip() # Skip the structure.read_pdb user function. 121 analysis.dipole_wizard._skip() # Skip the structure.get_pos user function. 122 analysis.dipole_wizard._go_next() # The dipole_pair.define user function. 123 interpreter.flush() # Required because of the asynchronous uf call. 124 analysis.dipole_wizard._go_next() # The dipole_pair.set_dist user function. 125 interpreter.flush() # Required because of the asynchronous uf call. 126 analysis.dipole_wizard._skip() # Skip the dipole_pair.unit_vectors user function. 127 128 # Set up the CSA interaction. 129 analysis.value_set_csa() 130 uf_store['value.set'].wizard._go_next() 131 interpreter.flush() # Required because of the asynchronous uf call. 132 133 # Set up the nuclear isotopes. 134 analysis.spin_isotope_heteronuc() 135 uf_store['spin.isotope'].wizard._go_next() 136 interpreter.flush() # Required because of the asynchronous uf call. 137 analysis.spin_isotope_proton() 138 uf_store['spin.isotope'].wizard._go_next() 139 interpreter.flush() # Required because of the asynchronous uf call. 140 141 # Select only the tm0 and tm1 local tm models. 142 analysis.local_tm_model_field.select = [True, True, False, False, False, False, False, False, False, False] 143 analysis.local_tm_model_field.modify() 144 145 # Select only the m1 and m2 model-free models. 146 analysis.mf_model_field.select = [False, True, True, False, False, False, False, False, False, False] 147 analysis.mf_model_field.modify() 148 149 # Change the grid increments. 150 analysis.grid_inc.SetValue(3) 151 analysis.data.diff_tensor_grid_inc = {'sphere': 5, 'prolate': 5, 'oblate': 5, 'ellipsoid': 3} 152 153 # Set the number of Monte Carlo simulations. 154 analysis.mc_sim_num.SetValue(2) 155 156 # Set the maximum number of iterations (changing the allowed values). 157 analysis.max_iter.control.SetRange(0, 100) 158 analysis.max_iter.SetValue(1) 159 160 # Modify some of the class variables to speed up optimisation. 161 auto_model_free.dauvergne_protocol.dAuvergne_protocol.opt_func_tol = 1e-5 162 auto_model_free.dauvergne_protocol.dAuvergne_protocol.opt_max_iterations = 1000 163 164 # Execute the 'local_tm', 'sphere' and 'final' protocol stages sequentially. 165 for protocol in ['local_tm', 'sphere', 'final']: 166 # Print out. 167 text = "Sequential global model optimisation: %s" % protocol 168 char = "%" 169 print("\n\n\n\n%s\n%s %s %s\n%s\n\n\n" % (char*(len(text)+4), char, text, char, char*(len(text)+4))) 170 171 # Set the protocol mode. 172 if protocol == 'local_tm': 173 analysis.mode_win.select_local_tm() 174 elif protocol == 'sphere': 175 analysis.mode_win.select_sphere() 176 else: 177 analysis.mode_win.select_final() 178 analysis.mode_dialog() 179 180 # Execute relax. 181 state = analysis.execute(wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, analysis.button_exec_relax.GetId())) 182 183 # Wait for execution to complete. 184 if hasattr(analysis, 'thread'): 185 analysis.thread.join() 186 187 # Flush all wx events. 188 wx.Yield() 189 190 # Exceptions in the thread. 191 self.check_exceptions()
192 193
194 - def test_mf_auto_analysis(self):
195 """Test the model-free auto-analysis. 196 197 This now catches U{bug #20603<https://web.archive.org/web/https://gna.org/bugs/?20603>}. 198 """ 199 200 # Simulate the new analysis wizard. 201 self.app.gui.analysis.menu_new(None) 202 page = self.app.gui.analysis.new_wizard.wizard.get_page(0) 203 page.select_mf(None) 204 page.analysis_name.SetValue(str_to_gui("Model-free test")) 205 self.app.gui.analysis.new_wizard.wizard._go_next(None) 206 page = self.app.gui.analysis.new_wizard.wizard.get_page(1) 207 self.app.gui.analysis.new_wizard.wizard._go_next(None) 208 209 # Get the data. 210 analysis_type, analysis_name, pipe_name, pipe_bundle = self.app.gui.analysis.new_wizard.get_data() 211 212 # Set up the analysis. 213 self.app.gui.analysis.new_analysis(analysis_type=analysis_type, analysis_name=analysis_name, pipe_name=pipe_name, pipe_bundle=pipe_bundle) 214 215 # Alias the analysis. 216 analysis = self.app.gui.analysis.get_page_from_name("Model-free test") 217 218 # Change the results directory. 219 analysis.field_results_dir.SetValue(str_to_gui(ds.tmpdir)) 220 221 # The data path. 222 data_path = status.install_path + sep + 'test_suite' + sep + 'shared_data' + sep + 'model_free' + sep + 'sphere' + sep 223 224 # Open and close the about window (mimicking user behaviour). 225 analysis._about() 226 analysis.about_dialog.Close() 227 228 # Launch the spin viewer window. 229 self.app.gui.show_tree() 230 231 # Spin loading wizard: Initialisation. 232 self.app.gui.spin_viewer.load_spins_wizard() 233 234 # Spin loading wizard: The PDB file. 235 page = self.app.gui.spin_viewer.wizard.get_page(0) 236 page.selection = 'new pdb' 237 self.app.gui.spin_viewer.wizard._go_next() 238 page = self.app.gui.spin_viewer.wizard.get_page(self.app.gui.spin_viewer.wizard._current_page) 239 page.uf_args['file'].SetValue(str_to_gui(status.install_path + sep + 'test_suite' + sep + 'shared_data' + sep + 'model_free' + sep + 'sphere' + sep + 'sphere.pdb')) 240 self.app.gui.spin_viewer.wizard._go_next() 241 interpreter.flush() # Required because of the asynchronous uf call. 242 243 # Spin loading wizard: The spin loading. 244 self.app.gui.spin_viewer.wizard._go_next() 245 interpreter.flush() # Required because of the asynchronous uf call. 246 247 # Close the spin viewer window. 248 self.app.gui.spin_viewer.handler_close() 249 250 # Flush the interpreter in preparation for the synchronous user functions of the peak list wizard. 251 interpreter.flush() 252 253 # Load the relaxation data. 254 data = [ 255 ['noe.500.out', 'noe_500', 'NOE', 500e6], 256 ['r1.500.out', 'r1_500', 'R1', 500e6], 257 ['r2.500.out', 'r2_500', 'R2', 500e6], 258 ['noe.900.out', 'noe_900', 'NOE', 900e6], 259 ['r1.900.out', 'r1_900', 'R1', 900e6], 260 ['r2.900.out', 'r2_900', 'R2', 900e6] 261 ] 262 for i in range(len(data)): 263 self._execute_uf(uf_name='relax_data.read', file=data_path+data[i][0], ri_id=data[i][1], ri_type=data[i][2], frq=data[i][3], mol_name_col=1, res_num_col=2, res_name_col=3, spin_num_col=4, spin_name_col=5, data_col=6, error_col=7) 264 265 # Simulate right clicking on the NOE to test the pop up menu (bug #20603, https://web.archive.org/web/https://gna.org/bugs/?20603). 266 analysis.relax_data.on_right_click(Fake_right_click()) 267 268 # Dipole-dipole interaction wizard: Initialisation. 269 analysis.setup_dipole_pair() 270 271 # Dipole-dipole interaction wizard: The dipole_pair.define, dipole_pair.set_dist, and dipole_pair.unit_vectors user functions. 272 analysis.dipole_wizard._apply() 273 interpreter.flush() # Required because of the asynchronous uf call. 274 page = analysis.dipole_wizard.get_page(0) 275 page.uf_args['spin_id1'].SetValue(str_to_gui("@NE1")) 276 page.uf_args['spin_id2'].SetValue(str_to_gui("@HE1")) 277 analysis.dipole_wizard._go_next() 278 interpreter.flush() # Required because of the asynchronous uf call. 279 analysis.dipole_wizard._go_next() 280 interpreter.flush() # Required because of the asynchronous uf call. 281 analysis.dipole_wizard._go_next() 282 interpreter.flush() # Required because of the asynchronous uf call. 283 284 # Set up the CSA interaction. 285 analysis.value_set_csa() 286 uf_store['value.set'].wizard._go_next() 287 interpreter.flush() # Required because of the asynchronous uf call. 288 289 # Set up the nuclear isotopes. 290 analysis.spin_isotope_heteronuc() 291 uf_store['spin.isotope'].wizard._go_next() 292 interpreter.flush() # Required because of the asynchronous uf call. 293 analysis.spin_isotope_proton() 294 uf_store['spin.isotope'].wizard._go_next() 295 interpreter.flush() # Required because of the asynchronous uf call. 296 297 # Select only the tm0 and tm1 local tm models. 298 analysis.local_tm_model_field.select = [True, True, False, False, False, False, False, False, False, False] 299 analysis.local_tm_model_field.modify() 300 301 # Select only the m1 and m2 model-free models. 302 analysis.mf_model_field.select = [False, True, True, False, False, False, False, False, False, False] 303 analysis.mf_model_field.modify() 304 305 # Change the grid increments. 306 analysis.grid_inc.SetValue(3) 307 analysis.data.diff_tensor_grid_inc = {'sphere': 5, 'prolate': 5, 'oblate': 5, 'ellipsoid': 3} 308 309 # Set the number of Monte Carlo simulations. 310 analysis.mc_sim_num.SetValue(2) 311 312 # Set the maximum number of iterations (changing the allowed values). 313 analysis.max_iter.control.SetRange(0, 100) 314 analysis.max_iter.SetValue(1) 315 316 # Set the protocol mode to automatic. 317 analysis.mode_win.select_full_analysis() 318 analysis.mode_dialog() 319 320 # Check that the data has been correctly updated prior to execution. 321 analysis.sync_ds(upload=True) 322 self.assertEqual(analysis.data.save_dir, ds.tmpdir) 323 self.assertEqual(analysis.data.local_tm_models, ['tm0', 'tm1']) 324 self.assertEqual(analysis.data.mf_models, ['m1', 'm2']) 325 self.assertEqual(analysis.data.grid_inc, 3) 326 self.assertEqual(analysis.data.mc_sim_num, 2) 327 self.assertEqual(analysis.data.max_iter, 1) 328 self.assertEqual(analysis.data.diff_tensor_grid_inc['sphere'], 5) 329 self.assertEqual(analysis.data.diff_tensor_grid_inc['prolate'], 5) 330 self.assertEqual(analysis.data.diff_tensor_grid_inc['oblate'], 5) 331 self.assertEqual(analysis.data.diff_tensor_grid_inc['ellipsoid'], 3) 332 333 # Modify some of the class variables to speed up optimisation. 334 auto_model_free.dauvergne_protocol.dAuvergne_protocol.opt_func_tol = 1e-5 335 auto_model_free.dauvergne_protocol.dAuvergne_protocol.opt_max_iterations = 1000 336 337 # Execute relax. 338 state = analysis.execute(wx.CommandEvent(wx.wxEVT_COMMAND_BUTTON_CLICKED, analysis.button_exec_relax.GetId())) 339 340 # Wait for execution to complete. 341 if hasattr(analysis, 'thread'): 342 analysis.thread.join() 343 344 # Flush all wx events. 345 wx.Yield() 346 347 # Exceptions in the thread. 348 self.check_exceptions() 349 350 # Check the relax controller. 351 # FIXME: skipping the checks for certain wxPython bugs. 352 if status.relax_mode != 'gui' and wx.version() != '2.9.4.1 gtk2 (classic)': 353 self.assertEqual(self.app.gui.controller.mc_gauge_mf.GetValue(), 100) 354 self.assertEqual(self.app.gui.controller.progress_gauge_mf.GetValue(), 100) 355 self.assertEqual(self.app.gui.controller.main_gauge.GetValue(), 100) 356 357 # Check the diffusion tensor. 358 self.assertEqual(cdp.diff_tensor.type, 'sphere') 359 self.assertAlmostEqual(cdp.diff_tensor.tm, 1e-8) 360 self.assertEqual(cdp.diff_tensor.fixed, True) 361 362 # The global minimisation info. 363 self.assertAlmostEqual(cdp.chi2, 4e-19) 364 365 # The spin ID info. 366 mol_names = ["sphere_mol1"] * 20 367 res_names = ["GLY"] * 20 368 res_nums = [] 369 for i in range(1, 10): 370 res_nums.append(i) 371 res_nums.append(i) 372 res_nums.append(i) 373 res_nums.append(i) 374 spin_names = ["N", "H"] * 9 + ["NE1", "HE1"] 375 spin_nums = list(range(1, 21)) 376 isotopes = ["15N", "1H"] * 10 377 csa = [-172e-6, None] * 10 378 select = [True, False] * 10 379 fixed = [False, False] * 10 380 s2 = [0.8, None] * 10 381 te = [20e-12, None] * 10 382 383 # Check the spin data. 384 i = 0 385 for spin, mol_name, res_num, res_name in spin_loop(full_info=True): 386 # The ID info. 387 self.assertEqual(mol_name, mol_names[i]) 388 self.assertEqual(res_name, res_names[i]) 389 self.assertEqual(res_num, res_nums[i]) 390 self.assertEqual(spin.name, spin_names[i]) 391 self.assertEqual(spin.num, spin_nums[i]) 392 393 # The data. 394 self.assertEqual(spin.select, select[i]) 395 self.assertEqual(spin.fixed, fixed[i]) 396 self.assertEqual(spin.isotope, isotopes[i]) 397 if csa[i] == None: 398 self.assertEqual(spin.csa, None) 399 else: 400 self.assertAlmostEqual(spin.csa, csa[i]) 401 402 # The model-free data. 403 self.assertEqual(spin.model, 'm2') 404 self.assertEqual(spin.equation, 'mf_orig') 405 self.assertEqual(len(spin.params), 2) 406 self.assertEqual(spin.params[0], 's2') 407 self.assertEqual(spin.params[1], 'te') 408 if s2[i] == None: 409 self.assertEqual(spin.s2, None) 410 else: 411 self.assertAlmostEqual(spin.s2, 0.8) 412 self.assertEqual(spin.s2f, None) 413 self.assertEqual(spin.s2s, None) 414 self.assertEqual(spin.local_tm, None) 415 if te[i] == None: 416 self.assertEqual(spin.te, None) 417 else: 418 self.assertAlmostEqual(spin.te, 20e-12) 419 self.assertEqual(spin.tf, None) 420 self.assertEqual(spin.ts, None) 421 self.assertEqual(spin.rex, None) 422 423 # The spin minimisation info. 424 self.assertEqual(spin.chi2, None) 425 self.assertEqual(spin.iter, None) 426 self.assertEqual(spin.f_count, None) 427 self.assertEqual(spin.g_count, None) 428 self.assertEqual(spin.h_count, None) 429 self.assertEqual(spin.warning, None) 430 431 # Increment the index. 432 i += 1 433 434 # Check the interatomic data. 435 i = 0 436 for interatom in interatomic_loop(): 437 self.assertAlmostEqual(interatom.r, 1.02 * 1e-10)
438 439 440
441 -class Fake_right_click:
442 """Simulate a grid_cell_right_click event .""" 443
444 - def GetRow(self):
445 """Overwrite the GetRow() method.""" 446 447 # Return the first row. 448 return 0
449