mailr19873 - in /branches/relax_disp/specific_analyses/relax_disp: __init__.py disp_data.py


Others Months | Index by Date | Thread Index
>>   [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Header


Content

Posted by edward on June 05, 2013 - 18:57:
Author: bugman
Date: Wed Jun  5 18:57:32 2013
New Revision: 19873

URL: http://svn.gna.org/viewcvs/relax?rev=19873&view=rev
Log:
Added support for model selection to the relaxation dispersion specific 
analysis package.

This involved redesigning the model_loop() method.  Instead of yielding both 
the spin containers and
the spin IDs, now only spin IDs are yielded.  This is important as the model 
loop is used
independently of the data pipes.  Hence the spin containers cannot be yielded 
as multiple pipes are
compared within the model loop.  The auxiliary method 
_spin_ids_to_containers(spin_ids) has been
added to obtain the list of spin containers from the list of spin IDs.

To support model selection, the methods duplicate_data(), model_desc() and 
model_statistics() have
been added, and model_type() aliased to the common _model_type_local() method.


Modified:
    branches/relax_disp/specific_analyses/relax_disp/__init__.py
    branches/relax_disp/specific_analyses/relax_disp/disp_data.py

Modified: branches/relax_disp/specific_analyses/relax_disp/__init__.py
URL: 
http://svn.gna.org/viewcvs/relax/branches/relax_disp/specific_analyses/relax_disp/__init__.py?rev=19873&r1=19872&r2=19873&view=diff
==============================================================================
--- branches/relax_disp/specific_analyses/relax_disp/__init__.py (original)
+++ branches/relax_disp/specific_analyses/relax_disp/__init__.py Wed Jun  5 
18:57:32 2013
@@ -40,6 +40,7 @@
 from random import gauss
 from re import match, search
 import sys
+from types import MethodType
 
 # relax module imports.
 from dep_check import C_module_exp_fn
@@ -51,7 +52,7 @@
 from lib.software.grace import write_xy_data, write_xy_header
 from lib.statistics import std
 from lib.text.sectioning import subsection
-from pipe_control import pipes
+from pipe_control import pipes, sequence
 from pipe_control.mol_res_spin import exists_mol_res_spin_data, return_spin, 
spin_loop
 from pipe_control.result_files import add_result_file
 from specific_analyses.api_base import API_base
@@ -79,6 +80,7 @@
 
         # Place methods into the API.
         self.data_init = self._data_init_spin
+        self.model_type = self._model_type_local
         self.return_conversion_factor = self._return_no_conversion_factor
         self.return_value = self._return_value_general
         self.set_param_values = self._set_param_values_spin
@@ -849,6 +851,27 @@
         self._model_setup(model, params)
 
 
+    def _spin_ids_to_containers(self, spin_ids):
+        """Take the list of spin IDs and return the corresponding spin 
containers.
+
+        This is useful for handling the data from the model_loop() method.
+
+
+        @param spin_ids:    The list of spin ID strings.
+        @type spin_ids:     list of str
+        @return:            The list of spin containers.
+        @rtype:             list of SpinContainer instances
+        """
+
+        # Loop over the IDs and fetch the container.
+        spins = []
+        for id in spin_ids:
+            spins.append(return_spin(id))
+
+        # Return the containers.
+        return spins
+
+
     def base_data_loop(self):
         """Custom generator method for looping over the base data.
 
@@ -1022,6 +1045,88 @@
 
         # Return the MC data.
         return values
+
+
+    def duplicate_data(self, pipe_from=None, pipe_to=None, model_info=None, 
global_stats=False, verbose=True):
+        """Duplicate the data specific to a single model.
+
+        @keyword pipe_from:     The data pipe to copy the data from.
+        @type pipe_from:        str
+        @keyword pipe_to:       The data pipe to copy the data to.
+        @type pipe_to:          str
+        @keyword model_info:    The model index from model_info().
+        @type model_info:       int
+        @keyword global_stats:  The global statistics flag.
+        @type global_stats:     bool
+        @keyword verbose:       A flag which if True will cause info to be 
printed out.
+        @type verbose:          bool
+        """
+
+        # First create the pipe_to data pipe, if it doesn't exist, but don't 
switch to it.
+        if not pipes.has_pipe(pipe_to):
+            pipes.create(pipe_to, pipe_type='relax_disp', switch=False)
+
+        # Get the data pipes.
+        dp_from = pipes.get_pipe(pipe_from)
+        dp_to = pipes.get_pipe(pipe_to)
+
+        # Duplicate all non-sequence specific data.
+        for data_name in dir(dp_from):
+            # Skip the container objects.
+            if data_name in ['mol', 'interatomic', 'structure', 'exp_info']:
+                continue
+
+            # Skip special objects.
+            if search('^_', data_name) or data_name in 
list(dp_from.__class__.__dict__.keys()):
+                continue
+
+            # Get the original object.
+            data_from = getattr(dp_from, data_name)
+
+            # The data already exists.
+            if hasattr(dp_to, data_name):
+                # Get the object in the target pipe.
+                data_to = getattr(dp_to, data_name)
+
+                # The data must match!
+                if data_from != data_to:
+                    raise RelaxError("The object " + repr(data_name) + " is 
not consistent between the pipes " + repr(pipe_from) + " and " + 
repr(pipe_to) + ".")
+
+                # Skip the data.
+                continue
+
+            # Duplicate the data.
+            setattr(dp_to, data_name, deepcopy(data_from))
+
+        # No sequence data, so skip the rest.
+        if dp_from.mol.is_empty():
+            return
+
+        # Duplicate the sequence data if it doesn't exist.
+        if dp_to.mol.is_empty():
+            sequence.copy(pipe_from=pipe_from, pipe_to=pipe_to, 
preserve_select=True, verbose=verbose)
+
+        # Loop over the cluster.
+        for id in model_info:
+            # The original spin container.
+            spin = return_spin(id, pipe=pipe_from)
+
+            # Duplicate the spin specific data.
+            for name in dir(spin):
+                # Skip special objects.
+                if search('^__', name):
+                    continue
+
+                # Get the object.
+                obj = getattr(spin, name)
+
+                # Skip methods.
+                if isinstance(obj, MethodType):
+                    continue
+
+                # Duplicate the object.
+                new_obj = deepcopy(getattr(spin, name))
+                
setattr(dp_to.mol[spin._mol_index].res[spin._res_index].spin[spin._spin_index],
 name, new_obj)
 
 
     def grid_search(self, lower=None, upper=None, inc=None, 
constraints=True, verbosity=1, sim_index=None):
@@ -1117,7 +1222,10 @@
             num_time_pts = cdp.num_time_pts
 
         # Loop over the spin blocks.
-        for spins, spin_ids in self.model_loop():
+        for spin_ids in self.model_loop():
+            # The spin containers.
+            spins = self._spin_ids_to_containers(spin_ids)
+
             # The R2eff/R1rho data.
             values, errors, missing, frqs = return_r2eff_arrays(spins=spins, 
spin_ids=spin_ids, fields=cdp.spectrometer_frq_list, 
field_count=cdp.spectrometer_frq_count)
 
@@ -1253,6 +1361,19 @@
                         spin.r2eff_bc[key] = model.back_calc[spin_index, 
frq_index, disp_pt_index]
 
 
+    def model_desc(self, model_info):
+        """Return a description of the model.
+
+        @param model_info:  The model index from model_info().
+        @type model_info:   int
+        @return:            The model description.
+        @rtype:             str
+        """
+
+        # The model loop is over the spin clusters, so return a description 
of the cluster.
+        return "The spin cluster %s." % model_info
+
+
     def model_loop(self):
         """Loop over the spin groupings for one model applied to multiple 
spins.
 
@@ -1261,8 +1382,44 @@
         """
 
         # The cluster loop.
-        for info in loop_cluster():
-            yield info
+        for spin_ids in loop_cluster():
+            yield spin_ids
+
+
+    def model_statistics(self, model_info=None, spin_id=None, 
global_stats=None):
+        """Return the k, n, and chi2 model statistics.
+
+        k - number of parameters.
+        n - number of data points.
+        chi2 - the chi-squared value.
+
+
+        @keyword model_info:    The model index from model_info().
+        @type model_info:       None or int
+        @keyword spin_id:       The spin identification string.  This is 
ignored in the N-state model.
+        @type spin_id:          None or str
+        @keyword global_stats:  A parameter which determines if global or 
local statistics are returned.  For the N-state model, this argument is 
ignored.
+        @type global_stats:     None or bool
+        @return:                The optimisation statistics, in tuple 
format, of the number of parameters (k), the number of data points (n), and 
the chi-squared value (chi2).
+        @rtype:                 tuple of (int, int, float)
+        """
+
+        # Unpack the data.
+        spin_ids = model_info
+        spins = self._spin_ids_to_containers(spin_ids)
+
+        # Take the number of parameters from the first spin.
+        k = len(spins[0].params)
+
+        # The number of points and chi-squared is the sum from all spins.
+        n = 0
+        chi2 = 0.0
+        for spin in spins:
+            n += len(spin.r2eff)
+            chi2 += spin.chi2
+
+        # Return the values.
+        return k, n, chi2
 
 
     def overfit_deselect(self, data_check=True, verbose=True):
@@ -1370,7 +1527,8 @@
         """
 
         # Unpack the data.
-        spins, spin_ids = model_info
+        spin_ids = model_info
+        spins = self._spin_ids_to_containers(spin_ids)
 
         # Convert the parameter index.
         param_name, spin_index = param_index_to_param_info(index=index, 
spins=spins, names=self.data_names(set='params'))
@@ -1403,7 +1561,8 @@
         """
 
         # Unpack the data.
-        spins, spin_ids = model_info
+        spin_ids = model_info
+        spins = self._spin_ids_to_containers(spin_ids)
 
         # Loop over the spins, storing the structure for each spin.
         for spin in spins:
@@ -1471,7 +1630,8 @@
         """
 
         # Unpack the data.
-        spins, spin_ids = model_info
+        spin_ids = model_info
+        spins = self._spin_ids_to_containers(spin_ids)
 
         # The number of parameters.
         total_param_num = param_num(spins=spins)
@@ -1514,7 +1674,8 @@
         """
 
         # Unpack the data.
-        spins, spin_ids = model_info
+        spin_ids = model_info
+        spins = self._spin_ids_to_containers(spin_ids)
 
         # Return the array from the first spin, as this array will be 
identical for all spins in the cluster.
         return spins[0].select_sim

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=19873&r1=19872&r2=19873&view=diff
==============================================================================
--- branches/relax_disp/specific_analyses/relax_disp/disp_data.py (original)
+++ branches/relax_disp/specific_analyses/relax_disp/disp_data.py Wed Jun  5 
18:57:32 2013
@@ -176,19 +176,15 @@
 def loop_cluster():
     """Loop over the spin groupings for one model applied to multiple spins.
 
-    @return:    The list of spins per block will be yielded, as well as the 
list of spin IDs.
-    @rtype:     tuple of list of SpinContainer instances and list of spin IDs
+    @return:    The list of spin IDs per block will be yielded.
+    @rtype:     list of str
     """
 
     # No clustering, so loop over the sequence.
     if not hasattr(cdp, 'clustering'):
-        for spin, spin_id in spin_loop(return_id=True):
-            # Skip deselected spins.
-            if not spin.select:
-                continue
-
-            # Return the spin container as a stop-gap measure.
-            yield [spin], [spin_id]
+        for spin, spin_id in spin_loop(return_id=True, skip_desel=True):
+            # Return the spin ID as a list.
+            yield [spin_id]
 
     # Loop over the clustering.
     else:
@@ -199,22 +195,17 @@
                 continue
 
             # Create the spin container and ID lists.
-            spin_list = []
             spin_id_list = []
             for spin_id in cdp.clustering[key]:
-                spin_list.append(return_spin(spin_id))
                 spin_id_list.append(spin_id)
 
             # Yield the cluster.
-            yield spin_list, spin_id_list
+            yield spin_id_list
 
         # The free spins.
         for spin_id in cdp.clustering['free spins']:
-            # Get the spin container.
-            spin = return_spin(spin_id)
-
             # Yield each spin individually.
-            yield [spin], [spin_id]
+            yield [spin_id]
 
 
 def loop_frq():




Related Messages


Powered by MHonArc, Updated Wed Jun 05 19:00:01 2013