solution_154b.py

#!/usr/bin/python3
# ====================================================================
# combine several sine/cosine waves and plot the results
#   0. signals start at different time
#   1. sine and cosine are part of this code
#   2. create your own value function
#      a. must be is continuous
#      b. must has a "value" method
# ====================================================================

import sys
import math

import numpy as np
import matplotlib.pyplot as plt

# --------------------------------------------------------------------
# ---- t0   start (time +/- ? if random)
# --------------------------------------------------------------------

class sineWave:

    def __init__(self,hz,st):
        self.hz  = hz         # frequence
        self.st  = st         # start time

    # ---- return wave's size/value/magnitude/strength at
    # ---- time t (seconds since time 0)

    def value(self,t):
        # ---- no negative sample time
        if t < 0.0: t = -t
        # ---- number of cycles since wave start time
        t = t + self.st
        cyc = t * self.hz
        # ---- number of degrees in a cycle at time t
        deg = (cyc * 360) % 360
        # ---- return degrees
        rad = math.radians(deg)
        return math.sin(rad)

# --------------------------------------------------------------------
# ---- class - cosine object
# ---- hz   frequency (cycles per second)
# --------------------------------------------------------------------

class cosineWave:

    def __init__(self,hz,st):
        self.hz  = hz         # frequence
        self.st  = st         # start time

    # ---- return wave's size/value/magnitude/strength at
    # ---- time t (seconds since time 0.0)

    def value(self,t):
        # ---- no negative sample time
        if t < 0.0: t = -t
        # ---- number of cycles since start time (never negative)
        t = t + self.st
        cyc =  t * self.hz
        # ---- number of degrees in a cycle in a cycle at time t
        deg = (cyc * 360) % 360
        # ---- return degrees
        rad = math.radians(deg)
        return math.cos(rad)

# -------------------------------------------------------------------
# ---- float range generator (start and end inclusive)
# -------------------------------------------------------------------

def frange(start,end,steps):
    step = abs((end-start)/(steps))
    f = start
    while True:
        yield(f)
        if f is not None: f += step
        if f >= end:      f = None

# --------------------------------------------------------------------
# ---- calculate/generate a list of values
# ----
# ---- tlst is a list of sample times within the sample
# ---- range. Every wave function should use the same tlst.
# ---- Sample times are monotonically increasing from sample
# ---- start time to sample end time (inclusive).
# --------------------------------------------------------------------

def calculate_wave_values(tlst,wave):
    slst = []
    for t in tlst:
        s = wave.value(t)
        slst.append(s)
    return slst

# --------------------------------------------------------------------
# ---- create a list of sample times
# ---- based on the sample start and end time, and the sample size
# ---- Note: the time list is a monotonic increasing list
# --------------------------------------------------------------------

def time_list(sstart,send,ssize):
    tlst = []
    for t in frange(sstart,send,ssize):
        if t is None: break     # end of range?
        tlst.append(t)
    return tlst

# --------------------------------------------------------------------
# ---- display list
# --------------------------------------------------------------------

def display_list(lst,num = -1,title=None):
    if title is not None: print(title)
    i = 0
    for x in lst:
        if num < 0 and i < num: break
        i += 1
        print(f'{x:.4f}, ',end='')
    print('\n')

# --------------------------------------------------------------------
# ---- main
# --------------------------------------------------------------------

if __name__ == '__main__':

    outfile = 'fft_dtat_data.csv'

   # ---- use the same sampling for each wave (signal)
    
    ssize  = 100            # sampling size (number of samples)
    sstart = 0.0            # sampling start time (seconds)
    send   = 0.01           # sampling end time (seconds)

    # ---- both signals start at time 0.0

    sin_start_time = 0.0    # seconds
    cos_start_time = -.43   # seconds
    sin_hz         = 100    # sine   (signal) frequency (hz)
    cos_hz         = 230    # cosine (signal) frequency (hz)

    # ---- get a list of sample times
    
    tim_lst = time_list(sstart,send,ssize)

    # ---- get a list of value samples for each time in tlst

    sin_wave = sineWave(sin_hz,sin_start_time)
    
    sin_lst = calculate_wave_values(tim_lst,sin_wave)

    # ---- get a list of value samples for each time in tlst

    cos_wave = cosineWave(cos_hz,cos_start_time)
    
    cos_lst = calculate_wave_values(tim_lst,cos_wave)

    # ---- combine (add) the two lists together

    combo_lst = list(np.add(sin_lst,cos_lst))

    # ---- plot sum of values vs time

    #plot(tim_lst,combo_lst)

    plt.plot(tim_lst,sin_lst, 'r')
    plt.plot(tim_lst,cos_lst, 'b')
    plt.plot(tim_lst,combo_lst, 'black')
    plt.xlabel('sample time', fontsize=14)
    plt.ylabel('sample value', fontsize=14)
    plt.grid()
    plt.show()
    
    print()