2
votes

I am learning Numpy as a substitute to Matlab. I am having problem mapping Matlab function to Numpy. Program is to add two signals using Matlab

Matlab version :

function [y.d = sigadd(xl,nl,x2,n2)
% implements y(n) = xi(n)+x2(n)
% [y,nl - sigadd(xi,nl,x2,n2)
X
% xi = first sequence over nl
% x2 - second sequence over n2 (n2 can be different from nl)
%
n = min(min(n1) ,min(n2)) :max(max(nl) ,max(n2)) ; X duration of y(n)
yl - zeros(l,length(n)); y2 = yl;
yl(find((n>=min(nl))&(n<cmar(nl))-l))lxl;
y2(find((n>=min(n2))&(n<=max(n2))==1))=x2;
y = yl+y2;

I have tried the following in Python :

def SigAdd(x1,n1,x2,n2):
    n_l =  min(min(n1),min(n2))
    n_h=  max(max(n1),max(n2))
    n = arange(n_l,n_h+1)
    y1 = zeros([1,len(n)],int)
    y2 = y1
    y1 = (argwhere((n>=min(n1))&(n<=max(n1)))==1)
    y1 = x1
    y2 = (argwhere((n>=min(n2))&(n<=max(n2)))==1)
    y2 = x2
    y = y1 + y2
    return y,n

Expected Results:

Example1: Arrays of unequal length

x1 = array([1,1,1,1,1])
x2 = array([1,1,1,1])
n1 = array([1,2,3,4,5])
n2 = array([1,2,3,4])
y,n = SigAdd(x1,n1,x2,n2)
>> y 
array[2,2,2,2,1]
>>n
array[1,2,3,4,5]

Example2:Arrays of equal length

x1 = array([1,1,1])
x2 = array([1,1,1])
n1 = array([1,2,3])
n2 = array([3,4,5])
y,n = SigAdd(x1,n1,x2,n2)
>> y 
array[1,1,2,1,1]
>>n
array[1,2,3,4,5]

It works fine if both the arrays are of equal length, but won't work for unequal arrays. I know the problem is i am overriding the y1 (which i initially created with zeros) with value of x1 causing problem. I have used argwhere command in Numpy which is equivalent to Find command of Matlab, but if I use it like Matlab program shown above, it shows error that value can't be assigned to callable function.

Basically in Matlab program, unequal arrays are filled with zero's. Matlab version handles condition even if two signals are of equal length but are at different positions. I want to use Python instead of Matlab but these conversion problems are causing pain.

Some Modifications : (But is not working, Indexing Error : Out of bound coming)

def SigAdd(x1,n1,x2,n2):
    n_l =  min(min(n1),min(n2))
    n_h=  max(max(n1),max(n2))
    n = arange(n_l,n_h+1)
    y1 = zeros([1,len(n)],int)
    y2 = y1
    y11 = argwhere((n>=min(n1))&(n<=max(n1)))
    q = 0
    for w in y11:
        y1[w]= x1[q]
        q = q + 1
    y22 = argwhere((n>=min(n2))&(n<=max(n2)))
    q = 0
    for w in y22:
        y2[w]= x2[q]
        q = q + 1
    y = y1 + y2
    return y
3
I would write a little function that pads an array with zeros to the size you want, so that you can always pass arrays of equal length to SigAdd(). - Brian L
Padding may not work for example2, i have modified code to address this problem, but i am just stuck with assignment. - sarbjit

3 Answers

4
votes

You can assign to a slice:

def SigAdd(x1,n1,x2,n2):
    n_l = min(n1[0], n2[0])
    n_h = max(n1[-1], n2[-1])
    n = arange(n_l, n_h+1)
    y = zeros(len(n), int)
    i = n1[0] - n[0]
    y[i:i+len(x1)] = x1
    i = n2[0] - n[0]
    y[i:i+len(x2)] += x2
    return y
2
votes

Using fancy indexing:

import numpy as np
high = max(n2[-1], n1[-1])
low = min(n2[0], n1[0])
n1_ = n1 - low  # use 0-based indexing
n2_ = n2 - low
y = np.zeros(high - low + 1, dtype=x1.dtype)
y[n1_] += x1
y[n2_] += x2
0
votes

This helped me for a similar problem. The idea is to first make the vectors equal length (with 0 padding the shorter at the end). Disadvantages are the conversion to lists and the memory overhead with those lists. However for quick and dirty tasks it has served well.

def MakeVectorsSameSize(v1,v2):
  """given two vectors zero pad smaller to match length of bigger"""
  #make the vectors length of longest 0 pad
  l1 = len(v1)
  l2 = len(v2)
  if l1 < l2:
    #put l2-l1 elements into v1
    z1 = numpy.ones(l2-l1)*0
    v1 = list(v1)
    v1.extend(z1)
    v1 = numpy.array(v1)
  elif l1 > l2:
    #put l1-l2 elements into v2
    z2 = numpy.ones(l1-l2)*0
    v2 = list(v2)
    v2.extend(z2)
    v2 = numpy.array(vTemp)

  return v1,v2