18

What is the most efficient way to produce an array of 100 numbers that form the shape of the triangle wave below, with a max/min amplitude of 0.5?

Triangle waveform in mind:

enter image description here

6
  • do you need just to arrange the data structure or to draw a graphical representation too? Commented Sep 8, 2012 at 16:29
  • Only need to make an array of 100 data entries that take that shape. Graphical representation not needed! Commented Sep 8, 2012 at 16:29
  • Wikipedia has 3 different formulas you can use to calculate a triangle wave: en.wikipedia.org/wiki/Triangle_wave#Definitions There might be quicker ways, but implementing one of those equations should be a nice starting point. Commented Sep 8, 2012 at 16:31
  • I think it might be simpler to build the array using three parts, as y=(-)x. I.e. The first would be pylab.arange(0,0.5,25) Commented Sep 8, 2012 at 16:36
  • How important is speed really for you? I assume it doesn't really matter much, but if it does, you should rewrite the examples below to make more use of np.arange as you said, create an empty array and then fill it with np.arange elements for example (instead of iterations below). Commented Sep 8, 2012 at 17:48

7 Answers 7

27

The simplest way to generate a triangle wave is by using signal.sawtooth. Notice that signal.sawtooth(phi, width) accepts two arguments. The first argument is the phase, the next argument specifies the symmetry. width = 1 gives a right-sided sawtooth, width = 0 gives a left-sided sawtooth and width = 0.5 gives a symmetric triangle. Enjoy!

from scipy import signal
import numpy as np
import matplotlib.pyplot as plt
t = np.linspace(0, 1, 500)
triangle = signal.sawtooth(2 * np.pi * 5 * t, 0.5)
plt.plot(t, triangle)
Sign up to request clarification or add additional context in comments.

1 Comment

9

Use a generator:

def triangle(length, amplitude):
     section = length // 4
     for direction in (1, -1):
         for i in range(section):
             yield i * (amplitude / section) * direction
         for i in range(section):
             yield (amplitude - (i * (amplitude / section))) * direction

This'll work fine for a length divisible by 4, you may miss up to 3 values for other lengths.

>>> list(triangle(100, 0.5))
[0.0, 0.02, 0.04, 0.06, 0.08, 0.1, 0.12, 0.14, 0.16, 0.18, 0.2, 0.22, 0.24, 0.26, 0.28, 0.3, 0.32, 0.34, 0.36, 0.38, 0.4, 0.42, 0.44, 0.46, 0.48, 0.5, 0.48, 0.46, 0.44, 0.42, 0.4, 0.38, 0.36, 0.33999999999999997, 0.32, 0.3, 0.28, 0.26, 0.24, 0.21999999999999997, 0.2, 0.18, 0.15999999999999998, 0.14, 0.12, 0.09999999999999998, 0.08000000000000002, 0.06, 0.03999999999999998, 0.020000000000000018, -0.0, -0.02, -0.04, -0.06, -0.08, -0.1, -0.12, -0.14, -0.16, -0.18, -0.2, -0.22, -0.24, -0.26, -0.28, -0.3, -0.32, -0.34, -0.36, -0.38, -0.4, -0.42, -0.44, -0.46, -0.48, -0.5, -0.48, -0.46, -0.44, -0.42, -0.4, -0.38, -0.36, -0.33999999999999997, -0.32, -0.3, -0.28, -0.26, -0.24, -0.21999999999999997, -0.2, -0.18, -0.15999999999999998, -0.14, -0.12, -0.09999999999999998, -0.08000000000000002, -0.06, -0.03999999999999998, -0.020000000000000018]

2 Comments

Much more efficient than my attempt. Thank you!
change range to xrange (if it's python < 3)
8

Triangle is absolute value of sawtooth.

from scipy import signal
time=np.arange(0,1,0.001)
freq=3
tri=np.abs(signal.sawtooth(2 * np.pi * freq * time)) 

Comments

7

To use numpy:

def triangle2(length, amplitude):
    section = length // 4
    x = np.linspace(0, amplitude, section+1)
    mx = -x
    return np.r_[x, x[-2::-1], mx[1:], mx[-2:0:-1]]

Comments

1

You can use an iterator generator along with the numpy fromiter method.

import numpy

def trigen(n, amp):
    y = 0
    x = 0
    s = amp / (n/4)
    while x < n:
        yield y
        y += s
        if abs(y) > amp:
            s *= -1
        x += 1

a = numpy.fromiter(trigen(100, 0.5), "d")

Now you have an array with the square wave.

Comments

1

Here is a home-made python function for triangular signals

import matplotlib.pyplot as plt
import numpy as np
phase=-10
length=30 # should be positive
amplitude=10
x=np.arange(0,100,0.1)
def triang(x,phase,length,amplitude):
    alpha=(amplitude)/(length/2)
    return -amplitude/2+amplitude*((x-phase)%length==length/2) \
            +alpha*((x-phase)%(length/2))*((x-phase)%length<=length/2) \
            +(amplitude-alpha*((x-phase)%(length/2)))*((x-phase)%length>length/2)

tr=triang(x,phase,length,amplitude)
plt.plot(tr)

Comments

1

You can simply use traditional trig functions (arcsin and sin) from the math library to create a triangle-wave as a function of x and call it inside a list comprehension that loops over 100 slices of the function's period (2π).

import math

triangle_function = lambda x: 0.5 * math.asin(math.sin(2*math.pi*x))
L = [triangle_function(i/2*math.pi) for i in range(100)]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.