On 1 March 2011 12:54, Pavel Kaderavek <
pavel.kaderavek@xxxxxxxxx> wrote:
> This change is related to the task #6397 (
https://gna.org/task/?6397)
>
> kada _at_ chemi _dot_ muni _dot_ cz
>
>
https://mail.gna.org/public/relax-devel/2011-03/msg00001.html
>
https://gna.org/task/download.php?file_id=12603
>
> This patch includes change in the functions calc_(d,d2)noe in a file
> maths_fns/ri.py , where (d,d2)ri_prime was renamed to (d,d2)ri. This patch
> covers also the related change of names in the function init_res_r1_data
> (class Mf, maths_fns/mf.py), where the variables are initialized.
>
> On 1 March 2011 10:36, Edward d'Auvergne <
edward@xxxxxxxxxxxxx> wrote:
>>
>> Hi,
>>
>> The renaming should be fine. I see no reason at the moment why we
>> cannot perform an in place replacement of sigma_NOE with the NOE value
>> inside the data[x][y].ri data structure. If sigma_NOE is needed in
>> the future, then the person who needs it can recalculate it from the
>> NOE and R1.
>>
>> Cheers,
>>
>> Edward
>>
>>
>> On 1 March 2011 10:22, Pavel Kaderavek <
pavel.kaderavek@xxxxxxxxx> wrote:
>> > Hi,
>> >
>> > Yes, you are right. It might be included in some of the following
>> > patches.
>> > First, we would like to discuss changes in the next patch, where we
>> > would
>> > like to replace variable name ri_prime in functions calc_(d,d2)noe in a
>> > file
>> > maths_fns/ri.py to follow the changes in the patch:
>> >
https://mail.gna.org/public/relax-devel/2011-02/msg00081.html
>> > It was pre-discussed in:
>> >
https://mail.gna.org/public/relax-devel/2011-02/msg00084.html
>> >
>> > The changes also imply renaming of variables r1_data.(d,d2)ri_prime to
>> > r1_data.(d,d2)ri in the initialization function init_res_r1_data (class
>> > Mf,
>> > maths_fns/mf.py).
>> >
>> > Best regards,
>> > Pavel
>> >
>> >
>> > On 1 March 2011 09:59, Edward d'Auvergne <
edward@xxxxxxxxxxxxx> wrote:
>> >>
>> >> Hi,
>> >>
>> >> The patch looks good, I've now applied it. In the future, you might
>> >> find that the self.diff_data structure does not need to be passed into
>> >> self.init_spin_data().
>> >>
>> >> Cheers,
>> >>
>> >> Edward
>> >>
>> >>
>> >>
>> >> On 28 February 2011 16:51, Pavel Kaderavek <
pavel.kaderavek@xxxxxxxxx>
>> >> wrote:
>> >> > This change is related to the task #6397 (
https://gna.org/task/?6397)
>> >> >
>> >> > kada _at_ chemi _dot_ muni _dot_ cz
>> >> >
>> >> >
https://mail.gna.org/public/relax-devel/2011-02/msg00088.html
>> >> >
https://gna.org/task/download.php?file_id=12598
>> >> >
>> >> > This patch includes change in init_res_data function of class Mf in a
>> >> > file
>> >> > maths_fns/mf.py. The function is split into init_interaction_data and
>> >> > init_spin_data. The initializations of data.ri_prime, data.dri_prime,
>> >> > and
>> >> > data.d2ri_prime are excluded. Calls for both newly introduced
>> >> > functions
>> >> > are
>> >> > incorporated in the patch.
>> >> >
>> >> > On 25 February 2011 20:38, Edward d'Auvergne <
edward@xxxxxxxxxxxxx>
>> >> > wrote:
>> >> >>
>> >> >> Hi,
>> >> >>
>> >> >> I agree, these are good designs. The init_res_data name is a relic
>> >> >> of
>> >> >> old code from relax 1.2 when only single residues were handled and
>> >> >> not
>> >> >> individual and multiple spins per residue. It should have been
>> >> >> renamed to init_spin_data.
>> >> >>
>> >> >> Cheers,
>> >> >>
>> >> >> Edward
>> >> >>
>> >> >>
>> >> >>
>> >> >> On 25 February 2011 20:18, Pavel Kaderavek
>> >> >> <
pavel.kaderavek@xxxxxxxxx>
>> >> >> wrote:
>> >> >> > Hi,
>> >> >> >
>> >> >> > We would like to discuss the initialization of the spin and
>> >> >> > interaction
>> >> >> > data
>> >> >> > (Spin_object, Data) in class Mf (maths_fns/mf.py). Currently,
>> >> >> > there
>> >> >> > is a
>> >> >> > function init_res_data which initializes variables in container
>> >> >> > Data.
>> >> >> > The
>> >> >> > container Data is now redesigned to store only the interaction
>> >> >> > specific
>> >> >> > information and the spin specific data were moved to Spin_object.
>> >> >> >
>> >> >> > We suggest to rename init_res_data to init_interaction_data and
>> >> >> > move
>> >> >> > spin
>> >> >> > data initialization parts to a newly created function
>> >> >> > init_spin_data.
>> >> >> > The
>> >> >> > function init_interaction_dat will be called at the same place as
>> >> >> > the
>> >> >> > original init_res_data, while init_spin_data will be called just
>> >> >> > after
>> >> >> > the
>> >> >> > Spin_object is appended to self.data.
>> >> >> >
>> >> >> > Best regards,
>> >> >> > Pavel
>> >> >> >
>> >> >> > On 25 February 2011 19:48, Edward d'Auvergne
>> >> >> > <
edward@xxxxxxxxxxxxx>
>> >> >> > wrote:
>> >> >> >>
>> >> >> >> I should have read the text of the commit message more carefully
>> >> >> >> :)
>> >> >> >>
>> >> >> >> Bye,
>> >> >> >>
>> >> >> >> Edward
>> >> >> >>
>> >> >> >>
>> >> >> >>
>> >> >> >> On 25 February 2011 19:46, Edward d'Auvergne
>> >> >> >> <
edward@xxxxxxxxxxxxx>
>> >> >> >> wrote:
>> >> >> >> > Ah, this will also work. I didn't release that one of the next
>> >> >> >> > changes would be the in place replacement of sigma_noe by the
>> >> >> >> > NOE
>> >> >> >> > value inside maths_fns/ri.py. Ok, I'll commit the patch.
>> >> >> >> >
>> >> >> >> > Cheers,
>> >> >> >> >
>> >> >> >> > Edward
>> >> >> >> >
>> >> >> >> >
>> >> >> >> >
>> >> >> >> > On 25 February 2011 19:34, Pavel Kaderavek
>> >> >> >> > <
pavel.kaderavek@xxxxxxxxx>
>> >> >> >> > wrote:
>> >> >> >> >> Hi,
>> >> >> >> >> maybe we misunderstood some parts of the code, but the
>> >> >> >> >> data.ri_prime
>> >> >> >> >> seems
>> >> >> >> >> to be used only in maths_fns/ri.py to calculate NOE value.
>> >> >> >> >> Therefore,
>> >> >> >> >> it
>> >> >> >> >> should be possible to replace data.ri_prime by data.ri
>> >> >> >> >> directly
>> >> >> >> >> and
>> >> >> >> >> later
>> >> >> >> >> change function defined in ri.py to use data.ri instead of
>> >> >> >> >> data.ri_prime.
>> >> >> >> >>
>> >> >> >> >> original code of maths_fns/ri.py:
>> >> >> >> >>
>> >> >> >> >> def calc_noe(data, i, frq_num, get_r1, params):
>> >> >> >> >> """Calculate the NOE value.
>> >> >> >> >>
>> >> >> >> >> Half this code needs to be shifted into the function
>> >> >> >> >> initialisation
>> >> >> >> >> code.
>> >> >> >> >> """
>> >> >> >> >>
>> >> >> >> >> # Get the r1 value either from data.ri_prime or by
>> >> >> >> >> calculation
>> >> >> >> >> if
>> >> >> >> >> the
>> >> >> >> >> value is not in data.ri_prime
>> >> >> >> >> data.r1[i] = get_r1[i](data, i, frq_num, params)
>> >> >> >> >>
>> >> >> >> >> # Calculate the NOE.
>> >> >> >> >> if data.r1[i] == 0.0 and data.ri_prime[i] == 0.0:
>> >> >> >> >> data.ri[i] = 1.0
>> >> >> >> >> elif data.r1[i] == 0.0:
>> >> >> >> >> data.ri[i] = 1e99
>> >> >> >> >> else:
>> >> >> >> >> data.ri[i] = 1.0 + data.g_ratio*(data.ri_prime[i] /
>> >> >> >> >> data.r1[i])
>> >> >> >> >>
>> >> >> >> >> modified version:
>> >> >> >> >>
>> >> >> >> >> def calc_noe(data, i, frq_num, get_r1, params):
>> >> >> >> >> """Calculate the NOE value.
>> >> >> >> >>
>> >> >> >> >> Half this code needs to be shifted into the function
>> >> >> >> >> initialisation
>> >> >> >> >> code.
>> >> >> >> >> """
>> >> >> >> >>
>> >> >> >> >> # Get the r1 value either from data.ri_prime or by
>> >> >> >> >> calculation
>> >> >> >> >> if
>> >> >> >> >> the
>> >> >> >> >> value is not in data.ri_prime
>> >> >> >> >> data.r1[i] = get_r1[i](data, i, frq_num, params)
>> >> >> >> >>
>> >> >> >> >> # Calculate the NOE.
>> >> >> >> >> if data.r1[i] == 0.0 and data.ri[i] == 0.0:
>> >> >> >> >> data.ri[i] = 1.0
>> >> >> >> >> elif data.r1[i] == 0.0:
>> >> >> >> >> data.ri[i] = 1e99
>> >> >> >> >> else:
>> >> >> >> >> data.ri[i] = 1.0 + data.g_ratio*(data.ri[i] /
>> >> >> >> >> data.r1[i])
>> >> >> >> >>
>> >> >> >> >> the data structure data.ri is created during the
>> >> >> >> >> initialization
>> >> >> >> >> and
>> >> >> >> >> data.ri
>> >> >> >> >> is calculated by function calc_noe. Therefore we
>> >> >> >> >> do not see a reason to keep this line in the code:
>> >> >> >> >>
>> >> >> >> >> data.ri = data.ri_prime * 1.0
>> >> >> >> >>
>> >> >> >> >> since data.ri would be calculated by cumulative summation as
>> >> >> >> >> we
>> >> >> >> >> suggested.
>> >> >> >> >> Is our understanding correct?
>> >> >> >> >>
>> >> >> >> >> Best regards,
>> >> >> >> >> Pavel
>> >> >> >> >>
>> >> >> >> >>
>> >> >> >> >> On 25 February 2011 18:16, Edward d'Auvergne
>> >> >> >> >> <
edward@xxxxxxxxxxxxx>
>> >> >> >> >> wrote:
>> >> >> >> >>>
>> >> >> >> >>> Hi,
>> >> >> >> >>>
>> >> >> >> >>> The line:
>> >> >> >> >>>
>> >> >> >> >>> data.ri = data.ri_prime * 1.0
>> >> >> >> >>>
>> >> >> >> >>> is also quite important. This creates a new data structure
>> >> >> >> >>> data.ri
>> >> >> >> >>> initialised to the values of data.ri_prime. These lines are
>> >> >> >> >>> probably
>> >> >> >> >>> still necessary.
>> >> >> >> >>>
>> >> >> >> >>> Cheers,
>> >> >> >> >>>
>> >> >> >> >>> Edward
>> >> >> >> >>>
>> >> >> >> >>>
>> >> >> >> >>>
>> >> >> >> >>> On 25 February 2011 18:14, Edward d'Auvergne
>> >> >> >> >>> <
edward@xxxxxxxxxxxxx>
>> >> >> >> >>> wrote:
>> >> >> >> >>> > Hi,
>> >> >> >> >>> >
>> >> >> >> >>> > I've just been looking at this patch, and it seems to have
>> >> >> >> >>> > a
>> >> >> >> >>> > problem.
>> >> >> >> >>> > The new lines are:
>> >> >> >> >>> >
>> >> >> >> >>> > data.ri = data.ri +
>> >> >> >> >>> > data[j].create_ri_prime(data[j])
>> >> >> >> >>> >
>> >> >> >> >>> > But this is ri_prime. data.ri is created later on with the
>> >> >> >> >>> > call
>> >> >> >> >>> > to
>> >> >> >> >>> > data.create_ri. Should this be:
>> >> >> >> >>> >
>> >> >> >> >>> > data.ri_prime = data.ri_prime +
>> >> >> >> >>> > data[j].create_ri_prime(data[j])
>> >> >> >> >>> >
>> >> >> >> >>> > Regards,
>> >> >> >> >>> >
>> >> >> >> >>> > Edward
>> >> >> >> >>> >
>> >> >> >> >>> >
>> >> >> >> >>> > On 25 February 2011 18:09, Pavel Kaderavek
>> >> >> >> >>> > <
pavel.kaderavek@xxxxxxxxx>
>> >> >> >> >>> > wrote:
>> >> >> >> >>> >> This change is related to the task #6397
>> >> >> >> >>> >> (
https://gna.org/task/?6397)
>> >> >> >> >>> >>
>> >> >> >> >>> >> kada _at_ chemi _dot_ muni _dot_ cz
>> >> >> >> >>> >>
>> >> >> >> >>> >>
>> >> >> >> >>> >>
https://mail.gna.org/public/relax-devel/2011-02/msg00076.html
>> >> >> >> >>> >>
https://gna.org/support/download.php?file_id=12556
>> >> >> >> >>> >>
>> >> >> >> >>> >> This patch includes change in func_mf, func_local_tm,
>> >> >> >> >>> >> func_diff,
>> >> >> >> >>> >> func_all,
>> >> >> >> >>> >> dfunc_mf, dfunc_local_tm, dfunc_diff, dfunc_all,
>> >> >> >> >>> >> d2func_mf,
>> >> >> >> >>> >> d2func_local_tm,
>> >> >> >> >>> >> d2func_diff, d2func_all functions of class Mf in a file
>> >> >> >> >>> >> maths_fns/mf.py. The
>> >> >> >> >>> >> functions were modified in order to handle data for more
>> >> >> >> >>> >> interactions.
>> >> >> >> >>> >> Due to the equality of (d,d2)ri and (d,d2)ri_prime
>> >> >> >> >>> >> variables,
>> >> >> >> >>> >> the
>> >> >> >> >>> >> (d,d2)ri_prime were replaced by (d,d2)ri and the equality
>> >> >> >> >>> >> was
>> >> >> >> >>> >> removed.
>> >> >> >> >>> >> Moreover, (d,d2)ri was redefined as a cumulative sum of
>> >> >> >> >>> >> individual
>> >> >> >> >>> >> interaction contributions to the total relaxation rate or
>> >> >> >> >>> >> corresponding
>> >> >> >> >>> >> derivatives.
>> >> >> >> >>> >>
>> >> >> >> >>> >>
>> >> >> >> >>> >> On 24 February 2011 12:26, Edward d'Auvergne
>> >> >> >> >>> >> <
edward@xxxxxxxxxxxxx>
>> >> >> >> >>> >> wrote:
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> Hi,
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> Please see below:
>> >> >> >> >>> >>>
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> On 24 February 2011 10:02, Pavel Kaderavek
>> >> >> >> >>> >>> <
pavel.kaderavek@xxxxxxxxx>
>> >> >> >> >>> >>> wrote:
>> >> >> >> >>> >>> > Hi,
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > We realized a problem during the preparation of the
>> >> >> >> >>> >>> > following
>> >> >> >> >>> >>> > patch.
>> >> >> >> >>> >>> > Currently, it is impossible to initialize variables in
>> >> >> >> >>> >>> > the
>> >> >> >> >>> >>> > originally
>> >> >> >> >>> >>> > suggested way:
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > data = "">
>> >> >> >> >>> >>> > data.ri_prime = 0.0
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > in the function func_mf (maths_fns/mf.py) and other
>> >> >> >> >>> >>> > similar
>> >> >> >> >>> >>> > functions
>> >> >> >> >>> >>> > (func_local_tm, func_diff, func_all, and their
>> >> >> >> >>> >>> > equivalents
>> >> >> >> >>> >>> > for a
>> >> >> >> >>> >>> > first
>> >> >> >> >>> >>> > and
>> >> >> >> >>> >>> > second derivatives).
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> Ah, yes. 'data' here is a list rather than a container,
>> >> >> >> >>> >>> so
>> >> >> >> >>> >>> you
>> >> >> >> >>> >>> can't
>> >> >> >> >>> >>> do this. If you like, what I can do is create a special
>> >> >> >> >>> >>> list-like
>> >> >> >> >>> >>> object for this. The you can access list elements, but
>> >> >> >> >>> >>> also
>> >> >> >> >>> >>> place
>> >> >> >> >>> >>> variables inside it.
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> The other problem is that ri_prime returned by
>> >> >> >> >>> >>> maths_fns.ri_prime.func_ri_prime() is not a number but a
>> >> >> >> >>> >>> numpy
>> >> >> >> >>> >>> array.
>> >> >> >> >>> >>> Its dimensions are Nx1, where N is the number of
>> >> >> >> >>> >>> relaxation
>> >> >> >> >>> >>> data
>> >> >> >> >>> >>> points. So the initialisation will have to be at the
>> >> >> >> >>> >>> very
>> >> >> >> >>> >>> start
>> >> >> >> >>> >>> rather than in the func_mf() methods, and it needs to be
>> >> >> >> >>> >>> initialised
>> >> >> >> >>> >>> to the correct numpy object using something like
>> >> >> >> >>> >>> 'zeros(num_ri[i],
>> >> >> >> >>> >>> float64)'. The dri_prime, d2ri_prime, ri, dri, and d2ri
>> >> >> >> >>> >>> prime
>> >> >> >> >>> >>> will
>> >> >> >> >>> >>> have similar problems.
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> I would suggest that 'ri_prime' does not need to be
>> >> >> >> >>> >>> summed,
>> >> >> >> >>> >>> but
>> >> >> >> >>> >>> only
>> >> >> >> >>> >>> 'ri'. Or am I missing something? The difference between
>> >> >> >> >>> >>> ri
>> >> >> >> >>> >>> and
>> >> >> >> >>> >>> ri_prime is that ri contains the steady-state NOE whereas
>> >> >> >> >>> >>> ri_prime
>> >> >> >> >>> >>> contains sigma_NOE. Do we need to store and sum ri_prime
>> >> >> >> >>> >>> at
>> >> >> >> >>> >>> all?
>> >> >> >> >>> >>>
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> > It is not possible because of the approved changes of
>> >> >> >> >>> >>> > __init__
>> >> >> >> >>> >>> > function
>> >> >> >> >>> >>> > in
>> >> >> >> >>> >>> > the class Mf (file maths_fns/mf.py). The array used to
>> >> >> >> >>> >>> > store
>> >> >> >> >>> >>> > data is
>> >> >> >> >>> >>> > created
>> >> >> >> >>> >>> > in the following way:
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > self.data = "">
>> >> >> >> >>> >>> > for i in xrange(self.num_spins):
>> >> >> >> >>> >>> > ...
>> >> >> >> >>> >>> > self.data.append([])
>> >> >> >> >>> >>> > ...
>> >> >> >> >>> >>> > # Loop over the relaxation interactions.
>> >> >> >> >>> >>> > for j in xrange(self.num_interactions[i]):
>> >> >> >> >>> >>> > self.data[i].append(Data()) # This is a
>> >> >> >> >>> >>> > list
>> >> >> >> >>> >>> > dedicated
>> >> >> >> >>> >>> > for
>> >> >> >> >>> >>> > the storage of interaction specific parameters (i.e.
>> >> >> >> >>> >>> > type
>> >> >> >> >>> >>> > of
>> >> >> >> >>> >>> > interaction,
>> >> >> >> >>> >>> > internuclei distance, ...)
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > self.data[i][j].interactions=interactions[i][j]
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > self.data[i][j].internuclei_distance=internuclei_distance[i][j]
>> >> >> >> >>> >>> > ...
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > Thus, the list for a storage of spin specific data does
>> >> >> >> >>> >>> > not
>> >> >> >> >>> >>> > exist
>> >> >> >> >>> >>> > and
>> >> >> >> >>> >>> > the
>> >> >> >> >>> >>> > suggested variable location does not exist:
>> >> >> >> >>> >>> > self.data[0].ri_prime
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> This can be created, if I make this special Python
>> >> >> >> >>> >>> list-like
>> >> >> >> >>> >>> object.
>> >> >> >> >>> >>> There is already one special object, the Data class at
>> >> >> >> >>> >>> the
>> >> >> >> >>> >>> very
>> >> >> >> >>> >>> end of
>> >> >> >> >>> >>> the file. I can create a list-like object here as well,
>> >> >> >> >>> >>> and
>> >> >> >> >>> >>> initialise each spin object to this. Ok, I've just added
>> >> >> >> >>> >>> this
>> >> >> >> >>> >>> code in
>> >> >> >> >>> >>> r12618. This should fix the problem and not cause too
>> >> >> >> >>> >>> many
>> >> >> >> >>> >>> problems
>> >> >> >> >>> >>> with your current code.
>> >> >> >> >>> >>>
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> > We found some possible ways to solve the problem.
>> >> >> >> >>> >>> > However
>> >> >> >> >>> >>> > we
>> >> >> >> >>> >>> > do
>> >> >> >> >>> >>> > not
>> >> >> >> >>> >>> > think,
>> >> >> >> >>> >>> > they are ideal.
>> >> >> >> >>> >>> > First, we can add for each spin a new list except those
>> >> >> >> >>> >>> > which
>> >> >> >> >>> >>> > store
>> >> >> >> >>> >>> > the
>> >> >> >> >>> >>> > interaction specific data. Data_spin list would be at
>> >> >> >> >>> >>> > the
>> >> >> >> >>> >>> > beginning
>> >> >> >> >>> >>> > of
>> >> >> >> >>> >>> > the
>> >> >> >> >>> >>> > array and therefore every loop over interactions in the
>> >> >> >> >>> >>> > code
>> >> >> >> >>> >>> > has
>> >> >> >> >>> >>> > to
>> >> >> >> >>> >>> > keep
>> >> >> >> >>> >>> > it
>> >> >> >> >>> >>> > in mind and start from index 1 not 0 to avoid Data_spin
>> >> >> >> >>> >>> > list.
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > The second possibility is based on the idea to declare
>> >> >> >> >>> >>> > for
>> >> >> >> >>> >>> > each
>> >> >> >> >>> >>> > spin
>> >> >> >> >>> >>> > a
>> >> >> >> >>> >>> > class
>> >> >> >> >>> >>> > Spin_data. The Spin_data would contain all spin
>> >> >> >> >>> >>> > specific
>> >> >> >> >>> >>> > variables
>> >> >> >> >>> >>> > (ri_prime, chi2, ...) and also a class Data which would
>> >> >> >> >>> >>> > contain
>> >> >> >> >>> >>> > interaction
>> >> >> >> >>> >>> > specific data.
>> >> >> >> >>> >>> >
>> >> >> >> >>> >>> > What do you think about these suggestions? We will be
>> >> >> >> >>> >>> > glad
>> >> >> >> >>> >>> > for
>> >> >> >> >>> >>> > any
>> >> >> >> >>> >>> > better
>> >> >> >> >>> >>> > suggestion, than ours.
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> I have taken your second idea, but it is inbuilt into the
>> >> >> >> >>> >>> self.data[i]
>> >> >> >> >>> >>> structure itself rather than a separate object inside
>> >> >> >> >>> >>> self.data.
>> >> >> >> >>> >>> I
>> >> >> >> >>> >>> hope this solution will be ok.
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> Cheers,
>> >> >> >> >>> >>>
>> >> >> >> >>> >>> Edward
>> >> >> >> >>> >>
>> >> >> >> >>> >>
>> >> >> >> >>> >
>> >> >> >> >>
>> >> >> >> >>
>> >> >> >> >
>> >> >> >
>> >> >> >
>> >> >
>> >> >
>> >
>> >
>
>