Saludos, hace varios días que estoy intentando modificar la escala de la grilla de un software en Python pero por más que lo intento no lo logro, agradecería muchísimo si alguien me ayuda a realizar la modificación o si me guía en el proceso, lo que necesito es que la grilla esté dividida en cuadros de 40 mili segundos, en la pantalla se muestran 5 segundos, eso quiere decir que dentro de cada segundo tendría que haber 25 cuadritos. 
Esta es la primera parte del código. El programa tiene varios archivos.
Esta es la segunda parte.
Esta la tercera parte.
Básicamente necesito que se vea así.
Ya que originalmente se ve así.
Este es el software en github.
En la documentación aquí se explica cómo lograrlo, pero aún así no ha sido posible.
Muchas gracias de ante mano
.
	
	
	
	
	
Esta es la primera parte del código. El programa tiene varios archivos.
Código:
"""
diyECG GUI for monitoring live ECG through sound card input (by Scott Harden).
If you haven't built the circuit, test this software by playing demo_ecg.wav
while you run this software. If you don't use a virtual audio cable to connect
the output (speaker jack) to the input (default microphone jack), consider
running an actual cable to connect these two.
"""
from PyQt4 import QtGui,QtCore
import sys
import ui_main
import numpy as np
import pyqtgraph
import swhear
import time
import pyqtgraph.exporters
import webbrowser
class ExampleApp(QtGui.QMainWindow, ui_main.Ui_MainWindow):
    def __init__(self, parent=None):
        pyqtgraph.setConfigOption('background', 'w') #before loading widget
        super(ExampleApp, self).__init__(parent)
        self.setupUi(self)
        self.grECG.plotItem.showGrid(True, True, 0.7)
        self.btnSave.clicked.connect(self.saveFig)
        self.btnSite.clicked.connect(self.website)
        stamp="DIY ECG by Scott Harden"
        self.stamp = pyqtgraph.TextItem(stamp,anchor=(-.01,1),color=(150,150,150),
                                        fill=pyqtgraph.mkBrush('w'))
        self.ear = swhear.Ear(chunk=int(100)) # determines refresh rate
        # optionally you can manually set the audio input device to use like this:
        # self.ear = swhear.Ear(chunk=int(100), device=5) # use audio input device 5
        if len(self.ear.valid_input_devices()):
            self.ear.stream_start()
            self.lblDevice.setText(self.ear.msg)
            self.update()
    def closeEvent(self, event):
        self.ear.close()
        event.accept()
    def saveFig(self):
        fname="ECG_%d.png"%time.time()
        exp = pyqtgraph.exporters.ImageExporter(self.grECG.plotItem)
        exp.parameters()['width'] = 1000
        exp.export(fname)
        print("saved",fname)
    def update(self):
        t1,timeTook=time.time(),0
        if len(self.ear.data) and not self.btnPause.isChecked():
            freqHighCutoff=0
            if self.spinLowpass.value()>0:
                freqHighCutoff=self.spinLowpass.value()
            data=self.ear.getFiltered(freqHighCutoff)
            if self.chkInvert.isChecked():
                data=np.negative(data)
            if self.chkAutoscale.isChecked():
                self.Yscale=np.max(np.abs(data))*1.1
            self.grECG.plotItem.setRange(xRange=[0,self.ear.maxMemorySec],
                            yRange=[-self.Yscale,self.Yscale],padding=0)
            self.grECG.plot(np.arange(len(data))/float(self.ear.rate),data,clear=True,
                            pen=pyqtgraph.mkPen(color='r'),antialias=True)
            self.grECG.plotItem.setTitle(self.lineTitle.text(),color=(0,0,0))
            self.stamp.setPos(0,-self.Yscale)
            self.grECG.plotItem.addItem(self.stamp)
            timeTook=(time.time()-t1)*1000
            print("plotting took %.02f ms"%(timeTook))
        msTillUpdate=int(self.ear.chunk/self.ear.rate*1000)-timeTook
        QtCore.QTimer.singleShot(max(0,msTillUpdate), self.update)
    def website(self):
        webbrowser.open("http://www.SWHarden.com")
if __name__=="__main__":
    app = QtGui.QApplication(sys.argv)
    form = ExampleApp()
    form.show()
    app.exec_()Esta es la segunda parte.
Código:
"""
The core SWHEar class for continuously monitoring microphone data.
The Ear class is the primary method used to access microphone data.
It has extra routines to audomatically detec/test sound card, channel,
and rate combinations to maximize likelyhood of finding one that
works on your system (all without requiring user input!)
Although this was designed to be a package, it's easy enough to work
as an entirely standalone python script. Just drop this .py file in
your project and import it by its filename. Done!
"""
import pyaudio
import time
import numpy as np
import threading
import scipy.io.wavfile
def FFT(data,rate):
    """given some data points and a rate, return [freq,power]"""
    data=data*np.hamming(len(data))
    fft=np.fft.fft(data)
    fft=10*np.log10(np.abs(fft))
    freq=np.fft.fftfreq(len(fft),1/rate)
    return freq[:int(len(freq)/2)],fft[:int(len(fft)/2)]
class Ear(object):
    def __init__(self,device=None,rate=None,chunk=4096,maxMemorySec=5):
        """
        Prime the Ear class to access audio data. Recording won't start
        until stream_start() is called.
        - if device is none, will use first valid input (not system default)
        - if a rate isn't specified, the lowest usable rate will be used.
        """
        # configuration
        self.chunk = chunk # doesn't have to be a power of 2
        self.maxMemorySec = maxMemorySec # delete if more than this around
        self.device=device
        self.rate=rate
        # internal variables
        self.chunksRecorded=0
        self.p=pyaudio.PyAudio() #keep this forever
        self.t=False #later will become threads
    ### SOUND CARD TESTING
    def valid_low_rate(self,device):
        """set the rate to the lowest supported audio rate."""
        for testrate in [8000, 9600, 11025, 12000, 16000, 22050, 24000,
                         32000, 44100, 48000, 88200, 96000, 192000]:
            if self.valid_test(device,testrate):
                return testrate
        print("SOMETHING'S WRONG! I can't figure out how to use DEV",device)
        return None
    def valid_test(self,device,rate=44100):
        """given a device ID and a rate, return TRUE/False if it's valid."""
        try:
            self.info=self.p.get_device_info_by_index(device)
            if not self.info["maxInputChannels"]>0:
                return False
            stream=self.p.open(format=pyaudio.paInt16,channels=1,
               input_device_index=device,frames_per_buffer=self.chunk,
               rate=int(self.info["defaultSampleRate"]),input=True)
            stream.close()
            return True
        except:
            return False
    def valid_input_devices(self):
        """
        See which devices can be opened for microphone input.
        call this when no PyAudio object is loaded.
        """
        mics=[]
        for device in range(self.p.get_device_count()):
            if self.valid_test(device):
                mics.append(device)
        if len(mics)==0:
            print("no microphone devices found!")
        else:
            print("found %d microphone devices: %s"%(len(mics),mics))
        return mics
    ### SETUP AND SHUTDOWN
    def initiate(self):
        """
        run this after changing settings (like rate) before recording.
        mostly just ensures the sound card settings are good.
        """
        if self.device is None:
            self.device=self.valid_input_devices()[0] #pick the first one
        if self.rate is None:
            self.rate=self.valid_low_rate(self.device)
        if not self.valid_test(self.device,self.rate):
            print("guessing a valid microphone device/rate...")
            self.device=self.valid_input_devices()[0] #pick the first one
            self.rate=self.valid_low_rate(self.device)
        self.msg='recording from "%s" '%self.info["name"]
        self.msg+='(device %d) '%self.device
        self.msg+='at %d Hz'%self.rate
        self.data=np.array([])
        print(self.msg)
    def close(self):
        """gently detach from things."""
        print(" -- sending stream termination command...")
        self.keepRecording=False #the threads should self-close
        if self.t:
            while(self.t.isAlive()):
                time.sleep(.1) #wait for all threads to close
            self.stream.stop_stream()
        self.p.terminate()
    ### LIVE AUDIO STREAM HANDLING
    def stream_readchunk(self):
        """reads some audio and re-launches itself"""
        try:
            data = np.fromstring(self.stream.read(self.chunk),dtype=np.int16)
            self.data=np.concatenate((self.data,data))
            self.chunksRecorded+=1
            self.dataFirstI=self.chunksRecorded*self.chunk-len(self.data)
            if len(self.data)>self.maxMemorySec*self.rate:
                pDump=len(self.data)-self.maxMemorySec*self.rate
                #print(" -- too much data in memory! dumping %d points."%pDump)
                self.data=self.data[pDump:]
                self.dataFirstI+=pDump
        except Exception as E:
            print(" -- exception! terminating...")
            print(E,"\n"*5)
            self.keepRecording=False
        if self.keepRecording==True:
            self.stream_thread_new()
        else:
            self.stream.close()
            self.p.terminate()
            self.keepRecording=None
            print(" -- stream STOPPED")
    def stream_thread_new(self):
        self.t=threading.Thread(target=self.stream_readchunk)
        self.t.start()
    def stream_start(self):
        """adds data to self.data until termination signal"""
        self.initiate()
        print(" -- starting stream")
        self.keepRecording=True # set this to False later to terminate stream
        self.dataFiltered=None #same
        self.stream=self.p.open(format=pyaudio.paInt16,channels=1,
                      rate=self.rate,input=True,frames_per_buffer=self.chunk)
        self.stream_thread_new()
    def stream_stop(self,waitForIt=True):
        """send the termination command and (optionally) hang till its done"""
        self.keepRecording=False
        if waitForIt==False:
            return
        while self.keepRecording is False:
            time.sleep(.1)
    ### WAV FILE AUDIO
    def loadWAV(self,fname):
        """Add audio into the buffer (self.data) from a WAV file"""
        self.rate,self.data=scipy.io.wavfile.read(fname)
        print("loaded %.02f sec of data (rate=%dHz)"%(len(self.data)/self.rate,
                                                     self.rate))
        self.initiate()
        return
    ### DATA RETRIEVAL
    def getPCMandFFT(self):
        """returns [data,fft,sec,hz] from current memory buffer."""
        if not len(self.data):
            return
        data=np.array(self.data) # make a copy in case processing is slow
        sec=np.arange(len(data))/self.rate
        hz,fft=FFT(data,self.rate)
        return data,fft,sec,hz
    def softEdges(self,data,fracEdge=.05):
        """multiple edges by a ramp of a certain percentage."""
        rampSize=int(len(data)*fracEdge)
        mult = np.ones(len(data))
        window=np.hanning(rampSize*2)
        mult[:rampSize]=window[:rampSize]
        mult[-rampSize:]=window[-rampSize:]
        return data*mult
    def getFiltered(self,freqHighCutoff=50):
        if freqHighCutoff<=0:
            return self.data
        fft=np.fft.fft(self.softEdges(self.data)) #todo: filter needed?
        trim=len(fft)/self.rate*freqHighCutoff
        fft[int(trim):-int(trim)]=0
        return np.real(np.fft.ifft(fft))
if __name__=="__main__":
    print("This script is intended to be imported, not run directly!")Esta la tercera parte.
Código:
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'ui_main.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!
from PyQt4 import QtCore, QtGui
try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s
try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName(_fromUtf8("MainWindow"))
        MainWindow.resize(993, 692)
        self.centralwidget = QtGui.QWidget(MainWindow)
        self.centralwidget.setObjectName(_fromUtf8("centralwidget"))
        self.verticalLayout_2 = QtGui.QVBoxLayout(self.centralwidget)
        self.verticalLayout_2.setMargin(10)
        self.verticalLayout_2.setSpacing(10)
        self.verticalLayout_2.setObjectName(_fromUtf8("verticalLayout_2"))
        self.frame_4 = QtGui.QFrame(self.centralwidget)
        self.frame_4.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_4.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_4.setObjectName(_fromUtf8("frame_4"))
        self.horizontalLayout = QtGui.QHBoxLayout(self.frame_4)
        self.horizontalLayout.setMargin(0)
        self.horizontalLayout.setSpacing(0)
        self.horizontalLayout.setObjectName(_fromUtf8("horizontalLayout"))
        self.label_3 = QtGui.QLabel(self.frame_4)
        font = QtGui.QFont()
        font.setPointSize(12)
        font.setBold(True)
        font.setWeight(75)
        self.label_3.setFont(font)
        self.label_3.setObjectName(_fromUtf8("label_3"))
        self.horizontalLayout.addWidget(self.label_3)
        self.label_4 = QtGui.QLabel(self.frame_4)
        self.label_4.setEnabled(True)
        self.label_4.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
        self.label_4.setObjectName(_fromUtf8("label_4"))
        self.horizontalLayout.addWidget(self.label_4)
        spacerItem = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.horizontalLayout.addItem(spacerItem)
        self.btnSite = QtGui.QPushButton(self.frame_4)
        self.btnSite.setStyleSheet(_fromUtf8("color: rgb(0, 0, 255);"))
        self.btnSite.setCheckable(False)
        self.btnSite.setFlat(True)
        self.btnSite.setObjectName(_fromUtf8("btnSite"))
        self.horizontalLayout.addWidget(self.btnSite)
        self.verticalLayout_2.addWidget(self.frame_4)
        self.frame_5 = QtGui.QFrame(self.centralwidget)
        self.frame_5.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_5.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_5.setObjectName(_fromUtf8("frame_5"))
        self.horizontalLayout_3 = QtGui.QHBoxLayout(self.frame_5)
        self.horizontalLayout_3.setMargin(0)
        self.horizontalLayout_3.setSpacing(0)
        self.horizontalLayout_3.setObjectName(_fromUtf8("horizontalLayout_3"))
        self.lblDevice = QtGui.QLabel(self.frame_5)
        self.lblDevice.setEnabled(False)
        self.lblDevice.setObjectName(_fromUtf8("lblDevice"))
        self.horizontalLayout_3.addWidget(self.lblDevice)
        spacerItem1 = QtGui.QSpacerItem(40, 20, QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Minimum)
        self.horizontalLayout_3.addItem(spacerItem1)
        self.verticalLayout_2.addWidget(self.frame_5)
        self.frame = QtGui.QFrame(self.centralwidget)
        self.frame.setFrameShape(QtGui.QFrame.NoFrame)
        self.frame.setFrameShadow(QtGui.QFrame.Plain)
        self.frame.setObjectName(_fromUtf8("frame"))
        self.verticalLayout = QtGui.QVBoxLayout(self.frame)
        self.verticalLayout.setMargin(0)
        self.verticalLayout.setSpacing(10)
        self.verticalLayout.setObjectName(_fromUtf8("verticalLayout"))
        self.frame_2 = QtGui.QFrame(self.frame)
        self.frame_2.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_2.setFrameShadow(QtGui.QFrame.Raised)
        self.frame_2.setObjectName(_fromUtf8("frame_2"))
        self.horizontalLayout_2 = QtGui.QHBoxLayout(self.frame_2)
        self.horizontalLayout_2.setMargin(0)
        self.horizontalLayout_2.setObjectName(_fromUtf8("horizontalLayout_2"))
        self.chkInvert = QtGui.QCheckBox(self.frame_2)
        self.chkInvert.setObjectName(_fromUtf8("chkInvert"))
        self.horizontalLayout_2.addWidget(self.chkInvert)
        self.chkAutoscale = QtGui.QCheckBox(self.frame_2)
        self.chkAutoscale.setChecked(True)
        self.chkAutoscale.setObjectName(_fromUtf8("chkAutoscale"))
        self.horizontalLayout_2.addWidget(self.chkAutoscale)
        self.line = QtGui.QFrame(self.frame_2)
        self.line.setFrameShape(QtGui.QFrame.VLine)
        self.line.setFrameShadow(QtGui.QFrame.Sunken)
        self.line.setObjectName(_fromUtf8("line"))
        self.horizontalLayout_2.addWidget(self.line)
        self.label_2 = QtGui.QLabel(self.frame_2)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.label_2.sizePolicy().hasHeightForWidth())
        self.label_2.setSizePolicy(sizePolicy)
        self.label_2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.label_2.setObjectName(_fromUtf8("label_2"))
        self.horizontalLayout_2.addWidget(self.label_2)
        self.spinLowpass = QtGui.QSpinBox(self.frame_2)
        self.spinLowpass.setPrefix(_fromUtf8(""))
        self.spinLowpass.setMinimum(0)
        self.spinLowpass.setMaximum(999999)
        self.spinLowpass.setSingleStep(1)
        self.spinLowpass.setProperty("value", 45)
        self.spinLowpass.setObjectName(_fromUtf8("spinLowpass"))
        self.horizontalLayout_2.addWidget(self.spinLowpass)
        self.label_5 = QtGui.QLabel(self.frame_2)
        sizePolicy = QtGui.QSizePolicy(QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Preferred)
        sizePolicy.setHorizontalStretch(0)
        sizePolicy.setVerticalStretch(0)
        sizePolicy.setHeightForWidth(self.label_5.sizePolicy().hasHeightForWidth())
        self.label_5.setSizePolicy(sizePolicy)
        self.label_5.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
        self.label_5.setObjectName(_fromUtf8("label_5"))
        self.horizontalLayout_2.addWidget(self.label_5)
        self.lineTitle = QtGui.QLineEdit(self.frame_2)
        self.lineTitle.setObjectName(_fromUtf8("lineTitle"))
        self.horizontalLayout_2.addWidget(self.lineTitle)
        self.line_2 = QtGui.QFrame(self.frame_2)
        self.line_2.setFrameShape(QtGui.QFrame.VLine)
        self.line_2.setFrameShadow(QtGui.QFrame.Sunken)
        self.line_2.setObjectName(_fromUtf8("line_2"))
        self.horizontalLayout_2.addWidget(self.line_2)
        self.btnPause = QtGui.QPushButton(self.frame_2)
        self.btnPause.setCheckable(True)
        self.btnPause.setObjectName(_fromUtf8("btnPause"))
        self.horizontalLayout_2.addWidget(self.btnPause)
        self.btnSave = QtGui.QPushButton(self.frame_2)
        self.btnSave.setObjectName(_fromUtf8("btnSave"))
        self.horizontalLayout_2.addWidget(self.btnSave)
        self.verticalLayout.addWidget(self.frame_2)
        self.frame_3 = QtGui.QFrame(self.frame)
        self.frame_3.setFrameShape(QtGui.QFrame.StyledPanel)
        self.frame_3.setFrameShadow(QtGui.QFrame.Plain)
        self.frame_3.setObjectName(_fromUtf8("frame_3"))
        self.verticalLayout_3 = QtGui.QVBoxLayout(self.frame_3)
        self.verticalLayout_3.setMargin(0)
        self.verticalLayout_3.setSpacing(0)
        self.verticalLayout_3.setObjectName(_fromUtf8("verticalLayout_3"))
        self.grECG = PlotWidget(self.frame_3)
        self.grECG.setFrameShape(QtGui.QFrame.NoFrame)
        self.grECG.setFrameShadow(QtGui.QFrame.Plain)
        self.grECG.setLineWidth(0)
        self.grECG.setObjectName(_fromUtf8("grECG"))
        self.verticalLayout_3.addWidget(self.grECG)
        self.verticalLayout.addWidget(self.frame_3)
        self.verticalLayout_2.addWidget(self.frame)
        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)
    def retranslateUi(self, MainWindow):
        MainWindow.setWindowTitle(_translate("MainWindow", "diyECG", None))
        self.label_3.setText(_translate("MainWindow", "diyECG", None))
        self.label_4.setText(_translate("MainWindow", "   open-source live soundcard monitor with realtime iFFT filtering by Scott Harden", None))
        self.btnSite.setText(_translate("MainWindow", "www.SWHarden.com", None))
        self.lblDevice.setText(_translate("MainWindow", "!!! ERROR !!! no valid input sound devices found. Plug in a microphone and restart this program!", None))
        self.chkInvert.setText(_translate("MainWindow", "invert", None))
        self.chkAutoscale.setText(_translate("MainWindow", "autoscale", None))
        self.label_2.setText(_translate("MainWindow", "lowpass:", None))
        self.spinLowpass.setToolTip(_translate("MainWindow", "set to 0 to disable", None))
        self.spinLowpass.setSuffix(_translate("MainWindow", " Hz", None))
        self.label_5.setText(_translate("MainWindow", "title:", None))
        self.lineTitle.setText(_translate("MainWindow", "DIY ECG", None))
        self.btnPause.setText(_translate("MainWindow", "Pause", None))
        self.btnSave.setText(_translate("MainWindow", "Save Figure", None))
from pyqtgraph import PlotWidgetBásicamente necesito que se vea así.
Ya que originalmente se ve así.
Este es el software en github.
En la documentación aquí se explica cómo lograrlo, pero aún así no ha sido posible.
Muchas gracias de ante mano
.
	
