Sei sulla pagina 1di 16

LABORATORIO NO.

Victor Tzorin1
1
Universidad Galileo
Guatemala, Guatemala

11 de noviembre del 2019

Resumen A continuación se explorarán algunos algo-


El objetivo de este laboratorio era ritmos que utilizan el complejo QRS para medir
implementar procesos de detección la frecuencia cardı́aca.
de complejos QRS. Se aplicaron dos
métodos, el algoritmo Tompkins y I-A. Algoritmo Tompkins
el algoritmo Murhty-Rangaraj, a tres
señales distintas obtenidas de la base Método que consiste de un prefiltrado que
de datos en lı́nea Physionet. Se eva- elimna las frecuencias bajas, un derivador, una
luó el desempeño estadı́stico de am- media móvil de orden bajo y un umbral cons-
bos y se obtuvo que ambos tenı́an tante.
una precisión y especificidad igual a
1.000 y sensibilidad igual o mayor a El derivador, a su vez, se divide en tres par-
0.985. El algoritmo Tompkins obtu- tes. Primero se obtiene una derivada de tres pun-
vo mejores resultados estadı́sticos pe- tos de la señal x(n) de la siguiente forma (Ran-
ro el Murthy-Rangaraj no necesita tan- gayyan, 2015) [3]:
tos ajustes de parámetros para adaptar-
se a las diversas señales. Sin embargo,
ambos métodos son funcionales y pue- y0 (n) = |x(n) − x(n − 2)| (1)
den utilizarse para estudios relaciona-
dos al ritmo cardiaco. Luego la segunda derivada se aproxima con
(Rangayyan, 2015) [3]:
I INTRODUCCIÓN

El complejo QRS es la onda más distintiva y1 (n) = |x(n) − 2x(n − 2) + x(n − 4)| (2)
del electrocardiograma (ECG, por sus siglas en
inglés). Dado que refleja la actividad eléctrica Por último, los dos resultados son ponde-
dentro del corazón durante la contracción ven- rados y combinados para obtener (Rangayyan,
tricular, el momento en que ocurre y su forma 2015) [3]:
proveen mucha información sobre el estado ac-
tual del corazón; también sirve como base pa- y2 (n) = 1.3y0 (n) + 1.1y1 (n) (3)
ra la determinación automática de la frecuencia
cardı́aca, como punto de entrada para los esque-
I-B. Algoritmo Murthy-Rangaraj
mas de clasificación del ciclo cardı́aco y a me-
nudo también se usa en algoritmos de compre- Método que consiste de un derivador, una
sión de datos de ECG (Kohler et. al, 2002) [1]. media móvil de orden alto y un umbral que es

1
igual a la mitad de la amplitud del pico más alto verdaderos negativos, en una población; mide el
de la señal evaluada. grado de veracidad de una prueba para evaluar
El resultado del derivador de la señal x(n), una condición en general (Zhu et. al., 2010) [4].
a su vez, es ponderado y elevado al cuadrado de
la siguiente forma (Rangayyan, 2015) [3]:

N
X
y0 (n) = |x(n−i+1)−x(n−i)|2 (N −i+1) II PROCEDIMIENTO
i=1
(4)
II-A. Materiales
I-C. Sensibilidad, especificidad y preci-
sión
Software ejecutado en computadora por-
Hay varios términos que se usan tatil Lenovo Yoga 730 (15”) con procesa-
comúnmente junto con la descripción de sen- dor Intel Core i5
sibilidad, especificidad y precisión. Estos son: Programa escrito en Python utilizando las
verdaderos positivos (VP), verdaderos negati- librerı́as PyQtGraph, Datetime, Random,
vos (VN), falsos negativos (FN) y falsos po- Numpy, Pandas, Math y Scipy.
sitivos (FP), donde las denominaciones dadas
son autodescriptivas. La sensibilidad, especifi- Datos extraı́dos de la base de datos en
cidad y precisión se describen en términos de lı́nea Physionet (Physionet, s.f.) [2].
VP, VN, FN y FP de la siguiente forma (Zhu et.
al., 2010) [4]:

VP
sensibilidad = (5)
V P + FN
II-B. Pasos del procedimiento
VN
especif icidad = (6)
V N + FP 1. Descargar archivos de Physionet.
2. Hacer un programa que:
VN +VP
precisión = (7) Grafique cada una de las señales no
V N + V P + FN + FP filtradas de los archivos.
Como lo sugieren las ecuaciones anteriores, Aplique el algoritmo de Tompkins y
la sensibilidad es la proporción de verdaderos grafique los resultados.
positivos que se identifican correctamente me- Aplique el algoritmo de Murthy-
diante una prueba; muestra cuán buena es dicha Rangaraj y grafique los resultados.
prueba para detectar positivamente una condi-
ción. La especificidad es la proporción de los Compare los resultados de los algo-
verdaderos negativos correctamente identifica- ritmos con los resultados del proce-
dos por una prueba; sugiere qué tan buena es la so de selección manual para obtener
prueba para identificar negativamente una con- sensibilidad, especificidad y preci-
dición. La precisión es la proporción de resul- sión.
tados verdaderos, ya sea verdaderos positivos o 3. Analizar los resultados.

2
III RESULTADOS utilizados por archivo

IV DISCUSIÓN/ANÁLISIS

En las figuras 1,2 y 3 se pueden ver, respec-


tivamente, los resultados de la aplicación del al-
goritmo de Tompkins y el algoritmo de Murthy-
Rangaraj a los distintos archivos. En la tabla
1 se aprecia el desempeño estadı́stico de di-
chos algoritmos para cada caso. Para obtener
el desempeño mencionado, se consideró una to-
lerancia de ±15muestras ≡ 0.15s, dado que
Figura 1: Complejos QRS identificados mediante el algoritmo
ambos métodos identifican la onda R con cierto
Murthy-Rangaraj del archivo apnea-ecg a01 retraso, aproximadamente constante.
El algoritmo Tompkins se aplicó utilizan-
do un filtro pasabajas elı́ptico de 25Hz, el de-
rivador descrito en la Introducción (sección I),
una media móvil de orden siete y un umbral de
0.75mV. Tanto el filtro pasabajas como el lı́mi-
te mencionado fueron seleccionados a prueba y
error a fin de optimizar los resultados. Como se
observa en la figura 2 y en la tabla 1, este al-
goritmo resultó eficiente para el análisis de to-
dos los archivos, menos apnea-ecg a16. El últi-
Figura 2: Complejos QRS identificados mediante el algoritmo
mo complejo QRS de este electrocardiograma
Tompkins del archivo apnea-ecg a16 probablemente no fue correctamente identifica-
do por el procedimiento con el cual se seleccio-
nan los picos de la señal, que no toma en cuenta
ciclos cardiacos incompletos, como el presen-
tado; por esta razón, el algoritmo obtuvo una
sensibilidad de 0.988 en este caso.
El algoritmo Murthy-Rangaraj se aplicó uti-
lizando el derivador descrito en la Introducción
(sección I), una media móvil de orden diez y
un umbral igual a la mitad del mayor pico de
la señal. Como se observa en la figura 1, 3 y en
Figura 3: Complejos QRS identificados mediante el algoritmo
la tabla 1, este algoritmo resultó menos eficien-
Murthy-Rangaraj del archivo apnea-ecg a16 te para el análisis de todos los archivos. Falló
con apnea-ecg a16, por las mismas razones ya
Caso Método Sensibilidad Especificidad Precisión
mencionadas en el párrafo previo, y con apnea-
Tompkins 1.000 1.000 1.000
a01 ecg a01. Uno de los complejos QRS de este
M. y R. 0.985 1.000 1.000
Tompkins 1.000 1.000 1.000 último electrocardiograma no fue correctamen-
a10
M. y R. 1.000 1.000 1.000
Tompkins 0.988 1.000 1.000 te identificado por el procedimiento con el cual
a16
M. y R. 0.988 1.000 1.000 se seleccionan los picos de la señal, puesto que
Tabla 1: Medidas estadı́sticas del desempeño de los métodos su amplitud está por debajo del umbral estable-

3
cido; por esta razón, el algoritmo obtuvo una [2] PhysioNet (s.f.). Recuperado de: https:
sensibilidad de 0.985 en este caso. //physionet.org/.
Ası́ que, debido a la forma de definir el um- [3] Rangayyan, R. M. (2015). Biomedical sig-
bral a prueba y error para garantizar los mejo- nal analysis (Vol. 33). John Wiley & Sons.
res resultados, el algortimo Tompkins obtuvo el [4] Zhu, W., Zeng, N., & Wang, N. (2010).
mejor desempeño. Pero la ventaja del Murthy- Sensitivity, specificity, accuracy, associated
Rangaraj sobre el Tompkins es que hay menos confidence interval and ROC analysis with
factores que hay que ajustar y adaptar a las di- practical SAS implementations. NESUG
versas señales. Sin embargo, ambos métodos proceedings: health care and life sciences,
son funcionales y pueden identificar todos los Baltimore, Maryland, 19, 67.
complejos QRS si se ajustan de mejor mane-
ra sus parámetros. Por esta razón, cualquiera de
estos procedimientos serı́a funcional para medir
ritmos cardiacos y, por lo tanto, detectar arrit-
mias. Pero hay que recordar que no es posible
usarlos para estudios que requieran evaluar la VII ANEXOS
morfologı́a de la señal, como cuando se estu-
dian los infartos al miocardio.
VII-A. Otras imágenes

V CONCLUSIÓN

Se cumplió el objetivo de implementar los


métodos de Tompkins y Murthy-Rangaraj. Am-
bos obtuvieron una sensibilidad mayor o igual
a 0.985, especificidad igual a 1.000 y preci-
sión igual a 1.000 para todos los casos. Algu-
nos de los complejos no fueron identificados
correctamente por ser datos con una amplitud
inusualmente baja o por estar ubicados al final
y ser ciclos cardiacos incompletos. El Tomp-
kins obtuvo mejores resultados estadı́sticos pe- Figura 4: Complejos QRS identificados mediante el algoritmo
Tompkins del archivo apnea-ecg a01
ro el Murthy-Rangaraj no necesita tantos ajus-
tes de parámetros para adaptarse a las diversas
señales. Sin embargo, ambos métodos son fun-
cionales y pueden utilizarse para estudios rela-
cionados al ritmo cardiaco.

VI REFERENCIAS

Referencias

[1] Kohler, B. U., Hennig, C., & Orglmeister,


R. (2002). The principles of software QRS Figura 5: Complejos QRS identificados mediante el algoritmo
Tompkins del archivo apnea-ecg a10
detection. IEEE Engineering in Medicine
and Biology Magazine, 21(1), 42-57.

4
Figura 6: Complejos QRS identificados mediante el algoritmo
Murthy-Rangaraj del archivo apnea-ecg a10

5
VII-B. Código de programa utilizado
Código fuente de programa utilizado para analizar y filtrar los ECGs:
# -*- coding: utf-8 -*-
"""
Created on Wed Nov 6 17:56:20 2019

@author: victor tzorin


"""

#LIBRARIES
#Import of libraries
import pyqtgraph as pg
import pyqtgraph.exporters
from datetime import datetime
import random
from scipy import signal
import numpy as np
import pandas as pd
import math

#FUNCTIONS
#Function that reads a csv document with the first column being time and
#two columns of values
def csvreadert1(file_name):

#Declaration of variables
file = open(file_name+’.csv’)
tempo = 0
x = []
y = []

#Cycle that reads every line of the file and adds the values to the
#corresponding list
for i in file:
try:
y.append(float((i.split(’,’)[1])))

tempo = i.split(’,’)[0].replace("’", "")


tempo = datetime.strptime(tempo,’%M:%S.%f’)-datetime(1900,1,1)
x.append(tempo.total_seconds())

except:
pass

return x,y

6
#Function that extracts the signal spectrum
def espectro(x,fs):
f,sp = signal.periodogram(x,fs,scaling=’spectrum’)
amp = np.sqrt(2*sp)
return f,amp

#Function that applies a filter


def nfiltro(x, no_polos_y_ceros, coeficientes):

#Variables to use
y=[]

#Operation feasibility check


if (no_polos_y_ceros/4)*7 == len(coeficientes):

for i in range(int(no_polos_y_ceros/4)):

#The first time the user data is used


if i==0:
y0=np.zeros(len(x))
for j in range(2,len(x)):
y0[j]=(1/coeficientes[i*7+4])*(coeficientes[i*7]*\
(coeficientes[i*7+1]*x[j]+coeficientes[i*7+2]*\
x[j-1]+coeficientes[i*7+3]*x[j-2])-\
coeficientes[i*7+5]*y0[j-1]-coeficientes[i*7+6]*\
y0[j-2])
y=y0

#The second time forward, data from previous processes is used


else:
y0=np.zeros(len(y))
for j in range(2,len(y)):
y0[j]=(1/coeficientes[i*7+4])*(coeficientes[i*7]*\
(coeficientes[i*7+1]*y[j]+coeficientes[i*7+2]*\
y[j-1]+coeficientes[i*7+3]*y[j-2])-\
coeficientes[i*7+5]*y0[j-1]-coeficientes[i*7+6]*\
y0[j-2])
y=y0

#Error message
else:

print(’ERROR’)
pass

7
return y

#Funcion that applies a moving average of N-order


def ma(x,N):

#Applying moving average using Pandas


x = pd.Series(x)
y = x.rolling(N).mean()

#Converting series to list, setting the NAN values to zero


z = []
for i in range(len(y)):
if math.isnan(float(y[i])):
z.append(0)
else:
z.append(float(y[i]))

return z

#Function that derives the data according to Tompkins’ algorithm


def derT(x):
#First derivative
y1 = []
for i in range(len(x)):
if i>=2:
y1.append(abs(x[i]-x[i-2]))
else:
y1.append(0)

#Second derivative
y2 = []
for j in range(len(x)):
if i>=4:
y2.append(abs(x[j]-2*x[j-2]+x[j-4]))
else:
y2.append(0)

#Sum of derivatives
y3 = []

for k in range(len(x)):
y3.append((1.3*y1[k]+1.1*y2[k])/2)

return y3

8
#Function that derives the data according to Murthy & Rangaraj’s algorithm
def derMR(x,N):

y1 = []
suma = 0
for i in range(len(x)):
if i>=N:
for j in range(1,N+1):
suma = (N-j+1)*(x[i-j+1]-x[i-j])**2

y1.append(suma)
suma = 0

else:
y1.append(0)

return y1

#Function that finds all the peaks of a signal above half of its max value
def picos(x, T):

#Trigger
h = T

#Cycle that obtains the limits of the intervals above the trigger
u = []
for i in range(1,len(x)-1):

if x[i]>=h and x[i-1]<h:


u.append(i)
elif x[i]>=h and x[i+1]<h and len(u)!=0:
u.append(i)
else:
pass

if len(u)%2==1:
del u[-1]
else:
pass

#Cycle that finds the time and values of the peaks of the intervals
y = []
for j in range(int(len(u)/2)):
y.append(int(u[2*j]+x[u[2*j]:u[2*j+1]].index(max(x[u[2*j]:u[2*j+1]]))))

9
return y

#Function that compares two lists with a given acceptance interval


def comparison(x,y,acceptance):
cont1 = 0
cont2 = 0
tempo = 0

for i in range(len(x)):
tempo = cont1
for j in range(acceptance+1):
if (x[i]-j in y) or (x[i]+j in y):
cont1 = cont1 + 1

else:
pass

if cont1 == tempo:
cont2 = cont2 + 1

return cont1, cont2

#PROGRAM FOR QRS DETECTION in ECGs


#List of all the files that are going to be graph
file_names = [’apnea-ecg_a01’,’apnea-ecg_a10’,’apnea-ecg_a16’]

#Filter’s coefficients to apply


#Lowpass 25Hz (Fs=100Hz)
elliptic1 = [0.53556,1,1.282,1,1,-0.171,0.264,0.5,1,0.277,1,1,0.5,0.877]

#Theoretical values
ideal01 = [40,128,212,295,378,466,560,657,751,844,938,1038,1140,1241,1340,1437,
1532,1630,1731,1825,1915,2001,2086,2183,2276,2369,2453,2530,2608,
2688,2769,2853,2937,3018,3101,3190,3290,3383,3471,3557,3642,3729,
3818,3909,4001,4089,4186,4286,4380,4466,4548,4632,4719,4807,4895,
4987,5077,5167,5259,5349,5439,5530,5621,5709,5797,5890,5980]
ideal10 = [80,179,276,373,473,575,672,771,874,979,1080,1178,1276,1374,1473,
1571,1668,1770,1869,1966,2064,2159,2254,2347,2439,2530,2620,2712,
2799,2886,2972,3058,3144,3229,3313,3394,3477,3562,3650,3738,3826,
3914,4003,4091,4181,4272,4363,4454,4544,4634,4724,4815,4908,4998,
5091,5184,5276,5367,5463,5560,5656,5750,5848,5946]
ideal16 = [5,83,158,232,306,381,458,535,614,694,776,859,941,1023,1104,1180,
1255,1328,1398,1468,1536,1604,1673,1743,1813,1885,1956,2029,2104,

10
2178,2252,2324,2395,2465,2533,2600,2666,2733,2802,2869,2938,3010,
3083,3157,3234,3310,3387,3464,3539,3615,3690,3765,3838,3913,3988,
4061,4135,4209,4281,4353,4426,4498,4570,4642,4715,4787,4860,4932,
5004,5074,5144,5213,5283,5353,5423,5493,5563,5634,5705,5776,5847,
5919,5991]

ideal = [ideal01,ideal10, ideal16]


dif = []

#List of all the window that are going to be made


win1 = 0
win2 = 0
win3 = 0
windows1 = [win1,win2,win3]

win4 = 0
win5 = 0
win6 = 0
windows2 = [win4,win5,win6]

#Number of samples require for filtered signal stabilization


N = 0
acceptance = 15

#Cycle that applies the Tompkins and the Murthy & Rangaraj algorithms to each fil
for i in range(len(file_names)):

#TOMPKINS
#Creation of the window where the graphs are going to be display
windows1[i] = pg.GraphicsWindow(title=’Algoritmo Tompkins para señal ’+file_n

#Variables to use
x,y = csvreadert1(file_names[i])
Fs = 1/(x[1]-x[0])

#UNFILTERED SIGNAL
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))
#Plot of unfiltered signal
plt = windows1[i].addPlot(row=1, col=1,
title = ’ECG unfiltered’)
plt.plot(x,y, pen=color)

#Plot of spectrum of unfiltered signal


plt = windows1[i].addPlot(row=1, col=2,
title= ’Spectrum of ECG unfiltered’)

11
f, amp = espectro(y, Fs)
plt.plot(f,amp,pen=color)

#FILTERED SIGNAL
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))

#Plot of filtered signal


plt = windows1[i].addPlot(row=2, col=1,
title = ’Filtered ECG’)
e = nfiltro(y,8,elliptic1)
plt.plot(x[N:],e[N:], pen=color)

#Plot of spectrum of filtered signal


plt = windows1[i].addPlot(row=2, col=2,
title= ’Spectrum of filtered ECG’)
f, amp = espectro(e, Fs)
plt.plot(f,amp,pen=color)

#DERIVATIVE OF SIGNAL
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))

#Plot of derivative of signal


plt = windows1[i].addPlot(row=3, col=1,
title = ’Derivative of ECG’)
d = derT(e)
plt.plot(x[N:],d[N:], pen=color)

#Plot of spectrum of derivative of signal


plt = windows1[i].addPlot(row=3, col=2,
title= ’Spectrum of derivative of ECG’)
f, amp = espectro(d, Fs)
plt.plot(f,amp,pen=color)

#MOVING AVERAGE
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))

#Plot of moving average of signal


plt = windows1[i].addPlot(row=4, col=1,
title = ’Moving average of ECG’)
m = ma(d,7)
plt.plot(x[N:],m[N:], pen=color)

t = picos(m, 0.75)

12
p = [m[i] for i in t]
t = [i/Fs for i in t]
plt.plot(t,p, pen=None, symbol=’o’)

#Plot of spectrum of moving average of signal


plt = windows1[i].addPlot(row=4, col=2,
title= ’Spectrum of moving average of ECG’)
f, amp = espectro(m, Fs)
plt.plot(f,amp,pen=color)

#QRS IDENTIFICATION
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))

#Plot of unfiltered signal


plt = windows1[i].addPlot(row=5, col=1,
title = ’ECG unfiltered’)
plt.plot(x,y, pen=color)

#Plot of QRS events


t = picos(m, 0.75)

vp,fp = comparison(t,ideal[i], acceptance)


vp,fn = comparison(ideal[i],t,acceptance)
vn = len(x)-vp

print(’\n\n\nTompkins de ’+file_names[i])
print(’Sensibilidad: ’+str(round(vp/(vp+fn),3)))
print(’Especificidad: ’+str(round(vn/(vn+fp),3)))
print(’Precisión: ’+str(round((vp+vn)/(vn+vp+fn+fp),3)))

p = [y[i] for i in t]
t = [i/Fs for i in t]
plt.plot(t,p, pen=None, symbol=’o’)

#Plot of spectrum of unfiltered signal


plt = windows1[i].addPlot(row=5, col=2,
title= ’Spectrum of ECG unfiltered’)
f, amp = espectro(y, Fs)
plt.plot(f,amp,pen=color)

del amp, d, e, f, m, p, t, vp, fp, fn, vn

#MURTHY & RANGARAJ


#Creation of the window where the graphs are going to be display
windows2[i] = pg.GraphicsWindow(title=’Algoritmo Murthy & Rangaraj para señal

13
#UNFILTERED SIGNAL
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))
#Plot of unfiltered signal
plt = windows2[i].addPlot(row=1, col=1,
title = ’ECG unfiltered’)
plt.plot(x,y, pen=color)

#Plot of spectrum of unfiltered signal


plt = windows2[i].addPlot(row=1, col=2,
title= ’Spectrum of ECG unfiltered’)
f, amp = espectro(y, Fs)
plt.plot(f,amp,pen=color)

#DERIVATIVE OF SIGNAL
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))

#Plot of derivative of signal


plt = windows2[i].addPlot(row=2, col=1,
title = ’Derivative of ECG’)
d = derMR(y,8)
plt.plot(x[N:],d[N:], pen=color)

#Plot of spectrum of derivative of signal


plt = windows2[i].addPlot(row=2, col=2,
title= ’Spectrum of derivative of ECG’)
f, amp = espectro(d, Fs)
plt.plot(f,amp,pen=color)

#MOVING AVERAGE
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))

#Plot of moving average of signal


plt = windows2[i].addPlot(row=3, col=1,
title = ’Moving average of ECG’)
m = ma(d,10)
plt.plot(x[N:],m[N:], pen=color)

t = picos(m, 0.5*max(m))
p = [m[i] for i in t]
t = [i/Fs for i in t]
plt.plot(t,p, pen=None, symbol=’o’)

14
#Plot of spectrum of moving average of signal
plt = windows2[i].addPlot(row=3, col=2,
title= ’Spectrum of moving average of ECG’)
f, amp = espectro(m, Fs)
plt.plot(f,amp,pen=color)

#QRS IDENTIFICATION
color = pg.mkPen(random.randint(0,255), random.randint(0,255),
random.randint(0,255))

#Plot of unfiltered signal


plt = windows2[i].addPlot(row=5, col=1,
title = ’ECG unfiltered’)
plt.plot(x,y, pen=color)

#Plot of QRS events


t = picos(m, 0.5*max(m))

vp,fp = comparison(t,ideal[i], acceptance)


vp,fn = comparison(ideal[i],t,acceptance)
vn = len(x)-vp

print(’\n\n\nMurthy & Rangaraj de ’+file_names[i])


print(’Sensibilidad: ’+str(round(vp/(vp+fn),3)))
print(’Especificidad: ’+str(round(vn/(vn+fp),3)))
print(’Precisión: ’+str(round((vp+vn)/(vn+vp+fn+fp),3)))

p = [y[i] for i in t]
t = [i/Fs for i in t]
plt.plot(t,p, pen=None, symbol=’o’)

#Plot of spectrum of unfiltered signal


plt = windows2[i].addPlot(row=5, col=2,
title= ’Spectrum of ECG unfiltered’)
f, amp = espectro(y, Fs)
plt.plot(f,amp,pen=color)

del amp, d, f, m, p, t, x, y, vp, fp, fn, vn

del i

#Start Qt event loop


if __name__ == ’__main__’:
import sys
if (sys.flags.interactive != 1) or not hasattr(QtCore, ’PYQT_VERSION’):

15
pg.QtGui.QApplication.instance().exec_()

16

Potrebbero piacerti anche