***[Possible UCE]*** [SciPy-user] Help with array functions

eric jones eric at enthought.com
Tue May 4 16:25:34 EDT 2004


Hey Travis,

The Fortran version didn't work for me.  It looks like g77 is detected 
on my machine, and I get compile errors in the code.  I also have an f90 
compiler on my machine that wasn't picked up.  Is there a way to switch 
which compiler is used through command line?

eric


Travis Oliphant wrote:

> Bob.Cowdery at CGI-Europe.com wrote:
>
>> Hi all,
>>  
>> Can anyone help me convert this loop to an array function. I can't 
>> have loops in my signal processing as they take far too much 
>> processing power. This is a fragment from a speech processor using 
>> Ferkins formula. Essentially the gain array (m_procGain) which is 
>> 2048 long (m_sampl_sz) needs its nth element processing into it's 
>> (n-1)th element. This is eventually used to multiply the samples in 
>> m_complexout, the first 2048 elements of this are used. Attack is a 
>> scaler currently 0.4.
>>
>>                 peak = 
>> abs(self.m_complexout[argmax(abs(self.m_complexout[:self.m_sampl_sz]))])
>>                 i = arange(1,self.m_sampl_sz)
>>                 for x in i:
>>                     if abs(self.m_complexout[x-1]) > 0:
>>                        self.m_procGain[x] = ( (self.m_procGain[x-1] * 
>> (1 - attack)) + ((attack * peak) / abs(self.m_complexout[x-1])) 
>> )                               if self.m_procGain[x] > level:
>>                            self.m_procGain[x] = level
>>                     else:
>>                        self.m_procGain[x] = 1
>>
>
> Bob,
>
> You have here something similar to an IIR filter.  The command 
> signal.lfilter is usually used in situations like this.
>
> If I read this code correctly then define y[n] = self.m_procGain[n]  
> with a = (1-attack)
>
> w[n] = (attack*peak) / abs(self.m_complexout[n])
>
> and you want to basically compute
>
> y[n] = a y[n-1] + w[n-1] 
> as long as w[n-1] is not infinite because of zero-valued 
> abs(self.m_complexout[n-1])
>
> The problem with using signal.lfilter is you have a non-linear filter 
> due to the if statements.  You could try to modify the algorithm a bit 
> to maintain a linear filter, or you will have to use weave (or f2py).
> Just to expose you to the many ways to accomplish the problem.  Here 
> is another test using f2py
>
>
>
> ******** Results *********************
> weave results: [ 0.      0.8     0.96    0.992   0.9984  1.      
> 1.      1.      1.         1.    ]
> python results: [ 0.      0.8     0.96    0.992   0.9984  1.      
> 1.      1.      1.         1.    ]
> f2py results: [ 0.      0.8     0.96    0.992   0.9984  1.      
> 1.      1.      1.         1.    ]
> C time: 0.08
> Python time: 6.13
> f2py time: 0.05
> weave vs. Python speedup: 76.625
> f2py vs. Python speedup: 122.6
>
>
> ********* Code below ***********
>
>
>
> # test.py
>
> fort_code = r"""
>
>       subroutine gain_compute(gain, abs_complexout, attack, peak,
>     $        level, samples)
>
>       integer samples
>       double precision attack, peak, level
>       double precision gain(samples), abs_complexout(samples)
>
>       double precision val
>       integer i
>
>       do i = 2, samples
>           if (abs_complexout(i-1).gt.0.0) then
>               val = gain(i-1)*(1.0-attack) +
>     $                 (attack*peak) / abs_complexout(i-1)
>               if (val.gt.level) then
>                   val = level
>               end if
>           else
>              val = 1.0
>           end if
>           gain(i) = val
>       end do
>
>       return
>       end subroutine gain_compute
> """
>    
> from scipy import zeros, ones, Float64, arange
> from scipy import stats
> import scipy_distutils
> import weave
> import f2py2e
>
> try:
>    import forttest
> except ImportError:
>    f2py2e.compile(fort_code, modulename='forttest')
>    import forttest
>
> def python_algorithm(gain, abs_complexout, attack, peak, level, samples):
>   # gain is changed *inplace*
>   i = arange(1,samples)
>   for x in i:
>       if abs_complexout[x-1] > 0:
>          gain[x] = ( (gain[x-1] * (1.0 - attack)) + ((attack * peak) / 
> abs_complexout[x-1]) )
>          if gain[x] > level:
>              gain[x] = level
>       else:
>          gain[x] = 1
>
> def weave_algorithm(gain, abs_complexout, attack, peak, level, samples):
>   # gain is changed *inplace*
>   code = """
>          for (int x=1; x < samples; x++)
>          {
>              if (abs_complexout[x-1] > 0.0)
>              {
>                 gain[x] = ( (gain[x-1] * (1.0 - attack)) +
>                             ((attack * peak) / abs_complexout[x-1]) 
> );                        if (gain[x] > level)
>                     gain[x] = level;
>              }
>              else
>                 gain[x] = 1;
>          }
>          """
>   weave.inline(code,
>                ['gain', 'abs_complexout', 'samples', 'attack', 'peak', 
> 'level'],
>                compiler='gcc')
>
> # some default parameters...
> samples = 2048
> gain = zeros(samples,typecode=Float64)
> complexout = stats.choice([-1.0,0.0,1.0],size=samples)
>
> attack = .8
> peak = 1.0
> level = 1.0
>
>
> # equivalence tests
> ac = abs(complexout)
> weave_algorithm(gain, ac, attack, peak, level, samples)
> print 'weave results:', gain[:10]
>
> gain = zeros(samples,typecode=Float64)
> python_algorithm(gain, ac, attack, peak, level, samples)
> print 'python results:', gain[:10]
>
> gain = zeros(samples,typecode=Float64)
> forttest.gain_compute(gain, ac, attack, peak, level, samples)
> print 'f2py results:', gain[:10]
>
>
> # speed tests
> import time
>
> N = 1000
>
> t1 = time.clock()
> for it in range(N):
>   weave_algorithm(gain, complexout, attack, peak, level, samples)
> t2 = time.clock()
> ct = t2 - t1
> print 'C time:', ct
>
> t1 = time.clock()
> for it in range(N):
>   python_algorithm(gain, complexout, attack, peak, level, samples)
> t2 = time.clock()
> pt = t2-t1
> print 'Python time:', pt
>
> f2py_algorithm = forttest.gain_compute
> t1 = time.clock()
> for it in range(N):
>   f2py_algorithm(gain, complexout, attack, peak, level, samples)
> t2 = time.clock()
> ft = t2-t1
> print 'f2py time:', ft
>
>
> ratio = pt/ct
> ratio2 = pt/ft
> print 'weave vs. Python speedup:', ratio
> print 'f2py vs. Python speedup:', ratio2
>
>
>
>
>
>
>
>
>
>
>
>
>> Thanks for any assistance.
>>  
>> Bob
>>  
>>  
>> Bob Cowdery
>> CGI Senior Technical Architect
>> +44(0)1438 791517
>> Mobile: +44(0)7771 532138
>> bob.cowdery at cgi-europe.com <mailto:bob.cowdery at cgi-europe.com>
>>  
>>  
>>  
>>
>> **** Confidentiality Notice **** Proprietary/Confidential
>> Information belonging to CGI Group Inc. and its affiliates
>> may be contained in this message. If you are not a recipient
>> indicated or intended in this message (or responsible for
>> delivery of this message to such person), or you think for
>> any reason that this message may have been addressed to you
>> in error, you may not use or copy or deliver this message
>> to anyone else.  In such case, you should destroy this
>> message and are asked to notify the sender by reply email.
>>
>> ------------------------------------------------------------------------
>>
>> _______________________________________________
>> SciPy-user mailing list
>> SciPy-user at scipy.net
>> http://www.scipy.net/mailman/listinfo/scipy-user
>>  
>>
>
> _______________________________________________
> SciPy-user mailing list
> SciPy-user at scipy.net
> http://www.scipy.net/mailman/listinfo/scipy-user






More information about the SciPy-User mailing list