# data[].attributes.body
Carte son

# data[].attributes.attachment_link.readable_text
#https://gist.github.com/deeplycloudy/2152643

import pyaudio
import wave
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button, TextBox, SpanSelector

#    ////////////////         variables
CHUNK = 1024 
FORMAT = pyaudio.paInt16 #paInt8
CHANNELS = 1  # 2 à l'origine 
#RATE = 44100 #sample rate  44100 à l'origine ==> 22050 ==> 16000 ==> 11025
RATE = 22050
#RATE = 11025
fs=RATE
#RECORD_SECONDS = 2
WAVE_OUTPUT_FILENAME = "output2.wav"
x = np.arange(22050*2)/fs
y = np.zeros((22050*2), dtype='f')

#  ///////////////////////    Prépararation du graphique
fig, (ax1, ax2) = plt.subplots(2,1, figsize=(10, 7),facecolor='silver')
plt.subplots_adjust(top = 0.95 ,bottom=0.2,wspace = 0.5,hspace=0.45,right=0.75)
ax1.set_title('Appuie sur le bouton gauche de la souris, puis déplace la souris pour sélectionner une partie du signal.',fontsize='9')
ax1.set_xlabel("temps en (s)"), ax1.set_ylabel("signal sonore complet (mV)")
ax1.grid(True),ax1.set(facecolor='palegreen')  #ax1.set_ylim(-10,10)

ax2.set_title('La mesure de durée peut se faire en sélectionnant sur le graphique ci-dessous une partie du signal.',fontsize='9')
ax2.set_xlabel("temps en (s)"), ax2.set_ylabel("signal sonore sélectionné (mV)")
ax2.set(facecolor='palegreen'),ax2.grid(True)

line1, = ax1.plot(x, y, 'b', lw=1)
line1.set_ydata(y)
line2, = ax2.plot(x, y, 'g', lw=1)
#line2.set_ydata(y)

#   ///////////  Fonctions

def enregistrement(dure,fe,canal,chunk):
    p = pyaudio.PyAudio()

    stream = p.open(format=FORMAT,
                channels=canal,
                rate=fe,
                input=True,
                frames_per_buffer=chunk)     #buffer

    print("// Enregistrement  // ")
    frames = []

    for i in range(0, int(fe / chunk * dure)):
        data = stream.read(chunk)
        frames.append(data) # 2 bytes(16 bits) per channel
    
    frames = [] # A python-list of chunks(numpy.ndarray)
    for _ in range(0, int(1+fe/chunk*dure)):
        data = stream.read(chunk)
        frames.append(np.frombuffer(data, dtype=np.int16))
    global signal
    signal = np.hstack(frames)/100 #Convert the list of numpy-arrays into a 1D array (column-wise)
    global t
    t = np.arange(len(signal)) / float(fe)
    
    stream.stop_stream()
    stream.close()
    p.terminate()
    print("// Enregistrement terminé",len(signal)," échantillons //")
        
    return t,signal

#  ///////////////////////    graphique    ////////
def trace(x,y,RECORD_SECONDS):
    line1.set_data(x,y)
    ax1.set_xlim(0, RECORD_SECONDS),ax1.set_ylim(min(y),max(y))
    fig.canvas.draw_idle()
    #nbs=RECORD_SECONDS*fs
    
 #  ///////////////////////    fonctions autres    ////////   
        
def affiche_dure_freq(dure):
    texte1.set_text(dure)
    texte2.set_text(int(1/dure))
    plt.draw()

def onselect1(xmin, xmax):
    x=t
    y=signal
    indmin, indmax = np.searchsorted(x, (xmin, xmax))
    indmax = min(len(x) - 1, indmax)

    thisx = x[indmin:indmax]
    thisy = y[indmin:indmax]
    #print(thisx,thisy)
    line2.set_data(thisx, thisy)
    ax2.set_xlim(thisx[0], thisx[-1])
    ax2.set_ylim(thisy.min(), thisy.max())
    ax2.set_xlabel("temps en (s)"), ax2.set_ylabel("signal sonore sélectionné")
    ax2.grid(True)
    fig.canvas.draw()

    
def onselect2(xmin, xmax):
    dure=int(100000*(xmax-xmin))/100000
    affiche_dure_freq(dure)
    fig.canvas.draw()

 #  ///////////////////////    menu    ////////
 
class Index(object):
    ind = 0
    def bouton01(self, event):
        self.ind += 1
        RECORD_SECONDS = 1
        #nbs=RECORD_SECONDS*fs
        x,y = enregistrement(RECORD_SECONDS,fs,CHANNELS,CHUNK)   
        trace(x,y,RECORD_SECONDS)
           
    def bouton02(self, event):
        self.ind += 1
        RECORD_SECONDS = 2
        nbs=RECORD_SECONDS*fs
        x,y = enregistrement(RECORD_SECONDS,fs,CHANNELS,CHUNK)   
        trace(x,y,RECORD_SECONDS)
        
    def bouton03(self, event):
        self.ind += 1
        RECORD_SECONDS = 3
        nbs=RECORD_SECONDS*fs
        x,y = enregistrement(RECORD_SECONDS,fs,CHANNELS,CHUNK)   
        trace(x,y,RECORD_SECONDS)

    def bouton04(self, event):
        self.ind += 1
        RECORD_SECONDS = 4
        x,y = enregistrement(RECORD_SECONDS,fs,CHANNELS,CHUNK)   
        trace(x,y,RECORD_SECONDS)

    def bouton05(self, event):
        self.ind += 1
        RECORD_SECONDS = 5
        x,y = enregistrement(RECORD_SECONDS,fs,CHANNELS,CHUNK)   
        trace(x,y,RECORD_SECONDS)

    def bouton06(self, event):
        self.ind += 1
        RECORD_SECONDS = 0.1
        x,y = enregistrement(RECORD_SECONDS,fs,CHANNELS,CHUNK)   
        trace(x,y,RECORD_SECONDS)

    def bouton07(self, event):
        self.ind += 1
        RECORD_SECONDS = 0.2
        x,y = enregistrement(RECORD_SECONDS,fs,CHANNELS,CHUNK)   
        trace(x,y,RECORD_SECONDS)
        
    def bouton08(self, event):
        self.ind += 1
        RECORD_SECONDS = 0.5
        x,y = enregistrement(RECORD_SECONDS,fs,CHANNELS,CHUNK)   
        trace(x,y,RECORD_SECONDS)
       
callback = Index()

 #  ///////////////////////    positionnement matplotlib.widgets    //////// 

span1 = SpanSelector(ax1, onselect1, 'horizontal', useblit=False,
                    rectprops=dict(alpha=0.5, facecolor='red'))

span2 = SpanSelector(ax2, onselect2, 'horizontal', useblit=True,
                    rectprops=dict(alpha=0.5, facecolor='red'))

aybout_01 = plt.axes([0.81, 0.85, 0.16, 0.075])
aybout_02 = plt.axes([0.81, 0.75, 0.16, 0.075])
aybout_03 = plt.axes([0.81, 0.65, 0.16, 0.075])
aybout_04 = plt.axes([0.81, 0.55, 0.16, 0.075])
aybout_05 = plt.axes([0.81, 0.45, 0.16, 0.075])

aybout_06 = plt.axes([0.81, 0.25, 0.16, 0.075])
aybout_07 = plt.axes([0.81, 0.15, 0.16, 0.075])
aybout_08 = plt.axes([0.81, 0.05, 0.16, 0.075])

bout_01 = Button(aybout_01, 'Enregistrement 1 s',color='coral')
bout_01.on_clicked(callback.bouton01)

bout_02 = Button(aybout_02, 'Enregistrement 2 s',color='coral')
bout_02.on_clicked(callback.bouton02)

bout_03 = Button(aybout_03, 'Enregistrement 3 s',color='coral')
bout_03.on_clicked(callback.bouton03)

bout_04 = Button(aybout_04, 'Enregistrement 4 s',color='coral')
bout_04.on_clicked(callback.bouton04)

bout_05 = Button(aybout_05, 'Enregistrement 5 s',color='coral')
bout_05.on_clicked(callback.bouton05)

bout_06 = Button(aybout_06, 'Enregistrement 0.1 s',color='coral')
bout_06.on_clicked(callback.bouton06)

bout_07 = Button(aybout_07, 'Enregistrement 0.2 s',color='coral')
bout_07.on_clicked(callback.bouton07)

bout_08 = Button(aybout_08, 'Enregistrement 0.5 s',color='coral')
bout_08.on_clicked(callback.bouton08)


ax1box = plt.axes([0.25, 0.02, 0.10, 0.075])
boite_box = TextBox(ax1box, "durée (s) = ",color='hotpink',hovercolor='blue')
texte1 = plt.text(0.5, 0.5, '', ha='center', va='center', fontsize='14')

ax2box = plt.axes([0.6, 0.02, 0.10, 0.075])
boite_box = TextBox(ax2box, "fréquence (Hz) = ",color='cyan',hovercolor='blue')
texte2 = plt.text(0.5, 0.5, '', ha='center', va='center', fontsize='14')

plt.show()

# data[].attributes.attachment_link.readable_text
#http://www.f-legrand.fr/scidoc/docmml/numerique/tfd/spectreson3/spectreson3.html
#conversion wave audacity ==> wave python via format factory ok"==> !! 1 seul canal
## WavFileWarning: Chunk (non-data) not understood, skipping it.

from matplotlib.offsetbox import TextArea, DrawingArea, OffsetImage, AnnotationBbox
import matplotlib.image as mpimg
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.widgets import Button, TextBox, SpanSelector, RadioButtons
from matplotlib.lines import Line2D
import matplotlib.animation as animation
from serial import *

nbs=500
port_ = "COM2"
x= np.arange(0,4, .016)
y= [-4]*len(x)
electro=[0,.4,0.6,0.4,0,0,0,0,0,-0.7,-1.5,1.5,4.5,7.5,10.5,7.5,4.5,1.5,-1.5,-2.5,0,0,0,0,0,0,0,0,0.5,1,1.4,1.3,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
i=0

#  ///////////////////////    Prépararation du graphique
fig, (ax1, ax2) = plt.subplots(2,1, figsize=(10, 7),facecolor='silver')
fig.text(0.5, 0.98, "Electrocardiogramme : Enregistrement de l'activité électrique du coeur.",
         horizontalalignment='center',verticalalignment='top',fontsize='14')

plt.subplots_adjust(top = 0.85 ,bottom=0.2,wspace = 0.5,hspace=0.45,right=0.75)
ax1.set_title('Introduction : Enregistrement d un électrocardiogramme',fontsize='9')

ax1.set_xlabel("temps en (s)"), ax1.set_ylabel("AEC patient (A) en (mV)")
ax1.grid(True),ax1.set(facecolor='palegreen')  #ax1.set_ylim(-10,10)
ax1.set_xlim(0, max(x)),ax1.set_ylim(-4, 12)

ax2.set_title('La mesure de durée peut se faire en sélectionnant sur le graphique ci-dessous une partie du signal.',fontsize='9')
ax2.set_xlabel("temps en (s)"), ax2.set_ylabel("AEC patient (A) en (mV)")
ax2.set(facecolor='palegreen'),ax2.grid(True)
ax2.set_xlim(0, max(x)),ax2.set_ylim(-4, 12)

line1, = ax1.plot(x, y, 'b', lw=1)
line2, = ax2.plot(x, y, 'g', lw=1)

#///// menu 2
rax = plt.axes([0.81, 0.18 , 0.16, 0.2], facecolor='yellow')
radio2 = RadioButtons(rax, ('COM2','COM3', 'COM4','COM5','COM6','COM7','COM8','COM9','COM10'))

def com(label):
    list_com = {'COM2':'COM2','COM3':'COM3','COM4':'COM4','COM5':'COM5','COM6':'COM6','COM7':'COM7','COM8':'COM8','COM9':'COM9','COM10':'COM10'}
    global port_
    port_ = list_com[label]
    #print(port_)
radio2.on_clicked(com)

#///////////////////// Trace : 1
def trace(x,y,xmax):
    line2.set_data(x,y)
    #ax1.set_xlim(0, RECORD_SECONDS*3/4),ax1.set_ylim(min(y),max(y))
    ax2.set_xlim(0, xmax),ax2.set_ylim(-4, 12)
    ax2.set_xlabel("temps en (s)"), ax1.set_ylabel("AEC patient (A) en (mV)")
    ax2.grid(True) 
    fig.canvas.draw_idle()

#///////////////////// Trace : 2
def trace2(x,y,xmax):
    line2.set_data(x,y)
    #ax1.set_xlim(0, RECORD_SECONDS*3/4),ax1.set_ylim(min(y),max(y))
    ax2.set_xlim(0, xmax),ax2.set_ylim(0.97*min(y),1.02*max(y))
    ax2.set_xlabel("temps en (s)"), ax2.set_ylabel("AEC patient (A) en (mV)")
    ax2.grid(True) 
    fig.canvas.draw_idle()

#   ///////////  Fonctions : port série

def com_serie(port_,case,Te):
    #global t
    t = np.arange(nbs)*Te
    global signal
    signal = np.zeros((nbs), dtype='f')
    with Serial(port_, baudrate = 9600, timeout=1, writeTimeout=1) as port_serie:
      time.sleep(2)
      port_serie.write(case.encode('ascii'))
      buffer=str(port_serie.readline())
      while (buffer == case or buffer == "b''") :
         buffer=str(port_serie.readline())
      buffer=str(port_serie.readline())  #print(buffer)
      i=0
      while (i < (nbs-1) and buffer[2:len(buffer)-5]!= "fin"):
           signal[i]=5/1024*float(buffer[2:len(buffer)-5])
           buffer=str(port_serie.readline())
           i=i+1
      return t[0:400],signal[0:400]

    
#///////////////  scope  //////////::
    
class Scope(object):
    def __init__(self, ax, maxt=4, dt=0.016):
        self.ax = ax1
        self.dt = dt
        self.maxt = maxt
        self.tdata = [0]
        self.ydata = [0]
        self.line = Line2D(self.tdata, self.ydata)
        self.ax.add_line(self.line)
        self.ax.set_ylim(-4, 12)
        self.ax.set_xlim(0, self.maxt)
       

    def update(self, y):
        lastt = self.tdata[-1]
        if lastt > self.tdata[0] + self.maxt:  # reset the arrays
            self.tdata = [self.tdata[-1]]
            self.ydata = [self.ydata[-1]]
            self.ax.set_xlim(self.tdata[0], self.tdata[0] + self.maxt)
            self.ax.figure.canvas.draw()

        t = self.tdata[-1] + self.dt
        self.tdata.append(t)
        self.ydata.append(y)
        self.line.set_data(self.tdata, self.ydata)
        return self.line,


def signal():
    y=electro+electro+electro+electro+electro
    while True:
        global i
        i=i+1 # print(i)
        if i>=250 :
            i=0
        yield y[i]


 #  ///////////////////////    fonctions autres    ////////   

def affiche_dure_freq(dure):
    texte1.set_text(dure)
    texte2.set_text(int(1/dure))
    texte3.set_text(int(60/dure))
    plt.draw()

def onselect2(xmin, xmax):
    dure=int(100000*(xmax-xmin))/100000
    affiche_dure_freq(dure)
    fig.canvas.draw()


#  ///////////////////////    menu    ////////
 
class Index(object):
    ind = 0
    def bouton01(self, event):
        self.ind += 1
        #print(self.ind/2)
        t= np.arange(0,4, .016)
        scope = Scope(ax1)
        ani = animation.FuncAnimation(fig, scope.update, signal, interval=16, repeat=False, blit=True)
        plt.show()
        

    def bouton02(self, event):
        self.ind += 1
        t= np.arange(0,4, .016)
        y=electro+electro+electro+electro+electro
        trace(t,y,4)
                
    def bouton03(self, event):
        self.ind += 1
        t = np.arange(0,4, .02)
        y=electro+electro+electro+electro
        trace(t,y,4)

    def bouton04(self, event):
        self.ind += 1
        t = np.arange(0,4, .033)
        y=electro+electro+[0,.4,0.6,0.4,0,0,0,0,0,-0.7,-1.5,1.5,4.5,7.5,10.5,7.5,4.5,1.5,-1.5,-2.5,0,0,]
        trace(t,y,4)
       

    def bouton05(self, event):
        self.ind += 1
        t= np.arange(0,4, .016)
        a=[0,0,0,0,0,0,0,0,0,0]
        y=a+electro+a+electro+a+a+a+electro+electro
        trace(t,y,4)
       
    def bouton06(self, event):
        self.ind += 1
        case='g'
        Te=10000/1000000 # µs
        x,y2 =com_serie(port_,case,Te)
        trace2(x,y2,4)
           
callback = Index()

 #  ///////////////////////    positionnement matplotlib.widgets    //////// 

span2 = SpanSelector(ax2, onselect2, 'horizontal', useblit=False,
                    rectprops=dict(alpha=0.5, facecolor='red'))

aybout_01 = plt.axes([0.81, 0.8, 0.16, 0.07])
aybout_02 = plt.axes([0.81, 0.7, 0.16, 0.055])
aybout_03 = plt.axes([0.81, 0.63, 0.16, 0.055])
aybout_04 = plt.axes([0.81, 0.56, 0.16, 0.055])
aybout_05 = plt.axes([0.81, 0.49, 0.16, 0.055])
aybout_06 = plt.axes([0.81, 0.40, 0.16, 0.055])

bout_01 = Button(aybout_01, 'intro',color='cyan')
bout_01.on_clicked(callback.bouton01)

bout_02 = Button(aybout_02, 'Patient (A)',color='coral')
bout_02.on_clicked(callback.bouton02)

bout_03 = Button(aybout_03, 'Patient (B)',color='coral')
bout_03.on_clicked(callback.bouton03)

bout_04 = Button(aybout_04, 'Patient (C)',color='coral')
bout_04.on_clicked(callback.bouton04)

bout_05 = Button(aybout_05, 'Patient (D)',color='coral')
bout_05.on_clicked(callback.bouton05)

bout_06 = Button(aybout_06, 'Et toi !!!',color='yellow')
bout_06.on_clicked(callback.bouton06)

ax1box = plt.axes([0.1, 0.02, 0.10, 0.075])
boite_box = TextBox(ax1box, "durée (s) = ",color='hotpink',hovercolor='blue')
texte1 = plt.text(0.5, 0.5, '', ha='center', va='center', fontsize='14')

ax2box = plt.axes([0.45, 0.02, 0.10, 0.075])
boite_box = TextBox(ax2box, "fréquence (Hz) = ",color='cyan',hovercolor='blue')
texte2 = plt.text(0.5, 0.5, '', ha='center', va='center', fontsize='14')

ax3box = plt.axes([0.8, 0.02, 0.10, 0.075])
boite_box = TextBox(ax3box, "fréquence (bats/min) = ",color='cyan',hovercolor='blue')
texte3 = plt.text(0.5, 0.5, '', ha='center', va='center', fontsize='14')

plt.show()
