Пример #1
0
class BatchOptions(QtWidgets.QDialog):
    def __init__(self, parent=None):
        super(BatchOptions, self).__init__(parent)

        self.s = g.settings['volumeSlider']

        self.slicesPerVolume = self.s['slicesPerVolume']
        self.baselineValue = self.s['baselineValue']
        self.f0Start = self.s['f0Start']
        self.f0End = self.s['f0End']
        self.f0VolStart = self.s['f0VolStart']
        self.f0VolEnd = self.s['f0VolEnd']
        self.multiplicationFactor = self.s['multiplicationFactor']
        self.currentDataType = self.s['currentDataType']
        self.newDataType = self.s['newDataType']
        self.inputArrayOrder = self.s['inputArrayOrder']
        self.displayArrayOrder = self.s['displayArrayOrder'] = 16
        self.theta = self.s['theta']
        self.shiftFactor = self.s['shiftFactor']
        self.trim_last_frame = self.s['trimLastFrame']

        self.subtractBaseline = False
        self.runDFF0 = False
        self.runMultiplication = False

        self.inputDirectory = ''

        #window geometry
        self.left = 300
        self.top = 300
        self.width = 300
        self.height = 200

        #labels
        self.label_slicesPerVolume = QtWidgets.QLabel("slices per volume:")
        self.label_theta = QtWidgets.QLabel("theta:")
        self.label_baselineValue = QtWidgets.QLabel('baseline Value:')
        self.label_f0Start = QtWidgets.QLabel('f0 Start:')
        self.label_f0End = QtWidgets.QLabel('f0 End:')
        self.label_f0VolStart = QtWidgets.QLabel('f0Vol Start:')
        self.label_f0VolEnd = QtWidgets.QLabel('f0Vol End:')
        self.label_multiplicationFactor = QtWidgets.QLabel(
            'multiplication Factor:')
        self.label_shiftFactor = QtWidgets.QLabel('shift Factor:')
        self.label_trim_last_frame = QtWidgets.QLabel('trim Last Frame:')
        self.label_inputDirectory = QtWidgets.QLabel('input directory:')

        self.label_subtractBaseline = QtWidgets.QLabel('subtract baseline:')
        self.label_runDFF0 = QtWidgets.QLabel('run DF/F0:')
        self.label_runMultiplication = QtWidgets.QLabel(
            'scale by multiplication factor:')

        #spinboxes/comboboxes
        self.volBox = QtWidgets.QSpinBox()
        self.volBox.setRange(0, 10000)
        self.volBox.setValue(self.slicesPerVolume)

        self.thetaBox = QtWidgets.QSpinBox()
        self.thetaBox.setRange(0, 360)
        self.thetaBox.setValue(self.theta)

        self.baselineBox = QtWidgets.QSpinBox()
        self.baselineBox.setRange(0, 100000)
        self.baselineBox.setValue(self.baselineValue)

        self.f0StartBox = QtWidgets.QSpinBox()
        self.f0StartBox.setRange(0, 100000)
        self.f0StartBox.setValue(self.f0Start)

        self.f0EndBox = QtWidgets.QSpinBox()
        self.f0EndBox.setRange(0, 100000)
        self.f0EndBox.setValue(self.f0End)

        self.f0VolStartBox = QtWidgets.QSpinBox()
        self.f0VolStartBox.setRange(0, 100000)
        self.f0VolStartBox.setValue(self.f0VolStart)

        self.f0VolEndBox = QtWidgets.QSpinBox()
        self.f0VolEndBox.setRange(0, 100000)
        self.f0VolEndBox.setValue(self.f0VolEnd)

        self.multiplicationFactorBox = QtWidgets.QSpinBox()
        self.multiplicationFactorBox.setRange(0, 100000)
        self.multiplicationFactorBox.setValue(self.multiplicationFactor)

        self.shiftFactorBox = QtWidgets.QSpinBox()
        self.shiftFactorBox.setRange(0, 100000)
        self.shiftFactorBox.setValue(self.shiftFactor)

        self.trim_last_frame_checkbox = CheckBox()
        self.trim_last_frame_checkbox.setChecked(self.trim_last_frame)

        self.subtractBaseline_checkbox = CheckBox()
        self.subtractBaseline_checkbox.setChecked(self.subtractBaseline)

        self.runDFF0_checkbox = CheckBox()
        self.runDFF0_checkbox.setChecked(self.runDFF0)

        self.runMultiplication_checkbox = CheckBox()
        self.runMultiplication_checkbox.setChecked(self.runMultiplication)

        self.inputDirectory_display = QtWidgets.QLabel(self.inputDirectory)

        #buttons
        self.button_setInputDirectory = QtWidgets.QPushButton("Set Folder")
        self.button_startBatch = QtWidgets.QPushButton("Go")

        #grid layout
        layout = QtWidgets.QGridLayout()
        layout.setSpacing(5)
        layout.addWidget(self.label_slicesPerVolume, 0, 0)
        layout.addWidget(self.volBox, 0, 1)
        layout.addWidget(self.label_theta, 1, 0)
        layout.addWidget(self.thetaBox, 1, 1)
        layout.addWidget(self.label_baselineValue, 2, 0)
        layout.addWidget(self.baselineBox, 2, 1)
        layout.addWidget(self.label_f0Start, 3, 0)
        layout.addWidget(self.f0StartBox, 3, 1)
        layout.addWidget(self.label_f0End, 4, 0)
        layout.addWidget(self.f0EndBox, 4, 1)
        layout.addWidget(self.label_f0VolStart, 5, 0)
        layout.addWidget(self.f0VolStartBox, 5, 1)
        layout.addWidget(self.label_f0VolEnd, 6, 0)
        layout.addWidget(self.f0VolEndBox, 6, 1)
        layout.addWidget(self.label_multiplicationFactor, 7, 0)
        layout.addWidget(self.multiplicationFactorBox, 7, 1)
        layout.addWidget(self.label_shiftFactor, 8, 0)
        layout.addWidget(self.shiftFactorBox, 8, 1)
        layout.addWidget(self.label_trim_last_frame, 9, 0)
        layout.addWidget(self.trim_last_frame_checkbox, 9, 1)

        layout.addWidget(self.label_subtractBaseline, 10, 0)
        layout.addWidget(self.subtractBaseline_checkbox, 10, 1)

        layout.addWidget(self.label_runDFF0, 11, 0)
        layout.addWidget(self.runDFF0_checkbox, 11, 1)
        layout.addWidget(self.label_runMultiplication, 12, 0)
        layout.addWidget(self.runMultiplication_checkbox, 12, 1)

        layout.addWidget(self.label_inputDirectory, 13, 0)
        layout.addWidget(self.inputDirectory_display, 13, 1)
        layout.addWidget(self.button_setInputDirectory, 13, 2)
        layout.addWidget(self.button_startBatch, 14, 2)

        self.setLayout(layout)
        self.setGeometry(self.left, self.top, self.width, self.height)

        #add window title
        self.setWindowTitle("Batch Options")

        #connect spinboxes/comboboxes
        self.volBox.valueChanged.connect(self.set_slicesPerVolume)
        self.thetaBox.valueChanged.connect(self.set_theta)
        self.baselineBox.valueChanged.connect(self.set_baselineValue)
        self.f0StartBox.valueChanged.connect(self.set_f0Start)
        self.f0EndBox.valueChanged.connect(self.set_f0End)
        self.f0VolStartBox.valueChanged.connect(self.set_f0VolStart)
        self.f0VolEndBox.valueChanged.connect(self.set_f0VolEnd)
        self.multiplicationFactorBox.valueChanged.connect(
            self.set_multiplicationFactor)
        self.shiftFactorBox.valueChanged.connect(self.set_shiftFactor)
        self.trim_last_frame_checkbox.stateChanged.connect(
            self.set_trim_last_frame)
        self.subtractBaseline_checkbox.stateChanged.connect(
            self.set_subtractBaseline)
        self.runDFF0_checkbox.stateChanged.connect(self.set_runDFF0)
        self.runMultiplication_checkbox.stateChanged.connect(
            self.set_runMultiplication)
        self.button_setInputDirectory.pressed.connect(
            lambda: self.setInput_button())
        self.button_startBatch.pressed.connect(lambda: self.start_button())
        return

    def set_slicesPerVolume(self, value):
        self.slicesPerVolume = value

    def set_baselineValue(self, value):
        self.baselineValue = value

    def set_f0Start(self, value):
        self.f0Start = value

    def set_f0End(self, value):
        self.f0End = value

    def set_f0VolStart(self, value):
        self.f0VolStart = value

    def set_f0VolEnd(self, value):
        self.f0VolEnd = value

    def set_multiplicationFactor(self, value):
        self.multiplicationFactor = value

    def set_theta(self, value):
        self.theta = value

    def set_shiftFactor(self, value):
        self.shiftFactor = value

    def set_trim_last_frame(self):
        self.trim_last_frame = self.trim_last_frame_checkbox.isChecked()

    def set_subtractBaseline(self):
        self.subtractBaseline = self.subtractBaseline_checkbox.isChecked()

    def set_runDFF0(self):
        self.runDFF0 = self.runDFF0_checkbox.isChecked()

    def set_runMultiplication(self):
        self.runMultiplication = self.runMultiplication_checkbox.isChecked()

    def setInput_button(self):
        self.inputDirectory = QtWidgets.QFileDialog.getExistingDirectory()
        self.inputDirectory_display.setText(
            '...\\' + os.path.basename(self.inputDirectory))
        return

    def start_button(self):
        paramDict = {
            'slicesPerVolume': self.slicesPerVolume,
            'theta': self.theta,
            'baselineValue': self.baselineValue,
            'f0Start': self.f0Start,
            'f0End': self.f0End,
            'f0VolStart': self.f0VolStart,
            'f0VolEnd': self.f0VolEnd,
            'multiplicationFactor': self.multiplicationFactor,
            'shiftFactor': self.shiftFactor,
            'trim_last_frame': self.trim_last_frame,
            'inputDirectory': self.inputDirectory,
            'subtractBaseline': self.subtractBaseline,
            'runDFF0': self.runDFF0,
            'runMultiplication': self.runMultiplication
        }

        self.hide()
        camVolumeSlider.batchProcess(paramDict)
        return

    def start(self):
        self.show()
Пример #2
0
class Simulate_mepp(BaseProcess_noPriorWindow):
    """
    Simulate MEPP events in a noisy time trace
    
    Trace generated by linear summation of randomly occuring unitary events hF(t) (MEPPs)
    see Segal et al. Biophys J, 1985
    
    h = time independent amplitude factor
    F(t) = nondimensional function of time
    hF(t) = h(exp(-t/dT) - exp(-t/dR))

    dT = decay time constant
    rT = rise time constant

    time of MEPP addition drawn from exponential distribution (np.random.exponential())
    amplitude of MEPP drawn from normal distribution (np.random.normal())
    duration of MEPP drawn from normal distribution (np.random.normal()) 
        
    """
    def __init__(self):

        if g.settings[
                'mepp_simulator'] is None or 'decayTime' not in g.settings[
                    'mepp_simulator']:
            s = dict()
            s['traceLength'] = 10000
            s['meppAmplitude'] = 5
            s['meppDuration'] = 1
            s['startTime'] = 0
            s['meanExp'] = 1000.0
            s['baseline'] = 0.0
            s['noiseSigma'] = 0.1
            s['riseTime'] = 1.0
            #s['riseTime_sigma'] = 0.01
            s['decayTime'] = 10.0
            #s['decayTime_sigma'] = 0.1
            g.settings['mepp_simulator'] = s
        super().__init__()

        self.data = np.array([])

    def gui(self):
        s = g.settings['mepp_simulator']
        self.gui_reset()
        self.meppWindow = PlotWindow('Single MEPP (No noise)')
        self.traceWindow = PlotWindow('Time Trace')
        self.meppWindow.hide()
        self.traceWindow.hide()

        self.traceLength = SliderLabel(0)
        self.traceLength.setRange(0, 1000000)
        self.traceLength.setValue(s['traceLength'])

        self.startTime = SliderLabel(0)
        self.startTime.setRange(0, s['traceLength'])
        self.startTime.setValue(s['startTime'])

        self.meppDuration_slider = pg.SpinBox(int=True, step=1)
        self.meppDuration_slider.setValue(s['meppDuration'])

        self.meppDuration_sigma_slider = pg.SpinBox(int=True, step=1)
        self.meppDuration_sigma_slider.setValue(1)

        self.baseline_slider = pg.SpinBox(int=False, step=.01)
        self.baseline_slider.setValue(s['baseline'])

        self.noiseSigma_slider = pg.SpinBox(int=False, step=.01)
        self.noiseSigma_slider.setValue(s['noiseSigma'])

        self.meppAmplitude_slider = pg.SpinBox(int=False, step=.01)
        self.meppAmplitude_slider.setValue(s['meppAmplitude'])

        self.meppAmplitude_sigma_slider = pg.SpinBox(int=False, step=.01)
        self.meppAmplitude_sigma_slider.setValue(1.0)

        self.meppRiseTime_slider = pg.SpinBox(int=False, step=.01)
        self.meppRiseTime_slider.setValue(s['riseTime'])

        #self.meppRiseTime_sigma_slider = pg.SpinBox(int=False, step=.01)
        #self.meppRiseTime_sigma_slider.setValue(0.01)

        self.meppDecayTime_slider = pg.SpinBox(int=False, step=.01)
        self.meppDecayTime_slider.setValue(s['decayTime'])

        #self.meppDecayTime_sigma_slider = pg.SpinBox(int=False, step=.01)
        #self.meppDecayTime_sigma_slider.setValue(0.1)

        self.randommeppsAdded = False

        self.meanExp_slider = pg.SpinBox(int=False, step=.01)
        self.meanExp_slider.setValue(1000.0)

        self.plotHistoTimes = CheckBox()
        self.plotHistoTimes.setValue(False)

        self.exportTimes_button = QPushButton('Export times')
        self.exportTimes_button.pressed.connect(self.exportTimes)

        self.randommeppButton = QPushButton('Generate Trace')
        self.randommeppButton.pressed.connect(self.addRandommepps)

        self.plotmeppButton = QPushButton('Plot single MEPP')
        self.plotmeppButton.pressed.connect(self.plotSingleMEPP)

        self.items.append({
            'name': 'traceLength',
            'string': 'Recording length',
            'object': self.traceLength
        })
        self.items.append({
            'name': 'startTime',
            'string': 'Start time',
            'object': self.startTime
        })
        self.items.append({
            'name': 'meppDuration',
            'string': 'MEPP duration (mean)',
            'object': self.meppDuration_slider
        })
        self.items.append({
            'name': 'meppDuration_sigma',
            'string': 'MEPP duration (standard deviation)',
            'object': self.meppDuration_sigma_slider
        })

        self.items.append({
            'name': 'riseTime',
            'string': 'MEPP rise time constant',
            'object': self.meppRiseTime_slider
        })
        #self.items.append({'name': 'riseTime_sigma','string':'MEPP rise time constant (standard deviation)','object':self.meppRiseTime_sigma_slider})

        self.items.append({
            'name': 'decayTime',
            'string': 'MEPP decay time constant',
            'object': self.meppDecayTime_slider
        })
        #self.items.append({'name': 'decayTime_sigma','string':'MEPP decay time constant (standard deviation)','object':self.meppDecayTime_sigma_slider})

        self.items.append({
            'name': 'meppAmplitude',
            'string': 'MEPP Amplitude (mean)',
            'object': self.meppAmplitude_slider
        })
        self.items.append({
            'name': 'meppAmplitude_sigma',
            'string': 'MEPP Amplitude (standard deviation)',
            'object': self.meppAmplitude_sigma_slider
        })
        self.items.append({
            'name': 'meanExp',
            'string': 'Mean of exponential distibution',
            'object': self.meanExp_slider
        })

        self.items.append({
            'name': 'baseline',
            'string': 'Baseline',
            'object': self.baseline_slider
        })
        self.items.append({
            'name': 'noiseSigma',
            'string': 'Noise Sigma',
            'object': self.noiseSigma_slider
        })

        self.items.append({
            'name': 'histoTimes',
            'string': 'Plot histogram of mepp start times:',
            'object': self.plotHistoTimes
        })
        self.items.append({
            'name': 'random_mepp_Button',
            'string': 'Click to add randomly distibuted mepps',
            'object': self.randommeppButton
        })
        self.items.append({
            'name': 'listTimes',
            'string': 'Export list of mepp start times',
            'object': self.exportTimes_button
        })
        self.items.append({
            'name': 'plotMEPP',
            'string': 'Plot single MEPP (without noise)',
            'object': self.plotmeppButton
        })
        super().gui()

    def __call__(self, keepSourceWindow=False):
        g.settings['mepp_simulator']['traceLength'] = self.getValue(
            'traceLength')
        g.settings['mepp_simulator']['meppAmplitude'] = self.getValue(
            'meppAmplitude')
        g.settings['mepp_simulator']['meppDuration'] = self.getValue(
            'meppDuration')
        g.settings['mepp_simulator']['startTime'] = self.getValue('startTime')
        g.settings['mepp_simulator']['meanExp'] = self.getValue('meanExp')
        g.settings['mepp_simulator']['baseline'] = self.getValue('baseline')
        g.settings['mepp_simulator']['noiseSigma'] = self.getValue(
            'noiseSigma')
        g.settings['mepp_simulator']['riseTime'] = self.getValue('riseTime')
        g.settings['mepp_simulator']['decayTime'] = self.getValue('decayTime')

        return

    def addMEPP(self, time, amplitude, duration, dT=10, rT=1):
        #using Segal et al. Biophys J, 1985 MINIATURE ENDPLATE POTENTIAL FREQUENCY AND AMPLITUDE DETERMINED BY AN EXTENSION OF CAMPBELL'S THEOREM
        #dT = decay time
        #rT = rise time
        ampList = []
        for t in range(0, duration):
            ampList.append(amplitude * (math.exp(-t / dT) - math.exp(-t / rT)))

        #square event test
        #self.data[time:time+duration] = self.data[time:time+duration] + amplitude

        #add MEPP to trace
        self.data[time:time +
                  duration] = self.data[time:time +
                                        duration] + np.array(ampList)

    def plotSingleMEPP(self):
        amp = self.getValue('meppAmplitude')
        duration = self.getValue('meppDuration')
        dT = self.getValue('decayTime')
        rT = self.getValue('riseTime')
        self.plotMEPP(amp, duration, dT=dT, rT=rT)

    def plotMEPP(self, amplitude, duration, dT=10, rT=1):
        ampList = []
        for t in range(0, duration):
            ampList.append(amplitude * (math.exp(-t / dT) - math.exp(-t / rT)))
        #plot matplot
        #plt.figure(3)
        #plt.plot(range(0,duration),ampList)
        #plt.show()
        #plot pg
        self.meppWindow.update(ampList, [0, len(ampList)],
                               [0, self.getValue('meppAmplitude')])
        self.meppWindow.show()

    def addRandommepps(self):
        self.data = np.array([])

        #generate noisy time trace
        n = int(self.getValue('traceLength'))

        self.data = np.random.normal(self.getValue('baseline'),
                                     self.getValue('noiseSigma'), n)

        #add MEPPS to trace
        mean = self.getValue('meanExp')
        meppsAdded = 0
        meppsOutsideOfRange = 0
        self.timesAdded = []

        amp = self.getValue('meppAmplitude')
        duration = self.getValue('meppDuration')
        dT = self.getValue('decayTime')
        rT = self.getValue('riseTime')

        # add first mepp
        try:
            time = int((np.random.exponential(scale=mean, size=1) +
                        self.getValue('startTime')))
            #draw random amplitude
            randAmp = int(
                np.random.normal(amp, self.getValue('meppAmplitude_sigma'), 1))
            #draw random duration
            randDuration = int(
                np.random.normal(duration, self.getValue('meppDuration_sigma'),
                                 1))
            # add MEPP
            self.addMEPP(time, randAmp, randDuration, dT=dT, rT=rT)
            #record time
            self.timesAdded.append(time)
            meppsAdded += 1
        except BaseException as e:
            #print(e)
            #meppsOutsideOfRange += 1
            #print('{} MEPPs added, {} MEPPs out of time range'.format(meppsAdded,meppsOutsideOfRange))
            #print('1st MEPP outside of time range, aborting')
            pass

        # add mepp after each time selection untill end of stack
        # casting the exponential continous value as an int to select frame
        while time < self.getValue('traceLength') - self.getValue(
                'meppDuration'):
            try:
                time = int((time + np.random.exponential(scale=mean, size=1)))

                #draw random amplitude
                randAmp = int(
                    np.random.normal(amp, self.getValue('meppAmplitude_sigma'),
                                     1))
                #draw random duration
                randDuration = int(
                    np.random.normal(duration,
                                     self.getValue('meppDuration_sigma'), 1))
                # add MEPP
                self.addMEPP(time, randAmp, randDuration, dT=dT, rT=rT)
                #record time
                self.timesAdded.append(time)
                meppsAdded += 1
            except BaseException as e:
                #print(e)
                meppsOutsideOfRange += 1

        #print number of MEPPS added to console
        #print('{} MEPPs added, {} MEPPs out of time range'.format(meppsAdded,meppsOutsideOfRange))

        if self.plotHistoTimes.isChecked():
            plt.figure(1)
            plt.hist(self.timesAdded)
            plt.xlabel('Time MEPP added')
            plt.ylabel('Number of MEPPs added')
            plt.show()

        self.randommeppsAdded = True

        #print data to console
        #print(self.data)

        #plot data matplotlib
        #plt.figure(0)
        #plt.plot(self.data)
        #plt.show()

        #plot data pg
        self.traceWindow.update(self.data, [0, len(self.data)], [
            self.getValue('baseline') - (3 * self.getValue('noiseSigma')),
            self.getValue('meppAmplitude') +
            (3 * self.getValue('meppAmplitude_sigma'))
        ])
        self.traceWindow.show()
        return

    def exportTimes(self):
        if self.randommeppsAdded == False:
            g.alert('Add MEPPs first')
            return

        #set export path
        savePath, _ = QFileDialog.getSaveFileName(None, "Save file", "",
                                                  "Text Files (*.csv)")

        #write file
        try:
            # opening the csv file in 'w+' mode
            file = open(savePath, 'w+', newline='')

            # writing the data into the file
            with file:
                write = csv.writer(file)
                write.writerows(map(lambda x: [x], self.timesAdded))

            print('List of times saved to: {}'.format(savePath))
        except BaseException as e:
            print(e)
            print('Export of times failed, printing times to console')
            print(self.timesAdded)
Пример #3
0
class PuffMapper(BaseProcess_noPriorWindow):
    """
    puff heat map generator
    ------------------
    
    input:      csv file with one or more time traces (columns) 
    
    variables:  
    
    analysis:   
    
    output:     
    """
    def __init__(self):
        if g.settings['puffMapper'] is None or 'yExpand' not in g.settings['puffMapper']:
            s = dict()            
            s['nFrames'] = 1000           
            s['startFrame'] = 0 
            s['sortedByMax'] = False             
            s['xBin'] = 0 
            s['yExpand'] = 0                  
            
            g.settings['puffMapper'] = s
                   
        BaseProcess_noPriorWindow.__init__(self)
            
        

    def __call__(self, nFrames, startFrame, sortedByMax, xBin, yExpand, keepSourceWindow=False):
        '''
        '''

        #currently not saving parameter changes on call
        g.settings['puffMapper']['nFrames'] = nFrames         
        g.settings['puffMapper']['startFrame'] = startFrame   
        g.settings['puffMapper']['sortedByMax'] = sortedByMax  
        g.settings['puffMapper']['xBin'] = xBin  
        g.settings['puffMapper']['yExpand'] = yExpand         
        
        g.m.statusBar().showMessage("Starting puff mapper...")
        return



    def closeEvent(self, event):
        self.clearPlots()
        BaseProcess_noPriorWindow.closeEvent(self, event)
        return

    def gui(self):      
        self.filename = ''          
        self.gui_reset()        
        s=g.settings['puffMapper']  
        
        #buttons      
        self.plotChart_button = QPushButton('Create Line plot')
        self.plotChart_button.pressed.connect(self.plotData)  
                
        self.generateHeatmap_button = QPushButton('Create Heatmap')        
        self.generateHeatmap_button.pressed.connect(self.createHeatmap)  

                         
        #checkbox
        self.sorted_checkbox = CheckBox()
        self.sorted_checkbox.setChecked(s['sortedByMax'])

        #comboboxes
        self.xFunc_Box = pg.ComboBox()
        xFuncs = {'mean':np.mean, 'max':np.max, 'median':np.median}
        self.xFunc_Box.setItems(xFuncs)

        
        #spinboxes
        #Frames
        self.startFrame_Box = pg.SpinBox(int=True, step=1)
        self.startFrame_Box.setMinimum(0)
        self.startFrame_Box.setMaximum(1000000)  
        self.startFrame_Box.setValue(s['startFrame'])            
                
        self.nFrames_Box = pg.SpinBox(int=True, step=1)
        self.nFrames_Box.setMinimum(0)
        self.nFrames_Box.setMaximum(1000000)  
        self.nFrames_Box.setValue(s['nFrames'])          

        self.xBin_Box = pg.SpinBox(int=True, step=2)
        self.xBin_Box.setMinimum(1)
        self.xBin_Box.setMaximum(10000)  
        self.xBin_Box.setValue(s['xBin'])   

        self.yExpand_Box = pg.SpinBox(int=True, step=1)
        self.yExpand_Box.setMinimum(1)
        self.yExpand_Box.setMaximum(1000)  
        self.yExpand_Box.setValue(s['yExpand'])   


        #export file selector
        self.getFile = FileSelector()
        
        #connections
        self.getFile.valueChanged.connect(self.loadData)
           
        #################################################################
        #self.exportFolder = FolderSelector('*.txt')
        #MEPPS
        self.items.append({'name': 'blank1 ', 'string': '-------------   Parameters    ---------------', 'object': None}) 
        self.items.append({'name': 'startFrame', 'string': 'Set start frame ', 'object': self.startFrame_Box})          
        self.items.append({'name': 'nFrames', 'string': 'Set number of frames ', 'object': self.nFrames_Box}) 
        self.items.append({'name': 'xBin', 'string': 'Set x-axis binning number ', 'object': self.xBin_Box})  
        self.items.append({'name': 'xBinType', 'string': 'Set x-axis bin function ', 'object': self.xFunc_Box})  
        self.items.append({'name': 'yExpand', 'string': 'Set y-axis expansion value ', 'object': self.yExpand_Box})          
        self.items.append({'name': 'sortedByMax', 'string': 'Sorted by maximum', 'object': self.sorted_checkbox})         
        self.items.append({'name': 'blank ', 'string': '-------------------------------------------', 'object': None})           
        
        self.items.append({'name': 'filepath ', 'string': '', 'object': self.getFile})              

        self.items.append({'name': 'heatmap', 'string': '', 'object': self.generateHeatmap_button })            
        self.items.append({'name': 'lineplot', 'string': '', 'object': self.plotChart_button }) 

        
        super().gui()
        ######################################################################
        return



    def loadData(self):
        self.filename = self.getFile.value()
        self.data = pd.read_csv(self.filename, header=None, skiprows=1, index_col = 0)
        
        #drop extra x columns
        self.data = self.data[self.data.columns[::2]] 
        #drop columns with na values
        self.data = self.data.dropna(axis=1, how='all')        
        #set column names by number
        nCols = len(self.data.columns)
        colNames = list(range(0,nCols))
        self.data.columns = colNames
        #copy df and make one sorted by intensity
        self.dataSorted = self.data.copy()
        self.dataSorted = self.dataSorted.iloc[:, self.dataSorted.max().sort_values(ascending=False).index]

        #set nFrames max
        nRows = len(self.data)
        self.nFrames_Box.setMaximum(nRows)  
        self.nFrames_Box.setValue(nRows)  

        print('-------------------------------------')
        print('Data loaded (first 5 rows displayed):')
        print(self.data.head())
        print('-------------------------------------')



    def plotData(self):
        ### plot test result
        self.data.plot()
        plt.show()
        g.m.statusBar().showMessage('scatter plot created') 
        print('scatter plot created')    
        return

    def createHeatmap(self):
        ### create heatmap image
        if self.sorted_checkbox.isChecked():
            try:
                mapData = self.dataSorted.to_numpy()
            except:
                mapData = self.dataSorted.values
        else:
            try:
                mapData = self.data.to_numpy()
            except:
                mapData = self.data.values              
            

        nRows,nCols = mapData.shape
        print('original data has: {} columns, {} rows'.format(nRows, nCols))
        start = self.startFrame_Box.value()
        end = self.startFrame_Box.value() + self.nFrames_Box.value()
        
        if end > nRows:
            end = nRows

        #crop data
        img = mapData[start:end]
        
        #x binning
        img = groupedAvg(img,block_size=(self.xBin_Box.value(),1),func=self.xFunc_Box.value())

        #y expansion
        img = np.repeat(img,self.yExpand_Box.value(),axis=1)
        print('y-axis expanded by {}'.format(self.yExpand_Box.value()))
        
        #get new img shape
        nRows_img,nCols_img = img.shape
        print('displayed image has: {} columns, {} rows'.format(nRows_img, nCols_img))
      
        self.heatmapImg = Window(img,name='puff map')
        print('puff map created')
        return

    
    def clearPlots(self):
        try:
            plt.close('all')  
        except:
            pass
        return
Пример #4
0
class Simulate_Puff(BaseProcess_noPriorWindow):
    """
    Add a simulated puff to an image stack
    
    """
    def __init__(self):
        super().__init__()
        self.currentWin = None
        self.currentROI = None
        self.data = None

    def get_init_settings_dict(self):
        s = dict()
        s['nFrames'] = 100
        s['puffAmplitude'] = 5
        s['x'] = 128
        s['y'] = 128
        s['startFrame'] = 100
        s['sigma'] = 20
        s['useROI'] = False
        s['meanExp'] = 5.0
        s['nPuffs'] = 0
        s['nSites'] = 10
        s['meanDuration'] = 10

        return s

    def gui(self):
        self.gui_reset()
        self.nFrames = pg.SpinBox(int=False, step=.01)
        #self.nFrames.setRange(0,10000)
        self.startFrame = SliderLabel(0)
        self.startFrame.setRange(0, 10000)

        self.puffAmplitude = pg.SpinBox(int=False, step=.01)
        self.puffAmplitude.setValue(1.0)
        self.sigma = SliderLabel(0)
        self.sigma.setRange(1, 1000)
        self.x = SliderLabel(0)
        self.x.setRange(1, 10000)
        self.y = SliderLabel(0)
        self.y.setRange(1, 10000)
        self.useROI = CheckBox()
        self.useFrame = CheckBox()
        self.active_window = WindowSelector()
        self.previewButton = QPushButton('Preview Puff')
        self.previewButton.pressed.connect(self.previewPuff)
        self.puffButton = QPushButton('Add Puff')
        self.puffButton.pressed.connect(self.addPuff)

        self.randomPuffsAdded = False

        self.nSites = 10
        columnNames = ['time of puff', 'duration', 'site']
        self.timesAdded = pd.DataFrame(columns=columnNames)
        self.siteNumber = int(0)

        self.nPuffs_slider = SliderLabel(0)
        self.nPuffs_slider.setRange(1, 1000)

        self.meanExp_slider = pg.SpinBox(int=False, step=.01)
        self.meanExp_slider.setValue(5.0)

        self.randomDuration = CheckBox()
        self.randomDuration.setValue(False)

        self.durationMean = 10.0
        self.durationMean_box = pg.SpinBox(int=False, step=.01)
        self.durationMean_box.setRange(0, 10000)
        self.durationMean_box.setValue(self.durationMean)

        self.plotHistoTimes = CheckBox()
        self.plotHistoTimes.setValue(False)

        self.addPuffsSequentially = CheckBox()
        self.addPuffsSequentially.setValue(False)

        self.exportTimes_button = QPushButton('Export times')
        self.exportTimes_button.pressed.connect(self.exportTimes)

        self.randomPuffButton = QPushButton('Add Puffs to site')
        self.randomPuffButton.pressed.connect(self.addRandomPuffs)

        self.multipleRandomPuffButton = QPushButton('Add Puffs inside ROI')
        self.multipleRandomPuffButton.pressed.connect(
            self.addMultipleRandomPuffs)

        self.nSites_box = QSpinBox()
        self.nSites_box.setRange(0, 10000)
        self.nSites_box.setValue(self.nSites)

        self.items.append({
            'name': 'active_window',
            'string': 'Select Window',
            'object': self.active_window
        })
        self.items.append({
            'name': 'nFrames',
            'string': 'Duration (frames)',
            'object': self.nFrames
        })
        self.items.append({
            'name': 'randomDuration',
            'string': 'Use exponentially distributed random duration',
            'object': self.randomDuration
        })
        self.items.append({
            'name': 'meanDuration',
            'string': 'Mean duration',
            'object': self.durationMean_box
        })
        self.items.append({
            'name': 'startFrame',
            'string': 'Start Frame',
            'object': self.startFrame
        })
        #self.items.append({'name': 'useCurrentFrame', 'string': 'Use Current Frame For Start', 'object': self.useFrame})
        self.items.append({
            'name': 'puffAmplitude',
            'string': 'Amplitude',
            'object': self.puffAmplitude
        })
        self.items.append({'name': 'x', 'string': 'x', 'object': self.x})
        self.items.append({'name': 'y', 'string': 'y', 'object': self.y})
        #self.items.append({'name': 'useROI', 'string': 'Use ROI for position', 'object': self.useROI})
        self.items.append({
            'name': 'sigma',
            'string': 'sigma',
            'object': self.sigma
        })
        self.items.append({
            'name': 'preview_Button',
            'string': 'Click to preview Puff',
            'object': self.previewButton
        })
        self.items.append({
            'name': 'puff_Button',
            'string': 'Click to add Puff',
            'object': self.puffButton
        })
        self.items.append({
            'name': 'blank',
            'string': '---------- RANDOM PUFFS ---------------------------',
            'object': None
        })
        #self.items.append({'name': 'nPuffs', 'string': 'Number of puffs to add', 'object': self.nPuffs_slider})
        self.items.append({
            'name': 'meanExp',
            'string': 'Mean of exponential distibution of puff start times',
            'object': self.meanExp_slider
        })
        self.items.append({
            'name': 'puffsSequential',
            'string': 'Wait until puff ends before adding next puff:',
            'object': self.addPuffsSequentially
        })
        self.items.append({
            'name': 'histoTimes',
            'string': 'Plot histogram of puff start times:',
            'object': self.plotHistoTimes
        })
        self.items.append({
            'name': 'random_puff_Button',
            'string': 'Click to add randomly distibuted puffs at one site',
            'object': self.randomPuffButton
        })
        self.items.append({
            'name': 'multipleRandom_puff_Button',
            'string':
            'Click to add randomly distibuted puffs at multiple sites',
            'object': self.multipleRandomPuffButton
        })
        self.items.append({
            'name': 'nSites',
            'string': 'Number of Sites to add',
            'object': self.nSites_box
        })
        self.items.append({
            'name': 'blank',
            'string': '---------- Export Puffs ---------------------------',
            'object': None
        })
        self.items.append({
            'name': 'listTimes',
            'string': 'Export list of puff start times',
            'object': self.exportTimes_button
        })

        super().gui()

    def __call__(self):
        pass
        return

    def update(self):
        self.currentWin = self.getValue('active_window')
        #get image data
        self.data = np.array(deepcopy(self.currentWin.image))
        self.dt, self.dy, self.dx = self.data.shape
        self.x.setRange(1, self.dx - 1)
        self.y.setRange(1, self.dy - 1)

        self.x.setValue(int((self.dx - 1) / 2))
        self.y.setValue(int((self.dy - 1) / 2))

        self.nFrames.setRange(0, self.dt)
        self.startFrame.setRange(0, self.dt - 1)

        self.sigma.setRange(1, int(self.dx / 7))

    def addPuff(self,
                time=False,
                singleSite=True,
                x=None,
                y=None,
                duration=False):
        '''add synthetic blip to image stack'''
        #select window
        self.currentWin = self.getValue('active_window')
        if self.currentWin == None:
            g.alert('First select window')
            return

        #generate blip
        sigma = self.getValue('sigma')
        amp = self.getValue('puffAmplitude')

        if self.randomDuration.isChecked():
            #get random duration
            if duration == False:
                duration = float(
                    np.random.exponential(scale=self.getValue('meanDuration'),
                                          size=1)[0])

        else:
            duration = self.getValue('nFrames')

        #scale puff amplitude to account for durations <1 frame
        if duration < 1:
            amp = amp * duration
            duration = ceil(duration)

        else:
            #round duration to nearest integer number of frames
            duration = ceil(duration)

        blip = generateBlip(sigma=sigma, amplitude=amp, duration=duration)

        blip_time, blip_x_size, blip_y_size = blip.shape

        x_size = int(blip_x_size / 2)
        y_size = int(blip_y_size / 2)

        #add blip to stack
        if time == False:
            t = self.getValue('startFrame')
        else:
            t = time

        if singleSite:
            x = self.getValue('x')
            y = self.getValue('y')

        tt = np.arange(t, t + duration, dtype=np.int)
        xx = np.arange(x - x_size - 1, x + x_size, dtype=np.int)
        yy = np.arange(y - y_size - 1, y + y_size, dtype=np.int)

        if time == False:
            try:
                self.data[np.ix_(tt, xx,
                                 yy)] = self.data[np.ix_(tt, xx, yy)] + blip
            except:
                g.alert(
                    'Error - Puff might be too large, too long or too close to edge'
                )
        else:
            self.data[np.ix_(tt, xx,
                             yy)] = self.data[np.ix_(tt, xx, yy)] + blip

        frame = self.currentWin.currentIndex
        self.currentWin.imageview.setImage(self.data)
        self.currentWin.image = self.data
        self.currentWin.setIndex(frame)

        print(
            'Puff added at time: {}, x: {}, y: {} with duration: {}, sigma: {}, amplitude:{}'
            .format(t, x, y, duration, sigma, amp))

        return

    def addRandomPuffs(self, singleSite=True, x=None, y=None):
        if self.getValue('active_window') == None:
            g.alert('First select window')
            return

        mean = self.getValue('meanExp')
        #nPuffs = self.getValue('nPuffs')

        puffsAdded = 0
        puffsOutsideOfRange = 0

        # add first puff
        try:
            if self.randomDuration.isChecked():
                startTime = int(
                    np.random.exponential(scale=mean, size=1) +
                    self.getValue('startFrame'))
                duration = float(
                    np.random.exponential(scale=self.getValue('meanDuration'),
                                          size=1)[0])
                self.addPuff(time=startTime,
                             singleSite=singleSite,
                             x=x,
                             y=y,
                             duration=duration)

            else:
                startTime = int(
                    np.random.exponential(scale=mean, size=1) +
                    self.getValue('startFrame'))
                duration = self.getValue('nFrames')
                self.addPuff(time=startTime, singleSite=singleSite, x=x, y=y)

            if self.getValue('puffsSequential'):
                endTime = startTime + duration
            else:
                endTime = startTime

        except Exception as e:
            print(e)
            puffsOutsideOfRange += 1
            print('{} puffs added, {} puffs out of range'.format(
                puffsAdded, puffsOutsideOfRange))
            print('1st puff outside of range, aborting')
            return

        # add puff after each time selection untill end of stack
        # rounding the exponential continous value to an int to select frame
        while startTime < self.dt - self.getValue('nFrames'):
            try:
                startTime = int(endTime +
                                np.random.exponential(scale=mean, size=1))

                #if random duration
                if self.randomDuration.isChecked():
                    #print('original time: ', startTime)
                    duration = np.random.exponential(
                        scale=self.getValue('meanDuration'), size=1)
                    startTime = startTime + ceil(duration)
                    #print('time: ', startTime)
                    #print('duration: ', duration)
                    #add puff at time
                    self.addPuff(time=startTime,
                                 singleSite=singleSite,
                                 x=x,
                                 y=y,
                                 duration=duration)

                    #if sequental, add puff duration to time
                    if self.getValue('puffsSequential'):
                        endTime = startTime + duration
                    else:
                        endTime = startTime
                #else use duration from GUI
                else:
                    startTime = startTime + self.getValue('nFrames')
                    duration = self.getValue('nFrames')
                    #add puff at time
                    self.addPuff(time=startTime,
                                 singleSite=singleSite,
                                 x=x,
                                 y=y)

                    #if sequental, add puff duration to time
                    if self.getValue('puffsSequential'):
                        endTime = startTime + duration
                    else:
                        endTime = startTime

                #update puff time log
                self.timesAdded = self.timesAdded.append(
                    {
                        'time of puff': startTime,
                        'duration': duration,
                        'site': int(self.siteNumber)
                    },
                    ignore_index=True)

                puffsAdded += 1
            except:
                puffsOutsideOfRange += 1

        print('{} puffs added, {} puffs out of range'.format(
            puffsAdded, puffsOutsideOfRange))

        if self.plotHistoTimes.isChecked():
            plt.hist(self.timesAdded)
            plt.xlabel('Time puff added (frames)')
            plt.ylabel('Number of puffs added')
            plt.show()

        self.randomPuffsAdded = True
        if singleSite:
            self.siteNumber += 1

        return

    def addMultipleRandomPuffs(self):
        nSites = self.getValue('nSites')

        if self.currentWin == None:
            g.alert('First select window')
            return

        #select current ROI
        self.currentROI = self.currentWin.currentROI

        if self.currentWin.currentROI == None:
            g.alert('First draw an ROI')
            return
        bounds = self.currentROI.parentBounds()

        topLeft_x = bounds.topLeft().x()
        topLeft_y = bounds.topLeft().y()

        bottomRight_x = bounds.bottomRight().x()
        bottomRight_y = bounds.bottomRight().y()

        print('adding puffs to {} sites from {},{} to {},{}'.format(
            nSites, topLeft_x, topLeft_y, bottomRight_x, bottomRight_y))

        sites = self.getRandomSites(topLeft_x, bottomRight_x, topLeft_y,
                                    bottomRight_y, nSites)

        for site in sites:
            print("Puff site: ", self.siteNumber)
            self.addRandomPuffs(singleSite=False, x=site[0], y=site[1])
            self.siteNumber += 1

        print('Finished adding sites')

        return

    def getRandomSites(self, xStart, xEnd, yStart, yEnd, qty, radius=0):
        import random

        rangeX = (xStart, xEnd)
        rangeY = (yStart, yEnd)

        deltas = set()
        for x in range(-radius, radius + 1):
            for y in range(-radius, radius + 1):
                if x * x + y * y <= radius * radius:
                    deltas.add((x, y))

        randPoints = []
        excluded = set()
        i = 0

        while i < qty:
            x = random.randrange(*rangeX)
            y = random.randrange(*rangeY)
            if (x, y) in excluded: continue
            randPoints.append((x, y))
            i += 1
            excluded.update((x + dx, y + dy) for (dx, dy) in deltas)

        return randPoints

    def exportTimes(self):
        if self.getValue('active_window') == None:
            g.alert('First select window')
            return

        if self.randomPuffsAdded == False:
            g.alert('Add puffs first')
            return

        #set export path
        savePath, _ = QFileDialog.getSaveFileName(None, "Save file", "",
                                                  "Text Files (*.csv)")

        #write file
        self.timesAdded.to_csv(savePath)
        print('List of times saved to: {}'.format(savePath))

        # #write file
        # try:
        #     # opening the csv file in 'w+' mode
        #     file = open(savePath, 'w+', newline ='')

        #     # writing the data into the file
        #     with file:
        #         write = csv.writer(file)
        #         write.writerows(map(lambda x: [x], self.timesAdded))

        #     print('List of times saved to: {}'.format(savePath))
        # except BaseException as e:
        #     print(e)
        #     print('Export of times failed, printing times to console')
        #     print(self.timesAdded)

    def previewPuff(self):
        '''preview blip to be added'''
        sigma = self.getValue('sigma')
        amp = self.getValue('puffAmplitude')

        if self.randomDuration.isChecked():
            #get random duration
            duration = np.random.exponential(
                scale=self.getValue('meanDuration'), size=1)

            #scale puff amplitude to account for durations <1 frame or spread across 2 frames
            spread = ceil(duration)
            if spread < 2:
                amp = amp * (duration / spread)

            #round duration to nearest integer number of frames
            duration = ceil(duration)

        else:
            duration = self.getValue('nFrames')

        blip = generateBlip(sigma=sigma, amplitude=amp, duration=duration)

        Window(blip)

        return

    def generateBlip(sigma=1, amplitude=1, duration=1):
        sigma = int(sigma)
        width = sigma * 8 + 1
        xorigin = sigma * 4
        yorigin = sigma * 4
        x = np.arange(width)
        y = np.arange(width)
        x = x[:, None]
        y = y[None, :]
        gaussian = amplitude * (np.exp(-(x - xorigin)**2 / (2. * sigma**2)) *
                                np.exp(-(y - yorigin)**2 / (2. * sigma**2)))
        blip = np.repeat(gaussian[None, :, :], repeats=duration, axis=0)
        return blip
Пример #5
0
class Synapse3D_batch(QtWidgets.QDialog):
    def __init__(self, parent = None):
        super(Synapse3D_batch, self).__init__(parent)
        #add window title
        self.setWindowTitle("Volume Slider GUI")
        
        self.pathName = ''

        self.eps  = clusterAnalysis.eps
        self.min_samples = clusterAnalysis.min_samples
        self.maxDistance = clusterAnalysis.maxDistance
        self.unitPerPixel = clusterAnalysis.unitPerPixel
        #self.multiThreadingFlag = clusterAnalysis.multiThreadingFlag
        self.displayFlag = clusterAnalysis.displayFlag
        
        self.clusterType = '3D'
        
        #window geometry
        self.left = 300
        self.top = 300
        self.width = 300
        self.height = 200

        #labels
        self.clusterTitle = QtWidgets.QLabel("----- Cluster Parameters -----") 
        self.label_eps = QtWidgets.QLabel("max distance between points:") 
        self.label_minSamples = QtWidgets.QLabel("minimum number of points:") 
        self.label_maxDistance = QtWidgets.QLabel("max distance between clusters:") 
        self.label_clustertype = QtWidgets.QLabel("clustering type:")        
        self.displayTitle = QtWidgets.QLabel("----- Display Parameters -----") 
        self.label_unitPerPixel = QtWidgets.QLabel("nanometers/pixel:") 
        #self.label_centroidSymbolSize = QtWidgets.QLabel("centroid symbol size:")  
        
        self.analysisTitle = QtWidgets.QLabel("----- Cluster Analysis -----") 
        self.label_analysis = QtWidgets.QLabel("Clusters to analyse: ")

        self.displayTitle = QtWidgets.QLabel("----- Display -----") 
        self.label_display = QtWidgets.QLabel("Plot results: ")         
        
        #self.multiThreadTitle = QtWidgets.QLabel("----- Multi-Threading -----") 
        #self.label_multiThread = QtWidgets.QLabel("Multi-Threading On: ")        
        
        #self.label_displayPlot = QtWidgets.QLabel("show plot")         

        #spinboxes
        self.epsBox = QtWidgets.QSpinBox()
        self.epsBox.setRange(0,10000)
        self.epsBox.setValue(self.eps)
        self.minSampleBox = QtWidgets.QSpinBox()    
        self.minSampleBox.setRange(0,10000)
        self.minSampleBox.setValue(self.min_samples)
        self.maxDistanceBox = QtWidgets.QSpinBox()    
        self.maxDistanceBox.setRange(0,10000)
        self.maxDistanceBox.setValue(self.maxDistance)    
        self.unitPerPixelBox = QtWidgets.QSpinBox()    
        self.unitPerPixelBox.setRange(0,1000)
        self.unitPerPixelBox.setValue(self.unitPerPixel)  
        #self.centroidSymbolSizeBox = QtWidgets.QSpinBox()    
        #self.centroidSymbolSizeBox.setRange(0,1000)
        #self.centroidSymbolSizeBox.setValue(self.centroidSymbolSize)          

        #combobox
        #self.analysis_Box = QtWidgets.QComboBox()
        #self.analysis_Box.addItems(["All Clusters", "Paired Clusters"])
        self.clustertype_Box = QtWidgets.QComboBox()
        self.clustertype_Box.addItems(["2D", "3D"])
        self.clustertype_Box.setCurrentText(self.clusterType)
        self.clustertype_Box.currentIndexChanged.connect(self.clusterTypeChange)
        
        #tickbox
        self.display_checkbox = CheckBox()
        self.display_checkbox.setChecked(self.displayFlag)
        self.display_checkbox.stateChanged.connect(self.displayClicked)
        #self.multiThread_checkbox = CheckBox()
        #self.multiThread_checkbox.setChecked(self.multiThreadingFlag)
        #self.multiThread_checkbox.stateChanged.connect(self.multiThreadClicked)

        #buttons
        self.button_getFolder = QtWidgets.QPushButton("Set Folder")
        self.button_start = QtWidgets.QPushButton("Start Batch Analysis")
        
        #grid layout
        layout = QtWidgets.QGridLayout()
        layout.setSpacing(5)
        layout.addWidget(self.clusterTitle, 0, 0, 1, 2)        
        layout.addWidget(self.label_eps, 1, 0)
        layout.addWidget(self.epsBox, 1, 1)       
        layout.addWidget(self.label_minSamples, 2, 0)        
        layout.addWidget(self.minSampleBox, 2, 1)     
        layout.addWidget(self.label_maxDistance, 3, 0)        
        layout.addWidget(self.maxDistanceBox, 3, 1)
        layout.addWidget(self.displayTitle, 4, 0, 1, 2)          
        layout.addWidget(self.label_unitPerPixel, 5, 0)  
        layout.addWidget(self.unitPerPixelBox, 5, 1)         
        layout.addWidget(self.label_clustertype, 6, 0) 
        layout.addWidget(self.clustertype_Box, 6, 1)
        layout.addWidget(self.displayTitle, 7, 0, 1, 2) 
        layout.addWidget(self.label_display, 8, 0)        
        layout.addWidget(self.display_checkbox, 8, 1)         
        layout.addWidget(self.button_getFolder, 9, 0)          
        layout.addWidget(self.button_start, 10, 0)         
        
        #layout.addWidget(self.label_centroidSymbolSize, 6, 0)  
        #layout.addWidget(self.centroidSymbolSizeBox, 6, 1) 
        
        #layout.addWidget(self.analysisTitle, 8, 0, 1, 2)  
        #layout.addWidget(self.label_analysis, 9, 0)  
        #layout.addWidget(self.analysis_Box, 9, 1)     
        
        #layout.addWidget(self.multiThreadTitle, 10, 0, 1, 2)  
        #layout.addWidget(self.label_multiThread, 11, 0)  
        #layout.addWidget(self.multiThread_checkbox, 11, 1)  
        

        
        self.setLayout(layout)
        self.setGeometry(self.left, self.top, self.width, self.height)

        #add window title
        self.setWindowTitle("Clustering Options")

        #connect spinboxes
        self.epsBox.valueChanged.connect(self.epsValueChange)
        self.minSampleBox.valueChanged.connect(self.minSampleChange) 
        self.maxDistanceBox.valueChanged.connect(self.maxDistanceChange)    
        self.unitPerPixelBox.valueChanged.connect(self.unitPerPixelChange) 
        #self.centroidSymbolSizeBox.valueChanged.connect(self.centroidSymbolSizeChange)  
        #connect combobox
        #self.analysis_Box.setCurrentIndex(0)
        #self.analysis_Box.currentIndexChanged.connect(self.analysisChange)         

        #connect buttons
        self.button_getFolder.clicked.connect(self.getSavePath)
        self.button_start.clicked.connect(self.run)

        
    def epsValueChange(self,value):
        self.epsBox = value
        clusterAnalysis.eps = self.epsBox
        return
    
    def minSampleChange(self,value):
        self.min_samples = value
        clusterAnalysis.min_samples = self.min_samples 
        return
        
    def maxDistanceChange(self,value):
        self.maxDistance = value
        clusterAnalysis.maxDistance = self.maxDistance
        return

    def unitPerPixelChange(self,value):
        self.unitPerPixel = value
        clusterAnalysis.unitPerPixel = self.unitPerPixel
        return
 
    def clusterTypeChange(self):
        self.clusterType = self.clustertype_Box.currentText
        clusterAnalysis.clusterType = self.clusterType
    
#    def centroidSymbolSizeChange(self,value):
#        self.centroidSymbolSize = value
#        self.viewer.centroidSymbolSize = self.centroidSymbolSize
#        return   
    
#    def analysisChange(self):
#        self.viewer.clusterAnaysisSelection = self.analysis_Box.currentText()
#        return
    
#    def multiThreadClicked(self):
#        self.viewer.multiThreadingFlag = self.multiThread_checkbox.isChecked()
#        return

    def getSavePath(self): 
        folder = QtWidgets.QFileDialog.getExistingDirectory(g.m, "Select batch folder.", os.path.expanduser("~"), QtWidgets.QFileDialog.ShowDirsOnly)
        self.pathName = folder
        return

    def run(self):
        if not os.path.exists(os.path.join(self.pathName,'results')):
            os.makedirs(os.path.join(self.pathName,'results'))
        clusterAnalysis.runBatch(self.pathName)
        return

    def displayClicked(self):
        clusterAnalysis.displayFlag = self.display_checkbox.isChecked()
        self.displayFlag = clusterAnalysis.displayFlag
        return

    def start(self):
        self.show()
        return
Пример #6
0
class Form2(QtWidgets.QDialog):
    def __init__(self, viewerInstance, parent=None):
        super(Form2, self).__init__(parent)
        self.batch = False
        self.viewer = viewerInstance
        self.fileName = self.viewer.getFileName()
        #print('loaded: ',self.fileName)
        self.s = g.settings['volumeSlider']

        self.arraySavePath = self.viewer.savePath
        self.arrayImportPath = "None"

        #window geometry
        windowGeometry(self, left=300, top=300, height=600, width=400)

        self.slicesPerVolume = self.s['slicesPerVolume']

        self.slicesDeletedPerVolume = self.s['slicesDeletedPerVolume']

        self.baselineValue = self.s['baselineValue']
        self.f0Start = self.s['f0Start']
        self.f0End = self.s['f0End']
        self.f0VolStart = self.s['f0VolStart']
        self.f0VolEnd = self.s['f0VolEnd']
        self.multiplicationFactor = self.s['multiplicationFactor']
        self.currentDataType = self.s['currentDataType']
        self.newDataType = self.s['newDataType']
        self.inputArrayOrder = self.s['inputArrayOrder']
        self.displayArrayOrder = self.s['displayArrayOrder'] = 16
        self.theta = self.s['theta']
        self.shiftFactor = self.s['shiftFactor']
        self.trim_last_frame = self.s['trimLastFrame']

        #spinboxes
        self.spinLabel1 = QtWidgets.QLabel("Slice #")
        self.SpinBox1 = QtWidgets.QSpinBox()
        self.SpinBox1.setRange(0, self.viewer.getNFrames())
        self.SpinBox1.setValue(0)

        self.spinLabel2 = QtWidgets.QLabel("# of slices per volume: ")
        self.SpinBox2 = QtWidgets.QSpinBox()
        self.SpinBox2.setRange(0, self.viewer.getNFrames())
        if self.slicesPerVolume < self.viewer.getNFrames():
            self.SpinBox2.setValue(self.slicesPerVolume)
        else:
            self.SpinBox2.setValue(1)

        self.spinLabel13 = QtWidgets.QLabel("# of slices removed per volume: ")
        self.SpinBox13 = QtWidgets.QSpinBox()
        self.SpinBox13.setRange(0, self.viewer.getNFrames())
        if self.slicesDeletedPerVolume < self.viewer.getNFrames():
            self.SpinBox13.setValue(self.slicesDeletedPerVolume)
        else:
            self.SpinBox13.setValue(0)

        self.spinLabel4 = QtWidgets.QLabel("baseline value: ")
        self.SpinBox4 = QtWidgets.QSpinBox()
        self.SpinBox4.setRange(0, self.viewer.getMaxPixel())
        if self.baselineValue < self.viewer.getMaxPixel():
            self.SpinBox4.setValue(self.baselineValue)
        else:
            self.SpinBox4.setValue(0)

        self.spinLabel6 = QtWidgets.QLabel("F0 start volume: ")
        self.SpinBox6 = QtWidgets.QSpinBox()
        self.SpinBox6.setRange(0, self.viewer.getNVols())
        if self.f0Start < self.viewer.getNVols():
            self.SpinBox6.setValue(self.f0Start)
        else:
            self.SpinBox6.setValue(0)

        self.spinLabel7 = QtWidgets.QLabel("F0 end volume: ")
        self.SpinBox7 = QtWidgets.QSpinBox()
        self.SpinBox7.setRange(0, self.viewer.getNVols())
        if self.f0End < self.viewer.getNVols():
            self.SpinBox7.setValue(self.f0End)
        else:
            self.SpinBox7.setValue(0)

        self.spinLabel8 = QtWidgets.QLabel("factor to multiply by: ")
        self.SpinBox8 = QtWidgets.QSpinBox()
        self.SpinBox8.setRange(0, 10000)
        self.SpinBox8.setValue(self.multiplicationFactor)

        self.spinLabel9 = QtWidgets.QLabel("theta: ")
        self.SpinBox9 = QtWidgets.QSpinBox()
        self.SpinBox9.setRange(0, 360)
        self.SpinBox9.setValue(self.theta)

        self.spinLabel10 = QtWidgets.QLabel("shift factor: ")
        self.SpinBox10 = QtWidgets.QSpinBox()
        self.SpinBox10.setRange(0, 100)
        self.SpinBox10.setValue(self.shiftFactor)

        self.SpinBox11 = QtWidgets.QSpinBox()
        self.SpinBox11.setRange(0, self.viewer.getNVols())
        if self.f0Start < self.viewer.getNVols():
            self.SpinBox11.setValue(self.f0VolStart)
        else:
            self.SpinBox6.setValue(0)

        self.SpinBox12 = QtWidgets.QSpinBox()
        self.SpinBox12.setRange(0, self.viewer.getNVols())
        if self.f0End <= self.viewer.getNVols():
            self.SpinBox12.setValue(self.f0VolEnd)
        else:
            self.SpinBox12.setValue(self.viewer.getNVols())

        #sliders
        self.slider1 = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        setSliderUp(self.slider1,
                    minimum=0,
                    maximum=self.viewer.getNFrames(),
                    tickInterval=1,
                    singleStep=1,
                    value=0)

        #ComboBox
        self.dTypeSelectorBox = QtWidgets.QComboBox()
        self.dTypeSelectorBox.addItems([
            "float16", "float32", "float64", "int8", "int16", "int32", "int64"
        ])
        self.inputArraySelectorBox = QtWidgets.QComboBox()
        self.inputArraySelectorBox.addItems(self.viewer.getArrayKeys())
        self.inputArraySelectorBox.setCurrentIndex(4)
        self.inputArraySelectorBox.currentIndexChanged.connect(
            self.inputArraySelectionChange)

        self.displayArraySelectorBox = QtWidgets.QComboBox()
        self.displayArraySelectorBox.addItems(self.viewer.getArrayKeys())
        self.displayArraySelectorBox.setCurrentIndex(18)
        self.displayArraySelectorBox.currentIndexChanged.connect(
            self.displayArraySelectionChange)

        #buttons
        self.button1 = QtWidgets.QPushButton("Autolevel")
        self.button2 = QtWidgets.QPushButton("Set Slices")
        #self.button3 = QtWidgets.QPushButton("Average Volumes")
        self.button4 = QtWidgets.QPushButton("subtract baseline")
        self.button5 = QtWidgets.QPushButton("run DF/F0")
        self.button6 = QtWidgets.QPushButton("export to Window")
        self.button7 = QtWidgets.QPushButton("set data Type")
        self.button8 = QtWidgets.QPushButton("multiply")
        self.button9 = QtWidgets.QPushButton("export to array")

        self.button12 = QtWidgets.QPushButton("open 3D viewer")
        self.button13 = QtWidgets.QPushButton("close 3D viewer")

        self.button14 = QtWidgets.QPushButton("load new file")

        self.button15 = QtWidgets.QPushButton("Set overlay to current volume")

        #labels
        self.ratioVolStartLabel = QtWidgets.QLabel("ratio start volume: ")
        self.ratioVolEndLabel = QtWidgets.QLabel("ratio End volume: ")
        self.volumeLabel = QtWidgets.QLabel("# of volumes: ")
        self.volumeText = QtWidgets.QLabel("  ")

        self.currentVolumeLabel = QtWidgets.QLabel("current volume: ")
        self.currentVolumeText = QtWidgets.QLabel("0")

        self.shapeLabel = QtWidgets.QLabel("array shape: ")
        self.shapeText = QtWidgets.QLabel(str(self.viewer.getArrayShape()))

        self.dataTypeLabel = QtWidgets.QLabel("current data type: ")
        self.dataTypeText = QtWidgets.QLabel(str(self.viewer.getDataType()))
        self.dataTypeChangeLabel = QtWidgets.QLabel("new data type: ")

        self.inputArrayLabel = QtWidgets.QLabel("input array order: ")
        self.displayArrayLabel = QtWidgets.QLabel("display array order: ")

        self.arraySavePathLabel = QtWidgets.QLabel(str(self.arraySavePath))

        self.trim_last_frameLabel = QtWidgets.QLabel("Trim Last Frame: ")
        self.trim_last_frame_checkbox = CheckBox()
        self.trim_last_frame_checkbox.setChecked(self.trim_last_frame)
        self.trim_last_frame_checkbox.stateChanged.connect(
            self.trim_last_frameClicked)

        self.fileNameLabel = QtWidgets.QLabel("file name: ")
        self.fileNameText = QtWidgets.QLabel(str(self.fileName))

        #grid layout
        layout = QtWidgets.QGridLayout()
        layout.setSpacing(10)

        layout.addWidget(self.spinLabel1, 1, 0)
        layout.addWidget(self.SpinBox1, 1, 1)

        layout.addWidget(self.slider1, 2, 0, 2, 5)

        layout.addWidget(self.spinLabel2, 4, 0)
        layout.addWidget(self.SpinBox2, 4, 1)
        layout.addWidget(self.button2, 4, 4)

        layout.addWidget(self.spinLabel13, 4, 2)
        layout.addWidget(self.SpinBox13, 4, 3)

        layout.addWidget(self.spinLabel4, 6, 0)
        layout.addWidget(self.SpinBox4, 6, 1)
        layout.addWidget(self.button4, 6, 2)

        layout.addWidget(self.spinLabel6, 7, 0)
        layout.addWidget(self.SpinBox6, 7, 1)
        layout.addWidget(self.spinLabel7, 7, 2)
        layout.addWidget(self.SpinBox7, 7, 3)
        layout.addWidget(self.button5, 7, 4)

        layout.addWidget(self.ratioVolStartLabel, 8, 0)
        layout.addWidget(self.SpinBox11, 8, 1)
        layout.addWidget(self.ratioVolEndLabel, 8, 2)
        layout.addWidget(self.SpinBox12, 8, 3)

        layout.addWidget(self.volumeLabel, 9, 0)
        layout.addWidget(self.volumeText, 9, 1)

        layout.addWidget(self.currentVolumeLabel, 9, 2)
        layout.addWidget(self.currentVolumeText, 9, 3)

        layout.addWidget(self.shapeLabel, 10, 0)
        layout.addWidget(self.shapeText, 10, 1)

        layout.addWidget(self.spinLabel8, 11, 0)
        layout.addWidget(self.SpinBox8, 11, 1)
        layout.addWidget(self.button8, 11, 2)

        layout.addWidget(self.button15, 12, 0)

        layout.addWidget(self.dataTypeLabel, 13, 0)
        layout.addWidget(self.dataTypeText, 13, 1)
        layout.addWidget(self.dataTypeChangeLabel, 13, 2)
        layout.addWidget(self.dTypeSelectorBox, 13, 3)
        layout.addWidget(self.button7, 13, 4)

        layout.addWidget(self.button6, 15, 0)
        layout.addWidget(self.button1, 15, 4)
        layout.addWidget(self.button6, 15, 0)
        layout.addWidget(self.button1, 15, 4)
        layout.addWidget(self.button9, 16, 0)

        layout.addWidget(self.arraySavePathLabel, 16, 1, 1, 4)

        layout.addWidget(self.spinLabel9, 18, 0)
        layout.addWidget(self.SpinBox9, 18, 1)

        layout.addWidget(self.spinLabel10, 19, 0)
        layout.addWidget(self.SpinBox10, 19, 1)
        layout.addWidget(self.trim_last_frameLabel, 20, 0)
        layout.addWidget(self.trim_last_frame_checkbox, 20, 1)

        layout.addWidget(self.inputArrayLabel, 21, 0)
        layout.addWidget(self.inputArraySelectorBox, 21, 1)

        layout.addWidget(self.displayArrayLabel, 21, 2)
        layout.addWidget(self.displayArraySelectorBox, 21, 3)

        layout.addWidget(self.button12, 22, 0)
        layout.addWidget(self.button13, 22, 1)
        layout.addWidget(self.button14, 22, 2)

        layout.addWidget(self.fileNameLabel, 23, 0)
        layout.addWidget(self.fileNameText, 23, 1, 1, 4)

        self.setLayout(layout)
        self.setGeometry(self.left, self.top, self.width, self.height)

        #add window title
        self.setWindowTitle("Volume Slider GUI")

        #connect sliders & spinboxes
        self.slider1.valueChanged.connect(self.slider1ValueChange)
        self.SpinBox1.valueChanged.connect(self.spinBox1ValueChange)
        self.SpinBox9.valueChanged.connect(self.setTheta)
        self.SpinBox10.valueChanged.connect(self.setShiftFactor)

        #connect buttons
        self.button1.clicked.connect(self.autoLevel)
        self.button2.clicked.connect(self.updateVolumeValue)
        #self.button3.clicked.connect(self.averageByVol)
        self.button4.clicked.connect(self.subtractBaseline)
        self.button5.clicked.connect(self.ratioDFF0)
        self.button6.clicked.connect(self.exportToWindow)
        self.button7.clicked.connect(self.dTypeSelectionChange)
        self.button8.clicked.connect(self.multiplyByFactor)
        self.button9.clicked.connect(self.exportArray)
        self.button12.clicked.connect(self.startViewer)
        self.button13.clicked.connect(self.closeViewer)
        self.button14.clicked.connect(lambda: self.loadNewFile(''))
        self.button15.clicked.connect(self.setOverlay)

        return

    #volume changes with slider & spinbox
    def loadNewFile(self, fileName):
        if self.batch == False:
            fileName = QtWidgets.QFileDialog.getOpenFileName(
                self, 'Open File', os.path.expanduser("~/Desktop"),
                'tiff files (*.tif *.tiff)')
            fileName = str(fileName[0])

        A, _, _ = openTiff(fileName)
        self.viewer.updateVolumeSlider(A)
        self.viewer.displayWindow.imageview.setImage(A)
        self.setFileName(fileName)
        self.viewer.setFileName(fileName)
        return

    def slider1ValueChange(self, value):
        self.SpinBox1.setValue(value)
        return

    def spinBox1ValueChange(self, value):
        self.slider1.setValue(value)
        self.viewer.updateDisplay_sliceNumberChange(value)
        return

    def autoLevel(self):
        self.viewer.displayWindow.imageview.autoLevels()
        return

    def updateVolumeValue(self):
        self.slicesPerVolume = self.SpinBox2.value()
        noVols = int(self.viewer.getNFrames() / self.slicesPerVolume)
        self.framesToDelete = self.SpinBox13.value()
        self.viewer.updateVolsandFramesPerVol(
            noVols, self.slicesPerVolume, framesToDelete=self.framesToDelete)
        self.volumeText.setText(str(noVols))

        self.viewer.updateDisplay_volumeSizeChange()
        self.shapeText.setText(str(self.viewer.getArrayShape()))

        if (self.slicesPerVolume) % 2 == 0:
            self.SpinBox1.setRange(
                0, self.slicesPerVolume - 1 -
                self.framesToDelete)  #if even, display the last volume
            self.slider1.setMaximum(self.slicesPerVolume - 1 -
                                    self.framesToDelete)
        else:
            self.SpinBox1.setRange(
                0, self.slicesPerVolume - 2 -
                self.framesToDelete)  #else, don't display the last volume
            self.slider1.setMaximum(self.slicesPerVolume - 2 -
                                    self.framesToDelete)

        self.updateVolSpinBoxes()
        return

    def updateVolSpinBoxes(self):
        rangeValue = self.viewer.getNVols() - 1
        #self.SpinBox3.setRange(0,self.viewer.getNVols())
        self.SpinBox6.setRange(0, rangeValue)
        self.SpinBox7.setRange(0, rangeValue)
        self.SpinBox11.setRange(0, rangeValue)
        self.SpinBox12.setRange(0, rangeValue)
        self.SpinBox12.setValue(rangeValue)
        return

    def getBaseline(self):
        return self.SpinBox4.value()

    def getF0(self):
        return self.SpinBox6.value(), self.SpinBox7.value(
        ), self.SpinBox11.value(), self.SpinBox12.value()

    def subtractBaseline(self):
        self.viewer.subtractBaseline()
        return

    def ratioDFF0(self):
        self.viewer.ratioDFF0()
        return

    def exportToWindow(self):
        self.viewer.savePath = self.arraySavePath
        self.viewer.exportToWindow()
        return

    def dTypeSelectionChange(self):
        self.viewer.setDType(self.dTypeSelectorBox.currentText())
        self.dataTypeText = QtWidgets.QLabel(str(self.viewer.getDataType()))
        return

    def multiplyByFactor(self):
        self.viewer.multiplyByFactor(self.SpinBox8.value())
        return

    def exportArray(self):
        if self.viewer.B == []:
            print('first set number of frames per volume')
            g.m.statusBar().showMessage(
                "first set number of frames per volume")
            return
        self.arraySavePath = QtWidgets.QFileDialog.getSaveFileName(
            self, 'Save File', self.arraySavePath, 'Numpy array (*.npy)')
        self.arraySavePath = str(self.arraySavePath[0])
        self.viewer.savePath = self.arraySavePath
        self.arraySavePathLabel.setText(self.arraySavePath)
        self.viewer.exportArray()
        return

    def startViewer(self):
        self.saveSettings()
        self.viewer.startViewer()
        return

    def setOverlay(self):
        self.viewer.setOverlay()

    def closeViewer(self):
        self.viewer.closeViewer()
        return

    def setTheta(self):
        self.theta = self.SpinBox9.value()

    def setShiftFactor(self):
        self.shiftFactor = self.SpinBox10.value()

    def trim_last_frameClicked(self):
        self.trim_last_frame = self.trim_last_frame_checkbox.isChecked()

    def inputArraySelectionChange(self, value):
        self.viewer.setInputArrayOrder(
            self.inputArraySelectorBox.currentText())
        return

    def displayArraySelectionChange(self, value):
        self.viewer.setDisplayArrayOrder(
            self.displayArraySelectorBox.currentText())
        return

    def saveSettings(self):
        self.s['theta'] = self.theta
        self.s['slicesPerVolume'] = self.slicesPerVolume
        self.s['slicesDeletedPerVolume'] = self.slicesDeletedPerVolume
        self.s['baselineValue'] = self.baselineValue
        self.s['f0Start'] = self.f0Start
        self.s['f0End'] = self.f0End
        self.s['multiplicationFactor'] = self.multiplicationFactor
        self.s['currentDataType'] = self.currentDataType
        self.s['newDataType'] = self.newDataType
        self.s['shiftFactor'] = self.shiftFactor
        self.s['trimLastFrame'] = self.trim_last_frame
        self.s['f0VolStart'] = self.f0VolStart
        self.s['f0VolEnd'] = self.f0VolEnd

        g.settings['volumeSlider'] = self.s

        return

    def setFileName(self, fileName):
        self.fileName = fileName
        self.fileNameText.setText(self.fileName)

    def getFileName(self):
        return self.fileName

    def close(self):
        self.saveSettings()
        self.viewer.closeViewer()
        self.viewer.displayWindow.close()
        self.viewer.dialogbox.destroy()
        self.viewer.end()
        self.closeAllWindows()
        gc.collect()
        return

    def clearData(self):
        self.viewer.A = []
        self.viewer.B = []
Пример #7
0
class FFT_Chunker(BaseProcess_noPriorWindow):
    """
    fft chunk analysis
    ------------------
    
    input:      csv file with one or more time traces (columns) 
    
    variables:  chunk_size and time_step (s)
    
    analysis:   trace broken into chunks using chunk_size
                FFT analysis on each chunk using scipy.fft -> FFT_chunk
                power reported as abs(FFT_chunk)
                frequency calculated using scipy.fftfreq(chunk.size, time_step)
    
    output:     saves seperate results csv file for each trace in folder of input file 
                each results file has power and frequency results for every chunk (columns)
    """
    def __init__(self):
        if g.settings['fft_Chunker'] is None or 'closeplots' not in g.settings[
                'fft_Chunker']:
            s = dict()
            # s['timestep'] = 1
            # s['chunkSize'] = 128
            # s['plot'] = True

            s['chunkSize'] = 128
            s['timestep'] = 1
            s['numFrames'] = None
            s['numChunks'] = None
            s['baseline_start'] = 0
            s['baseline_stop'] = 2
            s['puff1_start'] = 0
            s['puff1_stop'] = 0
            s['puff2_start'] = 0
            s['puff2_stop'] = 0
            s['puff3_start'] = 0
            s['puff3_stop'] = 0
            s['puff4_start'] = 0
            s['puff4_stop'] = 0
            s['filepath'] = None
            s['run'] = None
            s['plot'] = True
            s['closeplots'] = None

            g.settings['fft_Chunker'] = s

        BaseProcess_noPriorWindow.__init__(self)


#chunkSize , timestep , numFrames, numChunks, blank2, blank3, baseline_start , baseline_stop, puff1_start ,puff1_stop, puff2_start, puff2_stop, puff3_start , puff3_stop, puff4_start , puff4_stop, filepath , run, plot, closeplots

    def __call__(self):
        '''
        reset saved parameters
        '''

        #currently not saving parameter changes on call - using updateParms()
        self.clearPlots()
        self.updateParams()
        return

    def updateParams(self):
        g.settings['fft_Chunker']['chunkSize'] = self.chunkSize_Box.value()
        g.settings['fft_Chunker']['timestep'] = self.timestep_Box.value()
        # g.settings['fft_Chunker']['baseline_start'] = baseline_start
        # g.settings['fft_Chunker']['baseline_stop'] = baseline_stop
        # g.settings['fft_Chunker']['puff1_start'] = puff1_start
        # g.settings['fft_Chunker']['puff1_stop'] = puff1_stop
        # g.settings['fft_Chunker']['puff2_start'] = puff2_start
        # g.settings['fft_Chunker']['puff2_stop'] = puff2_stop
        # g.settings['fft_Chunker']['puff3_start'] = puff3_start
        # g.settings['fft_Chunker']['puff3_stop'] = puff3_stop
        # g.settings['fft_Chunker']['puff4_start'] = puff4_start
        # g.settings['fft_Chunker']['puff4_stop'] = puff4_stop
        # g.settings['fft_Chunker']['filepath'] = filepath
        g.settings['fft_Chunker']['plot'] = self.plot_checkbox.isChecked()

        return

    def closeEvent(self, event):
        self.clearPlots()
        BaseProcess_noPriorWindow.closeEvent(self, event)
        return

    def gui(self):

        self.filename = ''

        self.gui_reset()
        s = g.settings['fft_Chunker']

        #buttons
        self.runAnalysis_button = QPushButton('Run Analysis')
        self.runAnalysis_button.pressed.connect(self.runAnalysis)
        self.setSavename_button = QPushButton('Set SaveName')
        self.setSavename_button.pressed.connect(self.setSavename)

        self.closePlots_button = QPushButton('Close plots')
        self.closePlots_button.pressed.connect(self.clearPlots)

        #checkbox
        self.plot_checkbox = CheckBox()
        self.plot_checkbox.setChecked(s['plot'])

        #label
        self.numFrames_label = QLabel()
        self.numFrames_label.setText('No file selected')
        self.numChunks_label = QLabel()
        self.numChunks_label.setText('No file selected')
        self.savename_label = QLabel()
        self.savename_label.setText('')
        #self.setExportFolder_button = FolderSelector('*.csv')

        #spinboxes
        #MEPPS
        self.chunkSize_Box = pg.SpinBox(int=True, step=1)
        self.chunkSize_Box.setMinimum(0)
        self.chunkSize_Box.setMaximum(1000000)
        self.chunkSize_Box.setValue(s['chunkSize'])

        self.timestep_Box = pg.SpinBox(int=False, step=0.01)
        self.timestep_Box.setMinimum(0)
        self.timestep_Box.setMaximum(1000000)
        self.timestep_Box.setValue(s['timestep'])

        self.baseline_start = pg.SpinBox(int=True, step=1)
        self.baseline_start.setMinimum(1)
        self.baseline_start.setMaximum(1000000)
        self.baseline_start.setValue(1)

        self.baseline_stop = pg.SpinBox(int=True, step=1)
        self.baseline_stop.setMinimum(0)
        self.baseline_stop.setMaximum(1000000)
        self.baseline_stop.setValue(0)

        self.puff1_start = pg.SpinBox(int=True, step=1)
        self.puff1_start.setMinimum(1)
        self.puff1_start.setMaximum(1000000)
        self.puff1_start.setValue(1)

        self.puff1_stop = pg.SpinBox(int=True, step=1)
        self.puff1_stop.setMinimum(0)
        self.puff1_stop.setMaximum(1000000)
        self.puff1_stop.setValue(0)

        self.puff2_start = pg.SpinBox(int=True, step=1)
        self.puff2_start.setMinimum(1)
        self.puff2_start.setMaximum(1000000)
        self.puff2_start.setValue(1)

        self.puff2_stop = pg.SpinBox(int=True, step=1)
        self.puff2_stop.setMinimum(0)
        self.puff2_stop.setMaximum(1000000)
        self.puff2_stop.setValue(0)

        self.puff3_start = pg.SpinBox(int=True, step=1)
        self.puff3_start.setMinimum(1)
        self.puff3_start.setMaximum(1000000)
        self.puff3_start.setValue(1)

        self.puff3_stop = pg.SpinBox(int=True, step=1)
        self.puff3_stop.setMinimum(0)
        self.puff3_stop.setMaximum(1000000)
        self.puff3_stop.setValue(0)

        self.puff4_start = pg.SpinBox(int=True, step=1)
        self.puff4_start.setMinimum(1)
        self.puff4_start.setMaximum(1000000)
        self.puff4_start.setValue(1)

        self.puff4_stop = pg.SpinBox(int=True, step=1)
        self.puff4_stop.setMinimum(0)
        self.puff4_stop.setMaximum(1000000)
        self.puff4_stop.setValue(0)

        #export file selector
        self.getFile = FileSelector()

        #connections
        self.chunkSize_Box.valueChanged.connect(self.chunkSizeUpdate)
        self.getFile.valueChanged.connect(self.loadData)

        #################################################################
        #self.exportFolder = FolderSelector('*.txt')
        #MEPPS
        self.items.append({
            'name': 'blank1 ',
            'string': '-------------   Parameters    ---------------',
            'object': None
        })
        self.items.append({
            'name': 'chunksize ',
            'string': 'Set chunk size ',
            'object': self.chunkSize_Box
        })
        self.items.append({
            'name': 'timestep ',
            'string': 'Set timestep: ',
            'object': self.timestep_Box
        })
        self.items.append({
            'name': 'numFrames',
            'string': 'Number of frames in trace: ',
            'object': self.numFrames_label
        })
        self.items.append({
            'name': 'numChunks',
            'string': 'Number of chunks: ',
            'object': self.numChunks_label
        })
        self.items.append({
            'name': 'blank2 ',
            'string': '-------------    Averaging     ---------------',
            'object': None
        })
        self.items.append({
            'name': 'blank3 ',
            'string': '--  If  stop = 0 the group will be ignored  --',
            'object': None
        })
        self.items.append({
            'name': 'baseline_start ',
            'string': 'Baseline start: ',
            'object': self.baseline_start
        })
        self.items.append({
            'name': 'baseline_stop',
            'string': 'Baseline stop: ',
            'object': self.baseline_stop
        })
        self.items.append({
            'name': 'puff1_start ',
            'string': 'Puff Range 1 start: ',
            'object': self.puff1_start
        })
        self.items.append({
            'name': 'puff1_stop',
            'string': 'Puff Range 1 stop: ',
            'object': self.puff1_stop
        })
        self.items.append({
            'name': 'puff2_start ',
            'string': 'Puff Range 2 start: ',
            'object': self.puff2_start
        })
        self.items.append({
            'name': 'puff2_stop',
            'string': 'Puff Range 2 stop: ',
            'object': self.puff2_stop
        })
        self.items.append({
            'name': 'puff3_start ',
            'string': 'Puff Range 3 start: ',
            'object': self.puff3_start
        })
        self.items.append({
            'name': 'puff3_stop',
            'string': 'Puff Range 3 stop: ',
            'object': self.puff3_stop
        })
        self.items.append({
            'name': 'puff4_start ',
            'string': 'Puff Range 4 start: ',
            'object': self.puff4_start
        })
        self.items.append({
            'name': 'puff4_stop',
            'string': 'Puff Range 4 stop: ',
            'object': self.puff4_stop
        })
        self.items.append({
            'name': 'blank ',
            'string': '-------------------------------------------',
            'object': None
        })
        self.items.append({
            'name': 'filepath ',
            'string': '',
            'object': self.getFile
        })
        self.items.append({
            'name': 'plot',
            'string': 'Plot results',
            'object': self.plot_checkbox
        })
        self.items.append({
            'name': 'saveName_label',
            'string': 'Save Name (if blank, input filename used): ',
            'object': self.savename_label
        })
        self.items.append({
            'name': 'saveName',
            'string': '',
            'object': self.setSavename_button
        })
        #self.items.append({'name': 'setPath ', 'string': '', 'object': self.setExportFolder_button })
        self.items.append({
            'name': 'run',
            'string': '',
            'object': self.runAnalysis_button
        })
        self.items.append({
            'name': 'closeplots',
            'string': '',
            'object': self.closePlots_button
        })

        super().gui()
        ######################################################################
        return

    def chunkSizeUpdate(self):
        if self.filename == '':
            return

        else:
            self.numChunks = float(self.nFrames / self.chunkSize_Box.value())
            self.numChunks_label.setText(str(self.numChunks))
            maxChunks = int(self.numChunks) + 1
            self.baseline_start.setMaximum(maxChunks)
            self.baseline_stop.setMaximum(maxChunks)
            self.puff1_start.setMaximum(maxChunks)
            self.puff1_stop.setMaximum(maxChunks)
            self.puff2_start.setMaximum(maxChunks)
            self.puff2_stop.setMaximum(maxChunks)
            self.puff3_start.setMaximum(maxChunks)
            self.puff3_stop.setMaximum(maxChunks)
            self.puff4_start.setMaximum(maxChunks)
            self.puff4_stop.setMaximum(maxChunks)

        return

    def frameLengthUpdate(self):
        if self.filename == '':
            return
        else:
            self.nFrames = len(self.data[0].values)
            self.numFrames_label.setText(str(self.nFrames))
            self.chunkSizeUpdate()
        return

    def loadData(self):
        self.filename = self.getFile.value()
        self.data = pd.read_csv(self.filename,
                                header=None,
                                skiprows=1,
                                index_col=0)

        #drop extra x columns
        self.data = self.data[self.data.columns[::2]]
        #drop columns with na values
        self.data = self.data.dropna(axis=1, how='all')
        #set column names by number
        nCols = len(self.data.columns)
        colNames = list(range(0, nCols))
        self.data.columns = colNames
        #update
        self.frameLengthUpdate()

        print('-------------------------------------')
        print('Data loaded (first 5 rows displayed):')
        print(self.data.head())
        print('-------------------------------------')

    def setSavename(self):

        text, ok = QInputDialog.getText(None, 'SaveName Dialog',
                                        'Enter save name:')

        if ok:

            fft_Chunker.savename_label.setText(str(text))
        return

    def plotData(self):
        ### plot test result
        result_data = self.result_dict[0]  # just results for 1st trace
        numChunks = int(len(list(result_data.keys())) / 3)
        if numChunks > 40:
            g.alert(
                'More than 40 plots would be generated - aborting plotting')
            return

        for i in range(1, numChunks + 1):
            print('Plotting chunk {}'.format(str(i)))
            plt.figure(i)
            plt.subplot(211)
            plt.plot(result_data['chunk_{}'.format(str(i))])
            plt.xlabel("frame")
            plt.ylabel("DF/F0")
            plt.ylim(ymin=self.minTime, ymax=self.maxTime)

            plt.subplot(212)
            x = result_data['frequency_{}'.format(str(i))]
            y = result_data['power_{}'.format(str(i))]

            plt.scatter(x, y, s=8, c='blue')
            #plt.plot(result_data['frequency_{}'.format(str(i))],result_data['power_{}'.format(str(i))])
            plt.title("FFT analysis - chunk {}".format(str(i)))
            plt.xlabel("frequency")
            plt.ylabel("power")

            #add average line
            #y_mean = [np.mean(y)]*len(x)
            #plt.plot(x,y_mean, label='Mean', color='red')

            #plt.xscale('log')
            plt.yscale('log')
            #plt.xlim(xmin= 0.0001, xmax=self.X_max)
            plt.ylim(ymin=self.Y_min, ymax=self.Y_max)

            plt.show()

        return

    def plotAverages(self):
        #plot averaged chunks
        self.fig, (ax1, ax2, ax3, ax4, ax5) = plt.subplots(1,
                                                           5,
                                                           sharex=True,
                                                           sharey=True)
        self.fig.suptitle('Averaged chunks')
        ax1.semilogy(self.baseline_FreqAverage, self.baseline_PowerAverage)
        ax2.semilogy(self.puff1_FreqAverage, self.puff1_PowerAverage)
        ax3.semilogy(self.puff2_FreqAverage, self.puff2_PowerAverage)
        ax4.semilogy(self.puff3_FreqAverage, self.puff3_PowerAverage)
        ax5.semilogy(self.puff4_FreqAverage, self.puff4_PowerAverage)

        ax1.set_title('Baseline')
        ax2.set_title('Puff group 1')
        ax3.set_title('Puff group 2')
        ax4.set_title('Puff group 3')
        ax5.set_title('Puff group 4')

        plt.show()
        return

    def clearPlots(self):
        try:
            plt.close('all')
        except:
            pass
        return

    def makeAverage(self):
        self.averageResults_dict = {}

        for key in self.result_dict:
            result_data = self.result_dict[key]

            self.baseline_PowerAverage = []
            self.puff1_PowerAverage = []
            self.puff2_PowerAverage = []
            self.puff3_PowerAverage = []
            self.puff4_PowerAverage = []
            self.baseline_FreqAverage = []
            self.puff1_FreqAverage = []
            self.puff2_FreqAverage = []
            self.puff3_FreqAverage = []
            self.puff4_FreqAverage = []

            self.average_dict = {}

            def getAverage(start, end):
                powerList = []
                frequencyList = []

                print('Averaging Group {} - {}'.format(start, end))

                for i in range(start, end):
                    print('power_{}'.format(str(i)), )
                    #print(result_data['power_{}'.format(str(i))])
                    print('frequency_{}'.format(str(i)), )
                    #print(result_data['frequency_{}'.format(str(i))])
                    powerList.append(result_data['power_{}'.format(str(i))])
                    frequencyList.append(result_data['frequency_{}'.format(
                        str(i))])
                power = np.mean(powerList, axis=0)
                frequency = np.mean(frequencyList, axis=0)
                print('power mean'.format(str(i)), )
                print(power)
                print('log10 power mean'.format(str(i)), )
                print(np.log10(power))
                print('frequency mean'.format(str(i)), )
                print(frequency)
                print('log10 frequency mean'.format(str(i)), )
                print(np.log10(frequency))
                print('------------')
                return power, frequency

            base_start = self.baseline_start.value()
            base_stop = self.baseline_stop.value()
            puff1_start = self.puff1_start.value()
            puff1_stop = self.puff1_stop.value()
            puff2_start = self.puff2_start.value()
            puff2_stop = self.puff2_stop.value()
            puff3_start = self.puff3_start.value()
            puff3_stop = self.puff3_stop.value()
            puff4_start = self.puff4_start.value()
            puff4_stop = self.puff4_stop.value()

            #get average group settings
            if base_stop > 0 and base_stop >= base_start:
                self.baseline_PowerAverage, self.baseline_FreqAverage = getAverage(
                    base_start, base_stop)
                self.average_dict.update({
                    'baseline_PowerAverage':
                    self.baseline_PowerAverage,
                    'baseline_FreqAverage':
                    self.baseline_FreqAverage
                })

            if puff1_stop > 0 and puff1_stop >= puff1_start:
                self.puff1_PowerAverage, self.puff1_FreqAverage = getAverage(
                    puff1_start, puff1_stop)
                self.average_dict.update({
                    'puff1_PowerAverage':
                    self.puff1_PowerAverage,
                    'puff1_FreqAverage':
                    self.puff1_FreqAverage
                })

            if puff2_stop > 0 and puff2_stop >= puff2_start:
                self.puff2_PowerAverage, self.puff2_FreqAverage = getAverage(
                    puff2_start, puff2_stop)
                self.average_dict.update({
                    'puff2_PowerAverage':
                    self.puff2_PowerAverage,
                    'puff2_FreqAverage':
                    self.puff2_FreqAverage
                })

            if puff3_stop > 0 and puff3_stop >= puff3_start:
                self.puff3_PowerAverage, self.puff3_FreqAverage = getAverage(
                    puff3_start, puff3_stop)
                self.average_dict.update({
                    'puff3_PowerAverage':
                    self.puff3_PowerAverage,
                    'puff3_FreqAverage':
                    self.puff3_FreqAverage
                })

            if puff4_stop > 0 and puff4_stop >= puff4_start:
                self.puff4_PowerAverage, self.puff4_FreqAverage = getAverage(
                    puff4_start, puff4_stop)
                self.average_dict.update({
                    'puff4_PowerAverage':
                    self.puff4_PowerAverage,
                    'puff4_FreqAverage':
                    self.puff4_FreqAverage
                })

        self.averageResults_dict.update(
            {'AverageResult_{}'.format(str(key)): self.average_dict})
        return

    def exportAverage(self):
        for key in self.averageResults_dict:
            self.average_DF = pd.DataFrame.from_dict(
                data=self.averageResults_dict[key])
            savePath = os.path.dirname(self.filename)
            if self.savename_label.text() == '':
                saveName = os.path.join(
                    savePath, 'FFT_Chunker_Batch_{}_{}.csv'.format(
                        self.timeStr, str(key)))
            else:
                saveName = os.path.join(
                    savePath, '{}_{}.csv'.format(self.savename_label.text(),
                                                 str(key)))
            #self.average_DF.to_csv(saveName)

            #take logs
            logDF = pd.DataFrame(np.log10(self.average_DF),
                                 index=self.average_DF.index,
                                 columns=self.average_DF.columns)
            logDF.to_csv(saveName)
            print('average file saved')
        return

    def exportResult(self):
        savePath = os.path.dirname(self.filename)
        toAverage = []

        for key in self.result_dict:
            if self.savename_label.text() == '':
                saveName = os.path.join(
                    savePath, 'FFT_Chunker_Batch_{}_Trace_{}.csv'.format(
                        self.timeStr, str(key)))
            else:
                saveName = os.path.join(
                    savePath,
                    '{}_Trace_{}.csv'.format(self.savename_label.text(),
                                             str(key)))

            #self.result_dict[key].to_csv(saveName)

            #takeLogs
            logDF = pd.DataFrame(np.log10(self.result_dict[key]),
                                 index=self.result_dict[key].index,
                                 columns=self.result_dict[key].columns)
            logDF.to_csv(saveName)

            print('File {} saved'.format(saveName))
            g.m.statusBar().showMessage('File {} saved'.format(saveName))
            toAverage.append(self.result_dict[key])

        #if multiple ROI traces - take average of results and export as seperate file
        if len(self.result_dict) > 1:
            if self.savename_label.text() == '':
                saveName = os.path.join(
                    savePath, 'FFT_Chunker_Batch_{}_AveragedTraces.csv'.format(
                        self.timeStr))
            else:
                saveName = os.path.join(
                    savePath,
                    '{}_AveragedTraces.csv'.format(self.savename_label.text()))

            averagedDF = pd.concat(toAverage).groupby(level=0).mean()

            #remove extraneous columns for Ian
            freqCols = [c for c in averagedDF.columns if 'frequency' in c]
            powerCols = [c for c in averagedDF.columns if 'power' in c]
            #chunkCols = [c for c in averagedDF.columns  if 'chunk' in c]

            cols = [freqCols[0]] + powerCols

            averagedDF = averagedDF[cols]

            #take logs
            #logsDF = averagedDF.applymap(math.log10)
            logsDF = pd.DataFrame(np.log10(averagedDF),
                                  index=averagedDF.index,
                                  columns=averagedDF.columns)

            #print averaged traces df
            print('-----------------------------------------------')
            print('Averaged Traces DF')
            print(logsDF.head())
            print('-----------------------------------------------')
            logsDF.to_csv(saveName)
            print('Averaged ROI File {} saved'.format(saveName))
            g.m.statusBar().showMessage(
                'Averaged ROI File {} saved'.format(saveName))
        return

    def runAnalysis(self):
        chunk_size = self.chunkSize_Box.value()
        timestep = self.timestep_Box.value()
        self.timeStr = time.strftime("%Y%m%d-%H%M%S")

        if self.filename == '':
            print('File not loaded!')
            g.m.statusBar().showMessage('File not loaded!')
            return
        else:
            self.clearPlots()

            #import trace/traces
            columns = list(self.data)

            #initiate result dict (for multiple traces)
            self.result_dict = {}

            #fft analysis
            for i in columns:
                # analyse each column
                result, self.X_min, self.X_max, self.Y_min, self.Y_max, self.minTime, self.maxTime = (
                    fft_chunks(self.data[i].values, chunk_size, timestep))

                # add to self.result_dict
                self.result_dict.update({i: result})
                print('Trace {} analysed, {} chunks processed'.format(
                    str(i), str((len(self.data[i].values) / chunk_size))))

            #export results
            self.exportResult()

            #generate averages for groups
            self.makeAverage()
            self.exportAverage()

            #plots
            if self.plot_checkbox.isChecked():
                self.plotData()
                self.plotAverages()
Пример #8
0
class RoiExtras(BaseProcess_noPriorWindow):
    """
    Extends ROI menu features
    """
    def __init__(self):
        BaseProcess_noPriorWindow.__init__(self)

        self.currentWin = None
        self.currentROI = None
        self.displayStarted = False
        self.data = None
        self.img = None

        self.startScale = -3
        self.endScale = 50
        self.n = 50

        self.frame = 0
        self.ROIwindowExists = False
        self.ROI_ID = 0

    def __call__(self):
        '''
        
        '''
        self.closeAction()
        return

    def closeAction(self):
        self.currentWin = None
        self.currentROI = None
        self.displayStarted = False
        self.data = None
        self.img = None
        self.ROIwindowExists = False
        try:
            self.currentROI.sigRegionChanged.disconnect()
        except:
            pass
        try:
            self.currentWin.sigTimeChanged.disconnect()
        except:
            pass
        try:
            self.ROIwindow.close()
        except:
            pass

        try:
            self.histoWindow.close()
        except:
            pass

    def closeEvent(self, event):
        self.closeAction()
        #BaseProcess_noPriorWindow.closeEvent(self, event)
        event.accept()

    def gui(self):
        self.gui_reset()
        self.active_window = WindowSelector()

        self.startButton = QPushButton('Start')
        self.startButton.pressed.connect(self.start)

        self.autoscaleX = CheckBox()
        self.autoscaleY = CheckBox()

        self.autoscaleX.setChecked(True)
        self.autoscaleY.setChecked(True)

        self.autoscaleX.stateChanged.connect(self.updateX)
        self.autoscaleY.stateChanged.connect(self.updateY)

        self.items.append({
            'name': 'active_window',
            'string': 'Select Window',
            'object': self.active_window
        })
        self.items.append({
            'name': 'autoScaleX',
            'string': 'Autoscale Histogram X-axis',
            'object': self.autoscaleX
        })
        self.items.append({
            'name': 'autoScaleY',
            'string': 'Autoscale Histogram Y-axis',
            'object': self.autoscaleY
        })
        self.items.append({
            'name': 'start_button',
            'string': 'Click to select current ROI',
            'object': self.startButton
        })

        super().gui()

    def start(self):
        #select window
        self.currentWin = self.getValue('active_window')
        if self.currentWin == None:
            g.alert('First select window')
            return

        #disconnect previous ROI (if exists)
        try:
            self.currentROI.sigRegionChanged.disconnect()
        except:
            pass

        #disconnect previous time update (if exists)
        try:
            self.currentWin.sigTimeChanged.disconnect(self.update)
        except:
            pass

        try:
            self.ROIwindow.close()
        except:
            pass

        try:
            self.histoWindow.close()
        except:
            pass

        #select current ROI
        self.currentROI = self.currentWin.currentROI

        if self.currentWin.currentROI == None:
            g.alert('First draw an ROI')
            return

        #set updates
        self.currentROI.sigRegionChanged.connect(self.update)
        self.currentWin.sigTimeChanged.connect(self.update)
        self.currentWin.imageview.scene.sigMouseClicked.connect(self.update)

        #start plotting
        self.startPlot()
        self.displayStarted = True

        #get stack data
        self.data = np.array(deepcopy(self.currentWin.image))

        #get histo range from whole stack
        self.startScale = np.min(self.data)
        self.endScale = np.max(self.data)

        self.update()

    def update(self):
        if self.currentROI != self.currentWin.currentROI:
            self.currentROI = self.currentWin.currentROI
            self.currentROI.sigRegionChanged.connect(self.update)
            self.currentROI.sigClicked.connect(self.update)

        #get frame index
        self.frame = self.currentWin.currentIndex
        #get roi region
        self.selected = self.currentROI.getArrayRegion(
            self.data[self.frame], self.currentWin.imageview.getImageItem())
        #print(self.selected)

        #get roi mask (needed for freehand roi which returns square array)
        mask = self.currentROI.getMask()
        #reset indices to cropped roi
        mask_norm = (mask[0] - min(mask[0]), mask[1] - min(mask[1]))
        #invert mask
        invertMask = np.ones_like(self.selected, dtype=bool)
        invertMask[mask_norm] = False
        #select region within roi boundary
        self.selected[invertMask] = 0  #using 0 for now, np.nan is slow

        #count number of pixels
        n_pixels = (self.selected > 0).sum()

        #update plot
        self.histoWindow.update(self.selected,
                                start=self.startScale,
                                end=self.endScale,
                                n=self.n,
                                n_pixels=n_pixels)
        #update roi window
        try:
            self.ROIwindow.imageview.setImage(self.selected)
        except:
            self.ROIwindow = Window(self.selected, name='ROI')
            self.ROIwindowExists = True

    def updateX(self):
        try:
            self.histoWindow.autoscaleX = self.autoscaleX.isChecked()
        except:
            pass

    def updateY(self):
        try:
            self.histoWindow.autoscaleY = self.autoscaleY.isChecked()
        except:
            pass

    def startPlot(self):
        self.histoWindow = HistoWindow()
        self.histoWindow.show()
class Form2(QtWidgets.QDialog):
    def __init__(self, parent = None):
        super(Form2, self).__init__(parent)

        self.arraySavePath = camVolumeSlider.savePath
        self.arrayImportPath = "None"

        #window geometry
        self.left = 300
        self.top = 300
        self.width = 600
        self.height = 400

        self.theta = 45
        self.shiftFactor = 1
        self.trim_last_frame = False

        #spinboxes
        self.spinLabel1 = QtWidgets.QLabel("Slice #")
        self.SpinBox1 = QtWidgets.QSpinBox()
        self.SpinBox1.setRange(0,camVolumeSlider.getNFrames())
        self.SpinBox1.setValue(0)

        self.spinLabel2 = QtWidgets.QLabel("# of slices per volume: ")
        self.SpinBox2 = QtWidgets.QSpinBox()
        self.SpinBox2.setRange(0,camVolumeSlider.getNFrames())
        self.SpinBox2.setValue(camVolumeSlider.getNFrames())

        self.spinLabel4 = QtWidgets.QLabel("baseline value: ")
        self.SpinBox4 = QtWidgets.QSpinBox()
        self.SpinBox4.setRange(0,camVolumeSlider.getMaxPixel())
        self.SpinBox4.setValue(0)

        self.spinLabel6 = QtWidgets.QLabel("F0 start volume: ")
        self.SpinBox6 = QtWidgets.QSpinBox()
        self.SpinBox6.setRange(0,camVolumeSlider.getNVols())
        self.SpinBox6.setValue(0)

        self.spinLabel7 = QtWidgets.QLabel("F0 end volume: ")
        self.SpinBox7 = QtWidgets.QSpinBox()
        self.SpinBox7.setRange(0,camVolumeSlider.getNVols())
        self.SpinBox7.setValue(0)

        self.spinLabel8 = QtWidgets.QLabel("factor to multiply by: ")
        self.SpinBox8 = QtWidgets.QSpinBox()
        self.SpinBox8.setRange(0,10000)
        self.SpinBox8.setValue(100)

        self.spinLabel9 = QtWidgets.QLabel("theta: ")
        self.SpinBox9 = QtWidgets.QSpinBox()
        self.SpinBox9.setRange(0,360)
        self.SpinBox9.setValue(self.theta)

        self.spinLabel10 = QtWidgets.QLabel("shift factor: ")
        self.SpinBox10 = QtWidgets.QSpinBox()
        self.SpinBox10.setRange(0,100)
        self.SpinBox10.setValue(self.shiftFactor)


        #sliders
        self.slider1 = QtWidgets.QSlider(QtCore.Qt.Horizontal)
        self.slider1.setFocusPolicy(QtCore.Qt.StrongFocus)
        self.slider1.setTickPosition(QtWidgets.QSlider.TicksBothSides)
        self.slider1.setMinimum(0)
        self.slider1.setMaximum(camVolumeSlider.getNFrames())
        self.slider1.setTickInterval(1)
        self.slider1.setSingleStep(1)

        #ComboBox
        self.dTypeSelectorBox = QtWidgets.QComboBox()
        self.dTypeSelectorBox.addItems(["float16", "float32", "float64","int8","int16","int32","int64"])
        self.inputArraySelectorBox = QtWidgets.QComboBox()
        self.inputArraySelectorBox.addItems(camVolumeSlider.getArrayKeys())
        self.inputArraySelectorBox.setCurrentIndex(4)
        self.inputArraySelectorBox.currentIndexChanged.connect(self.inputArraySelectionChange)

        self.displayArraySelectorBox = QtWidgets.QComboBox()
        self.displayArraySelectorBox.addItems(camVolumeSlider.getArrayKeys())
        self.displayArraySelectorBox.setCurrentIndex(18)
        self.displayArraySelectorBox.currentIndexChanged.connect(self.displayArraySelectionChange)

        #buttons
        self.button1 = QtWidgets.QPushButton("Autolevel")
        self.button2 = QtWidgets.QPushButton("Set Slices")
        #self.button3 = QtWidgets.QPushButton("Average Volumes")
        self.button4 = QtWidgets.QPushButton("subtract baseline")
        self.button5 = QtWidgets.QPushButton("run DF/F0")
        self.button6 = QtWidgets.QPushButton("export to Window")
        self.button7 = QtWidgets.QPushButton("set data Type")
        self.button8 = QtWidgets.QPushButton("multiply")
        self.button9 = QtWidgets.QPushButton("export to array")        

        self.button12 = QtWidgets.QPushButton("open 3D viewer")
        self.button13 = QtWidgets.QPushButton("close 3D viewer")

        #labels
        self.volumeLabel = QtWidgets.QLabel("# of volumes: ")
        self.volumeText = QtWidgets.QLabel("  ")

        self.shapeLabel = QtWidgets.QLabel("array shape: ")
        self.shapeText = QtWidgets.QLabel(str(camVolumeSlider.getArrayShape()))

        self.dataTypeLabel = QtWidgets.QLabel("current data type: ")
        self.dataTypeText = QtWidgets.QLabel(str(camVolumeSlider.getDataType()))
        self.dataTypeChangeLabel = QtWidgets.QLabel("new data type: ")

        self.inputArrayLabel = QtWidgets.QLabel("input array order: ")
        self.displayArrayLabel = QtWidgets.QLabel("display array order: ")

        self.arraySavePathLabel = QtWidgets.QLabel(str(self.arraySavePath))

        self.trim_last_frameLabel = QtWidgets.QLabel("Trim Last Frame: ")
        self.trim_last_frame_checkbox = CheckBox()
        self.trim_last_frame_checkbox.setChecked(self.trim_last_frame)
        self.trim_last_frame_checkbox.stateChanged.connect(self.trim_last_frameClicked)


        #grid layout
        layout = QtWidgets.QGridLayout()
        layout.setSpacing(10)

        layout.addWidget(self.spinLabel1, 1, 0)
        layout.addWidget(self.SpinBox1, 1, 1)

        layout.addWidget(self.slider1, 2, 0, 2, 5)

        layout.addWidget(self.spinLabel2, 4, 0)
        layout.addWidget(self.SpinBox2, 4, 1)
        layout.addWidget(self.button2, 4, 2)

        layout.addWidget(self.spinLabel4, 6, 0)
        layout.addWidget(self.SpinBox4, 6, 1)
        layout.addWidget(self.button4, 6, 2)

        layout.addWidget(self.spinLabel6, 7, 0)
        layout.addWidget(self.SpinBox6, 7, 1)
        layout.addWidget(self.spinLabel7, 7, 2)
        layout.addWidget(self.SpinBox7, 7, 3)
        layout.addWidget(self.button5, 7, 4)

        layout.addWidget(self.volumeLabel, 8, 0)
        layout.addWidget(self.volumeText, 8, 1)
        layout.addWidget(self.shapeLabel, 9, 0)
        layout.addWidget(self.shapeText, 9, 1)

        layout.addWidget(self.spinLabel8, 10, 0)
        layout.addWidget(self.SpinBox8, 10, 1)
        layout.addWidget(self.button8, 10, 2)

        layout.addWidget(self.dataTypeLabel, 11, 0)
        layout.addWidget(self.dataTypeText, 11, 1)
        layout.addWidget(self.dataTypeChangeLabel, 11, 2)
        layout.addWidget(self.dTypeSelectorBox, 11,3)
        layout.addWidget(self.button7, 11, 4)

        layout.addWidget(self.button6, 13, 0)
        layout.addWidget(self.button1, 13, 4)
        layout.addWidget(self.button6, 13, 0)
        layout.addWidget(self.button1, 13, 4)
        layout.addWidget(self.button9, 14, 0)
        layout.addWidget(self.arraySavePathLabel, 14, 1, 1, 4)      
        
        
        layout.addWidget(self.spinLabel9, 16, 0)
        layout.addWidget(self.SpinBox9, 16, 1)

        layout.addWidget(self.spinLabel10, 17, 0)
        layout.addWidget(self.SpinBox10, 17, 1)
        layout.addWidget(self.trim_last_frameLabel, 18, 0)
        layout.addWidget(self.trim_last_frame_checkbox, 18, 1)

        layout.addWidget(self.inputArrayLabel, 19, 0)
        layout.addWidget(self.inputArraySelectorBox, 19, 1)

        layout.addWidget(self.displayArrayLabel, 19, 2)
        layout.addWidget(self.displayArraySelectorBox, 19, 3)

        layout.addWidget(self.button12, 20, 0)
        layout.addWidget(self.button13, 20, 1)


        self.setLayout(layout)
        self.setGeometry(self.left, self.top, self.width, self.height)

        #add window title
        self.setWindowTitle("Volume Slider GUI")

        #connect sliders & spinboxes
        self.slider1.valueChanged.connect(self.slider1ValueChange)
        self.SpinBox1.valueChanged.connect(self.spinBox1ValueChange)
        self.SpinBox9.valueChanged.connect(self.setTheta)
        self.SpinBox10.valueChanged.connect(self.setShiftFactor)

        #connect buttons
        self.button1.clicked.connect(self.autoLevel)
        self.button2.clicked.connect(self.updateVolumeValue)
        #self.button3.clicked.connect(self.averageByVol)
        self.button4.clicked.connect(self.subtractBaseline)
        self.button5.clicked.connect(self.ratioDFF0)
        self.button6.clicked.connect(self.exportToWindow)
        self.button7.clicked.connect(self.dTypeSelectionChange)
        self.button8.clicked.connect(self.multiplyByFactor)
        self.button9.clicked.connect(self.exportArray)            
        self.button12.clicked.connect(self.startViewer)
        self.button13.clicked.connect(self.closeViewer)

        return

     #volume changes with slider & spinbox
    def slider1ValueChange(self, value):
        self.SpinBox1.setValue(value)
        return

    def spinBox1ValueChange(self, value):
        self.slider1.setValue(value)
        camVolumeSlider.updateDisplay_sliceNumberChange(value)
        return

    def autoLevel(self):
        camVolumeSlider.displayWindow.imageview.autoLevels()
        return

    def updateVolumeValue(self):
        value = self.SpinBox2.value()
        noVols = int(camVolumeSlider.getNFrames()/value)
        camVolumeSlider.updateVolsandFramesPerVol(noVols, value)
        self.volumeText.setText(str(noVols))

        camVolumeSlider.updateDisplay_volumeSizeChange()
        self.shapeText.setText(str(camVolumeSlider.getArrayShape()))

        if (value)%2 == 0:
            self.SpinBox1.setRange(0,value-1) #if even, display the last volume
            self.slider1.setMaximum(value-1)
        else:
            self.SpinBox1.setRange(0,value-2) #else, don't display the last volume
            self.slider1.setMaximum(value-2)

        self.updateVolSpinBoxes()
        return

    def updateVolSpinBoxes(self):
        #self.SpinBox3.setRange(0,camVolumeSlider.getNVols())

        self.SpinBox6.setRange(0,camVolumeSlider.getNVols())
        self.SpinBox7.setRange(0,camVolumeSlider.getNVols())
        return

    def getBaseline(self):
        return self.SpinBox4.value()

    def getF0(self):
        return self.SpinBox6.value(), self.SpinBox7.value()

    def subtractBaseline(self):
        camVolumeSlider.subtractBaseline()
        return

    def ratioDFF0(self):
        camVolumeSlider.ratioDFF0()
        return

    def exportToWindow(self):
        camVolumeSlider.savePath = self.arraySavePath
        camVolumeSlider.exportToWindow()
        return

    def dTypeSelectionChange(self):
        camVolumeSlider.setDType(self.dTypeSelectorBox.currentText())
        self.dataTypeText = QtWidgets.QLabel(str(camVolumeSlider.getDataType()))
        return

    def multiplyByFactor(self):
        camVolumeSlider.multiplyByFactor(self.SpinBox8.value())
        return

    def exportArray(self):
        self.arraySavePath = QtWidgets.QFileDialog.getSaveFileName(self, 'Save File', self.arraySavePath, 'Numpy array (*.npy)')
        self.arraySavePath = str(self.arraySavePath[0])
        camVolumeSlider.savePath = self.arraySavePath
        self.arraySavePathLabel.setText(self.arraySavePath)
        camVolumeSlider.exportArray()
        return

    def startViewer(self):
        camVolumeSlider.startViewer()
        return

    def closeViewer(self):
        camVolumeSlider.closeViewer()
        return

    def setTheta(self):
        self.theta = self.SpinBox9.value()

    def setShiftFactor(self):
        self.shiftFactor = self.SpinBox10.value()

    def trim_last_frameClicked(self):
        self.trim_last_frame = self.trim_last_frame_checkbox.isChecked()

    def inputArraySelectionChange(self, value):
        camVolumeSlider.setInputArrayOrder(self.inputArraySelectorBox.currentText())
        return

    def displayArraySelectionChange(self, value):
        camVolumeSlider.setDisplayArrayOrder(self.displayArraySelectorBox.currentText())
        return

    def close(self):
        camVolumeSlider.closeViewer()
        camVolumeSlider.displayWindow.close()
        camVolumeSlider.dialogbox.destroy()
        camVolumeSlider.end()
        self.closeAllWindows()
        return