Example #1
0
 def __init__(self, name, **opts):
     PlottingCtrlNode.__init__(self, name, self.uiTemplate)
     #self.plotTerminal = self.addOutput('plot', optional=True)
     self.baseLine = InfiniteLine(angle=0, movable=True, pen='b')
     self.minPeakLine = InfiniteLine(angle=0, movable=True, pen='y')
     self.thresholdLine = InfiniteLine(angle=0, movable=True, pen='g')
     self.lines = [self.baseLine, self.minPeakLine, self.thresholdLine]
     
     self.ctrls['display'].toggled.connect(self.displayToggled)
     self.ctrls['baseline'].sigValueChanged.connect(self.adjustBaseLine)
     self.ctrls['threshold'].sigValueChanged.connect(self.adjustThresholdLine)
     self.ctrls['minPeak'].sigValueChanged.connect(self.adjustPeakLine)
     for line in self.lines:
         line.sigPositionChangeFinished.connect(self.updateCtrlValues)
Example #2
0
    def __init__(self, name, **opts):
        PlottingCtrlNode.__init__(self, name, self.uiTemplate)
        #self.plotTerminal = self.addOutput('plot', optional=True)
        self.baseLine = InfiniteLine(angle=0, movable=True, pen='b')
        self.minPeakLine = InfiniteLine(angle=0, movable=True, pen='y')
        self.thresholdLine = InfiniteLine(angle=0, movable=True, pen='g')
        self.lines = [self.baseLine, self.minPeakLine, self.thresholdLine]

        self.ctrls['display'].toggled.connect(self.displayToggled)
        self.ctrls['baseline'].sigValueChanged.connect(self.adjustBaseLine)
        self.ctrls['threshold'].sigValueChanged.connect(
            self.adjustThresholdLine)
        self.ctrls['minPeak'].sigValueChanged.connect(self.adjustPeakLine)
        for line in self.lines:
            line.sigPositionChangeFinished.connect(self.updateCtrlValues)
Example #3
0
class ThresholdEvents(PlottingCtrlNode):
    """Detects regions of a waveform that cross a threshold (positive or negative) and returns the time, length, sum, and peak of each event."""
    nodeName = 'ThresholdEvents'
    uiTemplate = [
        ('baseline', 'spin', {
            'value':
            0,
            'step':
            1,
            'minStep':
            0.1,
            'dec':
            True,
            'bounds': [None, None],
            'siPrefix':
            True,
            'tip':
            'Blue line -- Set the baseline to measure the minPeak and threshold from'
        }),
        ('minPeak', 'spin', {
            'value':
            0,
            'step':
            1,
            'minStep':
            0.1,
            'dec':
            True,
            'bounds': [None, None],
            'siPrefix':
            True,
            'tip':
            'Yellow line -- Events must reach this far from baseline to be detected.'
        }),
        ('threshold', 'spin', {
            'value':
            1e-12,
            'step':
            1,
            'minStep':
            0.1,
            'dec':
            True,
            'bounds': [None, None],
            'siPrefix':
            True,
            'tip':
            'Green line -- Events are detected only if they cross this threshold (distance from baseline).'
        }),
        ('display', 'check', {
            'value':
            True,
            'tip':
            'If checked display dragable lines for baseline, minPeak and threshold'
        }),
        #('index', 'combo', {'values':['start','peak'], 'index':0}),
        ('minLength', 'intSpin', {
            'value': 0,
            'min': 0,
            'max': 1e9,
            'tip': 'Events must contain this many samples to be detected.'
        }),
        ('minSum', 'spin', {
            'value': 0,
            'step': 1,
            'minStep': 0.1,
            'dec': True,
            'bounds': [None, None],
            'siPrefix': True
        }),
        ('eventLimit', 'intSpin', {
            'value':
            100,
            'min':
            1,
            'max':
            1e9,
            'tip':
            'Limits the number of events that may be detected in a single trace. This prevents runaway processes due to over-sensitive detection criteria.'
        }),
        ('deadTime', 'spin', {
            'value': 0,
            'step': 1,
            'minStep': 1e-4,
            'bounds': [0, None],
            'siPrefix': True,
            'suffix': 's',
            'tip':
            'Ignore events that occur too quickly following another event.'
        }),
        ('adjustTimes', 'check', {
            'value':
            True,
            'tip':
            'If False, then event times are reported where the trace crosses threshold. If True, the event time is adjusted to estimate when the trace would have crossed 0.'
        }),
        ('reverseTime', 'spin', {
            'value':
            0,
            'step':
            1,
            'minStep':
            1e-4,
            'bounds': [0, None],
            'siPrefix':
            True,
            'suffix':
            's',
            'tip':
            'Ignore events that 1) have the opposite sign of the event immediately prior and 2) occur within the given time window after the prior event. This is useful for ignoring rebound signals.'
        }),
    ]

    def __init__(self, name, **opts):
        PlottingCtrlNode.__init__(self, name, self.uiTemplate)
        #self.plotTerminal = self.addOutput('plot', optional=True)
        self.baseLine = InfiniteLine(angle=0, movable=True, pen='b')
        self.minPeakLine = InfiniteLine(angle=0, movable=True, pen='y')
        self.thresholdLine = InfiniteLine(angle=0, movable=True, pen='g')
        self.lines = [self.baseLine, self.minPeakLine, self.thresholdLine]

        self.ctrls['display'].toggled.connect(self.displayToggled)
        self.ctrls['baseline'].sigValueChanged.connect(self.adjustBaseLine)
        self.ctrls['threshold'].sigValueChanged.connect(
            self.adjustThresholdLine)
        self.ctrls['minPeak'].sigValueChanged.connect(self.adjustPeakLine)
        for line in self.lines:
            line.sigPositionChangeFinished.connect(self.updateCtrlValues)
        #self.remotePlot = None

    def restoreState(self, state):
        CtrlNode.restoreState(self, state)
        for c in self.plotTerminal.connections():
            #print c
            p = c.node().getPlot()
            for l in self.lines:
                p.addItem(l)
        self.baseLine.setPos(self.ctrls['baseline'].value())
        self.minPeakLine.setPos(self.ctrls['minPeak'].value())
        self.thresholdLine.setPos(self.ctrls['threshold'].value())

    def displayToggled(self):
        b = self.ctrls['display'].isChecked()
        for item in self.lines:
            item.setVisible(b)

    def adjustBaseLine(self, sb):
        #print "vlaue:", value
        self.baseLine.setValue(sb.value())

    def adjustThresholdLine(self, sb):
        self.thresholdLine.setValue(sb.value() + self.baseLine.value())

    def adjustPeakLine(self, sb):
        self.minPeakLine.setValue(sb.value() + self.baseLine.value())

    def updateCtrlValues(self, line):
        self.ctrls['baseline'].setValue(self.baseLine.value())
        self.ctrls['minPeak'].setValue(self.minPeakLine.value() -
                                       self.baseLine.value())
        self.ctrls['threshold'].setValue(self.thresholdLine.value() -
                                         self.baseLine.value())

    #def connected(self, term, remote):
    #CtrlNode.connected(self, term, remote)
    #if term is not self.plot:
    #return
    #node = remote.node()
    #node.sigPlotChanged.connect(self.connectToPlot)
    #self.connectToPlot(node)

    def connectToPlot(self, node):
        #if self.remotePlot is not None:
        #    self.remotePlot = None

        if node.plot is None:
            return
        for l in self.lines:
            node.getPlot().addItem(l)

    #def disconnected(self, term, remote):
    #CtrlNode.disconnected(self, term, remote)
    #if term is not self.plot:
    #return
    #remote.node().sigPlotChanged.disconnect(self.connectToPlot)
    #self.disconnectFromPlot(remote.node().getPlot())

    def disconnectFromPlot(self, plot):
        #if self.remotePlot is None:
        #    return
        for l in self.lines:
            plot.removeItem(l)

    def processData(self, data):
        s = self.stateGroup.state()
        #print "==== Threshold Events ====="
        #print "   baseline:", s['baseline']
        events = functions.thresholdEvents(data,
                                           s['threshold'],
                                           s['adjustTimes'],
                                           baseline=s['baseline'])

        ## apply first round of filters
        mask = events['len'] >= s['minLength']
        mask *= abs(events['sum']) >= s['minSum']
        mask *= abs(events['peak']) >= abs(s['minPeak'])
        events = events[mask]

        ## apply deadtime filter
        mask = np.ones(len(events), dtype=bool)
        last = 0
        dt = s['deadTime']
        rt = s['reverseTime']
        for i in xrange(1, len(events)):
            tdiff = events[i]['time'] - events[last]['time']
            if tdiff < dt:  ## check dead time
                mask[i] = False
            elif tdiff < rt and (events[i]['peak'] * events[last]['peak'] <
                                 0):  ## check reverse time
                mask[i] = False
            else:
                last = i
        #mask[1:] *= (events[1:]['time']-events[:-1]['time']) >= s['deadTime']
        events = events[mask]

        ## limit number of events
        events = events[:s['eventLimit']]
        return events
Example #4
0
class ThresholdEvents(PlottingCtrlNode):
    """Detects regions of a waveform that cross a threshold (positive or negative) and returns the time, length, sum, and peak of each event."""
    nodeName = 'ThresholdEvents'
    uiTemplate = [
        ('baseline', 'spin', {'value':0, 'step':1, 'minStep': 0.1, 'dec': True, 'range': [None, None], 'siPrefix': True, 'tip': 'Blue line -- Set the baseline to measure the minPeak and threshold from'}),
        ('minPeak', 'spin', {'value': 0, 'step': 1, 'minStep': 0.1, 'dec': True, 'range': [None, None], 'siPrefix': True, 'tip': 'Yellow line -- Events must reach this far from baseline to be detected.'}),
        ('threshold', 'spin', {'value': 1e-12, 'step': 1, 'minStep': 0.1, 'dec': True, 'range': [None, None], 'siPrefix': True, 'tip': 'Green line -- Events are detected only if they cross this threshold (distance from baseline).'}),
        ('display', 'check', {'value':True, 'tip':'If checked display dragable lines for baseline, minPeak and threshold'}),
        #('index', 'combo', {'values':['start','peak'], 'index':0}), 
        ('minLength', 'intSpin', {'value': 0, 'min': 0, 'max': 1e9, 'tip': 'Events must contain this many samples to be detected.'}),
        ('minSum', 'spin', {'value': 0, 'step': 1, 'minStep': 0.1, 'dec': True, 'range': [None, None], 'siPrefix': True}),
        ('eventLimit', 'intSpin', {'value': 100, 'min': 1, 'max': 1e9, 'tip': 'Limits the number of events that may be detected in a single trace. This prevents runaway processes due to over-sensitive detection criteria.'}),
        ('deadTime', 'spin', {'value': 0, 'step': 1, 'minStep': 1e-4, 'range': [0,None], 'siPrefix': True, 'suffix': 's', 'tip': 'Ignore events that occur too quickly following another event.'}),
        ('adjustTimes', 'check', {'value': True, 'tip': 'If False, then event times are reported where the trace crosses threshold. If True, the event time is adjusted to estimate when the trace would have crossed 0.'}),
        ('reverseTime', 'spin', {'value': 0, 'step': 1, 'minStep': 1e-4, 'range': [0,None], 'siPrefix': True, 'suffix': 's', 'tip': 'Ignore events that 1) have the opposite sign of the event immediately prior and 2) occur within the given time window after the prior event. This is useful for ignoring rebound signals.'}),
    ]

    def __init__(self, name, **opts):
        PlottingCtrlNode.__init__(self, name, self.uiTemplate)
        #self.plotTerminal = self.addOutput('plot', optional=True)
        self.baseLine = InfiniteLine(angle=0, movable=True, pen='b')
        self.minPeakLine = InfiniteLine(angle=0, movable=True, pen='y')
        self.thresholdLine = InfiniteLine(angle=0, movable=True, pen='g')
        self.lines = [self.baseLine, self.minPeakLine, self.thresholdLine]
        
        self.ctrls['display'].toggled.connect(self.displayToggled)
        self.ctrls['baseline'].sigValueChanged.connect(self.adjustBaseLine)
        self.ctrls['threshold'].sigValueChanged.connect(self.adjustThresholdLine)
        self.ctrls['minPeak'].sigValueChanged.connect(self.adjustPeakLine)
        for line in self.lines:
            line.sigPositionChangeFinished.connect(self.updateCtrlValues)
        #self.remotePlot = None
        
    def restoreState(self, state):
        CtrlNode.restoreState(self, state)
        for c in self.plotTerminal.connections():
            #print c
            p = c.node().getPlot()
            for l in self.lines:
                p.addItem(l)
        self.baseLine.setPos(self.ctrls['baseline'].value())
        self.minPeakLine.setPos(self.ctrls['minPeak'].value())
        self.thresholdLine.setPos(self.ctrls['threshold'].value())
        
    def displayToggled(self):
        b = self.ctrls['display'].isChecked()
        for item in self.lines:
            item.setVisible(b)
    
    def adjustBaseLine(self, sb):
        #print "vlaue:", value
        self.baseLine.setValue(sb.value())
        
    def adjustThresholdLine(self, sb):
        self.thresholdLine.setValue(sb.value()+self.baseLine.value())
        
    def adjustPeakLine(self, sb):
        self.minPeakLine.setValue(sb.value()+self.baseLine.value())
            
    def updateCtrlValues(self, line):
        self.ctrls['baseline'].setValue(self.baseLine.value())
        self.ctrls['minPeak'].setValue(self.minPeakLine.value()-self.baseLine.value())
        self.ctrls['threshold'].setValue(self.thresholdLine.value()-self.baseLine.value())
            
    #def connected(self, term, remote):
        #CtrlNode.connected(self, term, remote)
        #if term is not self.plot:
            #return
        #node = remote.node()
        #node.sigPlotChanged.connect(self.connectToPlot)
        #self.connectToPlot(node)

    def connectToPlot(self, node):
        #if self.remotePlot is not None:
        #    self.remotePlot = None
            
        if node.plot is None:
            return
        for l in self.lines:
            node.getPlot().addItem(l)
            
    #def disconnected(self, term, remote):
        #CtrlNode.disconnected(self, term, remote)
        #if term is not self.plot:
            #return
        #remote.node().sigPlotChanged.disconnect(self.connectToPlot)
        #self.disconnectFromPlot(remote.node().getPlot())

    def disconnectFromPlot(self, plot):
        #if self.remotePlot is None:
        #    return
        for l in self.lines:
            plot.removeItem(l)

    def processData(self, data):
        s = self.stateGroup.state()
        #print "==== Threshold Events ====="
        #print "   baseline:", s['baseline']
        events = functions.thresholdEvents(data, s['threshold'], s['adjustTimes'], baseline=s['baseline'])
        
        ## apply first round of filters
        mask = events['len'] >= s['minLength']
        mask *= abs(events['sum']) >= s['minSum']
        mask *= abs(events['peak']) >= abs(s['minPeak'])
        events = events[mask]
        
        ## apply deadtime filter
        mask = np.ones(len(events), dtype=bool)
        last = 0
        dt = s['deadTime']
        rt = s['reverseTime']
        for i in xrange(1, len(events)):
            tdiff = events[i]['time'] - events[last]['time']
            if tdiff < dt:  ## check dead time
                mask[i] = False
            elif tdiff < rt and (events[i]['peak'] * events[last]['peak'] < 0):  ## check reverse time
                mask[i] = False
            else:
                last = i
        #mask[1:] *= (events[1:]['time']-events[:-1]['time']) >= s['deadTime']
        events = events[mask]
        
        ## limit number of events
        events = events[:s['eventLimit']]
        return events