Bottom Page

Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
 'list' object has no attribute 'plot' problem
#1
Hi,

Forgive me if this post is in the wrong place. The code uses tkinter GUI with several plots on seperate note tabs, hence Ive posted it in GUI

Ive been using Python for about 3 weeks but have coded in C++, clipper and VB for about 30 years.

I want to write some code to read in a file of vibration data with up to 16k readings, perform an fft to convert from time based data to frequency based data so I can analyse the data for problems. Please refer to my website www.efftek.co.uk for further information on vibration analysis if you need.

I found an open source example of a program doing much of what I wanted. Basically, it talks to an arduino which is connected to a 3 axis accelerometer, takes readings and displays them. The original source code and details are here https://hackaday.io/project/12109-open-s...m-analyzer

I have used this code to learn Python and have been editing it to my own needs.

I dont want all three channels displayed on one plot as the source code has so where fig1 had three subplots - ax_11, ax_12 and ax_13, I have deleted two of the sub plots so I just have ax_11. The same for fig2, fig3 and fig4 (fig3 and fig4 are my additions to the original code)

Now when I removed ax_?3 and change the subplots to be .add_subplot(2,1,?) etc, it still works OK but when I delete plots ax_?2 and change it to .add_subplot(1,1,1), I get errors. Whilst it will start up OK and display an empty plot, when I open a file with data to be displayed, I get a 'list' object has no attribute 'plot' error for line 247

Here is the full code. In order to try this out, you will need to download the data file from here datos_3can_20-12-2016__11_39_50.txt

I'd be grateful if anyone can advise why this is happening and how to cure it. Thanks, Steve.

#!/usr/bin/env python3    ¡¡¡ OK !!!
# fft_spectrum_gui_3can_py3_02.py
# - Added velocity and envelop (using hilbert transform) plots
# 01/02/2018 - Steve Ferry.
# Program fft_spectrum_gui_3can_py3_01.py
# - Added a timeout control to a while loop.
# 12/01/2017
# Program fft_spectrum_gui_3can.py modified:
# - From Python 2.7 to Python 3.5.
# - Works with AVR program adxl335_3can_01.c
# 20/12/2016
# Program fft_spectrum_gui_3can.py
# Program fft_spectrum_gui.py modified:
# - 3 data channels (3 axes)
# 15/11/2016
# Program fft_spectrum_gui.py
# - Based on program frame_tab_plot_07.py
# - Sample acceleration data from a ADXL335 accelerometer.
# - Plot sampled data and its FFT spectrumsu
# - Save data on file and open files with saved data.
# - Serial communication with microcontroller.e
# - Serial port selection.
# - RadioButtons to select a Window function to apply.
# 13/07/2016

import matplotlib
import matplotlib.pyplot as plt
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg
from matplotlib.figure import Figure
from scipy import fftpack, arange, signal
import numpy as np
import tkinter as Tk
from tkinter import filedialog
from tkinter import messagebox
from tkinter.scrolledtext import ScrolledText
from tkinter import ttk
from scipy.signal import hilbert
from numpy import linalg as nl

datos_a_leer = 4096  # Amount of samples to read.
sample_rate = 5000  # Sampling frequency (SPS).
g_scale = 3.0 / 512  # +- 3g. 10 bit ADC.
max_freq = 1500  # Maximum signal frequency, X and Y axis (accelerometer).
max_freq_z = 500  # Maximum signal frequency, Z axis (accelerometer).
fftlen = 8192 # Samples to display FFT
twflen = 2048 # twf data points to display
twopi = 6.28318530717
gconst = 9806.65

g_canal_1 = []  # Global canal_1
g_canal_2 = []  # Global canal_2
g_canal_3 = []  # Global canal_3
t_timeout = 8  # Timeout time in seconds.

def simpleParse(mainString, beginString, endString):
    posBeginString = mainString.find(beginString) + len(beginString)
    posEndString = mainString.find(endString)
    resultado = mainString[posBeginString:posEndString]
    return resultado


def extraer_int_tag(datos_arch, tag):
    beginString = '<' + tag + '>'
    endString = '</' + tag + '>'
    str_parse = simpleParse(datos_arch, beginString, endString)
    str_canal = str_parse.split(',')
    canal = []
    n = len(str_canal)
    for i in range(n):
        canal.append(int(str_canal[i]))
    return canal

class Application:
    def __init__(self, parent):
        self.parent = parent
        self.frames()
        self.f_saved = True  # Sampled data saved
        root.protocol("WM_DELETE_WINDOW", self.on_closing)

    def on_closing(self):
        if (self.f_saved == False):
            if messagebox.askokcancel("Quit", "Sampled data not saved. Do you wanto to quit?"):
                root.destroy()
        else:
            root.destroy()

    def frames(self):
        frame1 = Tk.Frame(root, bd=5, relief='raised', borderwidth=1)
        frame2 = Tk.Frame(root, bd=5, relief='raised', borderwidth=1)

        note = ttk.Notebook(frame2)
        self.tab1 = ttk.Frame(note)
        self.tab2 = ttk.Frame(note)
        self.tab3 = ttk.Frame(note)
        self.tab4 = ttk.Frame(note)

        note.add(self.tab1, text=" Time Waveform ")
        note.add(self.tab2, text=" Acceleration Spectra ")
        note.add(self.tab3, text=" Velocity Spectra ")
        note.add(self.tab4, text=" Demodulated Spectra ")

        # Positioning
        frame1.pack(side='left', fill='both', padx=5, pady=5)
        frame2.pack(side='right', fill='both', expand='true')

        boton_open = Tk.Button(frame1, text="Open file", command=self.open_file)

        label4 = Tk.Label(frame1, text="Select Channel")
        self.text_message = ScrolledText(frame1, height=10, width=20)

        self.chan_var = Tk.IntVar()
        self.chan_var.set(1)

        channel_button1 = Tk.Radiobutton(frame1, text="Channel 1",
                                         variable=self.chan_var, value=1, command=self.chan_sel)
        channel_button2 = Tk.Radiobutton(frame1, text="Channel 2",
                                         variable=self.chan_var, value=2, command=self.chan_sel)
        channel_button3 = Tk.Radiobutton(frame1, text="Channel 3",
                                         variable=self.chan_var, value=3, command=self.chan_sel)
        channel_button4 = Tk.Radiobutton(frame1, text="Channel 4",
                                         variable=self.chan_var, value=3, command=self.chan_sel)

        label4.grid(row=4, column=0, padx=5, pady=5)
        channel_button1.grid(row=5, column=0, sticky="W")
        channel_button2.grid(row=6, column=0, sticky="W")
        channel_button3.grid(row=7, column=0, sticky="W")
        channel_button4.grid(row=8, column=0, sticky="W")
        note.pack(side='top', fill='both', padx=5, pady=5)
        boton_open.grid(row=13, column=0, padx=5, pady=5)
        plt.ion()

        # Figure 1
        fig1 = Figure(figsize=(10, 9))
        fig1.suptitle('Sampled signal - Acceleration')
        ax_11 = fig1.add_subplot(1, 1, 1)
        ax_11.set_ylabel('g')
        ax_11.grid()  # Shows grid.

        # Figure 2
        fig2 = Figure(figsize=(10, 9))
        fig2.suptitle('Acceleration Spectra')
        ax_21 = fig2.add_subplot(1, 1, 1)
        ax_21.set_ylabel('g')
        ax_21.set_xlim(xmin=0,xmax=max_freq)
        ax_21.grid()

        # Figure 3
        fig3 = Figure(figsize=(10, 9))
        fig3.suptitle('Velocity spectra')
        ax_31 = fig3.add_subplot(1, 1, 1)
        ax_31.set_ylabel('mm/sec')
        ax_31.set_xlim(xmin=0, xmax=max_freq)
        ax_31.grid()

        # Figure 4
        fig4 = Figure(figsize=(10, 9))
        fig4.suptitle('Demodulated spectra')
        ax_41 = fig4.add_subplot(1, 1, 1)
        ax_41.set_ylabel('g')
        ax_41.set_xlim(xmin=0, xmax=max_freq)
        ax_41.grid()

        # Canvas
        self.canvas1 = FigureCanvasTkAgg(fig1, master=self.tab1)
        self.canvas1.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

        self.canvas2 = FigureCanvasTkAgg(fig2, master=self.tab2)
        self.canvas2.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

        self.canvas3 = FigureCanvasTkAgg(fig3, master=self.tab3)
        self.canvas3.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

        self.canvas4 = FigureCanvasTkAgg(fig4, master=self.tab4)
        self.canvas4.get_tk_widget().pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)

        self.canvas1._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
        self.canvas2._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
        self.canvas3._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)
        self.canvas4._tkcanvas.pack(side=Tk.TOP, fill=Tk.BOTH, expand=1)


    def show_message(self, text_message, message_string):
        """Shows messages on a scrollable textbox"""
        text_message.config(state=Tk.NORMAL)  # Enable to modify
        text_message.insert(Tk.END, message_string)
        text_message.config(state=Tk.DISABLED)  # Disable - Read only
        text_message.see("end")  # Show the "end" of text
        root.update_idletasks()  # Needed to make message visible

    def plot(self, tab1, tab2, tab3, tab4, canal_1, canal_2, canal_3, chan_no):

        if chan_no == 1:
            twf = canal_1
        elif chan_no == 2:
            twf = canal_2
        else:
            twf = canal_3

        num_datos = len(twf)
        X = range(0, num_datos, 1)

        # Scale the signal in g's
        for indice in X:
            twf[indice] *= g_scale

        # Calculates average value for each channel.
        avg = 0
        for indice in X:
            avg += twf[indice]

        avg = avg / num_datos
        # print("Vdc Channel 1: {0}, Vdc Channel 2: {1}".format(vdc_canal_1, vdc_canal_2))

        # Substract DC offset
        for indice in X:
            twf[indice] -= avg

        X1 = np.linspace(0, num_datos / 5, num=num_datos)  # X axis, 5000 sps, 1/5 ms.

        canal_fft = twf
        N = len(canal_fft)  # length of the signal
        M = int(N / 2)
        T = 1.0 / sample_rate
        y = canal_fft
        w = signal.hann(N, sym=False)  # Hann (Hanning) window

        ax = np.abs(fftpack.fft(y * w) * (2 / N))
        ax = ax[:int(N / 2)]
        xx = np.linspace(0.0, 1.0 / (2.0 * T), int(N / 2))

        vx = [0] * M
        for i in range( 5, M):
            vx[i] = ((ax[i] * gconst) / (twopi * xx[i])) #calculate velocity

        analy = hilbert(canal_fft[::])
        y = abs(analy[0:M])
        sig_f = abs(np.abs(fftpack.rfft(y)))
        sig_n = sig_f / (nl.norm(sig_f))
        hx = sig_n[0:M]
        hx[0] = 0

        # Figure 1. twf

        ax_11 = self.canvas1.figure.get_axes()
        ax_11.clear()
        ax_11.plot(X1[0:twflen], twf[0:twflen])
        ax_11.set_ylabel('g')
        ax_11.grid()  # Shows grid.

        # Figure 2. FFT from signals.

        ax_21 = self.canvas2.figure.get_axes()
        ax_21.clear()
        ax_21.plot(xx, ax)
        ax_21.grid()
        ax_21.set_ylabel('g')
        ax_21.set_xlim(xmin=0, xmax=max_freq)

        ax_31 = self.canvas3.figure.get_axes()
        ax_31.clear()
        ax_31.plot(xx, vx)
        ax_31.grid()
        ax_31.set_ylabel('mm/sec')
        ax_31.set_xlim(xmin=0, xmax=max_freq)

        ax_41 = self.canvas4.figure.get_axes()
        ax_41.clear()
        ax_41.plot(xx, hx)
        ax_41.grid()
        ax_41.set_ylabel('g')
        ax_41.set_xlim(xmin=0, xmax=max_freq)

        self.canvas1.draw()
        self.canvas2.draw()
        self.canvas3.draw()
        self.canvas4.draw()

    def chan_sel(self):
        global g_canal_1, g_canal_2, g_canal_3
        canal_1 = g_canal_1[:]  # Copy list by value not by reference
        canal_2 = g_canal_2[:]
        canal_3 = g_canal_3[:]
        chan_no = self.chan_var.get()
        if (len(canal_1) != 0):  # Apply only if data available
            self.plot(self.tab1, self.tab2, self.tab3, self.tab4, canal_1, canal_2, canal_3, chan_no)

    def open_file(self):
        """Opens dialog to select a file, reads data from file and plots the data"""
        ftypes = [('Text files', '*.txt'), ('All files', '*')]
        dlg = filedialog.Open(root, filetypes=ftypes)
        fl = dlg.show()
        if fl != '':
            # Open file for reading
            arch = open(fl, "r")
            datos_arch = arch.read()
            # Searches for every channel, delimited by L1, L2 and L3 tags.
            canal_1 = extraer_int_tag(datos_arch, 'L1')
            canal_2 = extraer_int_tag(datos_arch, 'L2')
            canal_3 = extraer_int_tag(datos_arch, 'L3')

            print("Amount of samples in channel 1: %s" % len(canal_1))
            print("Amount of samples on channel 2: %s" % len(canal_2))
            print("Amount of samples on channel 3: %s" % len(canal_3))
            message_string = "Amount of samples \nChannel 1: {0} \n".format(len(canal_1))
            message_string += "Channel 2: {0} \n".format(len(canal_2))
            message_string += "Channel 3: {0} \n".format(len(canal_3))
            self.show_message(self.text_message, message_string)

            global g_canal_1, g_canal_2, g_canal_3
            # Keep a copy of the original values
            g_canal_1 = canal_1[:]  # Copy list by value not by reference
            g_canal_2 = canal_2[:]
            g_canal_3 = canal_3[:]

            self.plot(self.tab1, self.tab2, self.tab3, self.tab4, canal_1, canal_2, canal_3, chan_no=1)


if __name__ == '__main__':
    root = Tk.Tk()
    root.title('FFT spectrum analyser')
    app = Application(root)
    root.mainloop()
Quote
#2
please, post full traceback in error tags
Quote
#3
Error is as follows;

Error:
Traceback (most recent call last): File "C:\Users\Steve\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__ return self.func(*args) File "C:/Users/Steve/PycharmProjects/newGUI/main.py", line 316, in open_file self.plot(self.tab1, self.tab2, self.tab3, self.tab4, canal_1, canal_2, canal_3, chan_no=1) File "C:/Users/Steve/PycharmProjects/newGUI/main.py", line 247, in plot ax_11.plot(X1[0:twflen], twf[0:twflen]) AttributeError: 'list' object has no attribute 'plot'
Cheers, Steve.
Quote

Top Page

Possibly Related Threads...
Thread Author Replies Views Last Post
  [Tkinter] Problem loading an image from directory into a Canvas object tiotony 3 799 Sep-02-2018, 06:47 PM
Last Post: woooee
  [Tkinter] AttributeError: 'App' object has no attribute 'set_text' Sahil1313 6 2,845 Jun-17-2018, 05:01 AM
Last Post: woooee

Forum Jump:


Users browsing this thread: 1 Guest(s)