Example #1
0
class widgets_sample(object):
    def __init__(self):

        self.fig, ax = plt.subplots()
        plt.subplots_adjust(left=0.25, bottom=0.25)
        self.t = np.arange(0.0, 1.0, 0.001)
        a0 = 5
        f0 = 3
        s = a0 * np.sin(2 * np.pi * f0 * self.t)
        self.l, = plt.plot(self.t, s, lw=2, color='red')
        plt.axis([0, 1, -10, 10])

        axcolor = 'lightgoldenrodyellow'
        axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], facecolor=axcolor)
        axamp = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=axcolor)

        self.sfreq = Slider(axfreq, 'Freq', 0.1, 30.0, valinit=f0)
        self.samp = Slider(axamp, 'Amp', 0.1, 10.0, valinit=a0)
        self.sfreq.on_changed(self.update)
        self.samp.on_changed(self.update)

        resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
        self.button = Button(resetax,
                             'Reset',
                             color=axcolor,
                             hovercolor='0.975')
        self.button.on_clicked(self.reset)

        rax = plt.axes([0.025, 0.5, 0.15, 0.15], facecolor=axcolor)
        self.radio = RadioButtons(rax,
                                  ('red', 'blue', 'green', 'orange', 'gray'),
                                  active=0)
        self.radio.on_clicked(self.colorfunc)

        plt.show()

    def update(self, val):
        amp = self.samp.val
        freq = self.sfreq.val
        self.l.set_ydata(amp * np.sin(2 * np.pi * freq * self.t))
        self.fig.canvas.draw_idle()

    def reset(self, event):
        self.sfreq.reset()
        self.samp.reset()

    def colorfunc(self, label):
        self.l.set_color(label)
        self.fig.canvas.draw_idle()
class WaveCal_st():
    def __init__(self,
                 ObsFilename=None,
                 ModelFilename=None,
                 wave_min=None,
                 wave_max=None,
                 cull=50,
                 am=1.0,
                 H2O_scale=1.0,
                 CO_scale=1.0,
                 CH4_scale=1.0,
                 CO2_scale=1.0,
                 vrad=0.0,
                 vbary=0.0):

        ## SETUP MODEL ATMOSPHERE ##
        Envi = rfm.Environment()
        A = rfm.Atmosphere(filename=Envi.atm_file)
        A.scaleProf('H2O', H2O_scale)
        A.scaleProf('CO', CO_scale)
        A.scaleProf('CH4', CH4_scale)
        A.scaleProf('CO2', CO2_scale)
        A.writeAll('tmp.atm')
        self.A = A

        M = Model()
        M.RFM(atm_files=['tmp.atm'],
              wmin=1e4 / wave_max,
              wmax=1e4 / wave_min,
              am=am)
        M.blur(rpower=25000.)
        self.M = M

        ## GET MODEL SKY SPECTRUM ##
        ModInfo = M.getSpec()
        self.WaveMod = ModInfo['wavelength']
        self.SkyRadMod = ModInfo['Radiance'] / np.amax(ModInfo['Radiance'])
        self.SkyRadMod = 1 - self.SkyRadMod
        scale = np.amax(self.SkyRadMod)

        ## GET MODEL STELLAR SPECTRUM ##
        a = np.loadtxt(ModelFilename, skiprows=1)
        StellWL, StellFlux = 1e4 / a[:, 0], a[:, 1]
        #plt.plot(StellWL,StellFlux)
        if np.all(np.diff(StellWL) > 0) != True:
            StellWL = np.flip(StellWL, 0)
            StellFlux = np.flip(StellFlux, 0)

        ## BROADEN STELLAR SPECTRUM ##
        StellFlux_Broad = self.blur_function(StellWL, StellFlux, 25000.)
        #print StellFlux_Broad
        #plt.plot(StellWL,StellFlux_Broad)
        #plt.show()

        ## SHIFT STELLAR SPECTRUM ##
        StellWave_Shift = self.shift_wavelength(StellWL, vrad - vbary)
        print StellWL
        print StellWave_Shift

        ## INTERPOLATE STELLAR SPECTRUM ONTO COMMON WAVELENGTH GRID ##
        self.StellFlux_Interp = np.interp(self.WaveMod, StellWave_Shift,
                                          StellFlux_Broad)

        ## COMBINE STELLAR AND TELLURIC SPECTRA ##
        assert (np.shape(self.StellFlux_Interp) == np.shape(self.SkyRadMod))
        self.StellFlux_Interp = self.StellFlux_Interp / np.median(
            self.StellFlux_Interp)
        self.SkyRadMod = self.SkyRadMod / np.median(self.SkyRadMod)

        self.ModSpec = 1.0 * self.StellFlux_Interp + 1.0 * self.SkyRadMod  ####change these to change ratios - SkyRadMod = telluric
        self.ModSpec = self.ModSpec / np.median(self.ModSpec)

        ## colors combined model to show tell vs stell contributions
        self.color = self.colorinmodel(self.StellFlux_Interp, self.SkyRadMod)
        #plt.figure()
        #plt.plot(self.WaveMod, self.StellFlux_Interp, label='stell')
        #plt.plot(self.WaveMod, self.SkyRadMod, label='tell')
        #plt.plot(self.WaveMod, self.ModSpec, label='stell+tell')
        #self.plot_multicolored_lines(self.WaveMod, self.ModSpec,self.color,label='stell(c)+tell(k)')
        #plt.legend(loc=0)

        ## GET OBSERVED SKY ##
        ObsInfo = nt.WaveOrder(ObsFilename).getData()
        WaveObsPos = np.array(ObsInfo['wl_pos'])
        #        SkyObsPos  = np.array(ObsInfo['sky_pos']) / np.median(ObsInfo['sky_pos'])  # L BAND
        SkyObsPos = np.array(ObsInfo['flux_pos']) / np.median(
            ObsInfo['flux_pos'])  # K BAND
        WaveObsNeg = np.array(ObsInfo['wl_neg'])
        #        SkyObsNeg  = np.array(ObsInfo['sky_neg']) / np.median(ObsInfo['sky_neg'])  # L BAND
        SkyObsNeg = np.array(ObsInfo['flux_neg']) / np.median(
            ObsInfo['flux_neg'])  # K BAND

        ## FIT OUT CONTINUUM ## (DP 21 JAN 16)
        wn_data_all = [WaveObsPos, WaveObsNeg]
        flux_data_all = [SkyObsPos, SkyObsNeg]
        merp = 16  #64 ##32 #16
        factor = 64  #16 #32# 64
        posneg = 0
        baseline_pos, baseline_neg = np.ones(np.size(WaveObsPos)), np.ones(
            np.size(WaveObsNeg))
        #        SkyObsPos_contrmv, SkyObsNeg_contrmv = np.array(np.size(SkyObsPos)), np.array(np.size(SkyObsNeg))
        for wn_data, flux_data in zip(wn_data_all, flux_data_all):
            points_flux, points_wn, points_count = np.zeros(merp), np.zeros(
                merp), np.arange(merp)
            for count in points_count:
                startpoint = count * factor
                endpoint = (count + 1) * factor
                if count == 0: startpoint = 14
                if count == 15: endpoint = 1024 - 30
                #                if count==63 : endpoint = 1024-14
                points_flux[count] = np.max(flux_data[startpoint:endpoint])
                loc = np.argmax(flux_data[startpoint:endpoint])
                #                points_wn[count]=wn_data[loc+startpoint]
                points_wn[count] = loc + startpoint
            coeff = np.polyfit(points_wn, points_flux, 2)
            #            coeff = np.polyfit(points_wn, points_flux, 4)
            print coeff
            #            if posneg == 0 : baseline_pos = coeff[1] + coeff[0]*wn_data# + coeff[1]*wn_data**2 + coeff[0]*wn_data**3
            #            if posneg == 1 : baseline_neg = coeff[1] + coeff[0]*wn_data# + coeff[1]*wn_data**2 + coeff[0]*wn_data**3
            if posneg == 0:
                baseline_pos = coeff[2] + coeff[1] * np.arange(1024) + coeff[
                    0] * np.arange(1024)**2  # + coeff[0]*np.arange(1024)**3
            if posneg == 1:
                baseline_neg = coeff[2] + coeff[1] * np.arange(1024) + coeff[
                    0] * np.arange(1024)**2  # + coeff[0]*np.arange(1024)**3
            #            if posneg == 0 : baseline_pos = coeff[4] + coeff[3]*np.arange(1024) + coeff[2]*np.arange(1024)**2 + coeff[1]*np.arange(1024)**3 + coeff[0]*np.arange(1024)**4# + coeff[0]*np.arange(1024)**3
            #            if posneg == 1 : baseline_neg = coeff[4] + coeff[3]*np.arange(1024) + coeff[2]*np.arange(1024)**2 + coeff[1]*np.arange(1024)**3 + coeff[0]*np.arange(1024)**4# + coeff[0]*np.arange(1024)**3
            posneg += 1
        SkyObsPos_contrmv, SkyObsNeg_contrmv = SkyObsPos / baseline_pos, SkyObsNeg / baseline_neg
        self.ModSpec = 1 - self.ModSpec
        #plt.figure()
        #plt.plot(SkyObsPos, hold=True)
        #plt.plot(baseline_pos, hold=True)
        #plt.show()
        #plt.figure()
        #plt.plot(SkyObsNeg, hold=True)
        #plt.plot(baseline_neg, hold=True)
        #plt.show()

        self.ObsLabelPN = ['pos', 'neg']
        ### break spec into 4 pieces
        #fourth = int(len(WaveObsPos)/4)
        #Wavepos = []
        #Waveneg = []
        #for val in range(fourth):
        #    Wavepos.append(WaveObsPos[val])
        #    Waveneg.append(WaveObsNeg[val])
        self.WaveObsPN = [WaveObsPos, WaveObsNeg]
        SkyObsPos_contrmv_scaled = (1 - SkyObsPos_contrmv)
        SkyObsNeg_contrmv_scaled = (1 - SkyObsNeg_contrmv)
        self.Pixels = [np.arange(len(WaveObsPos)), np.arange(len(WaveObsNeg))]
        self.SkyObsPN_orig = [SkyObsPos, SkyObsNeg]
        self.SkyObsPN = [SkyObsPos_contrmv_scaled, SkyObsNeg_contrmv_scaled]

        self.Coefs, self.WaveObsPN = self.FitInitDS(self.WaveObsPN,
                                                    self.ObsLabelPN)

        secs = ['one', 'two', 'three', 'four']
        for self.sec in secs:
            #self.sec = 'full'										### this causes it to run full spec, not in quarters
            print "======================"
            print 'QUARTER', self.sec
            print "======================"

            self.GoodFit = [False, False]

            self.modflux, newfl_obs = self.comparemodelanddata(
                self.WaveMod, self.ModSpec, self.WaveObsPN[0],
                self.SkyObsPN[0])

            self.modellength = len(self.modflux)

            while (True):
                RawInput = raw_input('>> ').replace(" ", "").lower()
                if (RawInput == 'quit'):
                    break

                if (RawInput == 'pos'):
                    while (True):
                        try:
                            RawInput2 = raw_input(
                                "Pos. Coefficients?: ").split(",")
                            self.Coefs[0] = np.array(RawInput2, dtype=np.float)

                            if self.sec == 'full':
                                self.WaveObsPN[0] = self.DSFunc(
                                    self.Pixels[0], self.Coefs[0])
                                self.PlotModObs(self.WaveMod, self.modflux,
                                                self.WaveObsPN[0], newfl_obs,
                                                self.ObsLabelPN[0])

                            else:
                                if len(self.modflux) == self.modellength:
                                    wvm, fm = self.Breakintofour_better(
                                        self.WaveMod,
                                        self.modflux,
                                        section=self.sec)
                                    pixels_quarter = np.arange(256)  ### 1024/4
                                else:
                                    wvm = self.Breakintofour_better(
                                        self.WaveMod, section=self.sec)
                                    fm = self.modflux.copy()
                                    pixels_quarter = np.arange(256)

                                fo = self.Breakintofour_better(
                                    newfl_obs, section=self.sec)
                                wvo = self.DSFunc(pixels_quarter,
                                                  self.Coefs[0])
                                self.PlotModObs(wvm, fm, wvo, fo,
                                                self.ObsLabelPN[0])
                            break

                        except:
                            print "Fix typo"
                            pass

                if (RawInput == 'neg'):
                    while (True):
                        try:
                            RawInput2 = raw_input(
                                "Neg. Coefficients?: ").split(",")
                            self.Coefs[1] = np.array(RawInput2, dtype=np.float)

                            #modflux, newfl_obs = self.comparemodelanddata(self.WaveMod, self.ModSpec, self.WaveObsPN[1], self.SkyObsPN[1])
                            if self.sec == 'full':
                                self.WaveObsPN[1] = self.DSFunc(
                                    self.Pixels[1], self.Coefs[1])
                                self.PlotModObs(self.WaveMod, self.modflux,
                                                self.WaveObsPN[1], newfl_obs,
                                                self.ObsLabelPN[1])
                            else:
                                if len(self.modflux) == self.modellength:
                                    wvm, fm = self.Breakintofour_better(
                                        self.WaveMod,
                                        self.modflux,
                                        section=self.sec)
                                    pixels_quarter = np.arange(256)
                                else:
                                    wvm = self.Breakintofour_better(
                                        self.WaveMod, section=self.sec)
                                    fm = self.modflux.copy()
                                    pixels_quarter = np.arange(256)
                                fo = self.Breakintofour_better(
                                    newfl_obs, section=self.sec)
                                wvo = self.DSFunc(pixels_quarter,
                                                  self.Coefs[1])
                                self.PlotModObs(wvm, fm, wvo, fo,
                                                self.ObsLabelPN[1])
                            break

                        except:
                            print "Fix typo"
                            pass

                if (RawInput == 'fit'):
                    for i in range(0, len(self.Coefs)):
                        if (self.GoodFit[i] != True):

                            if self.sec == 'full':
                                #newfl_obs[632:650] = np.nan			### takes out unassigned absorption
                                #newfl_obs[-30:] = np.nan			## takes off mess at end
                                self.Coefs[i], self.WaveObsPN[i] = self.FitDS(
                                    self.WaveMod, self.modflux, newfl_obs,
                                    self.Coefs[i])
                                self.PlotModObs(self.WaveMod, self.modflux,
                                                self.WaveObsPN[i], newfl_obs,
                                                self.ObsLabelPN[i])
                            else:
                                if len(self.modflux) == self.modellength:
                                    wvm, fm = self.Breakintofour_better(
                                        self.WaveMod,
                                        self.modflux,
                                        section=self.sec)
                                else:
                                    wvm = self.Breakintofour_better(
                                        self.WaveMod, section=self.sec)
                                    fm = self.modflux.copy()
                                if len(self.WaveObsPN[i]) == 1024:
                                    wvo, fo = self.Breakintofour_better(
                                        self.WaveObsPN[i],
                                        newfl_obs,
                                        section=self.sec)
                                else:
                                    fo = self.Breakintofour_better(
                                        newfl_obs, section=self.sec)
                                    wvo = self.WaveObsPN[i].copy()

                                ### cut off edge: [-10:] = last 10 points are nan
                                #fo[-15:] = np.nan
                                #fo[:10] = np.nan

                                self.Coefs[i], self.WaveObsPN[i] = self.FitDS(
                                    wvm, fm, fo, self.Coefs[i])
                                self.PlotModObs(wvm, fm, self.WaveObsPN[i], fo,
                                                self.ObsLabelPN[i])

                            RawInput2 = raw_input(
                                "Good Fit? (yes/no): ").replace(" ",
                                                                "").lower()
                            while (True):
                                if (RawInput2 == 'yes'):
                                    self.GoodFit[i] = True
                                    break
                                if (RawInput2 == 'no'):
                                    break
                                else:
                                    print "Please type yes or no."
                                    break
                        else:
                            print ''
                            print '## Dispersion Solution for ' + self.ObsLabelPN[
                                i] + ' position is good.'

                if (RawInput == 'pf'):
                    self.PrintCoefs()

            if self.sec == 'full':
                break

    def find_contiguous_colors(self, colors):
        # finds the continuous segments of colors and returns those segments
        segs = []
        curr_seg = []
        prev_color = ''
        for c in colors:
            if c == prev_color or prev_color == '':
                curr_seg.append(c)
            else:
                segs.append(curr_seg)
                curr_seg = []
                curr_seg.append(c)
            prev_color = c
        segs.append(curr_seg)  # the final one
        return segs

    def plot_multicolored_lines(self, x, y, colors, label=None):
        segments = self.find_contiguous_colors(colors)
        #plt.figure()
        start = 0
        for num, seg in enumerate(segments):
            if num == 0:
                end = start + len(seg)
                l, = plt.gca().plot(x[start:end],
                                    y[start:end],
                                    c=seg[0],
                                    label=label)
                start = end
            else:
                end = start + len(seg)
                l, = plt.gca().plot(x[start:end], y[start:end], c=seg[0])
                start = end

    def colorinmodel(self, stellflux, tellflux):
        color = []
        for i, j in zip(stellflux, tellflux):
            if j < i:  ##tell
                color.append('k')
            else:
                color.append('c')
        return color

    def comparemodelanddata(self, modelwave, modelflux, obswave, obsflux):
        ## normalizes the model and data so they're on about the same scale
        fl_mod = []
        fl_obs = []

        if np.nanmax(modelflux) > np.nanmax(obsflux):
            for a in modelflux:
                fl_mod.append(a / list(modelflux)[np.argmax(obsflux)])
            for b in obsflux:
                fl_obs.append(b / np.nanmax(obsflux))
        elif np.nanmax(modelflux) < np.nanmax(obsflux):
            wave_max = modelwave[np.argmax(modelflux)]

            for num, x in enumerate(obswave):
                if x > wave_max - 0.05 and x < wave_max + 0.05:
                    index = num
                    break
                else:
                    index = 0

            ### to find index of second largest flux in obs flux
            arr = np.array(obsflux)
            secondlargest = arr.argsort()[-5:][
                0]  ## make number bigger to pick smaller flux index

            for a in modelflux:
                fl_mod.append(a / np.nanmax(modelflux))
            for b in obsflux:
                #fl_obs.append((b/list(obsflux)[index])-0.05)
                #fl_obs.append((b/np.nanmax(obsflux))-0.05)
                fl_obs.append((b / list(obsflux)[secondlargest]))  #-0.05)

        fl_mod = np.array(fl_mod)
        fl_obs = np.array(fl_obs)

        return fl_mod, fl_obs

    def Breakintofour_better(self, wave, flux=None, section='one'):
        num = len(wave)

        try:
            if section == 'one':
                new_wave = wave[0:int(num / 4.0)]
                new_flux = flux[0:int(num / 4.0)]
            elif section == 'two':
                new_wave = wave[int(num / 4.0):int(2.0 * num / 4.0)]
                new_flux = flux[int(num / 4.0):int(2.0 * num / 4.0)]
            elif section == 'three':
                new_wave = wave[int(2.0 * num / 4.0):int(3.0 * num / 4.0)]
                new_flux = flux[int(2.0 * num / 4.0):int(3.0 * num / 4.0)]
            elif section == 'four':
                new_wave = wave[int(3.0 * num / 4.0):int(4.0 * num / 4.0)]
                new_flux = flux[int(3.0 * num / 4.0):int(4.0 * num / 4.0)]
        except:
            if section == 'one':
                new_wave = wave[0:int(num / 4.0)]
            elif section == 'two':
                new_wave = wave[int(num / 4.0):int(2.0 * num / 4.0)]
            elif section == 'three':
                new_wave = wave[int(2.0 * num / 4.0):int(3.0 * num / 4.0)]
            elif section == 'four':
                new_wave = wave[int(3.0 * num / 4.0):int(4.0 * num / 4.0)]

        if not np.any(flux):
            return new_wave
        else:
            return new_wave, new_flux

    def Breakintofour(self,
                      modelwave,
                      modelflux,
                      obswave,
                      obsflux,
                      section='one'):
        mod_num = len(modelwave)
        obs_num = len(obswave)

        if section == 'one':
            new_modwave = modelwave[0:int(mod_num / 4.0)]
            new_modflux = modelflux[0:int(mod_num / 4.0)]
            new_obswave = obswave[0:int(obs_num / 4.0)]
            new_obsflux = obsflux[0:int(obs_num / 4.0)]
        elif section == 'two':
            new_modwave = modelwave[int(mod_num / 4.0):int(2.0 * mod_num /
                                                           4.0)]
            new_modflux = modelflux[int(mod_num / 4.0):int(2.0 * mod_num /
                                                           4.0)]
            new_obswave = obswave[int(obs_num / 4.0):int(2.0 * obs_num / 4.0)]
            new_obsflux = obsflux[int(obs_num / 4.0):int(2.0 * obs_num / 4.0)]
        elif section == 'three':
            new_modwave = modelwave[int(2.0 * mod_num /
                                        4.0):int(3.0 * mod_num / 4.0)]
            new_modflux = modelflux[int(2.0 * mod_num /
                                        4.0):int(3.0 * mod_num / 4.0)]
            new_obswave = obswave[int(2.0 * obs_num / 4.0):int(3.0 * obs_num /
                                                               4.0)]
            new_obsflux = obsflux[int(2.0 * obs_num / 4.0):int(3.0 * obs_num /
                                                               4.0)]
        elif section == 'four':
            new_modwave = modelwave[int(3.0 * mod_num /
                                        4.0):int(4.0 * mod_num / 4.0)]
            new_modflux = modelflux[int(3.0 * mod_num /
                                        4.0):int(4.0 * mod_num / 4.0)]
            new_obswave = obswave[int(3.0 * obs_num / 4.0):int(4.0 * obs_num /
                                                               4.0)]
            new_obsflux = obsflux[int(3.0 * obs_num / 4.0):int(4.0 * obs_num /
                                                               4.0)]

        return new_modwave, new_modflux, new_obswave, new_obsflux

    def PrintCoefs(self):

        Clab = ['A = ', 'B = ', 'C = ', 'D = ', 'E = ']

        for coef, label, goodf in zip(self.Coefs, self.ObsLabelPN,
                                      self.GoodFit):
            print ''
            print 'Position = ', label
            print 'Good Fit = ', goodf
            print '-------------------'
            for i in range(0, len(coef)):
                print Clab[i], coef[i]
            print ''
            print "{}, {}, {}, {}, {}".format(coef[0], coef[1], coef[2],
                                              coef[3], coef[4])
        print ''

    def ReadAux(self, FileName):
        ''' 
		Reads in auxillary data files from Terraspec or another source.
		'''
        FileInfo = np.loadtxt(FileName, skiprows=1, dtype='float')
        wn = FileInfo[:, 0]
        flux = FileInfo[:, 1]
        wl = 1.0e4 / wn

        if np.size(wl) > 1024:
            sec_out = np.where((wl >= self.WaveMin) & (wl <= self.WaveMax))
            wl_out = wl[sec_out]
            flux_out = flux[sec_out]
        else:
            wl_out = wl
            flux_out = flux

        return wl_out, flux_out

    def PlotModObs(self,
                   wave_mod,
                   flux_mod,
                   wave_obs,
                   flux_obs,
                   label,
                   block=False):
        plt.close()
        '''
		plt.figure(figsize=(20, 10))
		#plt.plot(wave_mod, flux_mod, color='blue')
		self.plot_multicolored_lines(wave_mod,flux_mod,self.color)    ### this tells stel (c) vs tel (k) lines
		#plt.plot(wave_obs, flux_obs, color='red')
		x1,x2,y1,y2 = plt.axis()
		plt.axis((x1, x2, np.amin([np.amin(flux_mod), np.amin(flux_obs)])-0.15, np.amax(flux_mod)))
		plt.title(label)
		'''

        plt.figure(figsize=(20, 10))
        self.l, = plt.plot(wave_mod, flux_mod, color='blue')
        #self.plot_multicolored_lines(wave_mod,flux_mod,self.color)    ### this tells stel vs tel lines
        plt.plot(wave_obs, flux_obs, color='red')
        x1, x2, y1, y2 = plt.axis()
        plt.axis((x1, x2, np.nanmin([np.nanmin(flux_mod),
                                     np.nanmin(flux_obs)]) - 0.15,
                  np.nanmax([np.amax(flux_mod), 1.0])))
        plt.title(label)

        axstell = plt.axes([0.25, 0.1, 0.55, 0.03])
        axtell = plt.axes([0.25, 0.15, 0.55, 0.03])

        try:
            s0 = self.stell_val
            t0 = self.tell_val
        except AttributeError:
            s0 = 1
            t0 = 1

        self.s_stell = Slider(axstell, 'Stellar', 0.0, 10.0, valinit=s0)
        self.s_tell = Slider(axtell, 'Telluric', 0.0, 10.0, valinit=t0)

        saveax = plt.axes([0.55, 0.025, 0.1, 0.04])
        button = Button(saveax, 'Save Values', hovercolor='0.975')

        self.s_stell.on_changed(self.update)
        self.s_tell.on_changed(self.update)

        button.on_clicked(self.save_ratios)

        resetax = plt.axes([0.35, 0.025, 0.1, 0.04])
        button2 = Button(resetax, 'Reset', hovercolor='0.975')
        button2.on_clicked(self.reset)

        plt.show()
        #plt.savefig('/home/cbuzard/Desktop/temp.pdf')

    def save_ratios(self, event):
        self.stell_val = self.stell
        self.tell_val = self.tell
        print self.stell_val, self.tell_val
        self.modflux = self.modspec.copy(
        )  ### should update model to have ratios you pick everywhere

    def reset(self, event):
        self.s_stell.reset()
        self.s_tell.reset()

    def update(self, val):
        self.stell = self.s_stell.val
        self.tell = self.s_tell.val
        if self.sec == 'full':
            modspec = self.stell * self.StellFlux_Interp + self.tell * self.SkyRadMod
        else:
            stellflux, skyradmod = self.Breakintofour_better(
                self.StellFlux_Interp, self.SkyRadMod, section=self.sec)
            modspec = self.stell * stellflux + self.tell * skyradmod

        modspec = modspec / np.median(modspec)
        self.modspec = 1 - modspec
        self.l.set_ydata(self.modspec)

    def FitInitDS(self, WaveLengths, Labels):
        porder = 1
        Coefs, WaveLengths_fit = [], []

        print 'Initial Coefficients'
        print '===================='

        for wl, label in zip(WaveLengths, Labels):
            pixels = np.arange(len(wl))

            coef = np.polyfit(pixels, wl, porder)[::-1]
            wl_fit = self.DSFunc(pixels, coef)

            print '# ' + label + ' #'
            print '---------------'
            for i in range(0, porder + 1):
                print i, coef[i]
            print ''

            plt.plot(pixels, wl, 'ko')
            plt.plot(pixels, wl_fit)
            plt.show()

            Coefs.append(coef)
            WaveLengths_fit.append(wl_fit)

        return Coefs, WaveLengths_fit

    def DSFunc(self, pixels, Coefs):

        WaveOut = np.zeros(len(pixels))
        for i in range(0, len(Coefs)):
            if i <= 1:
                WaveOut = WaveOut + Coefs[i] * (pixels)**i
            else:
                WaveOut = WaveOut + Coefs[i] * (pixels / 1000.)**i

        return WaveOut

    def residual(self, params, flux_data, wl_model, flux_model):
        npix = len(flux_data)
        pixels = np.arange(npix)

        #if self.sec != 'full':
        #	pixels = self.Breakintofour_better(pixels,section=self.sec)

        Coefs = [
            params['A'].value, params['B'].value, params['C'].value,
            params['D'].value, params['E'].value
        ]  #, params['F'].value]
        wl_fit = self.DSFunc(pixels, Coefs)

        flux_model_fit = np.interp(wl_fit,
                                   wl_model,
                                   flux_model,
                                   left=flux_model[0],
                                   right=flux_model[-1])

        index_use = np.where(flux_data > 0.005)

        residual = np.subtract(flux_model_fit[index_use], flux_data[index_use])

        return (residual)

    def FitDS(self, WLmod, Fmod, Fobs, CoefsInit):

        params = Parameters()
        params.add('A',
                   value=CoefsInit[0],
                   vary=True,
                   min=CoefsInit[0] - 0.05,
                   max=CoefsInit[0] + 0.05)
        params.add('B', value=CoefsInit[1], vary=True)
        params.add('C', value=1e-5, vary=True)
        params.add('D', value=1e-6, vary=True)
        params.add('E', value=1e-6, vary=True)
        #        params.add('F',value=1e-6, vary=True)

        result = minimize(self.residual,
                          params,
                          args=(Fobs, WLmod, Fmod),
                          method='least-sq')  #'least-sq')
        params = result.params
        print ''
        print '-----'
        print 'A = ', params['A']
        print 'B = ', params['B']
        print 'C = ', params['C']
        print 'D = ', params['D']
        print 'E = ', params['E']
        #        print 'F=  ', params['F']
        #print 'R = ', params['R']
        print 'RedChi / Success = ', result.redchi, ' / ', result.success
        print ''
        print '====='

        Coefs = [
            params['A'].value, params['B'].value, params['C'].value,
            params['D'].value, params['E'].value
        ]  #, params['F'].value]
        pixels = np.arange(len(Fobs))
        WLobs = self.DSFunc(pixels, Coefs)

        return Coefs, WLobs

    def blur_function(self, wave, tran, rpower):

        wmin = wave.min()
        wmax = wave.max()

        nx = wave.size
        x = np.arange(nx)

        A = wmin
        B = np.log(wmax / wmin) / nx
        wave_constfwhm = A * np.exp(B * x)

        if np.all(np.diff(wave) > 0) != True:
            print "wave list not increasing"
            wave = np.flip(wave, 0)
            tran = np.flip(tran, 0)
        tran_constfwhm = np.interp(wave_constfwhm, wave, tran)

        #Sanity check that the FWHM is indeed constant
        dwdx_constfwhm = np.diff(wave_constfwhm)
        fwhm_pix = wave_constfwhm[1:] / rpower / dwdx_constfwhm
        if (fwhm_pix.min() - fwhm_pix.max()) / fwhm_pix.max() > 1e-5:
            #This should not happen
            warnings.warn('The FWHM is not constant in units of pixels.')

        fwhm_pix = fwhm_pix[0]
        sigma_pix = fwhm_pix / 2.3548
        kx = np.arange(nx) - (nx - 1) / 2.
        kernel = 1. / (sigma_pix * np.sqrt(2. * np.pi)) * np.exp(
            -kx**2 / (2. * sigma_pix**2))

        tran_conv = fft.ifft(
            fft.fft(tran_constfwhm) * np.conj(fft.fft(kernel)))
        tran_conv = fft.fftshift(tran_conv).real
        tran_oldsampling = np.interp(wave, wave_constfwhm, tran_conv)

        return tran_oldsampling

    def shift_wavelength(self, wave, velshift):
        # velshift = velocity shift in km/s # vrad-vbary #
        c = 2.99792456e5  # speed of light in km/s

        wavelength_wn = 1.0e4 / wave
        shift_wavelength_wn = wavelength_wn / (1.0 + (velshift) / c)
        newwave = 1.0e4 / shift_wavelength_wn  # StarSpec[:,0] / (1.0+(vrad-vbary)/c)

        return newwave
Example #3
0
class PlotFrame(wx.Frame):
    """
        PlotFrame is a custom wxPython frame to hold the panel with a
        Figure and WxAgg backend canvas for matplotlib plots or other
        figures.  In this frame:

        self is an instance of a wxFrame;
        axes is an instance of MPL Axes;
        fig is an instance of MPL Figure;
        panel is an instance of wxPanel, used for the main panel, to hold
        canvas, an instance of MPL FigureCanvasWxAgg.
    """

    # Main function to set everything up when the frame is created
    def __init__(self, title, pos, size):
        """
           This will be executed when an instance of PlotFrame is created.
           It is the place to define any globals as "self.<name>".
        """
        wx.Frame.__init__(self, None, wx.ID_ANY, title, pos, size)

        if len(sys.argv) < 2:
            self.filename = ""
        else:
            self.filename = sys.argv[1]

        # set some Boolean flags
        self.STOP = False
        self.data_loaded = False
        self.reverse_play = False

        self.step = 1

        #    Make the main Matplotlib panel for plots
        self.create_main_panel()  # creates canvas and contents

        # Then add wxPython widgets below the MPL canvas
        # Layout with box sizers

        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
        self.sizer.AddSpacer(10)
        self.sizer.Add(self.toolbar, 0, wx.EXPAND)
        self.sizer.AddSpacer(10)

        #    Make the control panel with a row of buttons
        self.create_button_bar()
        self.sizer.Add(self.button_bar_sizer, 0, flag=wx.ALIGN_CENTER | wx.TOP)

        #    Make a Status Bar
        self.statusbar = self.CreateStatusBar()
        self.sizer.Add(self.statusbar, 0, wx.EXPAND)

        self.SetStatusText("Frame created ...")

        # -------------------------------------------------------
        #	       set up the Menu Bar
        # -------------------------------------------------------
        menuBar = wx.MenuBar()

        menuFile = wx.Menu()  # File menu
        menuFile.Append(1, "&Open", "Filename(s) or wildcard list to plot")
        menuFile.Append(3, "Save", "Save plot as a PNG image")
        menuFile.AppendSeparator()
        menuFile.Append(10, "E&xit")
        menuBar.Append(menuFile, "&File")

        menuHelp = wx.Menu()  # Help menu
        menuHelp.Append(11, "&About Netview")
        menuHelp.Append(12, "&Usage and Help")
        menuHelp.Append(13, "Program &Info")

        menuBar.Append(menuHelp, "&Help")
        self.SetMenuBar(menuBar)

        self.panel.SetSizer(self.sizer)
        self.sizer.Fit(self)

        # -------------------------------------------------------
        #      Bind the menu items to functions
        # -------------------------------------------------------

        self.Bind(wx.EVT_MENU, self.OnOpen, id=1)
        self.Bind(wx.EVT_MENU, self.OnSave, id=3)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=10)
        self.Bind(wx.EVT_MENU, self.OnAbout, id=11)
        self.Bind(wx.EVT_MENU, self.OnUsage, id=12)
        self.Bind(wx.EVT_MENU, self.OnInfo, id=13)

        # methods defined below to get and plot the data
        # Normally do the plot on request, and not here
        # self.get_data_params()
        # self.init_plot()
        # self.get_xyt_data()
        # plot_data()

# ---------- end of __init__ ----------------------------

# -------------------------------------------------------
#   Function to make the main Matplotlib panel for plots
# -------------------------------------------------------

    def create_main_panel(self):
        """ create_main_panel creates the main mpl panel with instances of:
             * mpl Canvas 
             * mpl Figure 
             * mpl Figure
             * mpl Axes with subplot
             * mpl Widget class Sliders and Button
             * mpl navigation toolbar
           self.axes is the instance of MPL Axes, and is where it all happens
        """

        self.panel = wx.Panel(self)

        # Create the mpl Figure and FigCanvas objects.
        # 3.5 x 5 inches, 100 dots-per-inch
        #
        self.dpi = 100
        self.fig = Figure((3.5, 5.0), dpi=self.dpi)
        self.canvas = FigCanvas(self.panel, wx.ID_ANY, self.fig)

        # Since we have only one plot, we could use add_axes
        # instead of add_subplot, but then the subplot
        # configuration tool in the navigation toolbar wouldn't work.

        self.axes = self.fig.add_subplot(111)
        # (111) == (1,1,1) --> row 1, col 1, Figure 1)
        # self.axes.set_title("View from: "+self.filename)

        # Now create some sliders below the plot after making room
        self.fig.subplots_adjust(left=0.1, bottom=0.20)

        self.axtmin = self.fig.add_axes([0.2, 0.10, 0.5, 0.03])
        self.axtmax = self.fig.add_axes([0.2, 0.05, 0.5, 0.03])

        self.stmin = Slider(self.axtmin, 't_min:', 0.0, 1.0, valinit=0.0)
        self.stmax = Slider(self.axtmax, 't_max:', 0.0, 1.0, valinit=1.0)
        self.stmin.on_changed(self.update_trange)
        self.stmax.on_changed(self.update_trange)

        self.axbutton = self.fig.add_axes([0.8, 0.07, 0.1, 0.07])
        self.reset_button = Button(self.axbutton, 'Reset')
        self.reset_button.color = 'skyblue'
        self.reset_button.hovercolor = 'lightblue'
        self.reset_button.on_clicked(self.reset_trange)

        # Create the navigation toolbar, tied to the canvas

        self.toolbar = NavigationToolbar(self.canvas)

    def update_trange(self, event):
        self.t_min = self.stmin.val
        self.t_max = self.stmax.val
        # print(self.t_min, self.t_max)

    def reset_trange(self, event):
        self.stmin.reset()
        self.stmax.reset()

    def create_button_bar(self):
        """
	create_button_bar makes a control panel bar with buttons and
	toggles for

	New Data - Play - STOP - Single Step - Forward/Back - Normal/Fast

	It does not create a Panel container, but simply creates Button
	objects with bindings, and adds  them to a horizontal BoxSizer
	self.button_bar_sizer.	This is added to the PlotFrame vertical
	BoxSizer, after the MPL canvas, during initialization of the frame.

	"""
        rewind_button = wx.Button(self.panel, -1, "New Data")
        self.Bind(wx.EVT_BUTTON, self.OnRewind, rewind_button)

        replot_button = wx.Button(self.panel, -1, "Play")
        self.Bind(wx.EVT_BUTTON, self.OnReplot, replot_button)

        sstep_button = wx.Button(self.panel, -1, "Single Step")
        self.Bind(wx.EVT_BUTTON, self.OnSstep, sstep_button)

        stop_button = wx.Button(self.panel, -1, "STOP")
        self.Bind(wx.EVT_BUTTON, self.OnStop, stop_button)

        # The toggle buttons need to be globally accessible

        self.forward_toggle = wx.ToggleButton(self.panel, -1, "Forward")
        self.forward_toggle.SetValue(True)
        self.forward_toggle.SetLabel("Forward")
        self.Bind(wx.EVT_TOGGLEBUTTON, self.OnForward, self.forward_toggle)

        self.fast_toggle = wx.ToggleButton(self.panel, -1, " Normal ")
        self.fast_toggle.SetValue(True)
        self.fast_toggle.SetLabel(" Normal ")
        self.Bind(wx.EVT_TOGGLEBUTTON, self.OnFast, self.fast_toggle)

        # Set button colors to some simple colors that are likely
        # to be independent on X11 color definitions.  Some nice
        # bit maps (from a media player skin?) should be used
        # or the buttons and toggle state colors in OnFast() below

        rewind_button.SetBackgroundColour('skyblue')
        replot_button.SetBackgroundColour('skyblue')
        sstep_button.SetBackgroundColour('skyblue')
        stop_button.SetBackgroundColour('skyblue')
        self.forward_toggle.SetForegroundColour('black')
        self.forward_toggle.SetBackgroundColour('yellow')
        self.fast_toggle.SetForegroundColour('black')
        self.fast_toggle.SetBackgroundColour('yellow')
        self.button_bar_sizer = wx.BoxSizer(wx.HORIZONTAL)
        flags = wx.ALIGN_CENTER | wx.ALL
        self.button_bar_sizer.Add(rewind_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(replot_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(sstep_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(stop_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(self.forward_toggle, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(self.fast_toggle, 0, border=3, flag=flags)

    # -------------------------------------------------------
    #	Functions to generate or read (x,y) data and plot it
    # -------------------------------------------------------

    def get_data_params(self):
        #  These parameters  would normally be provided in a file header,
        # past as arguments in a function, or from other file information
        #  Next version will bring up a dialog for dt NX NY if no file header

        # Here check to see if a filename should be entered from File/Open
        # self.filename = 'Ex_net_Vm_0001.txt'
        if len(self.filename) == 0:
            # fake a button press of File/Open
            self.OnOpen(wx.EVT_BUTTON)

        # should check here if file exists as specified [path]/filename

        # assume it is a bzip2 compressed file
        try:
            fp = bz2.BZ2File(self.filename)
            line = fp.readline()
        except IOError:
            # then assume plain text
            fp = open(self.filename)
            line = fp.readline()

        fp.close()

        # check if first line is a header line starting with '#'
        header = line.split()
        if header[0][0] == "#":
            self.Ntimes = int(header[1])
            self.t_min = float(header[2])
            self.dt = float(header[3])
            self.NX = int(header[4])
            self.NY = int(header[5])
        else:
            pdentry = self.ParamEntryDialog()
            if pdentry.ShowModal() == wx.ID_OK:
                self.Ntimes = int(pdentry.Ntimes_dialog.entry.GetValue())
                self.t_min = float(pdentry.tmin_dialog.entry.GetValue())
                self.dt = float(pdentry.dt_dialog.entry.GetValue())
                self.NX = int(pdentry.NX_dialog.entry.GetValue())
                self.NY = int(pdentry.NY_dialog.entry.GetValue())
                print 'Ntimes = ', self.Ntimes, ' t_min = ', self.t_min
                print 'NX = ', self.NX, ' NY = ', self.NY
            pdentry.Destroy()
        self.t_max = (self.Ntimes - 1) * self.dt
        # reset slider max and min
        self.stmin.valmax = self.t_max
        self.stmin.valinit = self.t_min
        self.stmax.valmax = self.t_max
        self.stmax.valinit = self.t_max
        self.stmax.set_val(self.t_max)
        self.stmin.reset()
        self.stmax.reset()
        fp.close()

    def init_plot(self):
        ''' 
        init_plot creates the initial plot display. A normal MPL plot
	would be created here with a command "self.axes.plot(x, y)" in
	order to create a plot of points in the x and y arrays on the
	Axes subplot.  Here, we create an AxesImage instance with
	imshow(), instead.  The initial image is a blank one of the
	proper dimensions, filled with zeroes.

        '''
        self.t_max = (self.Ntimes - 1) * self.dt
        self.axes.set_title("View of " + self.filename)
        # Note that NumPy array (row, col) = image (y, x)
        data0 = np.zeros((self.NY, self.NX))

        # Define a 'cold' to 'hot' color scale based in GENESIS 2 'hot'
        hotcolors = [
            '#000032', '#00003c', '#000046', '#000050', '#00005a', '#000064',
            '#00006e', '#000078', '#000082', '#00008c', '#000096', '#0000a0',
            '#0000aa', '#0000b4', '#0000be', '#0000c8', '#0000d2', '#0000dc',
            '#0000e6', '#0000f0', '#0000fa', '#0000ff', '#000af6', '#0014ec',
            '#001ee2', '#0028d8', '#0032ce', '#003cc4', '#0046ba', '#0050b0',
            '#005aa6', '#00649c', '#006e92', '#007888', '#00827e', '#008c74',
            '#00966a', '#00a060', '#00aa56', '#00b44c', '#00be42', '#00c838',
            '#00d22e', '#00dc24', '#00e61a', '#00f010', '#00fa06', '#00ff00',
            '#0af600', '#14ec00', '#1ee200', '#28d800', '#32ce00', '#3cc400',
            '#46ba00', '#50b000', '#5aa600', '#649c00', '#6e9200', '#788800',
            '#827e00', '#8c7400', '#966a00', '#a06000', '#aa5600', '#b44c00',
            '#be4200', '#c83800', '#d22e00', '#dc2400', '#e61a00', '#f01000',
            '#fa0600', '#ff0000', '#ff0a00', '#ff1400', '#ff1e00', '#ff2800',
            '#ff3200', '#ff3c00', '#ff4600', '#ff5000', '#ff5a00', '#ff6400',
            '#ff6e00', '#ff7800', '#ff8200', '#ff8c00', '#ff9600', '#ffa000',
            '#ffaa00', '#ffb400', '#ffbe00', '#ffc800', '#ffd200', '#ffdc00',
            '#ffe600', '#fff000', '#fffa00', '#ffff00', '#ffff0a', '#ffff14',
            '#ffff1e', '#ffff28', '#ffff32', '#ffff3c', '#ffff46', '#ffff50',
            '#ffff5a', '#ffff64', '#ffff6e', '#ffff78', '#ffff82', '#ffff8c',
            '#ffff96', '#ffffa0', '#ffffaa', '#ffffb4', '#ffffbe', '#ffffc8',
            '#ffffd2', '#ffffdc', '#ffffe6', '#fffff0'
        ]

        cmap = matplotlib.colors.ListedColormap(hotcolors)

        self.im = self.axes.imshow(data0, cmap=cmap, origin='lower')

        # http://matplotlib.sourceforge.net/examples/pylab_examples/show_colormaps.html
        # shows examples to use as a 'cold' to 'hot' mapping of value to color
        # cm.jet, cm.gnuplot and cm.afmhot are good choices, but are unlike G2 'hot'

        self.im.cmap = cmap

        # Not sure how to properly add a colorbar
        # self.cb = self.fig.colorbar(self.im, orientation='vertical')

        # refresh the canvas
        self.canvas.draw()

    def get_xyt_data(self):
        # Create scaled (0-1) luminance(x,y) array from ascii G-2 disk_out file
        # get the data to plot from the specified filename
        # Note that NumPy loadtxt transparently deals with bz2 compression
        self.SetStatusText('Data loading - please wait ....')
        rawdata = np.loadtxt(self.filename)
        # Note the difference between NumPy [row, col] order and network
        # x-y grid (x, y) = (col, row). We want a NumPy NY x NX, not
        # NX x NY, array to be used by the AxesImage object.

        xydata = np.resize(rawdata, (self.Ntimes, self.NY, self.NX))
        # imshow expects the data to be scaled to range 0-1.
        Vmin = xydata.min()
        Vmax = xydata.max()
        self.ldata = (xydata - Vmin) / (Vmax - Vmin)
        self.data_loaded = True
        self.SetStatusText('Data has been loaded - click Play')

    def plot_data(self):
        ''' plot_data() shows successive frames of the data that was loaded
            into the ldata array.  Creating a new self.im AxesImage instance
            for each frame is extremely slow, so the set_data method of
            AxesImage is used to load new data into the existing self.im for
            each frame.  Normally 'self.canvas.draw()' would be used to
            display a frame, but redrawing the entire canvas, redraws the
            axes, labels, sliders, buttons, or anything else on the canvas.
            This uses a method taken from an example in Ch 7, p. 192
            Matplotlib for Python developers, with draw_artist() and blit()
            redraw only the part that was changed.

        '''
        if self.data_loaded == False:
            # bring up a warning dialog
            msg = """
            Data for plotting has not been loaded!
            Please enter the file to plot with File/Open, unless
            it was already specified, and then click on 'New Data'
            to load the data to play back, before clicking 'Play'.
            """
            wx.MessageBox(msg, "Plot Warning", wx.OK | wx.ICON_ERROR, self)
            return

        # set color limits
        self.im.set_clim(0.0, 1.0)
        self.im.set_interpolation('nearest')
        # 'None' is is slightly faster, but not implemented for MPL ver < 1.1
        # self.im.set_interpolation('None')

        # do an initial draw, then save the empty figure axes
        self.canvas.draw()

        # self.bg = self.canvas.copy_from_bbox(self.axes.bbox)
        # However the save and restore is only  needed if I change
        # axes legends, etc.  The draw_artist(artist), and blit
        # are much faster than canvas.draw() and are sufficient.

        print 'system time (seconds) = ', time.time()

        # round frame_min down and frame_max up for the time window
        frame_min = int(self.t_min / self.dt)
        frame_max = min(int(self.t_max / self.dt) + 1, self.Ntimes)
        frame_step = self.step

        # Displaying simulation time to the status bar is much faster
        # than updating a slider progress bar, but location isn't optimum.
        # The check for the STOP button doesn't work because the button
        # click is not registered until this function exits.

        # check to see if self.reverse_play == True
        # then interchange frame_min, frame_max, and use negative step
        if self.reverse_play == True:
            frame_min = min(int(self.t_max / self.dt) + 1, self.Ntimes) - 1
            frame_max = int(self.t_min / self.dt) - 1
            frame_step = -self.step
        for frame_num in range(frame_min, frame_max, frame_step):
            self.SetStatusText('time: ' + str(frame_num * self.dt))
            if self.STOP == True:
                self.t_min = frame_num * self.dt
                # set t_min slider ?
                self.STOP = False
                break
            self.im.set_data(self.ldata[frame_num])
            self.axes.draw_artist(self.im)
            self.canvas.blit(self.axes.bbox)

        print 'system time (seconds) = ', time.time()

    #  ------------------------------------------------------------------
    #	Define the classes and functions for getting parameter values
    #  --------------------------------------------------------------

    class ParamEntryDialog(wx.Dialog):
        def __init__(self):
            wx.Dialog.__init__(self, None, wx.ID_ANY)
            self.SetSize((250, 200))
            self.SetTitle('Enter Data File Parameters')
            vbox = wx.BoxSizer(wx.VERTICAL)
            self.Ntimes_dialog = XDialog(self)
            self.Ntimes_dialog.entry_label.SetLabel('Number of entries')
            self.Ntimes_dialog.entry.ChangeValue(str(2501))
            self.tmin_dialog = XDialog(self)
            self.tmin_dialog.entry_label.SetLabel('Start time (sec)')
            self.tmin_dialog.entry.ChangeValue(str(0.0))

            self.dt_dialog = XDialog(self)
            self.dt_dialog.entry_label.SetLabel('Output time step (sec)')
            self.dt_dialog.entry.ChangeValue(str(0.0002))

            self.NX_dialog = XDialog(self)
            self.NX_dialog.entry_label.SetLabel('Number of cells on x-axis')
            self.NX_dialog.entry.ChangeValue(str(32))
            self.NY_dialog = XDialog(self)
            self.NY_dialog.entry_label.SetLabel('Number of cells on y-axis')
            self.NY_dialog.entry.ChangeValue(str(32))

            vbox.Add(self.Ntimes_dialog, 0, wx.EXPAND | wx.ALL, border=5)
            vbox.Add(self.tmin_dialog, 0, wx.EXPAND | wx.ALL, border=5)
            vbox.Add(self.dt_dialog, 0, wx.EXPAND | wx.ALL, border=5)
            vbox.Add(self.NX_dialog, 0, wx.EXPAND | wx.ALL, border=5)
            vbox.Add(self.NY_dialog, 0, wx.EXPAND | wx.ALL, border=5)

            okButton = wx.Button(self, wx.ID_OK, 'Ok')
            # vbox.Add(okButton,flag=wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM, border=10)
            vbox.Add(okButton, flag=wx.ALIGN_CENTER, border=10)

            self.SetSizer(vbox)
            self.SetSizerAndFit(vbox)

    #  ------------------------------------------------------------------
    #	Define the functions executed on menu choices
    #  ---------------------------------------------------------------

    def OnQuit(self, event):
        self.Close()

    def OnSave(self, event):
        file_choices = "PNG (*.png)|*.png"
        dlg = wx.FileDialog(self,
                            message="Save plot as...",
                            defaultDir=os.getcwd(),
                            defaultFile="plot.png",
                            wildcard=file_choices,
                            style=wx.SAVE)

        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.canvas.print_figure(path, dpi=self.dpi)
            # self.flash_status_message("Saved to %s" % path)

    def OnAbout(self, event):
        msg = """

                      G-3 Netview ver. 1.7

Netview is a stand-alone Python application for viewing
the output of GENESIS 2 and 3 network simulations.
It is intended to replace GENESIS 2 SLI scripts that use the
XODUS 'xview' widget.

The design and operation is based on the G3Plot application
for creating 2D plots of y(t) or y(x) from data files.
Unlike G3Plot, the image created with Netview is an animated
representation of a rectangular network with colored squares
used to indicate the value of some variable at that position
and time.  Typically, this would be the membrane potenial of
a cell soma, or a synaptic current in a dendrite segment.

Help/Usage gives HTML help for using Netview.
This is the main Help page.

Help/Program Info provides some information about the
objects and functions, and the wxPython and matplotlib
classes used here.

Dave Beeman, August 2012
	"""
        dlg = wx.MessageDialog(self, msg, "About G-3 Netview",
                               wx.OK | wx.ICON_QUESTION)
        dlg.ShowModal()
        dlg.Destroy()

    def OnOpen(self, event):
        dlg = wx.TextEntryDialog(self,
                                 "File with x,y data to plot",
                                 "File Open",
                                 self.filename,
                                 style=wx.OK | wx.CANCEL)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetValue()
            # A new filename has been entered, but the data has not been read
            self.data_loaded = False
            # print "You entered: %s" % self.filename
        dlg.Destroy()

    #  This starts with the long string of HTML to display
    class UsageFrame(wx.Frame):
        text = """
<HTML>
<HEAD></HEAD>
<BODY BGCOLOR="#D6E7F7">

<CENTER><H1>Using G-3 Netview</H1></CENTER>

<H2>Introduction and Quick Start</H2>

<p>Netview is a stand-alone Python application for viewing the output of
GENESIS 2 and 3 network simulations.  It is intended to replace GENESIS 2
SLI scripts that use the XODUS 'xview' widget.</p>

<p>The design and operation is based on the G3Plot application for creating 2D
plots of y(t) or y(x) from data files.  As with G3Plot, the main class
PlotFrame uses a basic wxPython frame to embed a matplotlib figure for
plotting.  It defines some basic menu items and a control panel of buttons
and toggles, each with bindings to a function to execute on a mouse click.</p>

<p>Unlike G3Plot, the image created with Netview is an animated
representation of a rectangular network with colored squares
used to indicate the value of some variable at that position
and time.  Typically, this would be the membrane potenial of
a cell soma, or a synaptic current in a dendrite segment.</p>

<h2>Usage</h2>

<p>The Menu Bar has <em>File/Open</em>, <em>File/Save</em>, and
<em>File/Exit</em> choices.  The Help Menu choices <em>About</em> and
<em>Usage</em> give further information.  The <em>Program Info</em>
selection shows code documentation that is contained in some of the main
function <em>docstrings</em>.</p>

<p>After starting the <em>netview</em> program, enter a data file name
in the dialog for File/Open, unless the filename was given as a
command line argument.  Then click on <strong>New Data</strong> to load the new
data and initialize the plot.  When the plot is cleared to black,
press <strong>Play</strong>.</p>

<p>The file types recognized are plain text or text files compressed with
bzip2.  The expected data format is one line for each output time step,
with each line having the membrane potential value of each cell in the net.
No time value should be given on the line.  In order to properly display
the data, netview needs some additional information about the network and
the data.  This can optionally be contained in a header line that precedes
the data.  If a header is not detected, a dialog will appear asking for the
needed parameters.</p>

<p>It is assumed that the cells are arranged on a NX x NY grid, numbered
from 0 (bottom left corner) to NX*NY - 1 (upper right corner).
In order to provide this information to netview, the data file should
begin with a header line of the form:</p>

<pre>
    #optional_RUNID_string Ntimes start_time dt NX NY SEP_X SEP_Y x0 y0 z0
</pre>

<p>The line must start with &quot;#&quot; and can optionally be followed immediately by any
string.  Typically this is some identification string generated by the
simulation run.  The following parameters, separated by blanks or any
whitespace, are:</p>

<ul>
<li>Ntimes - the number of lines in the file, exclusive of the header</li>
<li>start_time - the simulation time for the first data line (default 0.0)</li>
<li>dt - the time step used for output</li>
<li>NX, NY - the integer dimensions of the network</li>
<li>SEP_X, SEP_Y - the x,y distances between cells (optional)</li>
<li>x0, y0, z0 - the location of the compartment (data source) relative to the
cell origin</li>
</ul>

<p>The RUNID string and the last five parameters are not read or used
by netview.  These are available for other data analysis tools that
need a RUNID and the location of each source.</p>

<p>The slider bars can be used to set a time window for display, and the
<strong>Reset</strong> button can set t_min and t_max back to the defaults.
Use the <strong>Forward/Back</strong> toggle to reverse direction of
<strong>Play</strong>, and the <strong>Normal/Fast</strong> toggle to show
every tenth frame.</p> <p>The <strong>Single Step</strong> button can be
used to advance a single step at a time (or 10, if in 'Fast' mode).</p>

<p>The <strong>STOP</strong> button is currently not implemented</p>
<p>To plot different data, enter a new filename with <strong>File/Open</strong> and
repeat with <strong>New Data</strong> and <strong>Play</strong>.</p>

<HR>
</BODY>
</HTML>
        """

        def __init__(self, parent):
            wx.Frame.__init__(self,
                              parent,
                              -1,
                              "Usage and Help",
                              size=(640, 600),
                              pos=(400, 100))
            html = wx.html.HtmlWindow(self)
            html.SetPage(self.text)
            panel = wx.Panel(self, -1)
            button = wx.Button(panel, wx.ID_OK, "Close")
            self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(html, 1, wx.EXPAND | wx.ALL, 5)
            sizer.Add(panel, 0, wx.ALIGN_CENTER | wx.ALL, 5)
            self.SetSizer(sizer)
            self.Layout()

        def OnCloseMe(self, event):
            self.Close(True)

        # ----------- end of class UsageFrame ---------------

    def OnUsage(self, event):
        usagewin = self.UsageFrame(self)
        usagewin.Show(True)

    def OnInfo(self, event):
        msg = "Program information for PlotFrame obtained from docstrings:"
        msg += "\n" + self.__doc__ + "\n" + self.create_main_panel.__doc__
        msg += self.create_button_bar.__doc__
        msg += self.init_plot.__doc__
        msg += self.plot_data.__doc__
        dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg,
                                                   "PlotFrame Documentation")
        dlg.ShowModal()

    #  ---------------------------------------------------------------
    #	Define the functions executed on control button click
    #  ---------------------------------------------------------------

    def OnRewind(self, event):
        self.get_data_params()
        self.init_plot()
        self.get_xyt_data()

    def OnReplot(self, event):
        self.plot_data()
        self.canvas.draw()

    def OnSstep(self, event):
        if self.data_loaded == False:
            # bring up a warning dialog
            msg = """
            Data for plotting has not been loaded!
            Please enter the file to plot with File/Open, unless
            it was already specified, and then click on 'New Data'
            to load the data to play back, before clicking 'Play'.
            """
            wx.MessageBox(msg, "Plot Warning", wx.OK | wx.ICON_ERROR, self)
            return

        self.t_max = min(self.t_max + self.dt, (self.Ntimes - 1) * self.dt)
        self.stmax.set_val(self.t_max)
        frame_num = int(self.t_max / self.dt)
        self.SetStatusText('time: ' + str(frame_num * self.dt))
        self.im.set_data(self.ldata[frame_num])
        self.axes.draw_artist(self.im)
        self.canvas.blit(self.axes.bbox)

    def OnStop(self, event):
        self.STOP = 'True'

    def OnForward(self, event):
        state = self.forward_toggle.GetValue()
        if state:
            self.reverse_play = False
            self.forward_toggle.SetLabel("Forward ")
            self.forward_toggle.SetForegroundColour('black')
            self.forward_toggle.SetBackgroundColour('yellow')
        else:
            self.reverse_play = True
            self.forward_toggle.SetLabel("  Back  ")
            self.forward_toggle.SetForegroundColour('red')
            self.forward_toggle.SetBackgroundColour('green')

    def OnFast(self, event):
        state = self.fast_toggle.GetValue()
        if state:
            # print state
            self.fast_toggle.SetLabel(" Normal ")
            self.fast_toggle.SetForegroundColour('black')
            self.fast_toggle.SetBackgroundColour('yellow')
            self.step = 1
        else:
            # print state
            self.fast_toggle.SetLabel("  Fast  ")
            self.fast_toggle.SetForegroundColour('red')
            self.fast_toggle.SetBackgroundColour('green')
            self.step = 10
Example #4
0
class AtlasEditor(plot_support.ImageSyncMixin):
    """Graphical interface to view an atlas in multiple orthogonal 
    dimensions and edit atlas labels.
    
    :attr:`plot_eds` are dictionaries of keys specified by one of
    :const:`magmap.config.PLANE` plane orientations to Plot Editors.
    
    Attributes:
        image5d: Numpy image array in t,z,y,x,[c] format.
        labels_img: Numpy image array in z,y,x format.
        channel: Channel of the image to display.
        offset: Index of plane at which to start viewing in x,y,z (user) 
            order.
        fn_close_listener: Handle figure close events.
        borders_img: Numpy image array in z,y,x,[c] format to show label 
            borders, such as that generated during label smoothing. 
            Defaults to None. If this image has a different number of 
            labels than that of ``labels_img``, a new colormap will 
            be generated.
        fn_show_label_3d: Function to call to show a label in a 
            3D viewer. Defaults to None.
        title (str): Window title; defaults to None.
        fn_refresh_atlas_eds (func): Callback for refreshing other
            Atlas Editors to synchronize them; defaults to None.
            Typically takes one argument, this ``AtlasEditor`` object
            to refreshing it. Defaults to None.
        alpha_slider: Matplotlib alpha slider control.
        alpha_reset_btn: Maplotlib button for resetting alpha transparency.
        alpha_last: Float specifying the previous alpha value.
        interp_planes: Current :class:`InterpolatePlanes` object.
        interp_btn: Matplotlib button to initiate plane interpolation.
        save_btn: Matplotlib button to save the atlas.
        fn_status_bar (func): Function to call during status bar updates
            in :class:`pixel_display.PixelDisplay`; defaults to None.
        fn_update_coords (func): Handler for coordinate updates, which
            takes coordinates in z-plane orientation; defaults to None.
    """

    _EDIT_BTN_LBLS = ("Edit", "Editing")

    def __init__(self,
                 image5d,
                 labels_img,
                 channel,
                 offset,
                 fn_close_listener,
                 borders_img=None,
                 fn_show_label_3d=None,
                 title=None,
                 fn_refresh_atlas_eds=None,
                 fig=None,
                 fn_status_bar=None):
        """Plot ROI as sequence of z-planes containing only the ROI itself."""
        super().__init__()
        self.image5d = image5d
        self.labels_img = labels_img
        self.channel = channel
        self.offset = offset
        self.fn_close_listener = fn_close_listener
        self.borders_img = borders_img
        self.fn_show_label_3d = fn_show_label_3d
        self.title = title
        self.fn_refresh_atlas_eds = fn_refresh_atlas_eds
        self.fig = fig
        self.fn_status_bar = fn_status_bar

        self.alpha_slider = None
        self.alpha_reset_btn = None
        self.alpha_last = None
        self.interp_planes = None
        self.interp_btn = None
        self.save_btn = None
        self.edit_btn = None
        self.color_picker_box = None
        self.fn_update_coords = None

        self._labels_img_sitk = None  # for saving labels image

    def show_atlas(self):
        """Set up the atlas display with multiple orthogonal views."""
        # set up the figure
        if self.fig is None:
            fig = figure.Figure(self.title)
            self.fig = fig
        else:
            fig = self.fig
        fig.clear()
        gs = gridspec.GridSpec(2,
                               1,
                               wspace=0.1,
                               hspace=0.1,
                               height_ratios=(20, 1),
                               figure=fig,
                               left=0.06,
                               right=0.94,
                               bottom=0.02,
                               top=0.98)
        gs_viewers = gridspec.GridSpecFromSubplotSpec(2,
                                                      2,
                                                      subplot_spec=gs[0, 0])

        # set up a colormap for the borders image if present
        cmap_borders = colormaps.get_borders_colormap(self.borders_img,
                                                      self.labels_img,
                                                      config.cmap_labels)
        coord = list(self.offset[::-1])

        # editor controls, split into a slider sub-spec to allow greater
        # spacing for labels on either side and a separate sub-spec for
        # buttons and other fields
        gs_controls = gridspec.GridSpecFromSubplotSpec(1,
                                                       2,
                                                       subplot_spec=gs[1, 0],
                                                       width_ratios=(1, 1),
                                                       wspace=0.15)
        self.alpha_slider = Slider(
            fig.add_subplot(gs_controls[0, 0]),
            "Opacity",
            0.0,
            1.0,
            valinit=plot_editor.PlotEditor.ALPHA_DEFAULT)
        gs_controls_btns = gridspec.GridSpecFromSubplotSpec(
            1, 5, subplot_spec=gs_controls[0, 1], wspace=0.1)
        self.alpha_reset_btn = Button(fig.add_subplot(gs_controls_btns[0, 0]),
                                      "Reset")
        self.interp_btn = Button(fig.add_subplot(gs_controls_btns[0, 1]),
                                 "Fill Label")
        self.interp_planes = InterpolatePlanes(self.interp_btn)
        self.interp_planes.update_btn()
        self.save_btn = Button(fig.add_subplot(gs_controls_btns[0, 2]), "Save")
        self.edit_btn = Button(fig.add_subplot(gs_controls_btns[0, 3]), "Edit")
        self.color_picker_box = TextBox(
            fig.add_subplot(gs_controls_btns[0, 4]), None)

        # adjust button colors based on theme and enabled status; note
        # that colors do not appear to refresh until fig mouseover
        for btn in (self.alpha_reset_btn, self.edit_btn):
            enable_btn(btn)
        enable_btn(self.save_btn, False)
        enable_btn(self.color_picker_box, color=config.widget_color + 0.1)

        def setup_plot_ed(axis, gs_spec):
            # set up a PlotEditor for the given axis

            # subplot grid, with larger height preference for plot for
            # each increased row to make sliders of approx equal size and
            # align top borders of top images
            rows_cols = gs_spec.get_rows_columns()
            extra_rows = rows_cols[3] - rows_cols[2]
            gs_plot = gridspec.GridSpecFromSubplotSpec(
                2,
                1,
                subplot_spec=gs_spec,
                height_ratios=(1, 10 + 14 * extra_rows),
                hspace=0.1 / (extra_rows * 1.4 + 1))

            # transform arrays to the given orthogonal direction
            ax = fig.add_subplot(gs_plot[1, 0])
            plot_support.hide_axes(ax)
            plane = config.PLANE[axis]
            arrs_3d, aspect, origin, scaling = \
                plot_support.setup_images_for_plane(
                    plane,
                    (self.image5d[0], self.labels_img, self.borders_img))
            img3d_tr, labels_img_tr, borders_img_tr = arrs_3d

            # slider through image planes
            ax_scroll = fig.add_subplot(gs_plot[0, 0])
            plane_slider = Slider(ax_scroll,
                                  plot_support.get_plane_axis(plane),
                                  0,
                                  len(img3d_tr) - 1,
                                  valfmt="%d",
                                  valinit=0,
                                  valstep=1)

            # plot editor
            max_size = max_sizes[axis] if max_sizes else None
            plot_ed = plot_editor.PlotEditor(
                ax,
                img3d_tr,
                labels_img_tr,
                config.cmap_labels,
                plane,
                aspect,
                origin,
                self.update_coords,
                self.refresh_images,
                scaling,
                plane_slider,
                img3d_borders=borders_img_tr,
                cmap_borders=cmap_borders,
                fn_show_label_3d=self.fn_show_label_3d,
                interp_planes=self.interp_planes,
                fn_update_intensity=self.update_color_picker,
                max_size=max_size,
                fn_status_bar=self.fn_status_bar)
            return plot_ed

        # setup plot editors for all 3 orthogonal directions
        max_sizes = plot_support.get_downsample_max_sizes()
        for i, gs_viewer in enumerate(
            (gs_viewers[:2, 0], gs_viewers[0, 1], gs_viewers[1, 1])):
            self.plot_eds[config.PLANE[i]] = setup_plot_ed(i, gs_viewer)
        self.set_show_crosslines(True)

        # attach listeners
        fig.canvas.mpl_connect("scroll_event", self.scroll_overview)
        fig.canvas.mpl_connect("key_press_event", self.on_key_press)
        fig.canvas.mpl_connect("close_event", self._close)
        fig.canvas.mpl_connect("axes_leave_event", self.axes_exit)

        self.alpha_slider.on_changed(self.alpha_update)
        self.alpha_reset_btn.on_clicked(self.alpha_reset)
        self.interp_btn.on_clicked(self.interpolate)
        self.save_btn.on_clicked(self.save_atlas)
        self.edit_btn.on_clicked(self.toggle_edit_mode)
        self.color_picker_box.on_text_change(self.color_picker_changed)

        # initialize and show planes in all plot editors
        if self._max_intens_proj is not None:
            self.update_max_intens_proj(self._max_intens_proj)
        self.update_coords(coord, config.PLANE[0])

        plt.ion()  # avoid the need for draw calls

    def _close(self, evt):
        """Handle figure close events by calling :attr:`fn_close_listener`
        with this object.

        Args:
            evt (:obj:`matplotlib.backend_bases.CloseEvent`): Close event.

        """
        self.fn_close_listener(evt, self)

    def on_key_press(self, event):
        """Respond to key press events.
        """
        if event.key == "a":
            # toggle between current and 0 opacity
            if self.alpha_slider.val == 0:
                # return to saved alpha if available and reset
                if self.alpha_last is not None:
                    self.alpha_slider.set_val(self.alpha_last)
                self.alpha_last = None
            else:
                # make translucent, saving alpha if not already saved
                # during a halve-opacity event
                if self.alpha_last is None:
                    self.alpha_last = self.alpha_slider.val
                self.alpha_slider.set_val(0)
        elif event.key == "A":
            # halve opacity, only saving alpha on first halving to allow
            # further halving or manual movements while still returning to
            # originally saved alpha
            if self.alpha_last is None:
                self.alpha_last = self.alpha_slider.val
            self.alpha_slider.set_val(self.alpha_slider.val / 2)
        elif event.key == "up" or event.key == "down":
            # up/down arrow for scrolling planes
            self.scroll_overview(event)
        elif event.key == "w":
            # shortcut to toggle editing mode
            self.toggle_edit_mode(event)
        elif event.key == "ctrl+s" or event.key == "cmd+s":
            # support default save shortcuts on multiple platforms;
            # ctrl-s will bring up save dialog from fig, but cmd/win-S
            # will bypass
            self.save_fig(self.get_save_path())

    def update_coords(self, coord, plane_src=config.PLANE[0]):
        """Update all plot editors with given coordinates.
        
        Args:
            coord: Coordinate at which to center images, in z,y,x order.
            plane_src: One of :const:`magmap.config.PLANE` to specify the 
                orientation from which the coordinates were given; defaults 
                to the first element of :const:`magmap.config.PLANE`.
        """
        coord_rev = libmag.transpose_1d_rev(list(coord), plane_src)
        for i, plane in enumerate(config.PLANE):
            coord_transposed = libmag.transpose_1d(list(coord_rev), plane)
            if i == 0:
                self.offset = coord_transposed[::-1]
                if self.fn_update_coords:
                    # update offset based on xy plane, without centering
                    # planes are centered on the offset as-is
                    self.fn_update_coords(coord_transposed, False)
            self.plot_eds[plane].update_coord(coord_transposed)

    def view_subimg(self, offset, shape):
        """Zoom all Plot Editors to the given sub-image.

        Args:
            offset: Sub-image coordinates in ``z,y,x`` order.
            shape: Sub-image shape in ``z,y,x`` order.
        
        """
        for i, plane in enumerate(config.PLANE):
            offset_tr = libmag.transpose_1d(list(offset), plane)
            shape_tr = libmag.transpose_1d(list(shape), plane)
            self.plot_eds[plane].view_subimg(offset_tr[1:], shape_tr[1:])
        self.fig.canvas.draw_idle()

    def refresh_images(self, plot_ed=None, update_atlas_eds=False):
        """Refresh images in a plot editor, such as after editing one
        editor and updating the displayed image in the other editors.
        
        Args:
            plot_ed (:obj:`magmap.plot_editor.PlotEditor`): Editor that
                does not need updating, typically the editor that originally
                changed. Defaults to None.
            update_atlas_eds (bool): True to update other ``AtlasEditor``s;
                defaults to False.
        """
        for key in self.plot_eds:
            ed = self.plot_eds[key]
            if ed != plot_ed: ed.refresh_img3d_labels()
            if ed.edited:
                # display save button as enabled if any editor has been edited
                enable_btn(self.save_btn)
        if update_atlas_eds and self.fn_refresh_atlas_eds is not None:
            # callback to synchronize other Atlas Editors
            self.fn_refresh_atlas_eds(self)

    def scroll_overview(self, event):
        """Scroll images and crosshairs in all plot editors
        
        Args:
            event: Scroll event.
        """
        for key in self.plot_eds:
            self.plot_eds[key].scroll_overview(event)

    def alpha_update(self, event):
        """Update the alpha transparency in all plot editors.
        
        Args:
            event: Slider event.
        """
        for key in self.plot_eds:
            self.plot_eds[key].alpha_updater(event)

    def alpha_reset(self, event):
        """Reset the alpha transparency in all plot editors.
        
        Args:
            event: Button event, currently ignored.
        """
        self.alpha_slider.reset()

    def axes_exit(self, event):
        """Trigger axes exit for all plot editors.
        
        Args:
            event: Axes exit event.
        """
        for key in self.plot_eds:
            self.plot_eds[key].on_axes_exit(event)

    def interpolate(self, event):
        """Interpolate planes using :attr:`interp_planes`.
        
        Args:
            event: Button event, currently ignored.
        """
        try:
            self.interp_planes.interpolate(self.labels_img)
            # flag Plot Editors as edited so labels can be saved
            for ed in self.plot_eds.values():
                ed.edited = True
            self.refresh_images(None, True)
        except ValueError as e:
            print(e)

    def save_atlas(self, event):
        """Save atlas labels using the registered image suffix given by
        :attr:`config.reg_suffixes[config.RegSuffixes.ANNOTATION]`.
        
        Args:
            event: Button event, currently not used.
        
        """
        # only save if at least one editor has been edited
        if not any([ed.edited for ed in self.plot_eds.values()]): return

        # save to the labels reg suffix; use sitk Image if loaded and store
        # any Image loaded during saving
        reg_name = config.reg_suffixes[config.RegSuffixes.ANNOTATION]
        if self._labels_img_sitk is None:
            self._labels_img_sitk = config.labels_img_sitk
        self._labels_img_sitk = sitk_io.write_registered_image(
            self.labels_img,
            config.filename,
            reg_name,
            self._labels_img_sitk,
            overwrite=True)

        # reset edited flag in all editors and show save button as disabled
        for ed in self.plot_eds.values():
            ed.edited = False
        enable_btn(self.save_btn, False)
        print("Saved labels image at {}".format(datetime.datetime.now()))

    def get_save_path(self):
        """Get figure save path based on filename, ROI, and overview plane
         shown.
        
        Returns:
            str: Figure save path.

        """
        ext = config.savefig if config.savefig else config.DEFAULT_SAVEFIG
        return "{}.{}".format(
            naming.get_roi_path(os.path.basename(self.title), self.offset),
            ext)

    def toggle_edit_mode(self, event):
        """Toggle editing mode, determining the current state from the
        first :class:`magmap.plot_editor.PlotEditor` and switching to the 
        opposite value for all plot editors.

        Args:
            event: Button event, currently not used.
        """
        edit_mode = False
        for i, ed in enumerate(self.plot_eds.values()):
            if i == 0:
                # change edit mode based on current mode in first plot editor
                edit_mode = not ed.edit_mode
                toggle_btn(self.edit_btn, edit_mode, text=self._EDIT_BTN_LBLS)
            ed.edit_mode = edit_mode
        if not edit_mode:
            # reset the color picker text box when turning off editing
            self.color_picker_box.set_val("")

    def update_color_picker(self, val):
        """Update the color picker :class:`TextBox` with the given value.

        Args:
            val (str): Color value. If None, only :meth:`color_picker_changed`
                will be triggered.
        """
        if val is None:
            # updated picked color directly
            self.color_picker_changed(val)
        else:
            # update text box, which triggers color_picker_changed
            self.color_picker_box.set_val(val)

    def color_picker_changed(self, text):
        """Respond to color picker :class:`TextBox` changes by updating
        the specified intensity value in all plot editors.

        Args:
            text (str): String of text box value. Converted to an int if
                non-empty.
        """
        intensity = text
        if text:
            if not libmag.is_number(intensity): return
            intensity = int(intensity)
        print("updating specified color to", intensity)
        for i, ed in enumerate(self.plot_eds.values()):
            ed.intensity_spec = intensity
def update(val):
    amp = samp.val
    freq = sfreq.val
    l.set_ydata(amp*np.sin(2*np.pi*freq*t))
    fig.canvas.draw_idle()
sfreq.on_changed(update)
samp.on_changed(update)

resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')


def reset(event):
    sfreq.reset()
    samp.reset()
button.on_clicked(reset)

rax = plt.axes([0.025, 0.5, 0.15, 0.15], facecolor=axcolor)
radio = RadioButtons(rax, ('red', 'blue', 'green'), active=0)


def colorfunc(label):
    l.set_color(label)
    fig.canvas.draw_idle()
radio.on_clicked(colorfunc)

plt.show()


print (input("Fin ej 017_16 \n		continuar?"));
Example #6
0
def update_mrt1(val):
    global mrt1_point
    s = mrt1_slice.val
    axes[1].clear()
    axes[1].set(title="MR_T1")
    axes[1].imshow(mrt1_array[s], cmap='gray')
    axes[1].axis("off")
    for point in mrt1_point:
        z, x, y = point
        if s == z:
            axes[1].scatter(x, y, marker="+", c='yellow')


ct_slice.on_changed(update_ct)
ct_slice.reset()
ct_slice.set_val(0)

mrt1_slice.on_changed(update_mrt1)
mrt1_slice.reset()
mrt1_slice.set_val(0)


# 定义鼠标交互
def on_press(event):
    global ct_point, mrt1_point
    x_coord, y_coord = event.xdata, event.ydata
    if event.inaxes == axes[0]:
        z_coord = ct_slice.val
        ct_point.append([z_coord, x_coord, y_coord])
        axes[0].scatter(x_coord, y_coord, marker="+", c='lime')
Example #7
0
class Environment():
    def __init__(self, xBoundary, yBoundary, obs):
        self.xb = xBoundary  # of the form [ax, bx]
        self.yb = yBoundary  # of the form [ay, by]
        self.obstacles = obs  # of the form [[x0, y0,r0],[x1, y1, r1],[x2, y2, r2],...]
        print(self.obstacles)
        self.fig, self.ax = plt.subplots()
        plt.subplots_adjust(bottom=0.45, left=0.1)
        #setting the sliders
        self.axcolor = "lightgoldenrodyellow"
        # setting sliders for start pose
        self.axAngle1 = plt.axes(
            [0.2, 0.35, 0.2, 0.01], facecolor=self.axcolor
        )  #[distance from left, distance from bottom, length, width]
        self.axPos1x = plt.axes([0.2, 0.30, 0.2, 0.01], facecolor=self.axcolor)
        self.axPos1y = plt.axes([0.2, 0.25, 0.2, 0.01], facecolor=self.axcolor)
        # setting sliders for goal pose
        self.axAngle2 = plt.axes([0.6, 0.35, 0.2, 0.01],
                                 facecolor=self.axcolor)
        self.axPos2x = plt.axes([0.6, 0.30, 0.2, 0.01], facecolor=self.axcolor)
        self.axPos2y = plt.axes([0.6, 0.25, 0.2, 0.01], facecolor=self.axcolor)
        #setting the radius
        self.axRadius = plt.axes([0.2, 0.20, 0.2, 0.01],
                                 facecolor=self.axcolor)
        #creating sliders
        self.sAngle1 = Slider(self.axAngle1,
                              'Yaw 1 (deg)',
                              0,
                              360,
                              valinit=0,
                              valstep=5)
        self.sAngle2 = Slider(self.axAngle2,
                              'Yaw 2 (deg)',
                              0,
                              360,
                              valinit=90,
                              valstep=5)
        self.sRadius = Slider(self.axRadius,
                              'Radius (m)',
                              0,
                              2.33,
                              valinit=2.33,
                              valstep=0.1)
        self.sPos1x = Slider(self.axPos1x,
                             'pos1 x',
                             -10,
                             10,
                             valinit=0,
                             valstep=0.1)
        self.sPos2x = Slider(self.axPos2x,
                             'pos2 x',
                             -10,
                             10,
                             valinit=5,
                             valstep=0.1)
        self.sPos1y = Slider(self.axPos1y,
                             'pos1 y',
                             -10,
                             10,
                             valinit=0,
                             valstep=0.1)
        self.sPos2y = Slider(self.axPos2y,
                             'pos2 y',
                             -10,
                             10,
                             valinit=5,
                             valstep=0.1)
        #create a reset button
        self.resetax = plt.axes([0.8, 0.05, 0.1, 0.04])
        self.resetButton = Button(self.resetax,
                                  'Reset',
                                  color=self.axcolor,
                                  hovercolor='0.975')

    def plot_setup(self):
        self.ax.cla()
        self.ax.set_xlim(self.xb[0], self.xb[1])
        self.ax.set_aspect('equal')
        self.ax.set_ylim(self.yb[0], self.yb[1])
        self.plot_obstacles()

    def update(self, val):
        angle1 = self.sAngle1.val
        angle2 = self.sAngle2.val
        radius = self.sRadius.val
        pos1x = self.sPos1x.val
        pos2x = self.sPos2x.val
        pos1y = self.sPos1y.val
        pos2y = self.sPos2y.val

        self.plot_setup()

        self.ax.arrow(pos1x,
                      pos1y,
                      m.cos(wrapToPi(m.radians(angle1))),
                      m.sin(wrapToPi(m.radians(angle1))),
                      head_width=0.1,
                      head_length=0.5)
        self.ax.arrow(pos2x,
                      pos2y,
                      m.cos(wrapToPi(m.radians(angle2))),
                      m.sin(wrapToPi(m.radians(angle2))),
                      head_width=0.1,
                      head_length=0.5)

        # now we have got angles and we know start and end exactly
        start = [pos1x, pos1y, wrapToPi(m.radians(angle1))]
        goal = [pos2x, pos2y, wrapToPi(m.radians(angle2))]

        px, py = RSP_path(start, goal, radius)

        # now we need to plot it
        self.ax.plot(px, py, 'r')

    def reset_it(self, event):
        self.sAngle1.reset()
        self.sAngle2.reset()
        self.sRadius.reset()
        self.sPos1x.reset()
        self.sPos2x.reset()

    def set_sliders(self):
        # set the update loop
        self.sAngle1.on_changed(self.update)
        self.sAngle2.on_changed(self.update)
        self.sRadius.on_changed(self.update)
        self.sPos1x.on_changed(self.update)
        self.sPos2x.on_changed(self.update)
        self.sPos1y.on_changed(self.update)
        self.sPos2y.on_changed(self.update)
        self.resetButton.on_clicked(self.reset_it)

    def plot_obstacles(self):
        # source : https://stackoverflow.com/questions/9215658/plot-a-circle-with-pyplot
        for ob in self.obstacles:
            c = plt.Circle((ob[0], ob[1]), ob[2], color='k')
            self.ax.add_artist(c)
class PhasePlaneInteractive(object):
    """
    An interactive phase-plane plot generated from a TVB model object.

    A TVB integrator object will be use for generating sample trajectories
    -- not the phase-plane. This is mainly interesting for visualising
    the effect of noise on a trajectory.
    """


    def __init__(self, model, integrator):
        self.log = get_logger(self.__class__.__module__)
        self.model = model
        self.integrator = integrator
        #Make sure the model is fully configured...
        self.model.configure()
        self.model.update_derived_parameters()


    def get_required_memory_size(self, **kwargs):
        """
        Return the required memory to run this algorithm.
        """
        # Don't know how much memory is needed.
        return -1


    def draw_phase_plane(self):
        """Generate the interactive phase-plane figure."""
        self.log.debug("Plot started...")

        model_name = self.model.__class__.__name__
        msg = "Generating an interactive phase-plane plot for %s"
        self.log.info(msg % model_name)

        self.svx = self.model.state_variables[0]  # x-axis: 1st state variable
        self.svy = self.model.state_variables[1]  # y-axis: 2nd state variable
        self.mode = 0

        self._set_state_vector()

        #TODO: see how we can get the figure size from the UI to better 'fit' the encompassing div
        self.ipp_fig = pylab.figure(figsize=(10, 8))
        pylab.clf()
        self.pp_ax = self.ipp_fig.add_axes([0.265, 0.2, 0.7, 0.75])

        self.pp_splt = self.ipp_fig.add_subplot(212)
        self.ipp_fig.subplots_adjust(left=0.265, bottom=0.02, right=0.75, top=0.3, wspace=0.1, hspace=None)
        self.pp_splt.set_color_cycle(get_color(self.model.nvar))
        self.pp_splt.plot(numpy.arange(TRAJ_STEPS + 1) * self.integrator.dt,
                          numpy.zeros((TRAJ_STEPS + 1, self.model.nvar)))
        if hasattr(self.pp_splt, 'autoscale'):
            self.pp_splt.autoscale(enable=True, axis='y', tight=True)
        self.pp_splt.legend(self.model.state_variables)

        #Selectors
        self._add_state_variable_selector()
        self._add_mode_selector()

        #Sliders
        self._add_axes_range_sliders()
        self._add_state_variable_sliders()
        if isinstance(self.integrator, integrators_module.IntegratorStochastic):
            if self.integrator.noise.ntau > 0.0:
                self.integrator.noise.configure_coloured(self.integrator.dt,
                                                         (1, self.model.nvar, 1, self.model.number_of_modes))
            else:
                self.integrator.noise.configure_white(self.integrator.dt,
                                                      (1, self.model.nvar, 1, self.model.number_of_modes))

            self._add_noise_slider()
            self._add_reset_noise_button()
            self._add_reset_seed_button()

        #Reset buttons
        #self._add_reset_param_button()
        self._add_reset_sv_button()
        self._add_reset_axes_button()

        #Calculate the phase plane
        self._set_mesh_grid()
        self._calc_phase_plane()

        #Plot phase plane
        self._plot_phase_plane()

        # add mouse handler for trajectory clicking
        self.ipp_fig.canvas.mpl_connect('button_press_event', self._click_trajectory)
        self.ipp_fig.canvas.draw()

        return dict(serverIp=config.SERVER_IP, serverPort=config.MPLH5_SERVER_PORT,
                    figureNumber=self.ipp_fig.number, showFullToolbar=False)


    def _add_state_variable_selector(self):
        """
        Generate radio selector buttons to set which state variable is
        displayed on the x and y axis of the phase-plane plot.
        """
        svx_ind = self.model.state_variables.index(self.svx)
        svy_ind = self.model.state_variables.index(self.svy)

        #State variable for the x axis
        pos_shp = [0.08, 0.07, 0.065, 0.12 + 0.006 * self.model.nvar]
        rax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR, title="x-axis")
        self.state_variable_x = RadioButtons(rax, tuple(self.model.state_variables), active=svx_ind)
        self.state_variable_x.on_clicked(self._update_svx)

        #State variable for the y axis
        pos_shp = [0.16, 0.07, 0.065, 0.12 + 0.006 * self.model.nvar]
        rax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR, title="y-axis")
        self.state_variable_y = RadioButtons(rax, tuple(self.model.state_variables), active=svy_ind)
        self.state_variable_y.on_clicked(self._update_svy)


    def _add_mode_selector(self):
        """
        Add a radio button to the figure for selecting which mode of the model
        should be displayed.
        """
        pos_shp = [0.02, 0.07, 0.04, 0.1 + 0.002 * self.model.number_of_modes]
        rax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR, title="Mode")
        mode_tuple = tuple(range(self.model.number_of_modes))
        self.mode_selector = RadioButtons(rax, mode_tuple, active=0)
        self.mode_selector.on_clicked(self._update_mode)


    def _add_axes_range_sliders(self):
        """
        Add sliders to the figure to allow the phase-planes axes to be set.
        """
        self.axes_range_sliders = dict()

        default_range_x = (self.model.state_variable_range[self.svx][1] -
                           self.model.state_variable_range[self.svx][0])
        default_range_y = (self.model.state_variable_range[self.svy][1] -
                           self.model.state_variable_range[self.svy][0])
        min_val_x = self.model.state_variable_range[self.svx][0] - 4.0 * default_range_x
        max_val_x = self.model.state_variable_range[self.svx][1] + 4.0 * default_range_x
        min_val_y = self.model.state_variable_range[self.svy][0] - 4.0 * default_range_y
        max_val_y = self.model.state_variable_range[self.svy][1] + 4.0 * default_range_y

        sax = self.ipp_fig.add_axes([0.04, 0.835, 0.125, 0.025],
                                    axisbg=AXCOLOUR)
        sl_x_min = Slider(sax, "xlo", min_val_x, max_val_x,
                          valinit=self.model.state_variable_range[self.svx][0])
        sl_x_min.on_changed(self._update_range)

        sax = self.ipp_fig.add_axes([0.04, 0.8, 0.125, 0.025], axisbg=AXCOLOUR)
        sl_x_max = Slider(sax, "xhi", min_val_x, max_val_x, valinit=self.model.state_variable_range[self.svx][1])
        sl_x_max.on_changed(self._update_range)

        sax = self.ipp_fig.add_axes([0.04, 0.765, 0.125, 0.025], axisbg=AXCOLOUR)
        sl_y_min = Slider(sax, "ylo", min_val_y, max_val_y, valinit=self.model.state_variable_range[self.svy][0])
        sl_y_min.on_changed(self._update_range)

        sax = self.ipp_fig.add_axes([0.04, 0.73, 0.125, 0.025], axisbg=AXCOLOUR)
        sl_y_max = Slider(sax, "yhi", min_val_y, max_val_y, valinit=self.model.state_variable_range[self.svy][1])
        sl_y_max.on_changed(self._update_range)

        self.axes_range_sliders["sl_x_min"] = sl_x_min
        self.axes_range_sliders["sl_x_max"] = sl_x_max
        self.axes_range_sliders["sl_y_min"] = sl_y_min
        self.axes_range_sliders["sl_y_max"] = sl_y_max


    def _add_state_variable_sliders(self):
        """
        Add sliders to the figure to allow default values for the models state
        variable to be set.
        """
        msv_range = self.model.state_variable_range
        offset = 0.0
        self.sv_sliders = dict()
        for sv in range(self.model.nvar):
            offset += 0.035
            pos_shp = [0.04, 0.6 - offset, 0.125, 0.025]
            sax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR)
            sv_str = self.model.state_variables[sv]
            self.sv_sliders[sv_str] = Slider(sax, sv_str, msv_range[sv_str][0],
                                             msv_range[sv_str][1], valinit=self.default_sv[sv, 0, 0])
            self.sv_sliders[sv_str].on_changed(self._update_state_variables)


    def _add_noise_slider(self):
        """
        Add a slider to the figure to allow the integrators noise strength to
        be set.
        """
        pos_shp = [0.04, 0.365, 0.125, 0.025]
        sax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR)

        self.noise_slider = Slider(sax, "Noise", 0.0, 1.0, valinit=self.integrator.noise.nsig)
        self.noise_slider.on_changed(self._update_noise)


    def _add_reset_sv_button(self):
        """
        Add a button to the figure for reseting the model state variables to
        their default values.
        """
        bax = self.ipp_fig.add_axes([0.04, 0.60, 0.125, 0.04])
        self.reset_sv_button = Button(bax, 'Reset state-variables', color=BUTTONCOLOUR, hovercolor=HOVERCOLOUR)


        def reset_state_variables(event):
            for svsl in self.sv_sliders.itervalues():
                svsl.reset()


        self.reset_sv_button.on_clicked(reset_state_variables)


    def _add_reset_noise_button(self):
        """
        Add a button to the figure for reseting the noise to its default value.
        """
        bax = self.ipp_fig.add_axes([0.04, 0.4, 0.125, 0.04])
        self.reset_noise_button = Button(bax, 'Reset noise strength', color=BUTTONCOLOUR, hovercolor=HOVERCOLOUR)


        def reset_noise(event):
            self.noise_slider.reset()


        self.reset_noise_button.on_clicked(reset_noise)


    def _add_reset_seed_button(self):
        """
        Add a button to the figure for reseting the random number generator to
        its intial state. For reproducible noise...
        """
        bax = self.ipp_fig.add_axes([0.04, 0.315, 0.125, 0.04])
        self.reset_seed_button = Button(bax, 'Reset random stream', color=BUTTONCOLOUR, hovercolor=HOVERCOLOUR)


        def reset_seed(event):
            self.integrator.noise.trait["random_stream"].reset()


        self.reset_seed_button.on_clicked(reset_seed)


    def _add_reset_axes_button(self):
        """
        Add a button to the figure for reseting the phase-plane axes to their
        default ranges.
        """
        bax = self.ipp_fig.add_axes([0.04, 0.87, 0.125, 0.04])
        self.reset_axes_button = Button(bax, 'Reset axes', color=BUTTONCOLOUR, hovercolor=HOVERCOLOUR)


        def reset_ranges(event):
            self.axes_range_sliders["sl_x_min"].reset()
            self.axes_range_sliders["sl_x_max"].reset()
            self.axes_range_sliders["sl_y_min"].reset()
            self.axes_range_sliders["sl_y_max"].reset()


        self.reset_axes_button.on_clicked(reset_ranges)


    ##------------------------------------------------------------------------##
    ##------------------- Functions for updating the figure ------------------##
    ##------------------------------------------------------------------------##

    #NOTE: All the ax.set_xlim, poly.xy, etc, garbage below is fragile. It works 
    #      at the moment, but there are currently bugs in Slider and the hackery
    #      below takes these into account... If the bugs are fixed/changed then
    #      this could break. As an example, the Slider doc says poly is a
    #      Rectangle, but it's actually a Polygon. The Slider set_val method 
    #      assumes a Rectangle even though this is not the case, so the array 
    #      Slider.poly.xy is corrupted by that method. The corruption isn't 
    #      visible in the plot, which is probably why it hasn't been fixed...

    def update_xrange_sliders(self):
        """
        """
        default_range_x = (self.model.state_variable_range[self.svx][1] -
                           self.model.state_variable_range[self.svx][0])
        min_val_x = self.model.state_variable_range[self.svx][0] - 4.0 * default_range_x
        max_val_x = self.model.state_variable_range[self.svx][1] + 4.0 * default_range_x
        self.axes_range_sliders["sl_x_min"].valinit = self.model.state_variable_range[self.svx][0]
        self.axes_range_sliders["sl_x_min"].valmin = min_val_x
        self.axes_range_sliders["sl_x_min"].valmax = max_val_x
        self.axes_range_sliders["sl_x_min"].ax.set_xlim(min_val_x, max_val_x)
        self.axes_range_sliders["sl_x_min"].poly.axes.set_xlim(min_val_x, max_val_x)
        self.axes_range_sliders["sl_x_min"].poly.xy[[0, 1], 0] = min_val_x
        self.axes_range_sliders["sl_x_min"].vline.set_data(
            ([self.axes_range_sliders["sl_x_min"].valinit, self.axes_range_sliders["sl_x_min"].valinit], [0, 1]))
        self.axes_range_sliders["sl_x_max"].valinit = self.model.state_variable_range[self.svx][1]
        self.axes_range_sliders["sl_x_max"].valmin = min_val_x
        self.axes_range_sliders["sl_x_max"].valmax = max_val_x
        self.axes_range_sliders["sl_x_max"].ax.set_xlim(min_val_x, max_val_x)
        self.axes_range_sliders["sl_x_max"].poly.axes.set_xlim(min_val_x, max_val_x)
        self.axes_range_sliders["sl_x_max"].poly.xy[[0, 1], 0] = min_val_x
        self.axes_range_sliders["sl_x_max"].vline.set_data(
            ([self.axes_range_sliders["sl_x_max"].valinit, self.axes_range_sliders["sl_x_max"].valinit], [0, 1]))
        self.axes_range_sliders["sl_x_min"].reset()
        self.axes_range_sliders["sl_x_max"].reset()


    def update_yrange_sliders(self):
        """
        """
        default_range_y = (self.model.state_variable_range[self.svy][1] -
                           self.model.state_variable_range[self.svy][0])
        min_val_y = self.model.state_variable_range[self.svy][0] - 4.0 * default_range_y
        max_val_y = self.model.state_variable_range[self.svy][1] + 4.0 * default_range_y
        self.axes_range_sliders["sl_y_min"].valinit = self.model.state_variable_range[self.svy][0]
        self.axes_range_sliders["sl_y_min"].valmin = min_val_y
        self.axes_range_sliders["sl_y_min"].valmax = max_val_y
        self.axes_range_sliders["sl_y_min"].ax.set_xlim(min_val_y, max_val_y)
        self.axes_range_sliders["sl_y_min"].poly.axes.set_xlim(min_val_y, max_val_y)
        self.axes_range_sliders["sl_y_min"].poly.xy[[0, 1], 0] = min_val_y
        self.axes_range_sliders["sl_y_min"].vline.set_data(
            ([self.axes_range_sliders["sl_y_min"].valinit, self.axes_range_sliders["sl_y_min"].valinit], [0, 1]))
        self.axes_range_sliders["sl_y_max"].valinit = self.model.state_variable_range[self.svy][1]
        self.axes_range_sliders["sl_y_max"].valmin = min_val_y
        self.axes_range_sliders["sl_y_max"].valmax = max_val_y
        self.axes_range_sliders["sl_y_max"].ax.set_xlim(min_val_y, max_val_y)
        self.axes_range_sliders["sl_y_max"].poly.axes.set_xlim(min_val_y, max_val_y)
        self.axes_range_sliders["sl_y_max"].poly.xy[[0, 1], 0] = min_val_y
        self.axes_range_sliders["sl_y_max"].vline.set_data(
            ([self.axes_range_sliders["sl_y_max"].valinit, self.axes_range_sliders["sl_y_max"].valinit], [0, 1]))
        self.axes_range_sliders["sl_y_min"].reset()
        self.axes_range_sliders["sl_y_max"].reset()


    def _update_svx(self, label):
        """
        Update state variable used for x-axis based on radio buttton selection.
        """
        self.svx = label
        self.update_xrange_sliders()
        self._set_mesh_grid()
        self._calc_phase_plane()
        self._update_phase_plane()


    def _update_svy(self, label):
        """
        Update state variable used for y-axis based on radio buttton selection.
        """
        self.svy = label
        self.update_yrange_sliders()
        self._set_mesh_grid()
        self._calc_phase_plane()
        self._update_phase_plane()


    def _update_mode(self, label):
        """ Update the visualised mode based on radio button selection. """
        self.mode = label
        self._update_phase_plane()


    def _update_noise(self, nsig):
        """ Update integrator noise based on the noise slider value. """
        self.integrator.noise.nsig = numpy.array([nsig, ])


    def _update_range(self, val):
        """
        Update the axes ranges based on the current axes slider values.

        NOTE: Haven't figured out how to update independently, so just update everything.
        """
        #TODO: Grab caller and use val directly, ie independent range update.
        self.axes_range_sliders["sl_x_min"].ax.set_axis_bgcolor(AXCOLOUR)
        self.axes_range_sliders["sl_x_max"].ax.set_axis_bgcolor(AXCOLOUR)
        self.axes_range_sliders["sl_y_min"].ax.set_axis_bgcolor(AXCOLOUR)
        self.axes_range_sliders["sl_y_max"].ax.set_axis_bgcolor(AXCOLOUR)
        if self.axes_range_sliders["sl_x_min"].val >= self.axes_range_sliders["sl_x_max"].val:
            self.log.error("X-axis min must be less than max...")
            self.axes_range_sliders["sl_x_min"].ax.set_axis_bgcolor("Red")
            self.axes_range_sliders["sl_x_max"].ax.set_axis_bgcolor("Red")
            return
        if self.axes_range_sliders["sl_y_min"].val >= self.axes_range_sliders["sl_y_max"].val:
            self.log.error("Y-axis min must be less than max...")
            self.axes_range_sliders["sl_y_min"].ax.set_axis_bgcolor("Red")
            self.axes_range_sliders["sl_y_max"].ax.set_axis_bgcolor("Red")
            return

        msv_range = self.model.state_variable_range
        msv_range[self.svx][0] = self.axes_range_sliders["sl_x_min"].val
        msv_range[self.svx][1] = self.axes_range_sliders["sl_x_max"].val
        msv_range[self.svy][0] = self.axes_range_sliders["sl_y_min"].val
        msv_range[self.svy][1] = self.axes_range_sliders["sl_y_max"].val
        self._set_mesh_grid()
        self._calc_phase_plane()
        self._update_phase_plane()


    def _update_phase_plane(self):
        """ Clear the axes and redraw the phase-plane. """
        self.pp_ax.clear()
        self.pp_splt.clear()
        self.pp_splt.set_color_cycle(get_color(self.model.nvar))
        self.pp_splt.plot(numpy.arange(TRAJ_STEPS + 1) * self.integrator.dt,
                          numpy.zeros((TRAJ_STEPS + 1, self.model.nvar)))
        if hasattr(self.pp_splt, 'autoscale'):
            self.pp_splt.autoscale(enable=True, axis='y', tight=True)
        self.pp_splt.legend(self.model.state_variables)
        self._plot_phase_plane()


    def _update_state_variables(self, val):
        """
        Update the default state-variable values, used for non-visualised state
        variables, based of the current slider values.
        """
        for sv in self.sv_sliders:
            k = self.model.state_variables.index(sv)
            self.default_sv[k] = self.sv_sliders[sv].val

        self._calc_phase_plane()
        self._update_phase_plane()


    def _set_mesh_grid(self):
        """
        Generate the phase-plane gridding based on currently selected statevariables
        and their range values.
        """
        xlo = self.model.state_variable_range[self.svx][0]
        xhi = self.model.state_variable_range[self.svx][1]
        ylo = self.model.state_variable_range[self.svy][0]
        yhi = self.model.state_variable_range[self.svy][1]

        self.X = numpy.mgrid[xlo:xhi:(NUMBEROFGRIDPOINTS * 1j)]
        self.Y = numpy.mgrid[ylo:yhi:(NUMBEROFGRIDPOINTS * 1j)]


    def _set_state_vector(self):
        """
        """
        #import pdb; pdb.set_trace()
        svr = self.model.state_variable_range
        sv_mean = numpy.array([svr[key].mean() for key in self.model.state_variables])
        sv_mean = sv_mean.reshape((self.model.nvar, 1, 1))
        self.default_sv = sv_mean.repeat(self.model.number_of_modes, axis=2)
        self.no_coupling = numpy.zeros((self.model.nvar, 1, self.model.number_of_modes))


    def _calc_phase_plane(self):
        """ Calculate the vector field. """
        svx_ind = self.model.state_variables.index(self.svx)
        svy_ind = self.model.state_variables.index(self.svy)

        #Calculate the vector field discretely sampled at a grid of points
        grid_point = self.default_sv.copy()
        self.U = numpy.zeros((NUMBEROFGRIDPOINTS, NUMBEROFGRIDPOINTS, self.model.number_of_modes))
        self.V = numpy.zeros((NUMBEROFGRIDPOINTS, NUMBEROFGRIDPOINTS, self.model.number_of_modes))
        for ii in xrange(NUMBEROFGRIDPOINTS):
            grid_point[svy_ind] = self.Y[ii]
            for jj in xrange(NUMBEROFGRIDPOINTS):
                #import pdb; pdb.set_trace()
                grid_point[svx_ind] = self.X[jj]
                d = self.model.dfun(grid_point, self.no_coupling)

                for kk in range(self.model.number_of_modes):
                    self.U[ii, jj, kk] = d[svx_ind, 0, kk]
                    self.V[ii, jj, kk] = d[svy_ind, 0, kk]

        #self.UVmag = numpy.sqrt(self.U**2 + self.V**2)
        #import pdb; pdb.set_trace()
        if numpy.isnan(self.U).any() or numpy.isnan(self.V).any():
            self.log.error("NaN")


    def _plot_phase_plane(self):
        """ Plot the vector field and its nullclines. """
        # Set title and axis labels
        model_name = self.model.__class__.__name__
        self.pp_ax.set(title=model_name + " mode " + str(self.mode))
        self.pp_ax.set(xlabel="State Variable " + self.svx)
        self.pp_ax.set(ylabel="State Variable " + self.svy)
        #import pdb; pdb.set_trace()
        #Plot a discrete representation of the vector field
        if numpy.all(self.U[:, :, self.mode] + self.V[:, :, self.mode] == 0):
            self.pp_ax.set(title=model_name + " mode " + str(self.mode) + ": NO MOTION IN THIS PLANE")
            X, Y = numpy.meshgrid(self.X, self.Y)
            self.pp_quivers = self.pp_ax.scatter(X, Y, s=8, marker=".", c="k")
        else:
            self.pp_quivers = self.pp_ax.quiver(self.X, self.Y,
                                                self.U[:, :, self.mode],
                                                self.V[:, :, self.mode],
                                                #self.UVmag[:, :, self.mode],
                                                width=0.001, headwidth=8)

        #Plot the nullclines
        self.nullcline_x = self.pp_ax.contour(self.X, self.Y, self.U[:, :, self.mode], [0], colors="r")
        self.nullcline_y = self.pp_ax.contour(self.X, self.Y, self.V[:, :, self.mode], [0], colors="g")
        self.ipp_fig.canvas.draw()


    def _plot_trajectory(self, x, y):
        """
        Plot a sample trajectory, starting at the position x,y in the phase-plane.
        """
        svx_ind = self.model.state_variables.index(self.svx)
        svy_ind = self.model.state_variables.index(self.svy)

        #Calculate an example trajectory
        state = self.default_sv.copy()
        state[svx_ind] = x
        state[svy_ind] = y
        scheme = self.integrator.scheme
        traj = numpy.zeros((TRAJ_STEPS + 1, self.model.nvar, 1,
                            self.model.number_of_modes))
        traj[0, :] = state
        for step in range(TRAJ_STEPS):
            #import pdb; pdb.set_trace()
            state = scheme(state, self.model.dfun, self.no_coupling, 0.0, 0.0)
            traj[step + 1, :] = state

        self.pp_ax.scatter(x, y, s=42, c='g', marker='o', edgecolor=None)
        self.pp_ax.plot(traj[:, svx_ind, 0, self.mode], traj[:, svy_ind, 0, self.mode])

        #Plot the selected state variable trajectories as a function of time
        self.pp_splt.plot(numpy.arange(TRAJ_STEPS + 1) * self.integrator.dt, traj[:, :, 0, self.mode])

        pylab.draw()


    def _click_trajectory(self, event):
        """
        """
        if event.inaxes is self.pp_ax:
            x, y = event.xdata, event.ydata
            self.log.info('trajectory starting at (%f, %f)', x, y)
            self._plot_trajectory(x, y)


    def update_model_parameter(self, param_name, param_new_value):
        """
        Update model parameters based on the current parameter slider values.

        NOTE: Haven't figured out how to update independantly, so just update
            everything.
        """
        #TODO: Grab caller and use val directly, ie independent parameter update.
        setattr(self.model, param_name, numpy.array([param_new_value]))

        self.model.update_derived_parameters()
        self._calc_phase_plane()
        self._update_phase_plane()


    def update_all_model_parameters(self, model_instance):
        for key in model_instance.ui_configurable_parameters:
            attr = getattr(model_instance, key)
            if isinstance(attr, numpy.ndarray) and attr.size == 1:
                setattr(self.model, key, numpy.array([attr[0]]))

        self.model.update_derived_parameters()
        self._calc_phase_plane()
        self._update_phase_plane()


    def update_model_parameters_from_dict(self, parameters_dict):
        """
        NOTE: I expect that the given parameters exists on the current
        model and also that they are numpy arrays.

        Sets the parameters from the given dict on the current
        model instance and also updates the phase-plane.
        """
        for param_name in parameters_dict:
            setattr(self.model, param_name, numpy.array([parameters_dict[param_name]]))

        self.model.update_derived_parameters()
        self._calc_phase_plane()
        self._update_phase_plane()
Example #9
0
class AppForm(QMainWindow):
    '''
    Master GUI. To initialize:
    app = QApplication(sys.argv)
    form = AppForm()
    form.show()
    app.exec_()
    '''
    def __init__(self, parent=None):
        QMainWindow.__init__(self, parent)
        # Creates GUI framework
        self.create_main_frame()
        # Plots initial image
        self.init_draw()
    def create_main_frame(self):
        self.main_frame = QWidget()

        # Figure parameters. 
        # FIXME Probably change figure parameters given computer resolution
        self.fig = Figure((10.0, 10.0), dpi=100)
        self.canvas = FigureCanvas(self.fig)
        self.canvas.setParent(self.main_frame)
        self.canvas.setFocusPolicy(Qt.StrongFocus)
        self.canvas.setFocus()

        # Matplotlib move around 
        # FIXME remove zoom in button
        # http://stackoverflow.com/questions/12695678/how-to-modify-the-navigation-toolbar-easily-in-a-matplotlib-figure-window
        self.mpl_toolbar = NavigationToolbar(self.canvas, self.main_frame)

        # Add figures to GUI
        vbox = QVBoxLayout()
        vbox.addWidget(self.canvas)  # the matplotlib canvas
        vbox.addWidget(self.mpl_toolbar)

        # Image selection dropdown box
        self.image_selection_menu = QComboBox()
        self.image_selection_menu.addItem('Galaxy Simulation 1')
        self.image_selection_menu.addItem('Galaxy Image 1')
        self.image_selection_menu.addItem('Galaxy Image 2')
        self.image_selection_menu.addItem('Jupiter Narrow Field Simulation')
        self.image_selection_menu.addItem('Jupiter Wide Field Simulation')
        self.image_selection_menu.addItem('Star Formation Simulation 1')
        self.image_selection_menu.addItem('Star Formation Simulation 2')
        self.image_selection_menu.addItem('Star Formation Simulation 3')
        self.image_selection_menu.addItem('Star Formation Image 1')
        self.image_selection_menu.addItem('Star Formation Image 2')
        self.image_selection_menu.activated[str].connect(self.image_selection)
        vbox.addWidget(self.image_selection_menu)

        # Initialize GUI
        self.main_frame.setLayout(vbox)
        self.setCentralWidget(self.main_frame)
    def init_draw(self):
        '''
        Sets up all of the matplotlib widgets
        '''
        self.fig.clear()
#        gs = gridspec.GridSpec(3,1, height_ratios=[30,1,1])
        self.image_axes = self.fig.add_subplot(111)
        self.fig.subplots_adjust(bottom = .25)
        # Initial image 
        # FIXME add null image
        self.current_pixscale = .05
        im = misc.imread('galaxy_images/im1.jpg')
        self.obj = ImageObject(im, self.current_pixscale)
        self.image_object = self.obj.current_image
        
        # Initialize slider bars
        self.imshow = self.image_axes.imshow(self.image_object, interpolation='nearest')
        self.sample_axis = self.fig.add_axes([0.25, 0.1, 0.65, 0.03])
        self.fov_axis = self.fig.add_axes([0.25, 0.15, 0.65, 0.03])
#        self.sample_axis = self.fig.add_subplot(gs[1])
#        self.fov_axis = self.fig.add_subplot(gs[2])
        self.sample_slider = Slider(self.sample_axis, 'Sampling (arcsecs/pix)', self.current_pixscale, self.current_pixscale * 100., valinit = self.current_pixscale)
        self.fov_slider = Slider(self.fov_axis, 'Field of View (arsecs)', .05, 3., valinit = .05)
        def update(val):
            self.obj.update_sampling(self.sample_slider.val)
            self.imshow.set_data(self.obj.current_image)
            self.canvas.draw()
        self.sample_slider.on_changed(update)
        self.canvas.draw()

    def image_selection(self, image_name):
        ''' 
        Hacked together image selection. 
        Takes selection from the image_selection_menu widget 
        '''
        if image_name == 'Galaxy Image 1':
            im = misc.imread('galaxy_images/im1.jpg')
            pixscale = .05
            self.obj = ImageObject(im, pixscale)
            self.image_update()
        if image_name == 'Galaxy Image 2':
            im = misc.imread('galaxy_images/im2.jpg')
            pixscale = .05
            self.obj = ImageObject(im, pixscale)
            self.image_update()
        if image_name == 'Galaxy Simulation 1':
            im = misc.imread('galaxy_simulations/im1.jpg')
            pixscale = .1
            self.obj = ImageObject(im, pixscale)
            self.image_update()
        if image_name == 'Jupiter Narrow Field Simulation':
            im = misc.imread('jupiter_simulation/jupiter_zoomin.png')
            pixscale = .1
            self.obj = ImageObject(im, pixscale)
            self.image_update()

        if image_name == 'Jupiter Wide Field Simulation':
            im = misc.imread('jupiter_simulation/jupiter_zoomout.png')
            pixscale = .1
            self.obj = ImageObject(im, pixscale)
            self.image_update()
        if image_name == 'Star Formation Simulation 1':
            im = misc.imread('star_formation_simulation/im1.gif')
            pixscale = .1
            self.obj = ImageObject(im, pixscale)
            self.image_update()
        if image_name == 'Star Formation Simulation 2':
            im = misc.imread('star_formation_simulation/im2.gif')
            pixscale = .1
            self.obj = ImageObject(im, pixscale)
            self.image_update()
        if image_name == 'Star Formation Simulation 3':
            im = misc.imread('star_formation_simulation/im3.gif')
            pixscale = .1
            self.obj = ImageObject(im, pixscale)
            self.image_update()

        if image_name == 'Star Formation Image 1':
            im = misc.imread('star_formation_images/im1.jpg')
            pixscale = .1
            self.obj = ImageObject(im, pixscale)
            self.image_update()

        if image_name == 'Star Formation Image 2':
            im = misc.imread('star_formation_images/im2.gif')
            pixscale = .1
            self.obj = ImageObject(im, pixscale)
            self.image_update()



    def image_update(self):
        '''
        Helper function to image selection, resets image and sliders
        '''
        self.imshow.set_data(self.obj.current_image)
        self.canvas.draw()
        if self.obj.master_sampling != self.current_pixscale:
            self.current_pixscale = self.obj.master_sampling
            self.sample_axis.cla()
            self.sample_slider = Slider(self.sample_axis, 'Sampling (arcsecs/pix)', self.current_pixscale, self.current_pixscale * 20., valinit = self.current_pixscale)
            def update(val):
                self.obj.update_sampling(self.sample_slider.val)
                self.imshow.set_data(self.obj.current_image)
                self.canvas.draw()
            self.sample_slider.on_changed(update)
        else:
            self.sample_slider.reset()
Example #10
0
class PlanetarySurveyor(object):
    """
    The PlanetarySurveyor creates a Matplotlib "widget" letting the user
    navigate map data loaded from an image file.
    """

    def __init__(self, filename="templates/nowwhat.png"):
        """
        Initialized with filename of image file containing the equirectangular
        map data.
        """

        self.filename = filename
        self.load_image()

        # Setup display:
        self.fig = plt.figure(1)
        self.ax = plt.subplot(111)
        plt.clf()
        plt.subplots_adjust(left=0.1, bottom=0.20)

        self.meridian = -90
        self.parallel = 22.5
        self.projection = "orthographic"
        self.parallels = 16
        self.meridians = 16

        self.setup_display()

        # Setup mouse interaction:
        self.click = self.hemisphere_axes.figure.canvas.mpl_connect(
                        'button_press_event', self.mouseclick)

        self.cursor = Cursor(self.hemisphere_axes, useblit=True, color='red',
                             linewidth=1)

        # Setup axes:
        self.axes_step = plt.axes([0.13, 0.15, 0.60, 0.03])
        self.axes_meridians = plt.axes([0.13, 0.10, 0.60, 0.03])
        self.axes_parallels = plt.axes([0.13, 0.05, 0.60, 0.03])

        self.update_axes = plt.axes([0.79, 0.095, 0.08, 0.04])
        self.reset_axes = plt.axes([0.79, 0.05, 0.08, 0.04])

        self.radio_axes = plt.axes([0.88, 0.05, 0.11, 0.15])

        # Setup sliders:
        self.step = 22.5
        self.slider_step = Slider(self.axes_step, 'Step', 0, 90,
                                  valinit=self.step, valfmt='%2.1f')
        self.slider_meridians = Slider(self.axes_meridians, 'Meridians', 0,
                                       64, valinit=self.parallels,
                                       valfmt='%2d')
        self.slider_parallels = Slider(self.axes_parallels, 'Parallels', 0,
                                       64, valinit=self.parallels,
                                       valfmt='%2d')

        self.slider_step.on_changed(self.update)
        self.slider_meridians.on_changed(self.update)
        self.slider_parallels.on_changed(self.update)

        # Setup button(s):
        self.update_button = Button(self.update_axes, 'Update')
        self.update_button.on_clicked(self.update_display)

        self.button = Button(self.reset_axes, 'Reset')
        self.button.on_clicked(self.reset)

        # Setup radio buttons:
        self.radio = RadioButtons(self.radio_axes, ('ortho', 'eq.dist',
                                                    'rect'), active=0)
        self.radio.on_clicked(self.set_mode)
        self.projections = {"ortho": ("orthographic", "ortho"),
                            "eq.dist": ("equidistant", "aeqd"),
                            "rect": ("rectangular", "cyl")}

        # Almost done:
        self.update()
        plt.show()

    def load_image(self):
        """
        Checks if the image file specified exists and is an image file. If this
        fails, the default map is loaded.
        """

        try:
            map_image = plt.imread(self.filename)
        except IOError as e:
            print "Could not load file {0} ({1})".format(
                  self.filename, e.strerror)
            print "Using default image..."
            self.filename = "templates/nowwhat.png"

    def setup_display(self):
        """
        Setup parameters and map display.
        """

        self.hemisphere_axes = plt.gca()
        self.R = 10000 * 360.0 / (2 * np.pi)
        self.width = 180 * 10000
        self.height = 180 * 10000

        if self.projection == 'orthographic':
            self.hemisphere = Basemap(projection="ortho", lon_0=self.meridian,
                              lat_0=self.parallel, resolution='c',
                              area_thresh=100000, ax=self.hemisphere_axes)
        elif self.projection == 'equidistant':
            self.hemisphere = Basemap(projection="aeqd", lon_0=self.meridian,
                              lat_0=self.parallel, resolution='c',
                              area_thresh=100000, rsphere=self.R,
                              ax=self.hemisphere_axes, width=self.width,
                              height=self.height)
        elif self.projection == 'rectangular':
            self.hemisphere = Basemap(projection="cyl", lon_0=0, lat_0=0,
                              resolution='c', area_thresh=100000,
                              ax=self.hemisphere_axes)

        self.hemisphere.warpimage(self.filename)
        self.hemisphere.drawmapboundary()
        self.draw_graticules()

    def update_display(self):
        """
        Update map display.
        """

        if self.projection == 'orthographic':
            self.hemisphere = Basemap(projection="ortho", lon_0=self.meridian,
                              lat_0=self.parallel, resolution='c',
                              area_thresh=100000, ax=self.hemisphere_axes)
        elif self.projection == 'equidistant':
            self.hemisphere = Basemap(projection="aeqd", lon_0=self.meridian,
                              lat_0=self.parallel, resolution='c',
                              area_thresh=100000, rsphere=self.R,
                              ax=self.hemisphere_axes, width=self.width,
                              height=self.height)
        elif self.projection == 'rectangular':
            self.hemisphere = Basemap(projection="cyl", lon_0=0, lat_0=0,
                              resolution='c', area_thresh=100000,
                              ax=self.hemisphere_axes)

        self.hemisphere_axes.cla()
        self.hemisphere.warpimage(self.filename)
        self.hemisphere.drawmapboundary()
        self.draw_graticules()

        self.update()

    def update(self, val=0):
        """
        Update internal parameters from sliders, update coordiantes and draw.
        """

        if self.step != self.slider_step.val:
            self.step = np.round(self.slider_step.val / 0.5) * 0.5
            self.slider_step.set_val(self.step)

        if (self.meridians != self.slider_meridians.val or
                self.parallels != self.slider_parallels.val):

            self.meridians = np.round(self.slider_meridians.val
                                      ).astype(np.int)
            self.parallels = np.round(self.slider_parallels.val
                                      ).astype(np.int)

        self.fix_coordinates()

        plt.draw()

    def set_mode(self, val="ortho"):
        """
        Set projection mode.
        """

        self.projection = self.projections[val][0]

        self.update_display()

    def reset(self, event):
        """
        Reset widget
        """

        self.slider_step.reset()
        self.slider_meridians.reset()
        self.slider_parallels.reset()
        self.meridian = 90
        self.parallel = 0
        self.update()

    def mouseclick(self, event):
        """
        Handle mouse navigation of map display for the different projections.
        """

        if event.inaxes == self.hemisphere_axes:
            if event.button == 1:
                if self.projection == "rectangular":
                    self.parallel = np.round(event.ydata / 0.5) * 0.5
                    self.meridian = np.round(event.xdata / 0.5) * 0.5
                else:
                    xlim = self.hemisphere_axes.get_xlim()
                    x = np.round(3 * (event.xdata -
                        0.5 * (xlim[1] - xlim[0])) / (xlim[1] - xlim[0]))

                    ylim = self.hemisphere_axes.get_ylim()
                    y = np.round(3 * (event.ydata -
                        0.5 * (ylim[1] - ylim[0])) / (ylim[1] - ylim[0]))

                    self.meridian += self.step * x
                    self.parallel += self.step * y

                    self.update_display()

                self.update()

    def fix_coordinates(self):
        """
        Fix coordinates so they comply to standard representation for maps.
        """

        if self.parallel > 90.0:
            self.parallel = 180.0 - self.parallel
        elif self.parallel < -90.0:
            self.parallel = -180.0 - self.parallel

        if self.meridian > 180.0:
            self.meridian = 360.0 - self.meridian
        elif self.meridian < -180.0:
            self.meridian = -360.0 - self.meridian

        self.hemisphere_axes.set_title("{0}: {1}".format(self.projection,
                                                  self.get_coordinates()))

    def get_coordinates(self):
        """
        Return string representation of coordinates in N-S/E-W standard.
        """

        parallel = np.abs(self.parallel)
        meridian = np.abs(self.meridian)

        if self.parallel >= 0:
            NS = "N"
        else:
            NS = "S"

        if self.meridian >= 0:
            EW = "E"
        else:
            EW = "W"

        return "{0} {1}, {2} {3}".format(parallel, NS, meridian, EW)

    def get_graticule(self):
        """
        Return resolution of the current graticule (distances between parallel
        and meridian lines).
        """

        try:
            dLat = 180.0 / self.parallels
        except ZeroDivisionError:
            dLat = None

        try:
            dLon = 360.0 / self.meridians
        except ZeroDivisionError:
            dLon = 0

        return dLat, dLon

    def draw_graticules(self):
        """
        Draw parallel and meridian lines.
        """

        parallel_step = 180.0 / self.parallels
        meridian_step = 360.0 / self.meridians

        if self.parallels > 0:
            min_parallel = -90
            max_parallel = 90 - parallel_step
            self.hemisphere.drawparallels(
                            np.arange(min_parallel, max_parallel + 1,
                            parallel_step), latmax=90 - parallel_step)

        if self.meridians > 0:
            min_meridian = -180
            max_meridian = 180 - meridian_step
            self.hemisphere.drawmeridians(
                            np.arange(min_meridian, max_meridian + 1,
                            meridian_step), latmax=90 - parallel_step)
Example #11
0
class viewer:
    def __init__(self,fnames,selectX=False):
        self.fnames=fnames
        self.labels=make_short_labels(fnames)
        self.allchains=read_all_chains(self.fnames)
        #print('allchains:',self.allchains)
        
        self.fig, self.ax = plt.subplots()
        if selectX:
            leftlim=0.35
            bottomlim=0.30
        else:
            leftlim=0.25
            bottomlim=0.25
        plt.subplots_adjust(left=leftlim, bottom=bottomlim)

        cx0 = 1
        cy0 = 0
        s0 = 3
        d0 = 2
        
        x,y=get_xydata(self.allchains[0].data,cx0,cy0,10**d0,10**s0)
        try:
            cmapname='tab10'
            self.cmap = matplotlib.cm.get_cmap(cmapname)
        except ValueError:
            cmapname='Vega10'
            self.cmap = matplotlib.cm.get_cmap(cmapname)
        self.cmap_norm=10
        self.scat = plt.scatter(x, y, s=1, c=x, cmap=cmapname,norm=colors.Normalize(0,self.cmap_norm))
        #scat = plt.scatter([], [], s=1,cmap="tab10")

        axcolor = 'lightgoldenrodyellow'
        axstart = plt.axes([leftlim, 0.1, 0.9-leftlim, 0.03])
        axdens = plt.axes([leftlim, 0.15, 0.9-leftlim, 0.03])
        height=(len(allparnames)-1)*0.05
        resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
        if not selectX:
            #rax = plt.axes([0.025, 0.5-height/2, 0.1, height], facecolor=axcolor)
            rYax = plt.axes([0.025, 0.5-height/2, 0.1, height])
        else:
            rXax = plt.axes([0.025, 0.5-height/2, 0.1, height])
            rXax.text(0.9, 0.95, "X", transform=rXax.transAxes, fontsize=11,
                      verticalalignment='top',horizontalalignment='right')
            rYax = plt.axes([0.15, 0.5-height/2, 0.1, height])
            rYax.text(0.9, 0.95, "Y", transform=rYax.transAxes, fontsize=11,
                      verticalalignment='top',horizontalalignment='right')

        ilogS=(math.log10(Smax))
        ilogSamps=int(math.log10(Nmax))
        print("ilogSmax=",ilogS)
        
        #Start slider
        print('axstart',axstart)
        self.sstart = Slider(axstart, 'log-Start', 2, ilogS, valinit=s0)
        self.sstart.on_changed(self.update)

        #Density slider
        self.sdens = Slider(axdens, 'log-Density', 1, ilogSamps, valinit=d0)
        self.sdens.on_changed(self.update)

        #X/y-axis radio buttons
        if selectX:
            self.radioX = RadioButtons(rXax, allparnames, active=cx0)
            self.radioY = RadioButtons(rYax, allparnames, active=cy0)
            parnameswidth=max([len(x) for x in allparnames])
            fontsize=self.radioX.labels[0].get_fontsize()/max([1,parnameswidth/5.])
            #print("fontsize=",fontsize)
            for label in self.radioX.labels:
                label.set_fontsize(fontsize)
            for label in self.radioY.labels:
                label.set_fontsize(fontsize)
            for circle in self.radioX.circles: # adjust radius here. The default is 0.05
                circle.set_radius(0.03)
            self.radioX.on_clicked(self.update)
            self.haveX=True
            #print('set radio')
        else:
            self.radioY = RadioButtons(rYax, allparnames, active=0)
            parnameswidth=max([len(x) for x in allparnames])
            fontsize=self.radioY.labels[0].get_fontsize()/max([1,parnameswidth/5.])
            #print("fontsize=",fontsize)
            for label in self.radioY.labels:
                label.set_fontsize(fontsize)
            self.haveX=False
        for circle in self.radioY.circles: # adjust radius here. The default is 0.05
            circle.set_radius(0.03)
        self.radioY.on_clicked(self.update)

        #Reset button
        self.button = Button(resetax, 'Reset', color=axcolor, hovercolor='0.975')
        self.button.on_clicked(self.reset)

        #print('calling update')
        self.update()
        #print('save fig')
        #plt.savefig('junk.png')
        #print('calling show')
        plt.show()
        #print('finished init')
    
    
    def update(self,val=0): #argument is not used
        #c0=1+allparnames[1:].index(radio.value_selected)
        #print("index->",c0)
        start = int(10**self.sstart.val)
        samps = int(10**self.sdens.val)
        xmin=1e100;xmax=-1e100
        ymin=1e100;ymax=-1e100
        xy=np.array([])
        cc=np.array([])
        ic0=0.5;
        ind=0
        plotlabels=[]
        for chain in self.allchains:
            includeChain=True
            if self.haveX:
                if(self.radioX.value_selected in chain.names):
                    cx=chain.names.index(self.radioX.value_selected)
                else: includeChain=False
            else: cx=0
            if(self.radioY.value_selected in chain.names):
                cy=chain.names.index(self.radioY.value_selected)
            else: includeChain=False
            if includeChain:
                x,y=get_xydata(chain.data,cx,cy,samps,start)
                n=len(x)
                #xy=np.array([xyi for xyi in xy if np.all(np.isfinite(xyi))])
                colorval=ic0+ind
                if(cc.size>0):
                    cc = np.concatenate((cc,[colorval]*n))
                    xy = np.vstack((xy,np.vstack((x, y)).T))
                else:
                    cc=np.array([colorval]*n)
                    xy = np.vstack((x, y)).T
                if(n==0):
                    ind+=1
                    continue
                lim=x.min()
                if(xmin>lim):xmin=lim
                lim=x.max()
                if(xmax<lim):xmax=lim
                lim=y.min()
                if(ymin>lim):ymin=lim
                lim=y.max()
                if(ymax<lim):ymax=lim
                plotlabels.append(mpatches.Patch(color=self.cmap(colorval/self.cmap_norm), label=self.labels[ind],hatch='.'))
                ind=ind+1            

        self.scat.set_offsets(xy)
        self.scat.set_array(cc)
        self.ax.set_xlim(xmin-0.1*(xmax-xmin),xmax+0.1*(xmax-xmin))
        self.ax.set_ylim(ymin-0.1*(ymax-ymin),ymax+0.1*(ymax-ymin))
        self.ax.legend(handles=plotlabels,fontsize=8)

        for tick in self.ax.get_xticklabels():
            tick.set_rotation(20)

        self.fig.canvas.draw_idle()
   
    def reset(self,event): #fixme
        self.allchains=read_all_chains(self.fnames)
        self.sstart.reset()
        self.sdens.reset()
Example #12
0
class guiMenu:
    fig = None

    gauss_params = [33, 7]

    logTextLabels = []
    logText = []

    axMisc = None
    axAlgorithm = None
    axSaveOptions = None
    axGauss = None
    axLog = None
    axRadio = None
    axLogLabels = None

    line_gaussian = None

    ax_window_size = None
    slider_window_size = None

    ax_sigma = None
    slider_sigma = None

    originalStdOut = None

    #------------------------------------------------------------------------------
    # Class initialization
    #
    def __init__(self):
        self.strTitle = 'Gesture Analysis Configuration - ' + settings.appVersion
        self.fig = plt.figure()
        self.fig.canvas.set_window_title(self.strTitle)
        self.fig.set_size_inches((settings.screen_cx * 0.49) / self.fig.dpi,
                                 (settings.screen_cy * 0.465) / self.fig.dpi)

        self.fig.canvas.mpl_connect('resize_event', self.onresize)
        self.fig.canvas.mpl_connect('close_event', self.onclose)

        self.fig.edgecolor = 'blue'
        self.fig.set_facecolor('0.90')

        left = 0.03  # the left side of the subplots of the figure
        right = 0.97  # the right side of the subplots of the figure
        bottom = 0.04  # the bottom of the subplots of the figure
        top = 0.92  # the top of the subplots of the figure
        wspace = 0.3  # the amount of width reserved for blank space between subplots
        hspace = 0.7  # the amount of height reserved for white space between subplots

        plt.subplots_adjust(left=left,
                            top=top,
                            right=right,
                            bottom=bottom,
                            wspace=wspace,
                            hspace=hspace)

        self.axMisc = plt.subplot2grid((6, 4), (0, 0),
                                       rowspan=1,
                                       colspan=1,
                                       aspect='auto',
                                       anchor='NW')
        self.axAlgorithm = plt.subplot2grid((6, 4), (1, 0),
                                            rowspan=2,
                                            colspan=1,
                                            aspect='auto',
                                            anchor='NW')
        self.axSaveOptions = plt.subplot2grid((6, 4), (3, 0),
                                              rowspan=3,
                                              colspan=1,
                                              aspect='equal',
                                              anchor='NW')
        self.axGauss = plt.subplot2grid((6, 4), (0, 1), rowspan=4, colspan=3)
        self.axLog = plt.subplot2grid((6, 4), (5, 1),
                                      rowspan=1,
                                      colspan=3,
                                      aspect='auto',
                                      anchor='NW')

        # create the various groups of UI controls
        self.createUIMiscellaneous()
        self.createUILog()

        self.createUIAlgorithm()
        self.createUIGaussianFilterControls()
        self.createUIMiscellaneousControls()

        # set settings.tkGuiCanvas for use for modal dialogs
        try:
            if (self.fig is not None) and (self.fig.canvas is not None) and (
                    self.fig.canvas._tkcanvas is not None):
                settings.tkGuiCanvas = self.fig.canvas._tkcanvas
        except Exception as e:
            pass

    #------------------------------------------------------------------------------
    #
    def get_aspect(self, ax):
        # Total figure size
        figW, figH = ax.get_figure().get_size_inches()
        # Axis size on figure
        _, _, w, h = ax.get_position().bounds
        # Ratio of display units
        disp_ratio = (figH * h) / (figW * w)
        # Ratio of data units
        # Negative over negative because of the order of subtraction
        data_ratio = sub(*ax.get_ylim()) / sub(*ax.get_xlim())

        return disp_ratio / data_ratio

    #------------------------------------------------------------------------------
    #
    def createUIAlgorithm(self):
        algorithm = settings.application.algorithm.lower()
        defaultAlgoritmIdx = 0
        if (algorithm == 'total'):
            defaultAlgoritmIdx = 0
        elif (algorithm == 'parallel'):
            defaultAlgoritmIdx = 1
        elif (algorithm == 'naive'):
            defaultAlgoritmIdx = 2

        self.axAlgorithm.set_title('Algorithm',
                                   x=0,
                                   horizontalalignment='left')

        # create an axis to host to radio buttons. make its aspect ratio
        # equal so the radiobuttons stay round
        aspect = self.get_aspect(self.axAlgorithm)
        rect = [0, 0, 1.0 * aspect, 1.0]
        ip = InsetPosition(self.axAlgorithm, rect)
        self.axRadio = plt.axes(rect)
        self.axRadio.set_axes_locator(ip)
        self.axRadio.axis('off')

        self.radioAlgorithm = RadioButtons(
            self.axRadio,
            ('Total Energy', 'Parallel Energy', 'Naive (no filter)'),
            active=defaultAlgoritmIdx)
        self.radioAlgorithm.on_clicked(self.onClickAlgorithm)

    #------------------------------------------------------------------------------
    #
    def createUIGaussianFilterControls(self):
        axcolor = 'lightgoldenrodyellow'

        rect = [0.82, -0.158, 0.14, 0.07]
        ax_btnapply = plt.axes(rect)
        ip = InsetPosition(self.axGauss, rect)  #posx, posy, width, height
        ax_btnapply.set_axes_locator(ip)
        self.btnApply = Button(ax_btnapply, 'Apply')
        self.btnApply.on_clicked(self.onclickApply)

        rect = [0.82, -0.245, 0.14, 0.07]
        ax_btnreset = plt.axes(rect)
        ip = InsetPosition(self.axGauss, rect)  #posx, posy, width, height
        ax_btnreset.set_axes_locator(ip)
        self.btnReset = Button(ax_btnreset,
                               'Reset',
                               color='0.950',
                               hovercolor='0.975')
        self.btnReset.on_clicked(self.onclickReset)

        rect = [0.1, -0.155, 0.55, 0.04]
        self.ax_window_size = plt.axes(rect, facecolor=axcolor)
        ip = InsetPosition(self.axGauss, rect)  #posx, posy, width, height
        self.ax_window_size.set_axes_locator(ip)
        self.slider_window_size = Slider(self.ax_window_size,
                                         'Window Size',
                                         1, (self.gauss_params[0] + 1) * 2 + 1,
                                         valinit=self.gauss_params[0],
                                         valstep=2)
        self.slider_window_size.on_changed(self.updateGaussianFilter)

        rect = [0.1, -0.235, 0.55, 0.04]
        self.ax_sigma = plt.axes(rect, facecolor=axcolor)
        ip = InsetPosition(self.axGauss, rect)  #posx, posy, width, height
        self.ax_sigma.set_axes_locator(ip)
        self.slider_sigma = Slider(self.ax_sigma,
                                   'Sigma',
                                   1, (self.gauss_params[1] + 1) * 2,
                                   valinit=self.gauss_params[1],
                                   valstep=1)
        self.slider_sigma.on_changed(self.updateGaussianFilter)

        self.updateGaussianFilter()

    #------------------------------------------------------------------------------
    #
    def createUIMiscellaneous(self):
        self.axMisc.set_title('', x=0, horizontalalignment='left')

        # removing top and right borders
        self.axMisc.xaxis.set_visible(False)
        self.axMisc.yaxis.set_visible(False)

        # remove ticks
        self.axSaveOptions.set_xticks([])
        self.axSaveOptions.set_yticks([])

        # remove ticks
        self.axAlgorithm.set_xticks([])
        self.axAlgorithm.set_yticks([])

        bbox = self.axMisc.get_window_extent()
        self.axMisc.set_xlim(0, bbox.width)
        self.axMisc.set_ylim(0, bbox.height)

    #------------------------------------------------------------------------------
    #
    def createUILog(self):
        self.axLog.set_title('Console Log', x=0, horizontalalignment='left')

        # removing top and right borders
        self.axLog.xaxis.set_visible(False)
        self.axLog.yaxis.set_visible(False)

        self.resetLogLabels()

        # redirect console messages to gui's log
        self.originalStdOut = sys.stdout
        sys.stdout = CaptureOutput()

    # -----------------------------------------------------------------------------
    #
    def resetLogLabels(self):
        cnt = len(self.logTextLabels)
        for i in range(0, cnt):
            self.logTextLabels[i].remove()

        self.logTextLabels = []

        bbox = self.axLog.get_window_extent()
        self.axLog.set_xlim(0, bbox.width)
        self.axLog.set_ylim(0, bbox.height)

        aspect = self.get_aspect(self.axLog)
        rect = [0, 0, 1.0 * aspect, 1.0]
        ip = InsetPosition(self.axLog, rect)

        if (self.axLogLabels is None):
            self.axLogLabels = plt.axes(rect)
        else:
            self.axLogLabels.set_position(rect)

        self.axLogLabels.set_axes_locator(ip)
        self.axLogLabels.axis('off')

        aspectLog = 1.0 / self.get_aspect(self.axLog)
        strText = 'Tyg'
        tmp, self.logTextHeight = settings.getTextExtent(self.axLog, strText)
        self.logTextHeight = self.logTextHeight * aspectLog  # * self.fig.dpi

        # pre-create empty log label placeholders
        self.logTextLabels = []
        y = (self.logTextHeight / 4.0)
        cy = bbox.height
        idx = len(self.logText) - 1
        while (y < cy):
            str = self.logText[idx] if (idx >= 0) else ''
            idx = idx - 1

            lbl = self.axLogLabels.text(
                8.0,
                y,
                str,
                horizontalalignment='left',
                verticalalignment='bottom',
                color='dimgray',
                clip_on=True,
                transform=self.axLog.transData
            )  #, bbox={'facecolor':'lightgray', 'alpha':0.7, 'pad':0.0})

            self.logTextLabels.append(lbl)
            y += self.logTextHeight

    # -----------------------------------------------------------------------------
    #
    def createUIMiscellaneousControls(self):
        rect = [0.06, 0.30, 0.70, 0.40]
        ip = InsetPosition(self.axMisc, rect)  #posx, posy, width, height
        ax_btnbrowse = plt.axes(rect)
        ax_btnbrowse.set_axes_locator(ip)
        self.btnBrowse = Button(ax_btnbrowse, 'Input File')
        self.btnBrowse.on_clicked(self.onclickBrowse)

        self.axSaveOptions.set_title('Output Files',
                                     x=0,
                                     horizontalalignment='left')

        x = 0.06
        dx = 0.70  # 0.80
        dy = 0.10  # 0.17
        cy = 0.14  # 0.24
        y = 0.80
        rect = [x, y, dx, dy]
        ip = InsetPosition(self.axSaveOptions,
                           rect)  #posx, posy, width, height
        ax_btn = plt.axes(rect)
        ax_btn.set_axes_locator(ip)
        self.btnSaveJSON = Button(ax_btn, 'JSON')
        self.btnSaveJSON.on_clicked(self.onclickSaveJSON)

        rect = [x, y - 1 * cy, dx, dy]
        ip = InsetPosition(self.axSaveOptions,
                           rect)  #posx, posy, width, height
        ax_btn = plt.axes(rect)
        ax_btn.set_axes_locator(ip)
        self.btnSaveTXT = Button(ax_btn, 'Text')
        self.btnSaveTXT.on_clicked(self.onclickSaveTXT)

        rect = [x, y - 2 * cy, dx, dy]
        ip = InsetPosition(self.axSaveOptions,
                           rect)  #posx, posy, width, height
        ax_btn = plt.axes(rect)
        ax_btn.set_axes_locator(ip)
        self.btnSaveFilterView = Button(ax_btn, 'Filter Graph')
        self.btnSaveFilterView.on_clicked(self.onclickSaveFilterView)

        rect = [x, y - 3 * cy, dx, dy]
        ip = InsetPosition(self.axSaveOptions,
                           rect)  #posx, posy, width, height
        ax_btn = plt.axes(rect)
        ax_btn.set_axes_locator(ip)
        self.btnSaveSkeletonView = Button(ax_btn, '3D Joint Data')
        self.btnSaveSkeletonView.on_clicked(self.onclickSaveSkeletonView)

        rect = [x, y - 4 * cy, dx, dy]
        ip = InsetPosition(self.axSaveOptions,
                           rect)  #posx, posy, width, height
        ax_btn = plt.axes(rect)
        ax_btn.set_axes_locator(ip)
        self.btnSaveScoreView = Button(ax_btn, 'Score View')
        self.btnSaveScoreView.on_clicked(self.onclickSaveScoreView)

        rect = [x, y - 5 * cy, dx, dy]
        ip = InsetPosition(self.axSaveOptions,
                           rect)  #posx, posy, width, height
        ax_btn = plt.axes(rect)
        ax_btn.set_axes_locator(ip)
        self.btnSavePNG = Button(ax_btn, 'Full Score')
        self.btnSavePNG.on_clicked(self.onclickSaveImage)

    #------------------------------------------------------------------------------
    # canvas resize event
    #
    def onresize(self, event):
        # plt.tight_layout()

        # keep tha radio buttons round...
        if (self.axRadio is not None) and (self.axAlgorithm is not None):
            aspect = self.get_aspect(self.axAlgorithm)
            rect = [0, 0, 1.0 * aspect, 1.0]

            ip = InsetPosition(self.axAlgorithm, rect)
            self.axRadio.set_axes_locator(ip)
            self.axRadio.set_position(rect)

        self.resetLogLabels()

    # -----------------------------------------------------------------------------
    # canvas close event
    #
    def onclose(self, event):
        self.fig = None
        # if user closes this figure, let the main application know and to exit
        settings.application.close()

    # -----------------------------------------------------------------------------
    #
    def updateUIControls(self, algorithm):
        algorithm = algorithm.lower()
        fEnable = False if (algorithm == 'naive') else True
        alpha = 0.2 if (algorithm == 'naive') else 1.0

        self.btnApply.set_active(fEnable)
        self.btnReset.set_active(fEnable)

        self.btnApply.label.set_alpha(alpha)
        self.btnReset.label.set_alpha(alpha)

        fUpdateGaussianPlot = False
        if (self.gauss_params[0] != self.slider_window_size.val):
            self.ax_window_size.clear()
            self.slider_window_size.__init__(
                self.ax_window_size,
                'Window Size',
                valmin=1,
                valmax=(self.gauss_params[0] + 1) * 2 + 1,
                valinit=self.gauss_params[0],
                valstep=2)
            self.slider_window_size.on_changed(self.updateGaussianFilter)
            fUpdateGaussianPlot = True

        if (self.gauss_params[1] != self.slider_sigma.val):
            self.ax_sigma.clear()
            self.slider_sigma.__init__(self.ax_sigma,
                                       'Sigma',
                                       valmin=1,
                                       valmax=(self.gauss_params[1] + 1) * 2,
                                       valinit=self.gauss_params[1],
                                       valstep=1)
            self.slider_sigma.on_changed(self.updateGaussianFilter)
            fUpdateGaussianPlot = True

        if (fUpdateGaussianPlot):
            self.updateGaussianFilter()

        self.line_gaussian.set_alpha(alpha)

        self.ax_window_size.patch.set_alpha(alpha)
        if (self.slider_window_size.poly):
            self.slider_window_size.poly.set_alpha(alpha)
        self.slider_window_size.set_active(fEnable)
        for r in self.slider_window_size.ax.texts:
            r.set_alpha(alpha)

        self.ax_sigma.patch.set_alpha(alpha)
        if (self.slider_sigma.poly):
            self.slider_sigma.poly.set_alpha(alpha)
        self.slider_sigma.set_active(fEnable)
        for r in self.slider_sigma.ax.texts:
            r.set_alpha(alpha)

        self.fig.canvas.draw_idle()

    # -----------------------------------------------------------------------------
    #
    def updateInputName(self):
        self.fig.canvas.set_window_title(
            self.strTitle + ' - [' +
            settings.application.strBeautifiedInputFile + ']')

    # -----------------------------------------------------------------------------
    #
    def getAlgorithmSelection(self):
        if (self.radioAlgorithm.value_selected == 'Total Energy'):
            return 'Total'
        elif (self.radioAlgorithm.value_selected == 'Parallel Energy'):
            return 'Parallel'

        return 'Naive'

    # -----------------------------------------------------------------------------
    #
    def onClickAlgorithm(self, label):
        algorithm = self.getAlgorithmSelection()

        if (settings.application.labanotation is not None):
            self.gauss_params = settings.application.labanotation.getGaussianParameters(
                algorithm)

        self.updateUIControls(algorithm)
        settings.application.applyAlgoritm(algorithm)

    #------------------------------------------------------------------------------
    # updateGaussianFilter() has an unused parameter, though needs it because the
    # sliders use this function as their update callback...
    def updateGaussianFilter(self, val=0):
        # remove current gaussian lines
        if (self.line_gaussian is not None):
            self.line_gaussian.remove()
            del self.line_gaussian
            self.line_gaussian = None

        gauss_params = (int(self.slider_window_size.val),
                        int(self.slider_sigma.val))

        self._t = np.arange(-gauss_params[0] / 2.0 + 0.5,
                            gauss_params[0] / 2.0 + 0.5, 1.0)
        s = wf.gaussFilter(gauss_params[0], gauss_params[1])
        self.line_gaussian, = self.axGauss.plot(self._t,
                                                s,
                                                marker="o",
                                                linestyle='-',
                                                color='red',
                                                lw=1)

        # for i, txt in enumerate(s):
        #    self.axGauss.annotate("{:0.2f}".format(txt), (self._t[i], s[i]))

        wnd = int(gauss_params[0] / 2) + 1
        self.axGauss.set_xlim(-wnd, wnd)
        self.axGauss.set_ylim(0, 0.42)  # np.max(s))
        self.fig.canvas.draw_idle()

    #------------------------------------------------------------------------------
    #
    def onclickApply(self, event):
        algorithm = self.getAlgorithmSelection()

        self.gauss_params = (int(self.slider_window_size.val),
                             int(self.slider_sigma.val))

        if (settings.application.labanotation is not None):
            settings.application.labanotation.setGaussianParameters(
                algorithm, self.gauss_params)

        settings.application.applyAlgoritm(algorithm)

    #------------------------------------------------------------------------------
    #
    def onclickSaveJSON(self, event):
        settings.application.saveJSON()

    #------------------------------------------------------------------------------
    #
    def onclickSaveTXT(self, event):
        settings.application.saveTXT()

    #------------------------------------------------------------------------------
    #
    def onclickSaveImage(self, event):
        settings.application.saveImage()

    #------------------------------------------------------------------------------
    #
    def onclickSaveFilterView(self, event):
        settings.application.saveFilterView()

    #------------------------------------------------------------------------------
    #
    def onclickSaveSkeletonView(self, event):
        settings.application.saveSkeletonView()

    #------------------------------------------------------------------------------
    #
    def onclickSaveScoreView(self, event):
        settings.application.saveScoreView()

    #------------------------------------------------------------------------------
    #
    def onclickReset(self, event):
        self.slider_window_size.reset()
        self.slider_sigma.reset()

    #------------------------------------------------------------------------------
    #
    def onclickBrowse(self, event):
        file = self.selectInputFile()
        if (file is None):
            return

        settings.application.openAndProcessInputfile(file)

    #------------------------------------------------------------------------------
    #
    def selectInputFile(self):
        fTyp = [("Kinect Joint Data File", "*.csv")]

        splitInput = os.path.split(
            os.path.abspath(settings.application.inputFilePath))

        options = {}
        options['filetypes'] = fTyp
        options['initialdir'] = splitInput[0].replace('/', os.sep)

        if (settings.tkGuiCanvas is not None):
            options['parent'] = settings.tkGuiCanvas

        file = tkFileDialog.askopenfilename(**options)

        if not file:
            return None

        return file

    #------------------------------------------------------------------------------
    #
    def logMessage(self, str, ioRedirect=False):
        # also write message to console
        if (self.originalStdOut is not None):
            extra = "\r\n" if (ioRedirect is False) else ""
            self.originalStdOut.write(str + extra)

        self.logText.append(str)
        cnt = len(self.logTextLabels)
        if (cnt > 0):
            for i in range(cnt - 1, 0, -1):
                self.logTextLabels[i].set_text(
                    self.logTextLabels[i - 1].get_text())

            self.logTextLabels[0].set_text(str)

            self.fig.canvas.draw_idle()
Example #13
0
class PlotFrame(wx.Frame):
    """
        PlotFrame is a custom wxPython frame to hold the panel with a
        Figure and WxAgg backend canvas for matplotlib plots or other
        figures.  In this frame:

        self is an instance of a wxFrame;
        axes is an instance of MPL Axes;
        fig is an instance of MPL Figure;
        panel is an instance of wxPanel, used for the main panel, to hold
        canvas, an instance of MPL FigureCanvasWxAgg.
    """

    # Main function to set everything up when the frame is created
    def __init__(self, title, pos, size):

        """
           This will be executed when an instance of PlotFrame is created.
           It is the place to define any globals as "self.<name>".
        """
        wx.Frame.__init__(self, None, wx.ID_ANY, title, pos, size)

        if len(sys.argv) < 2:
            self.filename = ""
        else:
            self.filename =  sys.argv[1]

        # set some Boolean flags
        self.STOP = False
        self.data_loaded = False
        self.reverse_play = False

        self.step = 1

        #    Make the main Matplotlib panel for plots
        self.create_main_panel()  # creates canvas and contents

        # Then add wxPython widgets below the MPL canvas
	# Layout with box sizers

        self.sizer = wx.BoxSizer(wx.VERTICAL)
	self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.EXPAND)
	self.sizer.AddSpacer(10)
	self.sizer.Add(self.toolbar, 0, wx.EXPAND)
	self.sizer.AddSpacer(10)

        #    Make the control panel with a row of buttons
        self.create_button_bar()
        self.sizer.Add(self.button_bar_sizer, 0, flag = wx.ALIGN_CENTER | wx.TOP)

        #    Make a Status Bar
        self.statusbar = self.CreateStatusBar()
        self.sizer.Add(self.statusbar, 0, wx.EXPAND)

        self.SetStatusText("Frame created ...")

        # -------------------------------------------------------
        #	       set up the Menu Bar
        # -------------------------------------------------------
        menuBar = wx.MenuBar()

        menuFile = wx.Menu() # File menu
        menuFile.Append(1, "&Open", "Filename(s) or wildcard list to plot")
        menuFile.Append(3, "Save", "Save plot as a PNG image")
        menuFile.AppendSeparator()
        menuFile.Append(10, "E&xit")
        menuBar.Append(menuFile, "&File")

        menuHelp = wx.Menu() # Help menu
        menuHelp.Append(11, "&About Netview")
        menuHelp.Append(12, "&Usage and Help")
        menuHelp.Append(13, "Program &Info")

        menuBar.Append(menuHelp, "&Help")
        self.SetMenuBar(menuBar)

        self.panel.SetSizer(self.sizer)
        self.sizer.Fit(self)

        # -------------------------------------------------------
        #      Bind the menu items to functions
        # -------------------------------------------------------

        self.Bind(wx.EVT_MENU, self.OnOpen, id=1)
        self.Bind(wx.EVT_MENU, self.OnSave, id=3)
        self.Bind(wx.EVT_MENU, self.OnQuit, id=10)
        self.Bind(wx.EVT_MENU, self.OnAbout, id=11)
	self.Bind(wx.EVT_MENU, self.OnUsage, id=12)
        self.Bind(wx.EVT_MENU, self.OnInfo, id=13)
	
        # methods defined below to get and plot the data
        # Normally do the plot on request, and not here
        # self.get_data_params()
        # self.init_plot()
        # self.get_xyt_data()
        # plot_data()

	# ---------- end of __init__ ----------------------------

    # -------------------------------------------------------
    #   Function to make the main Matplotlib panel for plots
    # -------------------------------------------------------

    def create_main_panel(self):
        """ create_main_panel creates the main mpl panel with instances of:
             * mpl Canvas 
             * mpl Figure 
             * mpl Figure
             * mpl Axes with subplot
             * mpl Widget class Sliders and Button
             * mpl navigation toolbar
           self.axes is the instance of MPL Axes, and is where it all happens
        """

        self.panel = wx.Panel(self)
        
        # Create the mpl Figure and FigCanvas objects. 
        # 3.5 x 5 inches, 100 dots-per-inch
        #
        self.dpi = 100
        self.fig = Figure((3.5, 5.0), dpi=self.dpi)
        self.canvas = FigCanvas(self.panel, wx.ID_ANY, self.fig)
        
        # Since we have only one plot, we could use add_axes 
        # instead of add_subplot, but then the subplot
        # configuration tool in the navigation toolbar wouldn't work.


        self.axes = self.fig.add_subplot(111)
        # (111) == (1,1,1) --> row 1, col 1, Figure 1)
        # self.axes.set_title("View from: "+self.filename)

        # Now create some sliders below the plot after making room
        self.fig.subplots_adjust(left=0.1, bottom=0.20)

        self.axtmin = self.fig.add_axes([0.2, 0.10, 0.5, 0.03])
        self.axtmax = self.fig.add_axes([0.2, 0.05, 0.5, 0.03])

        self.stmin = Slider(self.axtmin, 't_min:', 0.0, 1.0, valinit = 0.0)
        self.stmax = Slider(self.axtmax, 't_max:', 0.0, 1.0, valinit = 1.0)
        self.stmin.on_changed(self.update_trange)
        self.stmax.on_changed(self.update_trange)

        self.axbutton = self.fig.add_axes([0.8, 0.07, 0.1, 0.07])
        self.reset_button = Button(self.axbutton, 'Reset')
        self.reset_button.color = 'skyblue'
        self.reset_button.hovercolor = 'lightblue'
        self.reset_button.on_clicked(self.reset_trange)

        # Create the navigation toolbar, tied to the canvas

        self.toolbar = NavigationToolbar(self.canvas)

    def update_trange(self, event):
        self.t_min = self.stmin.val
        self.t_max = self.stmax.val
        # print(self.t_min, self.t_max)

    def reset_trange(self, event):
        self.stmin.reset()
        self.stmax.reset()

    def create_button_bar(self):
	"""
	create_button_bar makes a control panel bar with buttons and
	toggles for

	New Data - Play - STOP - Single Step - Forward/Back - Normal/Fast

	It does not create a Panel container, but simply creates Button
	objects with bindings, and adds  them to a horizontal BoxSizer
	self.button_bar_sizer.	This is added to the PlotFrame vertical
	BoxSizer, after the MPL canvas, during initialization of the frame.

	"""
	rewind_button = wx.Button(self.panel, -1, "New Data")
	self.Bind(wx.EVT_BUTTON, self.OnRewind, rewind_button)

	replot_button = wx.Button(self.panel, -1, "Play")
	self.Bind(wx.EVT_BUTTON, self.OnReplot, replot_button)

	sstep_button = wx.Button(self.panel, -1, "Single Step")
	self.Bind(wx.EVT_BUTTON, self.OnSstep, sstep_button)

	stop_button = wx.Button(self.panel, -1, "STOP")
	self.Bind(wx.EVT_BUTTON, self.OnStop, stop_button)

	# The toggle buttons need to be globally accessible

	self.forward_toggle = wx.ToggleButton(self.panel, -1, "Forward")
	self.forward_toggle.SetValue(True)
	self.forward_toggle.SetLabel("Forward")
	self.Bind(wx.EVT_TOGGLEBUTTON, self.OnForward, self.forward_toggle)

	self.fast_toggle = wx.ToggleButton(self.panel, -1, " Normal ")
        self.fast_toggle.SetValue(True)
        self.fast_toggle.SetLabel(" Normal ")
        self.Bind(wx.EVT_TOGGLEBUTTON, self.OnFast, self.fast_toggle)

        # Set button colors to some simple colors that are likely
        # to be independent on X11 color definitions.  Some nice
        # bit maps (from a media player skin?) should be used
        # or the buttons and toggle state colors in OnFast() below

        rewind_button.SetBackgroundColour('skyblue')
        replot_button.SetBackgroundColour('skyblue')
        sstep_button.SetBackgroundColour('skyblue')
        stop_button.SetBackgroundColour('skyblue')
        self.forward_toggle.SetForegroundColour('black')
        self.forward_toggle.SetBackgroundColour('yellow')
        self.fast_toggle.SetForegroundColour('black')
        self.fast_toggle.SetBackgroundColour('yellow')
        self.button_bar_sizer = wx.BoxSizer(wx.HORIZONTAL)
        flags = wx.ALIGN_CENTER | wx.ALL
        self.button_bar_sizer.Add(rewind_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(replot_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(sstep_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(stop_button, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(self.forward_toggle, 0, border=3, flag=flags)
        self.button_bar_sizer.Add(self.fast_toggle, 0, border=3, flag=flags)

    # -------------------------------------------------------
    #	Functions to generate or read (x,y) data and plot it
    # -------------------------------------------------------

    def get_data_params(self):
        #  These parameters  would normally be provided in a file header,
        # past as arguments in a function, or from other file information
        #  Next version will bring up a dialog for dt NX NY if no file header

        # Here check to see if a filename should be entered from File/Open
        # self.filename = 'Ex_net_Vm_0001.txt'
        if len(self.filename) == 0:
            # fake a button press of File/Open
            self.OnOpen(wx.EVT_BUTTON)

        # should check here if file exists as specified [path]/filename

        # assume it is a bzip2 compressed file
        try:
      	    fp = bz2.BZ2File(self.filename)
	    line = fp.readline()
        except IOError:
            # then assume plain text
            fp = open(self.filename)
	    line = fp.readline()
       
        fp.close()

        # check if first line is a header line starting with '#'
        header = line.split()
        if header[0][0] == "#": 
            self.Ntimes = int(header[1])
            self.t_min =  float(header[2])
            self.dt = float(header[3])
            self.NX = int(header[4])
            self.NY = int(header[5])
        else:
            pdentry = self.ParamEntryDialog()
            if pdentry.ShowModal() ==  wx.ID_OK:
                self.Ntimes = int(pdentry.Ntimes_dialog.entry.GetValue())
		self.t_min = float(pdentry.tmin_dialog.entry.GetValue())
		self.dt = float(pdentry.dt_dialog.entry.GetValue())
                self.NX	= int(pdentry.NX_dialog.entry.GetValue())
                self.NY = int(pdentry.NY_dialog.entry.GetValue())
                print 'Ntimes = ', self.Ntimes, ' t_min = ', self.t_min
                print 'NX = ', self.NX, ' NY = ', self.NY
            pdentry.Destroy()
        self.t_max = (self.Ntimes - 1)*self.dt
        # reset slider max and min
        self.stmin.valmax = self.t_max
        self.stmin.valinit = self.t_min
        self.stmax.valmax = self.t_max
        self.stmax.valinit = self.t_max
        self.stmax.set_val(self.t_max)
        self.stmin.reset()
        self.stmax.reset()
        fp.close()

    def init_plot(self):
        ''' 
        init_plot creates the initial plot display. A normal MPL plot
	would be created here with a command "self.axes.plot(x, y)" in
	order to create a plot of points in the x and y arrays on the
	Axes subplot.  Here, we create an AxesImage instance with
	imshow(), instead.  The initial image is a blank one of the
	proper dimensions, filled with zeroes.

        '''
        self.t_max = (self.Ntimes - 1)*self.dt
        self.axes.set_title("View of "+self.filename)
        # Note that NumPy array (row, col) = image (y, x)
        data0 = np.zeros((self.NY,self.NX))

        # Define a 'cold' to 'hot' color scale based in GENESIS 2 'hot'
        hotcolors = ['#000032', '#00003c', '#000046',
        '#000050', '#00005a', '#000064', '#00006e', '#000078', '#000082',
        '#00008c', '#000096', '#0000a0', '#0000aa', '#0000b4', '#0000be',
        '#0000c8', '#0000d2', '#0000dc', '#0000e6', '#0000f0', '#0000fa',
        '#0000ff', '#000af6', '#0014ec', '#001ee2', '#0028d8', '#0032ce',
        '#003cc4', '#0046ba', '#0050b0', '#005aa6', '#00649c', '#006e92',
        '#007888', '#00827e', '#008c74', '#00966a', '#00a060', '#00aa56',
        '#00b44c', '#00be42', '#00c838', '#00d22e', '#00dc24', '#00e61a',
        '#00f010', '#00fa06', '#00ff00', '#0af600', '#14ec00', '#1ee200',
        '#28d800', '#32ce00', '#3cc400', '#46ba00', '#50b000', '#5aa600',
        '#649c00', '#6e9200', '#788800', '#827e00', '#8c7400', '#966a00',
        '#a06000', '#aa5600', '#b44c00', '#be4200', '#c83800', '#d22e00',
        '#dc2400', '#e61a00', '#f01000', '#fa0600', '#ff0000', '#ff0a00',
        '#ff1400', '#ff1e00', '#ff2800', '#ff3200', '#ff3c00', '#ff4600',
        '#ff5000', '#ff5a00', '#ff6400', '#ff6e00', '#ff7800', '#ff8200',
        '#ff8c00', '#ff9600', '#ffa000', '#ffaa00', '#ffb400', '#ffbe00',
        '#ffc800', '#ffd200', '#ffdc00', '#ffe600', '#fff000', '#fffa00',
        '#ffff00', '#ffff0a', '#ffff14', '#ffff1e', '#ffff28', '#ffff32',
        '#ffff3c', '#ffff46', '#ffff50', '#ffff5a', '#ffff64', '#ffff6e',
        '#ffff78', '#ffff82', '#ffff8c', '#ffff96', '#ffffa0', '#ffffaa',
        '#ffffb4', '#ffffbe', '#ffffc8', '#ffffd2', '#ffffdc', '#ffffe6',
        '#fffff0']

        cmap = matplotlib.colors.ListedColormap(hotcolors)

        self.im = self.axes.imshow(data0, cmap=cmap, origin='lower')

        # http://matplotlib.sourceforge.net/examples/pylab_examples/show_colormaps.html
        # shows examples to use as a 'cold' to 'hot' mapping of value to color
        # cm.jet, cm.gnuplot and cm.afmhot are good choices, but are unlike G2 'hot'

        self.im.cmap=cmap

        # Not sure how to properly add a colorbar
        # self.cb = self.fig.colorbar(self.im, orientation='vertical')

        # refresh the canvas
        self.canvas.draw()      

    def get_xyt_data(self):
        # Create scaled (0-1) luminance(x,y) array from ascii G-2 disk_out file
        # get the data to plot from the specified filename
        # Note that NumPy loadtxt transparently deals with bz2 compression
        self.SetStatusText('Data loading - please wait ....')
        rawdata = np.loadtxt(self.filename)
        # Note the difference between NumPy [row, col] order and network
        # x-y grid (x, y) = (col, row). We want a NumPy NY x NX, not 
        # NX x NY, array to be used by the AxesImage object.

        xydata = np.resize(rawdata, (self.Ntimes, self.NY, self.NX))
        # imshow expects the data to be scaled to range 0-1.
        Vmin = xydata.min()
        Vmax = xydata.max()
        self.ldata = (xydata - Vmin)/(Vmax - Vmin)
        self.data_loaded = True
        self.SetStatusText('Data has been loaded - click Play')

    def plot_data(self):
        ''' plot_data() shows successive frames of the data that was loaded
            into the ldata array.  Creating a new self.im AxesImage instance
            for each frame is extremely slow, so the set_data method of
            AxesImage is used to load new data into the existing self.im for
            each frame.  Normally 'self.canvas.draw()' would be used to
            display a frame, but redrawing the entire canvas, redraws the
            axes, labels, sliders, buttons, or anything else on the canvas.
            This uses a method taken from an example in Ch 7, p. 192
            Matplotlib for Python developers, with draw_artist() and blit()
            redraw only the part that was changed.

        '''
        if self.data_loaded == False:
            # bring up a warning dialog
            msg = """
            Data for plotting has not been loaded!
            Please enter the file to plot with File/Open, unless
            it was already specified, and then click on 'New Data'
            to load the data to play back, before clicking 'Play'.
            """
            wx.MessageBox(msg, "Plot Warning", wx.OK | wx.ICON_ERROR,self)
            return

        # set color limits
        self.im.set_clim(0.0, 1.0)
        self.im.set_interpolation('nearest')
        # 'None' is is slightly faster, but not implemented for MPL ver < 1.1
        # self.im.set_interpolation('None')

        # do an initial draw, then save the empty figure axes
        self.canvas.draw()      

        # self.bg = self.canvas.copy_from_bbox(self.axes.bbox)
        # However the save and restore is only  needed if I change
        # axes legends, etc.  The draw_artist(artist), and blit
        # are much faster than canvas.draw() and are sufficient.

        print 'system time (seconds) = ', time.time()

        # round frame_min down and frame_max up for the time window
        frame_min = int(self.t_min/self.dt)
        frame_max = min(int(self.t_max/self.dt) + 1, self.Ntimes)
        frame_step = self.step

        # Displaying simulation time to the status bar is much faster
        # than updating a slider progress bar, but location isn't optimum.
        # The check for the STOP button doesn't work because the button
        # click is not registered until this function exits.

        # check to see if self.reverse_play == True
        # then interchange frame_min, frame_max, and use negative step
        if self.reverse_play == True:
            frame_min = min(int(self.t_max/self.dt) + 1, self.Ntimes) - 1
            frame_max = int(self.t_min/self.dt) - 1
            frame_step = -self.step
        for frame_num in range(frame_min, frame_max, frame_step):
            self.SetStatusText('time: '+str(frame_num*self.dt))
            if self.STOP == True:
                self.t_min = frame_num*self.dt
                # set t_min slider ?
                self.STOP = False
                break
            self.im.set_data(self.ldata[frame_num])
            self.axes.draw_artist(self.im)
            self.canvas.blit(self.axes.bbox)

        print 'system time (seconds) = ', time.time()

    #  ------------------------------------------------------------------
    #	Define the classes and functions for getting parameter values
    #  --------------------------------------------------------------

    class ParamEntryDialog(wx.Dialog):
        def __init__(self):
	    wx.Dialog.__init__(self, None, wx.ID_ANY)
	    self.SetSize((250, 200))
	    self.SetTitle('Enter Data File Parameters')
	    vbox = wx.BoxSizer(wx.VERTICAL)
	    self.Ntimes_dialog = XDialog(self)
	    self.Ntimes_dialog.entry_label.SetLabel('Number of entries')
	    self.Ntimes_dialog.entry.ChangeValue(str(2501))
	    self.tmin_dialog = XDialog(self)
	    self.tmin_dialog.entry_label.SetLabel('Start time (sec)')
	    self.tmin_dialog.entry.ChangeValue(str(0.0))

	    self.dt_dialog = XDialog(self)
	    self.dt_dialog.entry_label.SetLabel('Output time step (sec)')
	    self.dt_dialog.entry.ChangeValue(str(0.0002))

	    self.NX_dialog = XDialog(self)
	    self.NX_dialog.entry_label.SetLabel('Number of cells on x-axis')
            self.NX_dialog.entry.ChangeValue(str(32))
            self.NY_dialog = XDialog(self)
            self.NY_dialog.entry_label.SetLabel('Number of cells on y-axis')
            self.NY_dialog.entry.ChangeValue(str(32))

            vbox.Add(self.Ntimes_dialog, 0, wx.EXPAND|wx.ALL, border=5)
            vbox.Add(self.tmin_dialog, 0, wx.EXPAND|wx.ALL, border=5)
            vbox.Add(self.dt_dialog, 0, wx.EXPAND|wx.ALL, border=5)
            vbox.Add(self.NX_dialog, 0, wx.EXPAND|wx.ALL, border=5)
            vbox.Add(self.NY_dialog, 0, wx.EXPAND|wx.ALL, border=5)

            okButton = wx.Button(self, wx.ID_OK,'Ok')
	    # vbox.Add(okButton,flag=wx.ALIGN_CENTER|wx.TOP|wx.BOTTOM, border=10)
	    vbox.Add(okButton,flag=wx.ALIGN_CENTER, border=10)

            self.SetSizer(vbox)
	    self.SetSizerAndFit(vbox)

    #  ------------------------------------------------------------------
    #	Define the functions executed on menu choices
    #  ---------------------------------------------------------------
         
    def OnQuit(self, event):
        self.Close()

    def OnSave(self, event):
	file_choices = "PNG (*.png)|*.png"
        dlg = wx.FileDialog(
	    self, 
	    message="Save plot as...",
            defaultDir=os.getcwd(),
            defaultFile="plot.png",
            wildcard=file_choices,
            style=wx.SAVE)

        if dlg.ShowModal() == wx.ID_OK:
            path = dlg.GetPath()
            self.canvas.print_figure(path, dpi=self.dpi)
            # self.flash_status_message("Saved to %s" % path)
         
    def OnAbout(self, event):
	msg = """

                      G-3 Netview ver. 1.7

Netview is a stand-alone Python application for viewing
the output of GENESIS 2 and 3 network simulations.
It is intended to replace GENESIS 2 SLI scripts that use the
XODUS 'xview' widget.

The design and operation is based on the G3Plot application
for creating 2D plots of y(t) or y(x) from data files.
Unlike G3Plot, the image created with Netview is an animated
representation of a rectangular network with colored squares
used to indicate the value of some variable at that position
and time.  Typically, this would be the membrane potenial of
a cell soma, or a synaptic current in a dendrite segment.

Help/Usage gives HTML help for using Netview.
This is the main Help page.

Help/Program Info provides some information about the
objects and functions, and the wxPython and matplotlib
classes used here.

Dave Beeman, August 2012
	"""
        dlg = wx.MessageDialog(self, msg, "About G-3 Netview",
            wx.OK | wx.ICON_QUESTION)
	dlg.ShowModal()
	dlg.Destroy()

    def OnOpen(self, event):
        dlg = wx.TextEntryDialog(self, "File with x,y data to plot",
	    "File Open", self.filename, style=wx.OK|wx.CANCEL)
        if dlg.ShowModal() == wx.ID_OK:
            self.filename = dlg.GetValue()
            # A new filename has been entered, but the data has not been read
            self.data_loaded = False
            # print "You entered: %s" % self.filename     
        dlg.Destroy()

    #  This starts with the long string of HTML to display
    class UsageFrame(wx.Frame):
        text = """
<HTML>
<HEAD></HEAD>
<BODY BGCOLOR="#D6E7F7">

<CENTER><H1>Using G-3 Netview</H1></CENTER>

<H2>Introduction and Quick Start</H2>

<p>Netview is a stand-alone Python application for viewing the output of
GENESIS 2 and 3 network simulations.  It is intended to replace GENESIS 2
SLI scripts that use the XODUS 'xview' widget.</p>

<p>The design and operation is based on the G3Plot application for creating 2D
plots of y(t) or y(x) from data files.  As with G3Plot, the main class
PlotFrame uses a basic wxPython frame to embed a matplotlib figure for
plotting.  It defines some basic menu items and a control panel of buttons
and toggles, each with bindings to a function to execute on a mouse click.</p>

<p>Unlike G3Plot, the image created with Netview is an animated
representation of a rectangular network with colored squares
used to indicate the value of some variable at that position
and time.  Typically, this would be the membrane potenial of
a cell soma, or a synaptic current in a dendrite segment.</p>

<h2>Usage</h2>

<p>The Menu Bar has <em>File/Open</em>, <em>File/Save</em>, and
<em>File/Exit</em> choices.  The Help Menu choices <em>About</em> and
<em>Usage</em> give further information.  The <em>Program Info</em>
selection shows code documentation that is contained in some of the main
function <em>docstrings</em>.</p>

<p>After starting the <em>netview</em> program, enter a data file name
in the dialog for File/Open, unless the filename was given as a
command line argument.  Then click on <strong>New Data</strong> to load the new
data and initialize the plot.  When the plot is cleared to black,
press <strong>Play</strong>.</p>

<p>The file types recognized are plain text or text files compressed with
bzip2.  The expected data format is one line for each output time step,
with each line having the membrane potential value of each cell in the net.
No time value should be given on the line.  In order to properly display
the data, netview needs some additional information about the network and
the data.  This can optionally be contained in a header line that precedes
the data.  If a header is not detected, a dialog will appear asking for the
needed parameters.</p>

<p>It is assumed that the cells are arranged on a NX x NY grid, numbered
from 0 (bottom left corner) to NX*NY - 1 (upper right corner).
In order to provide this information to netview, the data file should
begin with a header line of the form:</p>

<pre>
    #optional_RUNID_string Ntimes start_time dt NX NY SEP_X SEP_Y x0 y0 z0
</pre>

<p>The line must start with &quot;#&quot; and can optionally be followed immediately by any
string.  Typically this is some identification string generated by the
simulation run.  The following parameters, separated by blanks or any
whitespace, are:</p>

<ul>
<li>Ntimes - the number of lines in the file, exclusive of the header</li>
<li>start_time - the simulation time for the first data line (default 0.0)</li>
<li>dt - the time step used for output</li>
<li>NX, NY - the integer dimensions of the network</li>
<li>SEP_X, SEP_Y - the x,y distances between cells (optional)</li>
<li>x0, y0, z0 - the location of the compartment (data source) relative to the
cell origin</li>
</ul>

<p>The RUNID string and the last five parameters are not read or used
by netview.  These are available for other data analysis tools that
need a RUNID and the location of each source.</p>

<p>The slider bars can be used to set a time window for display, and the
<strong>Reset</strong> button can set t_min and t_max back to the defaults.
Use the <strong>Forward/Back</strong> toggle to reverse direction of
<strong>Play</strong>, and the <strong>Normal/Fast</strong> toggle to show
every tenth frame.</p> <p>The <strong>Single Step</strong> button can be
used to advance a single step at a time (or 10, if in 'Fast' mode).</p>

<p>The <strong>STOP</strong> button is currently not implemented</p>
<p>To plot different data, enter a new filename with <strong>File/Open</strong> and
repeat with <strong>New Data</strong> and <strong>Play</strong>.</p>

<HR>
</BODY>
</HTML>
        """

        def __init__(self, parent):
            wx.Frame.__init__(self, parent, -1, "Usage and Help",
                size=(640,600), pos=(400,100))
            html = wx.html.HtmlWindow(self)
            html.SetPage(self.text)
            panel = wx.Panel(self, -1)
            button = wx.Button(panel, wx.ID_OK, "Close")
            self.Bind(wx.EVT_BUTTON, self.OnCloseMe, button)
            sizer = wx.BoxSizer(wx.VERTICAL)
            sizer.Add(html, 1, wx.EXPAND|wx.ALL, 5)
            sizer.Add(panel, 0, wx.ALIGN_CENTER|wx.ALL, 5)
            self.SetSizer(sizer)
            self.Layout()

	def OnCloseMe(self, event):
            self.Close(True)

        # ----------- end of class UsageFrame ---------------

    def OnUsage(self,event):
        usagewin = self.UsageFrame(self)
        usagewin.Show(True)

    def OnInfo(self,event):
        msg = "Program information for PlotFrame obtained from docstrings:"
        msg += "\n" + self.__doc__ + "\n" + self.create_main_panel.__doc__
        msg += self.create_button_bar.__doc__
        msg += self.init_plot.__doc__
        msg += self.plot_data.__doc__
        dlg = wx.lib.dialogs.ScrolledMessageDialog(self, msg,
            "PlotFrame Documentation")
        dlg.ShowModal()

    #  ---------------------------------------------------------------
    #	Define the functions executed on control button click
    #  ---------------------------------------------------------------

    def OnRewind(self,event):
        self.get_data_params()
        self.init_plot()
        self.get_xyt_data()

    def OnReplot(self,event):
        self.plot_data()
        self.canvas.draw()

    def OnSstep(self,event):
        if self.data_loaded == False:
            # bring up a warning dialog
            msg = """
            Data for plotting has not been loaded!
            Please enter the file to plot with File/Open, unless
            it was already specified, and then click on 'New Data'
            to load the data to play back, before clicking 'Play'.
            """
            wx.MessageBox(msg, "Plot Warning", wx.OK | wx.ICON_ERROR,self)
            return

        self.t_max = min(self.t_max + self.dt, (self.Ntimes - 1)*self.dt)
        self.stmax.set_val(self.t_max)
        frame_num = int(self.t_max/self.dt)
        self.SetStatusText('time: '+str(frame_num*self.dt))
        self.im.set_data(self.ldata[frame_num])
        self.axes.draw_artist(self.im)
        self.canvas.blit(self.axes.bbox)

    def OnStop(self,event):
        self.STOP = 'True'

    def OnForward(self,event):
        state =	 self.forward_toggle.GetValue()
        if state:
            self.reverse_play = False
            self.forward_toggle.SetLabel("Forward ")
            self.forward_toggle.SetForegroundColour('black')
            self.forward_toggle.SetBackgroundColour('yellow')
        else:
            self.reverse_play = True
            self.forward_toggle.SetLabel("  Back  ")
            self.forward_toggle.SetForegroundColour('red')
            self.forward_toggle.SetBackgroundColour('green')

    def OnFast(self,event):
        state =	 self.fast_toggle.GetValue()
        if state:
            # print state
            self.fast_toggle.SetLabel(" Normal ")
            self.fast_toggle.SetForegroundColour('black')
            self.fast_toggle.SetBackgroundColour('yellow')
            self.step = 1
        else:
            # print state
            self.fast_toggle.SetLabel("  Fast  ")
            self.fast_toggle.SetForegroundColour('red')
            self.fast_toggle.SetBackgroundColour('green')
            self.step = 10
class RotatableAxes:
    def __init__(self, fig: mpl.figure.Figure, axes: mpl.axes.Axes,
                 rect_angle: list, rect_reset: list):
        self.fig = fig
        # Suppose that there exists an image in the axes
        self.axes = axes
        self.renderer = self.axes.figure.canvas.get_renderer()
        self.axes_img_instance = self.axes.get_images()[0]
        self.original_axes_img = self.axes_img_instance.make_image(
            self.renderer, unsampled=True)[0]

        self.axes_for_angle_slider = self.fig.add_axes(rect_angle)
        self.axes_for_reset_button = self.fig.add_axes(rect_reset)
        self.angle_slider = Slider(self.axes_for_angle_slider,
                                   'Angle(Degree)',
                                   0.0,
                                   359.0,
                                   valinit=0.0,
                                   valstep=0.1)
        self.angle_slider.on_changed(self.update_img)
        self.reset_button = Button(self.axes_for_reset_button, 'Reset')
        self.reset_button.on_clicked(self.reset)

    def connect(self) -> None:
        # connect to all the events we need
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)

    def disconnect(self) -> None:
        # disconnect all the stored connection ids
        self.fig.canvas.mpl_disconnect(self.onclick)

    def update_la_img(self):
        self.axes_img_instance = self.axes.get_images()[0]
        self.original_axes_img = self.axes_img_instance.make_image(
            self.renderer, unsampled=True)[0]
        self.angle_slider.reset()

    def onclick(self, event: mpl.backend_bases.Event) -> None:
        if self.axes == event.inaxes:
            cur_img = self.axes_img_instance.make_image(self.renderer,
                                                        unsampled=True)[0]
            if event.button == mpl.backend_bases.MouseButton.LEFT and event.inaxes is not None:
                rotated_image = ndimage.rotate(cur_img, 90.0, reshape=False)
                self.axes_img_instance.set_data(rotated_image)
            elif event.button == mpl.backend_bases.MouseButton.RIGHT and event.inaxes is not None:
                flipped_img = cur_img[:, ::-1]
                self.axes_img_instance.set_data(flipped_img)
            self.axes.figure.canvas.draw()
            self.axes.figure.canvas.flush_events()

    def update_img(self, new_angle: float) -> None:
        axes_images_list = self.axes.get_images()
        rotated_img = ndimage.rotate(self.original_axes_img,
                                     new_angle,
                                     reshape=False)
        axes_images_list[0].set_data(rotated_img)
        self.axes.figure.canvas.update()
        self.axes.figure.canvas.flush_events()

    def reset(self, event: mpl.backend_bases.Event):
        self.angle_slider.reset()
class RotatableAxes:
    def __init__(self, fig: mpl.figure.Figure, axes: mpl.axes.Axes,
                 rect_angle: list, rect_reset: list):
        self.fig = fig
        # Suppose that there exists an image in the axes
        self.axes = axes
        self.renderer = self.axes.figure.canvas.get_renderer()
        self.axes_img = self.axes.get_images()[0]
        self.original_axes_img = self.axes_img
        self.original_img_list = [[
            np.rot90(img, i) for i in range(4)
        ] for img in [self.axes_img._A, self.axes_img._A[::-1, :]]]
        self.rot_idx = 0
        self.flip_idx = 0
        self.axes_for_angle_slider = self.fig.add_axes(rect_angle)
        self.axes_for_reset_button = self.fig.add_axes(rect_reset)
        self.angle_slider = Slider(self.axes_for_angle_slider,
                                   'Angle(Degree)',
                                   0.0,
                                   359.9,
                                   valinit=0.0,
                                   valstep=0.1)
        self.angle_slider.on_changed(self.update_img)
        self.reset_button = Button(self.axes_for_reset_button, 'Reset')
        self.reset_button.on_clicked(self.reset)

    def connect(self) -> None:
        # connect to all the events we need
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)

    def disconnect(self) -> None:
        # disconnect all the stored connection ids
        self.fig.canvas.mpl_disconnect(self.onclick)

    def update_la_img(self) -> None:
        self.axes_img = self.axes.get_images()[0]
        self.original_axes_img = self.axes_img
        self.original_img_list = [[
            np.rot90(img, i) for i in range(4)
        ] for img in [self.axes_img._A, self.axes_img._A[::-1, :]]]
        self.rot_idx = 0
        self.flip_idx = 0
        self.angle_slider.reset()

    def update_after_rot90(self) -> None:
        self.rot_idx = (self.rot_idx + 1) % 4
        left, right, bottom, top = self.original_axes_img.get_extent()
        self.axes_img.set_extent([top, bottom, right, left])

    def update_after_flip(self) -> None:
        self.flip_idx = (self.flip_idx + 1) % 2

    def onclick(self, event: mpl.backend_bases.Event) -> None:
        if self.axes == event.inaxes:
            if event.button == mpl.backend_bases.MouseButton.LEFT:
                self.update_after_rot90()
            elif event.button == mpl.backend_bases.MouseButton.RIGHT:
                self.update_after_flip()
            self.angle_slider.set_val(self.angle_slider.val)
            self.axes.figure.canvas.draw()
            self.axes.figure.canvas.flush_events()

    def update_img(self, new_angle: float) -> None:
        rotated_img = rotate_img(
            self.original_img_list[self.flip_idx][self.rot_idx], new_angle)
        self.axes_img.set_data(rotated_img)
        self.axes.figure.canvas.update()
        self.axes.figure.canvas.flush_events()

    def reset(self, event: mpl.backend_bases.Event) -> None:
        self.angle_slider.reset()
Example #16
0
class UHIDisplay:
    def __init__(self, sample_dir):
        self.sample_dir = sample_dir
        self.sample_idx = 0
        self.uhi = None
        self.h, self.w, self.d = 0, 0, 0
        self.px_min, self.px_max, self.refl_min, self.refl_max = 0, 0, 0, 0
        self.has_refl = False
        self.show_refl = False
        self.autoscale = True

        # List sample files
        print(f'Reading sample directory... ({self.sample_dir})')
        self.sample_files = [
            fname for fname in os.listdir(self.sample_dir)
            if fname.endswith('.h5')
        ]
        if not self.sample_files:
            print('No samples found in given directory, exiting...')
            exit()

        self.sample_files = sorted(self.sample_files)

        # Initialize first sample
        self.update_sample()

        # Create figure
        self.fig = plt.figure(figsize=(12, 4))
        plt.tight_layout()
        gridspec.GridSpec(1, 2)
        self.ax_uhi = plt.subplot2grid((3, 1), (0, 0), colspan=1, rowspan=3)
        self.image = self.ax_uhi.imshow(self.uhi.px[:, :, self.d // 2],
                                        origin='lower')

        # Wavelength slider
        axfreq = plt.axes([0.1, 0.1, 0.8, 0.05],
                          facecolor='lightgoldenrodyellow')
        self.sband = Slider(axfreq,
                            'Band [nm]',
                            0,
                            self.d - 1,
                            valinit=self.d // 2)
        self.sband.on_changed(self.update_band)

        # Previous button
        self.btn_prev_ax = plt.axes([0.04, 0.8, 0.1, 0.075])
        self.btn_prev = Button(self.btn_prev_ax, 'Prev')
        self.btn_prev.on_clicked(self.click_prev)

        # Next button
        self.btn_next_ax = plt.axes([0.15, 0.8, 0.1, 0.075])
        self.btn_next = Button(self.btn_next_ax, 'Next')
        self.btn_next.on_clicked(self.click_next)

        # Raw data / reflectance button
        self.btn_toggle_ax = plt.axes([0.26, 0.8, 0.1, 0.075])
        self.btn_toggle = Button(self.btn_toggle_ax, 'Reflectance')
        self.btn_toggle.on_clicked(self.click_toggle)

        # Autoscaling (per-band) / uniform scaling button
        self.btn_autoscale_ax = plt.axes([0.37, 0.8, 0.1, 0.075])
        self.btn_autoscale = Button(self.btn_autoscale_ax, 'Autoscale off')
        self.btn_autoscale.on_clicked(self.click_autoscale)

        self.update_title()
        self.fig.tight_layout()
        plt.tight_layout()
        plt.show()

    def update_sample(self):
        self.uhi = UHIData()
        self.uhi.read_hdf5(
            os.path.join(self.sample_dir, self.sample_files[self.sample_idx]))
        (self.w, self.h, self.d) = self.uhi.px.shape

        # Calculate reflectance
        self.uhi.calc_refl()
        self.refl_min, self.refl_max = np.min(
            self.uhi.refl[:, :, 50:-50]), np.max(self.uhi.refl[:, :, 50:-50])
        self.px_min, self.px_max = np.min(self.uhi.px[:, :, 50:-50]), np.max(
            self.uhi.px[:, :, 50:-50])

        self.has_refl = self.uhi.refl is not None

    def update_band(self, val=None):
        if val is None:
            val = self.sband.val
        band = np.floor(self.sband.val).astype(np.int)
        px = self.uhi.refl[:, :, band] if self.show_refl else self.uhi.px[:, :,
                                                                          band]
        self.image.set_data(px)

        if self.autoscale:
            self.image.autoscale()
        else:
            self.image.set_clim(
                vmin=self.refl_min if self.show_refl else self.px_min,
                vmax=self.refl_max if self.show_refl else self.px_max)

        self.sband.valtext.set_text(f'{self.uhi.wl[int(np.floor(val))]:.2f}')
        self.fig.canvas.draw_idle()

    def update_title(self):
        self.fig.suptitle(
            f'Sample {os.path.splitext(self.sample_files[self.sample_idx])[0]}'
        )

    def click_prev(self, event):
        self.sample_idx -= 1
        self.sample_idx = self.sample_idx if self.sample_idx > 0 else len(
            self.sample_files) - 1
        self.update_sample()
        self.update_band()
        self.update_title()

    def click_next(self, event):
        self.sample_idx += 1
        self.sample_idx = self.sample_idx % len(self.sample_files)
        self.update_sample()
        self.update_band()
        self.update_title()

    def click_toggle(self, event):
        if not self.has_refl:
            print(
                'Sample does not have calibration data embedded. Cannot show reflectance'
            )
            self.show_refl = False
        else:
            self.show_refl = not self.show_refl

        self.btn_toggle.label.set_text(
            'Reflectance' if not self.show_refl else 'Raw data')
        print('Displaying reflectance' if self.
              show_refl else 'Displaying raw data')
        self.update_band()

    def click_autoscale(self, event):
        self.autoscale = not self.autoscale
        self.btn_autoscale.label.set_text(
            'Autoscale off' if self.autoscale else 'Autoscale on')
        print('Autoscale on' if self.autoscale else 'Autoscale off')
        self.update_band()

    def reset(self, event):
        self.sband.reset()
Example #17
0
class vlm_slicer_interactive:
    def __init__(self, seis_vlm, pred_vlm, flag_slice):
        axis_color = 'lightgoldenrodyellow'
        idx_max = np.shape(seis_vlm)[2]
        self.seis_vlm = seis_vlm
        self.pred_vlm = pred_vlm
        self.cmap_bg = plt.cm.gray_r
        self.flag_slice = flag_slice

        fig = plt.figure()
        fig.subplots_adjust(left=0.25, bottom=0.25)
        self.ax = fig.add_subplot(111)
        self.idx_slider_ax = fig.add_axes([0.4, 0.1, 0.35, 0.03],
                                          facecolor=axis_color)
        self.idx_slider = Slider(self.idx_slider_ax,
                                 'Z',
                                 0,
                                 idx_max,
                                 valinit=0,
                                 valfmt='%d')
        self.idx_slider.on_changed(self.sliders_on_changed)
        self.reset_button_ax = fig.add_axes([0.8, 0.025, 0.1, 0.04])
        self.reset_button = Button(self.reset_button_ax,
                                   'Reset',
                                   color=axis_color,
                                   hovercolor='0.975')
        self.reset_button.on_clicked(self.reset_button_on_clicked)
        self.plot_slice(idx=0)
        self.fig = fig
        self.imshow_alpha()
        plt.show()

    def plot_slice(self, idx):
        if self.flag_slice == 0:
            self.seis_slice = self.seis_vlm[:, :, idx]
            self.pred_slice = self.pred_vlm[:, :, idx]
        elif self.flag_slice == 1:
            self.seis_slice = self.seis_vlm[:, idx, :]
            self.pred_slice = self.pred_vlm[:, idx, :]
        elif self.flag_slice == 2:
            self.seis_slice = self.seis_vlm[idx, :, :]
            self.pred_slice = self.pred_vlm[idx, :, :]

    def create_img_alpha(self, img_input):
        img_alpha = np.zeros(
            [np.shape(img_input)[0],
             np.shape(img_input)[1], 4])
        threshold = 0.1
        img_input[img_input < threshold] = 0
        # Yellow: (1,1,0), Red: (1,0,0)
        img_alpha[:, :, 0] = 1
        img_alpha[:, :, 1] = 0
        img_alpha[:, :, 2] = 0
        img_alpha[..., -1] = img_input
        return img_alpha

    def imshow_alpha(self, idx=0):
        self.plot_slice(idx)
        img_alpha = self.create_img_alpha(self.pred_slice.T)
        self.ax.imshow(self.seis_slice.T, self.cmap_bg)
        self.ax.imshow(img_alpha, alpha=0.5)

    def sliders_on_changed(self, val):
        self.imshow_alpha(int(val))
        self.fig.canvas.draw_idle()

    def reset_button_on_clicked(self, mouse_event):
        self.idx_slider.reset()
class Visualisation:

    def __init__(self, probability, big_dates, small_dates):
        self.probability = probability
        self.big_dates = big_dates
        self.small_dates = small_dates
        self.days = int(input("Number of days to visualize: "))
        self.x_data = np.arange(0.0, self.days, 1)

        self.initial_work_rate = int(input("Initial work rate: "))
        self.init_price_big = int(input("Initial price for a recovery try of full backups: "))
        self.init_price_small = int(input("Initial price for a recovery try of incremental backups: "))

        self.ax_color = 'lightgoldenrodyellow'
        self.s_work_rate = Slider
        self.s_price_big = Slider
        self.s_price_small = Slider

    def y_data(self, price_big, price_small, work_r):
        fail_big = 0
        fail_small = 0
        counter = 0
        prices = self.x_data.copy()
        for time_iterator in self.x_data:
            for date_iterator in self.big_dates:
                if time_iterator == date_iterator:
                    fail_big += 1
            for date_iterator in self.small_dates:
                if time_iterator == date_iterator:
                    fail_small += 1
            prices[counter] = self.x_data[counter] * work_r + price_big * fail_big + price_small * fail_small
            counter += 1
        return prices

    def slider_setup(self):
        ax_work_rate = plt.axes([0.25, 0.15, 0.65, 0.03], facecolor=self.ax_color)
        ax_price_big = plt.axes([0.25, 0.10, 0.65, 0.03], facecolor=self.ax_color)
        ax_price_small = plt.axes([0.25, 0.05, 0.65, 0.03], facecolor=self.ax_color)
        self.s_work_rate = Slider(ax_work_rate, 'Work Rate', 0.1, 300.0, valinit=self.initial_work_rate)
        self.s_price_big = Slider(ax_price_big, 'Big backup price', 0.1, 250.0, valinit=self.init_price_big)
        self.s_price_small = Slider(ax_price_small, 'Small backup price', 0.1, 250.0, valinit=self.init_price_small)

    def button_setup(self):
        reset_ax = plt.axes([0.8, 0.01, 0.1, 0.04])
        button = Button(reset_ax, 'Reset', color=self.ax_color, hovercolor='0.975')
        return button

    def defining_plots(self):
        fig, ax = plt.subplots()
        plt.subplots_adjust(left=0.25, bottom=0.25)
        l, = plt.plot(self.x_data, self.y_data(self.init_price_big, self.init_price_small, self.initial_work_rate),
                      lw=1.2)
        ax.margins(x=0)
        return [fig, l]

    def actual_plot(self):
        self.defining_plots()
        self.s_work_rate.on_changed(self.update)
        self.s_price_big.on_changed(self.update)
        self.s_price_small.on_changed(self.update)
        self.button_setup()
        button = self.button_setup()
        button.on_clicked(self.reset)
        plt.show()

    def reset(self, event):
        self.s_work_rate.reset()
        self.s_price_big.reset()
        self.s_price_small.reset()
        self.button_setup.on_clicked(self.reset)

    def update(self, val):
        plots = self.defining_plots()
        work_rate = self.s_work_rate.val
        price_big = self.s_price_big.val
        price_small = self.s_price_small.val
        plots[0].canvas.draw_idle()
        plots[1].set_ydata(self.y_data(price_big, price_small, work_rate))
Example #19
0
class Graphics(object):
    def __init__(self, wl, r1, r2):  # Initialize graphics using Matplotlib
        global mask
        self.wli = wl
        self.ri1 = r1
        self.ri2 = r2
        self.wl_msk = np.array([])
        self.dwl_msk = np.array([])
        self.fig1 = plt.figure(figsize=(15, 6))
        self.ax1 = self.fig1.add_subplot(1, 1, 1)
        plt.subplots_adjust(bottom=0.35)
        self.ax1.set_xlabel('Wavelength, Angstroms')
        self.ax1.set_ylabel('Residual intensity')
        if mask == "":
            # Widgets
            # Button "Select line"
            axis_line = plt.axes([0.04, 0.025, 0.1, 0.04])
            self.button_line = Button(axis_line,
                                      'Select line',
                                      color='grey',
                                      hovercolor='0.975')
            self.button_line.on_clicked(self.lineselect)
            # Button "Measure line"
            axis_measure = plt.axes([0.15, 0.025, 0.1, 0.04])
            self.button_measure = Button(axis_measure,
                                         'Measure line',
                                         color='grey',
                                         hovercolor='0.975')
            self.button_measure.on_clicked(self.measure_line)
            # Button "Write result"
            axis_writeout = plt.axes([0.26, 0.025, 0.1, 0.04])
            self.button_writeout = Button(axis_writeout,
                                          'Write results',
                                          color='green',
                                          hovercolor='0.975')
            self.button_writeout.on_clicked(self.write_line)
            # Button "Dump line"
            axis_dumpline = plt.axes([0.37, 0.025, 0.1, 0.04])
            self.button_dumpline = Button(axis_dumpline,
                                          'Dump line',
                                          color='grey',
                                          hovercolor='0.975')
            self.button_dumpline.on_clicked(self.dump_line)
        # Button "Save mask"
        axis_savemask = plt.axes([0.48, 0.025, 0.1, 0.04])
        if mask == "":
            name = 'Save mask'
        else:
            name = 'Measure by mask'
        self.button_savemask = Button(axis_savemask,
                                      name,
                                      color='grey',
                                      hovercolor='0.975')
        if args.usemask == "":
            self.button_savemask.on_clicked(self.save_mask)
        else:
            self.button_savemask.on_clicked(self.measure_mask)
        # Button "Analyse"
        axis_analyse = plt.axes([0.59, 0.025, 0.1, 0.04])
        self.button_analyse = Button(axis_analyse,
                                     'Analyse results',
                                     color='blue',
                                     hovercolor='0.975')
        self.button_analyse.on_clicked(self.analyse)
        # Button "Reset plot"
        axis_reset = plt.axes([0.74, 0.025, 0.1, 0.04])
        self.button_reset = Button(axis_reset,
                                   'Reset plot',
                                   color='orange',
                                   hovercolor='0.975')
        self.button_reset.on_clicked(self.reset)
        # Button "Exit"
        axis_exit = plt.axes([0.85, 0.025, 0.1, 0.04])
        self.button_exit = Button(axis_exit,
                                  'Exit app.',
                                  color='red',
                                  hovercolor='0.975')
        self.button_exit.on_clicked(self.exit)
        # draw initial plot
        self.ax1.plot(self.wli,
                      self.ri1,
                      linestyle='-',
                      lw=1,
                      marker='.',
                      ms=1.1,
                      color='red')
        self.ax1.plot(self.wli,
                      self.ri2,
                      linestyle='-',
                      lw=1,
                      marker='.',
                      ms=1.1,
                      color='blue')
        self.ax1.set_xlim([self.wli[0] - 1., self.wli[-1] + 1.])
        if mask != "":
            self.readin_mask(mask)
        cursor = Cursor(self.ax1, useblit=True, color='red', linewidth=0.5)
        # Controls
        if mask != "":
            # Slider "Shift mask"
            axis_shiftmask = plt.axes([0.15, 0.10, 0.65, 0.03])
            self.slider_shiftmask = Slider(axis_shiftmask,
                                           'Shift mask [km/s]',
                                           -150,
                                           150,
                                           valinit=0)
            self.slider_shiftmask.on_changed(self.shiftmask)
        else:
            # Slider "line width"
            axis_width = plt.axes([0.15, 0.1, 0.65, 0.03])
            self.slider_width = Slider(axis_width,
                                       'Selection Width',
                                       0.5,
                                       22.0,
                                       valinit=1.4)
            self.slider_width.on_changed(self.change_range)
            # Slider "line center"
            axis_shift = plt.axes([0.15, 0.20, 0.65, 0.03])
            self.slider_shift = Slider(axis_shift,
                                       'Selection shift',
                                       -6.,
                                       6.,
                                       valinit=0.)
            self.slider_shift.on_changed(self.change_range)
        plt.show()

    def lineselect(self, event):
        print("Mark center of measured line")
        self.cid1 = self.fig1.canvas.mpl_connect('button_press_event',
                                                 self.selected)

    def selected(self, event):
        if (event.button == 1):
            yc = self.ax1.get_ylim()
            self.lc = event.xdata
            self.fig1.canvas.mpl_disconnect(self.cid1)
            width = self.slider_width.val
            shift = self.slider_shift.val
            center = (self.lc + shift)
            self.band, = self.ax1.bar(center,
                                      width=width,
                                      height=max(self.ri1),
                                      color='blue',
                                      alpha=0.3,
                                      align='center')
            self.ax1.set_ylim(yc[0], yc[1])
            plt.draw()
            self.line = ZLine()
            self.line.change_range(center - width / 2., width)

    def change_range(self, event):
        width = self.slider_width.val
        shift = self.slider_shift.val
        center = self.lc + self.slider_shift.val
        self.band.set_width(width)
        self.band.set_x(center - width / 2.)
        plt.draw()
        self.line.change_range(center - width / 2., width)

    def measure_line(self, event):
        global mask
        self.line.measure_line()
        if hasattr(self.line, 'func1') and hasattr(self.line, 'func2'):
            self.ax1.plot(self.line.fit_wl, self.line.func1, 'g-', lw=1)
            self.ax1.plot(self.line.fit_wl, self.line.func2, 'k-', lw=1)
            mingfit = min(min(self.line.func1), min(self.line.func2))
            self.ax1.plot([self.line.gcent1, self.line.gcent1],
                          [mingfit - 0.03, mingfit - 0.01],
                          'g-',
                          lw=0.7)
            self.ax1.plot([self.line.gcent2, self.line.gcent2],
                          [mingfit - 0.03, mingfit - 0.01],
                          'k-',
                          lw=0.7)
            # self.ax1.plot(self.line.nwl1, self.line.cont1, 'r-') # draw semi-continuum
            # self.ax1.plot(self.line.nwl2, self.line.cont2, 'b-') # the same
            plt.draw()
        if mask == "":
            self.slider_shift.reset()

    def analyse(self, event):
        global report_fh
        ZSpec().analyse()

    def measure_mask(self, event):
        for ln in range(len(self.wl_msk)):
            self.line = ZLine()
            self.line.change_range(self.wl_msk[ln] - self.dwl_msk[ln],
                                   2 * self.dwl_msk[ln])
            self.measure_line(self)
            if hasattr(self.line, 'func1') and hasattr(self.line, 'func2'):
                self.write_line(self)
        print("Measuring using the mask has completed.")

    def readin_mask(self, file_mask):
        self.wl_msk, self.dwl_msk = np.loadtxt(file_mask,
                                               unpack=True,
                                               usecols=(0, 1),
                                               delimiter=';',
                                               comments='#')
        self.wl0_msk = self.wl_msk
        self.band_msk = self.ax1.bar(self.wl_msk,
                                     width=self.dwl_msk * 2.,
                                     height=max(self.ri1),
                                     color='orange',
                                     alpha=0.5,
                                     align='center')
        plt.draw()

    def shiftmask(self, event):
        yc = self.ax1.get_ylim()
        self.wl_msk = self.wl0_msk * np.sqrt(
            (1. + self.slider_shiftmask.val / c) /
            (1. - self.slider_shiftmask.val / c))
        for i in range(len(self.wl_msk)):
            self.band_msk[i].set_x(self.wl_msk[i] - self.dwl_msk[i])
        plt.draw()
        self.ax1.set_ylim(yc[0], yc[1])

    def reset(self, event):
        global mask
        self.ax1.clear()
        self.ax1.plot(self.wli, self.ri1, 'r-', lw=0.7)
        self.ax1.plot(self.wli, self.ri2, 'b-', lw=0.7)
        self.ax1.set_xlim([self.wli[0] - 1., self.wli[-1] + 1.])
        if mask == "":
            self.slider_width.reset()
            self.slider_shift.reset()
        else:
            self.slider_shiftmask.reset()

    def write_line(self, event):
        global fh
        if len(self.line.res) > 1:
            np.savetxt(fh, self.line.res.transpose(), fmt='%10.4f')
            self.line.close()
            print("...saved")
            self.ax1.text(
                (self.line.gcent1 + self.line.gcent2) / 2,
                min(min(self.line.func1), min(self.line.func2)) - 0.04, 'S')
            self.wl_msk = np.append(self.wl_msk, np.mean(self.line.wl))
            self.dwl_msk = np.append(self.dwl_msk,
                                     np.mean(self.line.wl) - self.line.wl[0])
        else:
            print("...skipped")

    def save_mask(self, event):
        global mask_fh
        output = np.zeros(self.wl_msk.size,
                          dtype=[('wave', float), ('width', float),
                                 ('id', 'U32'), ('lande', float)])
        output['wave'] = self.wl_msk
        output['width'] = self.dwl_msk
        output['id'] = np.repeat('NoID', len(self.wl_msk))
        output['lande'] = 1.23 * np.ones(len(self.wl_msk))
        try:
            np.savetxt(mask_fh,
                       output,
                       header='Wl0  ;  dWl  ;   ID   ;  g_lande',
                       fmt="%.4f; %.4f; %s; %.2f")
        finally:
            print(f"Mask {mask_fh} saved.")

    def dump_line(self, event):
        # Make text dump of lines
        outname = str(int(self.line.cent1))
        outarr1 = self.line.wl
        outarr2 = self.line.wl
        np.savetxt(outname + '_1.line',
                   np.vstack((outarr1, self.line.r1)).transpose(),
                   fmt='%10.4f',
                   delimiter='\t')
        np.savetxt(outname + '_2.line',
                   np.vstack((outarr2, self.line.r2)).transpose(),
                   fmt='%10.4f',
                   delimiter='\t')

    def exit(self, event):
        self.ax1.set_xlim([self.wli[0] - 1., self.wli[-1] + 1.])
        self.ax1.set_ylim([0, 1.1])
        self.fig1.savefig(report_fh + ".visual.pdf", dpi=350)
        exit(0)
Example #20
0
class Vorwaertsproblem():
    
    def __init__(self, l_e=10, l_r=3, h_m=30, h_b=90, phi_0=135, delta_phi=45, psi=90, show_legend=True):
        self.l_e = l_e
        self.l_r = l_r
        self.h_m = h_m
        self.h_b = h_b        
        self.phi = phi_0
        self.delta_phi = delta_phi 
        self.psi = psi 
        self.show_legend = show_legend
        
    def initUI(self):
        self.fig, self.ax = plt.subplots()
        self.fig.canvas.set_window_title('Numerik DGL 2 - Schattenprojektion')
        self.fig.suptitle('Vorwaertsproblem')
        plt.subplots_adjust(bottom=0.3)
        plt.axis([0, 200, -100, 100])
        plt.axis('equal')
        axColor = 'lightgoldenrodyellow'
        
        # Slider - Phi
        axPhi = plt.axes([0.18, 0.2, 0.65, 0.03], axisbg=axColor)                
        self.sliderPhi = Slider(axPhi, 'Phi', 0, 360, valinit=self.phi, valfmt='%1d')
        self.sliderPhi.on_changed(self.onUpdate)
        # Slider - Delta Phi
        axDeltaPhi = plt.axes([0.18, 0.15, 0.65, 0.03], axisbg=axColor)        
        self.sliderDeltaPhi = Slider(axDeltaPhi, 'Delta Phi', 5, 360, valinit=self.delta_phi, valfmt='%1d')        
        self.sliderDeltaPhi.on_changed(self.onUpdate)
        # Slider - Psi
        axPsi = plt.axes([0.18, 0.1, 0.65, 0.03], axisbg=axColor)        
        self.sliderPsi = Slider(axPsi, 'Psi', 0, 180, valinit=self.psi, valfmt='%1d')        
        self.sliderPsi.on_changed(self.onUpdate)
        # Button - Previous
        axPrev = plt.axes([0.18, 0.03, 0.1, 0.05])
        self.buttonPrev = Button(axPrev, 'Previous')
        self.buttonPrev.on_clicked(self.onPrevious)
        # Button - Next
        axNext = plt.axes([0.29, 0.03, 0.1, 0.05])
        self.buttonNext = Button(axNext, 'Next')
        self.buttonNext.on_clicked(self.onNext)        
        # Button - Reset        
        axReset = plt.axes([0.73, 0.03, 0.1, 0.05])
        self.buttonReset = Button(axReset, 'Reset')
        self.buttonReset.on_clicked(self.onReset)
        
        self.onDraw()
    
    def onPrevious(self, event):        
        self.phi -= self.delta_phi    
        self.phi = self.phi % 360
        self.onDraw()
    
    def onNext(self, event):    
        self.phi += self.delta_phi
        self.phi = self.phi % 360
        self.onDraw()
    
    def onReset(self, event):
        self.sliderPhi.reset()
        self.sliderDeltaPhi.reset()    
        self.sliderPsi.reset()    
        self.onDraw()
        
    def onUpdate(self, val):
        self.phi = int(self.sliderPhi.val)
        self.delta_phi = int(self.sliderDeltaPhi.val)
        self.psi = int(self.sliderPsi.val)
        self.onDraw()        
        self.fig.canvas.draw_idle()
        
    def onDraw(self):
        self.ax.cla()  # clear the axes 
        self.ax.margins(x=.1, y=.1)  # add margins
        self.ax.autoscale(enable=False)
        psi = np.radians(self.psi)
        phi = np.radians(self.phi)
        # Werte berechnen
        h_r = vw.get_h_r(self.l_e, self.h_m, phi)
        alpha = vw.get_alpha(self.l_e, phi, h_r)
        beta = vw.get_beta(alpha, psi)
        h = vw.get_h(psi, self.h_b, beta)    
        gamma = vw.get_gamma(self.l_r, h_r)
        b_bottom = vw.get_b_bottom(h, beta, gamma)
        b_top = vw.get_b_top(h, beta, gamma)
        b = vw.get_b(h, beta, gamma)
        # Abstand bis Drehteller vom Ursprung
        point_phi_x, point_phi_y = self.plot_line(0, 0, np.radians(0), self.h_m, name="hm", color='k-')
        self.ax.plot(self.h_m, 0, 'kx')
        self.ax.text(self.h_m, -0.3, 'h_m')
        # Untere Bodenlinie
        point_psi_x, point_psi_y = self.plot_line(0, 0, np.radians(0), self.h_b, name="hb", color='k-')
        self.ax.plot(self.h_b, 0, 'kx')
        self.ax.text(self.h_b, -0.3, 'h_b')
        # Drehteller
        circlele = plt.Circle((point_phi_x, point_phi_y), self.l_e, color='k', linestyle='dashed', fill=False)
        self.ax.add_artist(circlele)    
        # Winkelhalbierende
        point_b_x, point_b_y = self.plot_line(0,0, alpha, h, name="h", color='g-')
        # Winkelhalbierende bis Kreismittelpunkt
        point_r_x, point_r_y = self.plot_line(0, 0, alpha, h_r, name="hr", color = 'b-')
        # Abstand Mitte Drehteller, Mitte Zylinder
        self.ax.plot((self.h_m, point_r_x), (0, point_r_y), 'y-', label='l_e')
        self.ax.plot(point_r_x, point_r_y, 'kx')
        self.ax.text(point_r_x, point_r_y-0.3, 'M')
        # Zylinder
        circler = plt.Circle((point_r_x,point_r_y), self.l_r, color='k', fill=False)
        self.ax.add_artist(circler)
        # x,y Koordinate der Punkt b_top und b_bottom bestimmen
        b_top_x, b_top_y = self.plot_line(point_b_x, point_b_y, np.pi-psi, b_top, plot=False)
        b_bottom_x, b_bottom_y = self.plot_line(point_b_x, point_b_y, 2*np.pi-psi, b_bottom, plot=False)
        # Wand
        if b_bottom_y > point_psi_y and b_top_y > point_psi_y:  # Schatten oberhalb der Mittellinie
            kathete_top_a = np.abs(b_bottom_x-point_psi_x)
            kathete_top_b = np.abs(b_bottom_y-point_psi_y)
            len_top = 2*np.sqrt(kathete_top_a**2+kathete_top_b**2)+b
            len_bottom = 1
        elif b_bottom_y < point_psi_y and b_top_y < point_psi_y:  # Schatten unterhalb der Mittellinie            
            kathete_bottom_a = np.abs(b_top_x-point_psi_x)
            kathete_bottom_b = np.abs(b_top_y-point_psi_y)
            len_bottom = 2*np.sqrt(kathete_bottom_a**2+kathete_bottom_b**2)+b
            len_top = 1
        else:  # Schatten ober- und unterhalb der Mittellinie
            kathete_top_a = np.abs(b_top_x-point_psi_x)
            kathete_top_b = np.abs(b_top_y-point_psi_y)
            len_top = np.sqrt(kathete_top_a**2+kathete_top_b**2) + 5
            kathete_bottom_a = np.abs(b_bottom_x-point_psi_x)
            kathete_bottom_b = np.abs(b_bottom_y-point_psi_y)
            len_bottom = np.sqrt(kathete_bottom_a**2+kathete_bottom_b**2) + 5 
        self.plot_line(point_psi_x, point_psi_y, np.pi-psi, len_top, color="k-")  # obere Haelfte
        self.plot_line(point_psi_x, point_psi_y, 2*np.pi-psi, len_bottom, color="k-") # untere Haelfte
        # b an Wand
        self.plot_line(b_top_x, b_top_y, 2*np.pi-psi, b, name="b", color='r-')
        # Unterer Scheitel
        self.ax.plot((0, b_bottom_x), (0, b_bottom_y), 'c-.')
        self.ax.plot(b_bottom_x, b_bottom_y, 'kx')
        # Oberer Scheitel
        self.ax.plot((0, b_top_x), (0, b_top_y), 'c-.')
        self.ax.plot(b_top_x, b_top_y, 'kx')
        self.ax.axis('equal')
        if self.show_legend:
            self.ax.legend()
        
    def plot_line(self, pointx, pointy, angle, distance, plot=True, name=None, color='-'):
        x = np.cos(angle)*distance+pointx
        y = np.sin(angle)*distance+pointy
        if plot:
            self.ax.plot((pointx,x),(pointy,y),color, label=name)
        return x,y
        
    def plot(self):
        self.initUI()
        plt.show()
Example #21
0
class PlanetarySurveyor(object):
    """
    The PlanetarySurveyor creates a Matplotlib "widget" letting the user
    navigate map data loaded from an image file.
    """
    def __init__(self, filename):
        """
        Initialized with filename of image file containing the equirectangular
        map data.
        """

        self.filename = filename

        self.load_image()

        # Setup display:
        self.fig = plt.figure(1)
        self.ax = plt.subplot(111)
        plt.clf()
        plt.subplots_adjust(left=0.1, bottom=0.25)

        self.meridian = 90
        self.parallel = 90
        self.parallels = 16
        self.meridians = 16
        self.mode = "azimuthal"
        self.projection = "orthographic"

        self.setup_display()

        # Setup mouse interaction:
        self.click = self.display.figure.canvas.mpl_connect(
            'button_press_event', self.mouseclick)

        self.cursor = Cursor(self.display.axes,
                             useblit=True,
                             color='red',
                             linewidth=1)

        # Setup axes:
        self.axes_step = plt.axes([0.13, 0.15, 0.60, 0.03])
        self.axes_meridians = plt.axes([0.13, 0.10, 0.60, 0.03])
        self.axes_parallels = plt.axes([0.13, 0.05, 0.60, 0.03])

        self.update_axes = plt.axes([0.79, 0.095, 0.08, 0.04])
        self.reset_axes = plt.axes([0.79, 0.05, 0.08, 0.04])

        self.radio_axes = plt.axes([0.88, 0.05, 0.11, 0.15])

        # Setup sliders:
        self.step = 22.5

        self.slider_step = Slider(self.axes_step,
                                  'Step',
                                  0,
                                  90,
                                  valinit=self.step,
                                  valfmt='%2.1f')
        self.slider_meridians = Slider(self.axes_meridians,
                                       'Meridians',
                                       0,
                                       64,
                                       valinit=self.parallels,
                                       valfmt='%2d')
        self.slider_parallels = Slider(self.axes_parallels,
                                       'Parallels',
                                       0,
                                       64,
                                       valinit=self.parallels,
                                       valfmt='%2d')

        self.slider_step.on_changed(self.update)
        self.slider_meridians.on_changed(self.update)
        self.slider_parallels.on_changed(self.update)

        # Setup button(s):
        self.update_button = Button(self.update_axes, 'Update')
        self.update_button.on_clicked(self.update_display)

        self.reset_button = Button(self.reset_axes, 'Reset')
        self.reset_button.on_clicked(self.reset)

        # Setup radio buttons:
        self.radio = RadioButtons(
            self.radio_axes, ('ortho', 'eq.area', 'eq.dist', 'stereo', 'rect'),
            active=0)
        self.radio.on_clicked(self.set_mode)
        self.projections = {
            "ortho": ("orthographic", "azimuthal"),
            "eq.area": ("lambert", "azimuthal"),
            "eq.dist": ("equidistant", "azimuthal"),
            "stereo": ("stereographic", "azimuthal"),
            "rect": ("rectangular", "rectangular")
        }

        # Almost ready:
        self.update()
        plt.show()

    def load_image(self):
        """
        Load and flatten specified image file. If this fails, the default map
        is loaded.  """

        try:
            map_image = plt.imread(self.filename)
        except IOError as e:
            print "Could not load file {0} ({1})".format(
                self.filename, e.strerror)
            print "Using default image..."
            self.filename = "templates/nowwhat.png"
            map_image = plt.imread(self.filename)

        while len(map_image.shape) > 2:
            map_image = map_image.mean(-1)

        self.map_image = map_image

    def setup_display(self):
        """
        Setup parameters and map display.
        """

        self.R = 180
        self.padding = self.R / 10

        if self.mode == 'azimuthal':
            self.hemisphere = p.get_azimuthal_hemisphere(
                self.map_image, self.meridian, 90, self.R, self.projection, 0,
                self.padding)
            self.display = plt.imshow(self.hemisphere,
                                      cmap=plt.cm.gray,
                                      extent=[-1.5, 1.5, -1.5, 1.5])
            plt.axis([-1.5, 1.5, -1.5, 1.5])
            plt.axis('off')
        elif self.mode == 'rectangular':
            plt.axis([-180, 180, -90, 90])
            pass

        if self.meridians > 0 or self.parallels > 0:
            self.draw_graticules()

    def update_display(self, val=0):
        """
        Update map display.
        """

        if self.mode == 'azimuthal':
            self.hemisphere = p.get_azimuthal_hemisphere(
                self.map_image, self.meridian, 90, self.R, self.projection, 0,
                self.padding)
            ax = self.display.axes
            self.display.axes.cla()
            self.display = ax.imshow(self.hemisphere,
                                     cmap=plt.cm.gray,
                                     extent=[-1.5, 1.5, -1.5, 1.5])
            plt.axis([-1.5, 1.5, -1.5, 1.5])
            plt.axis('off')
        elif self.mode == 'rectangular':
            self.hemisphere = p.get_rectangular_hemisphere(
                self.map_image, self.meridian, self.parallel, False)
            ax = self.display.axes
            self.display.axes.cla()
            self.display = ax.imshow(self.hemisphere,
                                     cmap=plt.cm.gray,
                                     extent=[
                                         self.meridian - 90,
                                         self.meridian + 90,
                                         self.parallel - 90, self.parallel + 90
                                     ])
            plt.axis([
                self.meridian - 90, self.meridian + 90, self.parallel - 90,
                self.parallel + 90
            ])

        self.fix_coordinates()

        if self.meridians > 0 or self.parallels > 0:
            self.draw_graticules()

        self.update()

    def update(self, val=0):
        """
        Update internal parameters from sliders, update coordiantes and draw.
        """

        if self.step != self.slider_step.val:
            self.step = np.round(self.slider_step.val / 0.5) * 0.5
            self.slider_step.set_val(self.step)

        if (self.meridians != self.slider_meridians.val
                or self.parallels != self.slider_parallels.val):

            self.meridians = np.round(self.slider_meridians.val).astype(np.int)
            self.parallels = np.round(self.slider_parallels.val).astype(np.int)

        self.fix_coordinates()

        plt.draw()

    def set_mode(self, val="ortho"):
        """
        Set projection and mode.
        """

        self.projection = self.projections[val][0]
        self.mode = self.projections[val][1]

        if self.mode == "azimuthal":
            self.parallel = 90

        self.update_display()

    def reset(self, event):
        """
        Reset widget
        """

        self.slider_step.reset()
        self.slider_meridians.reset()
        self.slider_parallels.reset()
        self.meridian = 90
        self.parallel = 90
        self.update()
        self.set_mode()

    def mouseclick(self, event):
        """
        Handle mouse navigation of map display for the different projections.
        """

        if event.inaxes == self.display.axes:
            if event.button == 1:
                if self.mode == "azimuthal":
                    self.meridian += self.step * np.round(event.xdata)
                elif self.mode == "rectangular":
                    self.parallel = 180 - np.round(event.ydata / 0.5) * 0.5
                    self.meridian = np.round(event.xdata / 0.5) * 0.5

                self.update()
                self.update_display()

    def fix_coordinates(self):
        """
        Fix coordinates so they comply to standard representation for maps.
        """

        self.parallel %= 180
        self.meridian %= 360

        self.display.axes.set_title("{0}: {1}".format(self.projection,
                                                      self.get_coordinates()))

    def get_coordinates(self):
        """
        Return string representation of coordinates in N-S/E-W standard.
        """

        parallel = self.parallel
        meridian = self.meridian - 180

        if parallel > 90.0:
            parallel = 180.0 - parallel
        elif parallel < -90.0:
            parallel = -180.0 - parallel

        if meridian > 180.0:
            meridian = 360.0 - meridian
        elif meridian < -180.0:
            meridian = -360.0 - meridian

        if parallel >= 0:
            NS = "N"
        else:
            NS = "S"

        if meridian >= 0:
            EW = "E"
        else:
            EW = "W"

        return "{0} {1}, {2} {3}".format(np.abs(parallel), NS,
                                         np.abs(meridian), EW)

    def get_graticule(self):
        """
        Return resolution of the current graticule (distances between parallel
        and meridian lines).
        """

        try:
            dLat = 180.0 / self.parallels
        except ZeroDivisionError:
            dLat = None

        try:
            dLon = 360.0 / self.meridians
        except ZeroDivisionError:
            dLon = 0

        return dLat, dLon

    def draw_graticules(self):
        """
        Draw parallel and meridian lines using testgrids-module.
        """

        dLat, dLon = self.get_graticule()
        ax = self.display.axes

        if self.meridians > 0:
            if self.mode == "azimuthal":
                x_mer, z_mer = grids.get_meridians(self.meridian, dLon, 1,
                                                   1.5 / 1.1, self.projection)

                ax.plot(x_mer, z_mer, ':k', label="meridians")
                ax.axis('off')
            elif self.mode == "rectangular":
                mer_min = np.ceil((self.meridian - 90) / dLon) * dLon
                mer_max = np.floor((self.meridian + 90) / dLon) * dLon

                ax.set_xticks(np.arange(mer_min, mer_max + 1, dLon))
                ax.grid(True)

        if self.parallels > 0:
            if self.mode == "azimuthal":
                x_par, z_par = grids.get_parallels(self.parallel, dLat, 1,
                                                   1.5 / 1.1, self.projection)

                ax.plot(x_par, z_par, ':k', label="parallels")
                ax.axis('off')
            elif self.mode == "rectangular":
                par_min = np.ceil((self.parallel - 90) / dLat) * dLat
                par_max = np.floor((self.parallel + 90) / dLat) * dLat

                ax.set_yticks(np.arange(par_min, par_max + 1, dLat))
                ax.grid(True)
class slider_factory(object):
    """
        Accepts: my overloaded subplot from adials_gui
        returns: a slider for a relational interval
    """
    def __init__(self, ax, a=.1, b=10.):
        self.ax = ax
        self.fig = self.ax.figure
        self.plt = plt

        t = np.arange(0.0, 1.0, 0.001)
        self.t = t
        a0 = 5
        f0 = 3
        self.a0 = a0
        self.f0 = f0
        s = a0 * np.sin(2 * np.pi * f0 * t)
        self.l, = plt.plot(t, s, lw=2, color='red')
        plt.axis([0, 1, -10, 10])

        self.axcolor = 'lightgoldenrodyellow'
        axcolor = self.axcolor
        self.axfreq = plt.axes([0.25, 0.1, 0.65, 0.03], axisbg=axcolor)
        self.axamp = plt.axes([0.25, 0.15, 0.65, 0.03], axisbg=axcolor)

        self.sfreq = Slider(self.axfreq, 'Freq', 0.1, 30.0, valinit=f0)
        self.samp = Slider(self.axamp, 'Amp', a, b, valinit=a0)

        self.resetax = self.plt.axes([0.8, 0.025, 0.1, 0.04])
        self.button = Button(self.resetax,
                             'Reset',
                             color=self.axcolor,
                             hovercolor='0.975')

        self.rax = plt.axes([0.025, 0.5, 0.15, 0.15], axisbg=axcolor)
        self.radio = RadioButtons(self.rax, ('red', 'blue', 'green'), active=0)
        self.radio.on_clicked(self.colorfunc)

        self.update()
        return

    def update_(self, val):
        t = self.t
        amp = self.samp.val
        freq = self.sfreq.val
        self.l.set_ydata(amp * np.sin(2 * np.pi * freq * t))
        self.fig.canvas.draw_idle()
        return

    def update_freq(self, values):
        """
            TODO: implement
        """
        a = values[0]
        b = values[1]

        self.sfreq = Slider(self.axfreq, 'Freq', a, b, valinit=self.f0)
        self.update()
        self.fig.canvas.draw_idle()
        return

    def update_amp(self, values):
        a = values[0]
        b = values[1]
        self.fig.clear()
        self = slider_factory(ax, a, b)
        return

    def update(self):
        self.sfreq.on_changed(self.update_)
        self.samp.on_changed(self.update_)
        return

    def reset(self, event):
        self.sfreq.reset()
        self.samp.reset()

    def colorfunc(self, label):
        self.l.set_color(label)
        self.fig.canvas.draw_idle()
        return
Example #23
0
    ax.set_yticklabels([r'$\mathcal{P}_{B}$', r'$\Omega$', r'$\mathcal{P}_{A}$'])
    ax.set_xlabel('timesteps', labelpad=3)
    ax.set_ylabel('excitation energy', labelpad=5)

    initial = excitation_histogram(axhist, full, Ua, Ub, N)

    def update_plot(du):
        sim, simc, full, Ub, Ua  = calc_timeseries(N, du, tmax, phi, avg_steps=per_timestep)
        ln_const.set_ydata(simc[:ixs-brk])
        ln_fluc.set_ydata(sim[ixs+brk:])
        ax.set_yticks([N*Ub, N, N*Ua])

        axhist.cla()
        excitation_histogram(axhist, full, Ua, Ub, N, fit=initial)

        fig.canvas.draw_idle()

    duslider = Slider(ax_duslider, r'$\Delta$', 0.1, 1.9, valinit=du, dragging=False)
    duslider.on_changed(update_plot)

    button = Button(axreset, 'Reset')
    button.on_clicked(lambda e : duslider.reset())

    ttl = str(N) + " absorbers" + "        "
    ttl = ttl + str(per_timestep) + " events/timestep" + "        "
    ttl = ttl + r"$\phi =$ " + str(phi)
    plt.suptitle(ttl, fontsize=14)

    fig.show()
    plt.show()
Example #24
0
class Handler:
    def __init__(self):
        # plt.ion()
        self.url = "https://seasweb.azurewebsites.net/data.json"
        self.filter_const = 25
        self.by1 = None
        self.by2 = None
        self.py1 = None
        self.py2 = None
        self.unfiltered_series = None
        self.filtered_series = None
        self.data_to_plot = None
        self.subplot_axes = None
        self.radio = None
        self.slider = None
        self.func = None
        self.df = None

    # Downloading data and creating dataset
    def create_dataset(self):
        # Loading dataset from given url
        rawData = json.loads(requests.get(self.url).text)
        self.df = pd.DataFrame(rawData)
        # Creating numpy arrays for further processing
        self.by1 = self.df['BY1'].astype('float').to_numpy()
        self.by2 = self.df['BY2'].astype('float').to_numpy()
        self.py1 = self.df['PY1'].astype('float').to_numpy()
        self.py2 = self.df['PY2'].astype('float').to_numpy()
        # Creating lists of series
        self.unfiltered_series = [self.by1, self.by2, self.py1, self.py2]
        self.filtered_series = [
            self.__filter(self.by1),
            self.__filter(self.by2),
            self.__filter(self.py1),
            self.__filter(self.py2)
        ]

    # Plotting all series together on one figure
    def plot_all(self):
        # Testing if dataset was created
        if self.df is None:
            raise ValueError("Dataset is not created")

        # Plotting and setting up graph
        ax1 = self.df.plot(x='category', figsize=(10, 9))
        ax1.title.set_text(
            'European Energy Exchange (EEX) data for years 2021 and 2022')
        ax1.set_ylabel('Price[€]', fontsize='large', fontweight='bold')
        ax1.set_xlabel('Date', fontsize='large', fontweight='bold')
        ax1.legend([
            "BY1 BaseLoad 2021 in €/MWh", "BY2 BaseLoad 2022 in €/MWh",
            "PY1 PeakLoad 2021 in €/MWh", "PY2 PeakLoad 2022 in €/MWh",
            "CO2 - Price of emission allowances in €/tonne"
        ])
        plt.draw()

    # Plotting all series separately on subplots
    def plot_by_one(self):
        # Testing if dataset was created
        if self.df is None:
            raise ValueError("Dataset is not created")

        # Plotting and setting up graph
        fig2, self.subplot_axes = plt.subplots(2, 2, figsize=(10, 9))
        fig2.subplots_adjust(left=0.3, wspace=0.2, hspace=0.3)
        fig2.suptitle('All series separately')
        fig2.text(0.25,
                  0.5,
                  'Price[€/MWh]',
                  rotation='vertical',
                  verticalalignment='center',
                  fontsize='large',
                  fontweight='bold')
        fig2.text(0.6,
                  0.03,
                  'Date',
                  fontsize='large',
                  horizontalalignment='center',
                  fontweight='bold')
        fig2.text(
            0.05,
            0.1,
            'Use slider only when filtered series is selected\nSlider for changing filter constant (filtering rate)',
            rotation='vertical',
            fontsize='large',
            fontweight='bold')

        # Reshaping list of axes for usage in for loop
        self.subplot_axes = np.reshape(self.subplot_axes, 4, 'F')
        # Updating which data will be plotted
        self.data_to_plot = self.unfiltered_series
        # Updating subplots by class function
        self.__subplot_update()

        # Creating radio button for changing which series to plot
        rax = plt.axes([0.05, 0.7, 0.15, 0.15])
        self.radio = RadioButtons(rax,
                                  ('Unfiltered series', 'Filtered series'))
        self.func = {
            'Unfiltered series': self.unfiltered_series,
            'Filtered series': self.filtered_series
        }

        # Creating slider for changing filter constant
        axSlider = plt.axes([0.1, 0.1, 0.05, 0.5])
        self.slider = Slider(axSlider,
                             'Slider',
                             valmin=1,
                             valmax=125,
                             valinit=25,
                             orientation='vertical',
                             valfmt='%d')

        # Assign a function handler to a button and slider
        self.radio.on_clicked(self.__radioButton_update)
        self.slider.on_changed(self.__slider_update)
        plt.draw()

    # Printing max values
    def print_max_values(self):
        # Printing 5 highest values to console for every series
        print("--------------------------------------------------")
        print("Highest values of series [BY1, BY2, PY1, PY2] :\n")
        # Iterating throught all series
        for s in self.unfiltered_series:
            # Indirect partition
            ind = np.argpartition(-s, 5)[:5]
            a = s[ind]
            # Swapping order
            a = -np.sort(-a)
            print(a)
        print("--------------------------------------------------")

    # Regression analysis
    def nonlinear_regression(self):
        # Prepocessing data for reggresion
        fig3 = plt.figure(3, figsize=(10, 9))
        X = [i for i in range(len(self.unfiltered_series[0]))]
        X = np.asfarray(X).reshape(-1, 1)
        y = self.unfiltered_series[0]

        # Fit regression model
        svr_rbf = SVR(kernel='rbf', C=100, gamma=0.1, epsilon=.1)

        # Plot graph of reggresion
        plt.plot(X,
                 svr_rbf.fit(X, y).predict(X),
                 color='m',
                 lw=2,
                 label='{} model'.format('RBF'))

        # Plot points
        plt.scatter(X, y, s=10)

        # Displaying information
        a = svr_rbf.score(X, y)
        fig3.suptitle('RBF regression')
        fig3.text(0.5,
                  0.9,
                  'Coefficient of determination R^2 is %s' % (a),
                  horizontalalignment='center',
                  fontsize='large',
                  fontweight='bold')
        plt.ylabel('Price[€]', fontsize='large', fontweight='bold')
        plt.xlabel('Days', fontsize='large', fontweight='bold')
        plt.draw()

    # The function which handle subplots updating every time data to plot or slider value was changed
    def __subplot_update(self):
        self.__plot_on_axis()

        # Positioning x label elements
        for a in self.subplot_axes:
            plt.setp(a.get_xticklabels(), rotation=30, ha='right')

        # Naming each subplot
        self.subplot_axes[0].title.set_text('BY1')
        self.subplot_axes[1].title.set_text('BY2')
        self.subplot_axes[2].title.set_text('PY1')
        self.subplot_axes[3].title.set_text('PY2')

        plt.draw()

    # Handler for radio button
    def __radioButton_update(self, label):
        # Updating which data will be plotted
        self.data_to_plot = self.func[label]
        # Updating subplots by class function
        self.__subplot_update()
        # Reseting slider
        self.slider.reset()

    # Handler for slider
    def __slider_update(self, val):
        # Slider is working only in filtered series state
        if self.radio.value_selected == 'Filtered series':
            # Updating filter constant
            self.filter_const = int(self.slider.val)
            # Updating list of filtered series
            self.filtered_series = [
                self.__filter(self.by1),
                self.__filter(self.by2),
                self.__filter(self.py1),
                self.__filter(self.py2)
            ]
            # Updating which data to plot
            self.data_to_plot = self.filtered_series
            # Updating subplots by class function
            self.__subplot_update()

    # The function for plotting columns of dataset to separated subplots
    def __plot_on_axis(self):
        # Each axis, one graph
        if len(self.data_to_plot) != len(self.subplot_axes):
            raise ValueError(
                'This function plot one column of dataset stored in array on one axis. Data array length is not the same as axes array length.'
            )
        i = 0
        for a in self.subplot_axes:
            a.clear()
            a.plot(pd.to_datetime(self.df['category']), self.data_to_plot[i])
            i += 1

    # The filter, it uses Furier transformation
    # ???!Malokedy vyuzijem v praxi nieco co som sa naucil v skole, ale toto je jedna z tych veci ktore som pochopil a pouzil!???
    def __filter(self, input):
        furrier_transform = np.fft.fft(input)
        shifted_furrier_transform = np.fft.fftshift(furrier_transform)
        HP_filter = np.zeros(len(shifted_furrier_transform), dtype=int)
        n = int(len(HP_filter))
        HP_filter[int(n / 2) - self.filter_const:int(n / 2) +
                  self.filter_const] = 1
        output = shifted_furrier_transform * HP_filter
        output = abs(np.fft.ifft(output))

        return output
class TCG():

    # @profile
    def __init__(self):

        self.dim_x = 1280  # * Horizonal pixel dimension
        self.dim_y = 720  # * Vertical pixel dimension
        self.limits = [-5, 15]  # * Curve View axis limits
        extent = self.limits * 2
        aspect_ratio = self.dim_x / self.dim_y
        bg_path = "./bg_images/"
        self.bg_list = [bg_path + s for s in os.listdir(bg_path)]

        axis_color = "#ede5c0"
        slider_color = "#bf616a"

        self.fig = plt.figure("TCG", (14, 8))
        self.fig.suptitle("Trash Cluster Generator", fontsize=14, y=0.95)
        self.fig.patch.set_facecolor("#D8DEE9")
        self.ax_bez = self.fig.add_subplot(121)
        self.ax_img = self.fig.add_subplot(122)

        self.fig.subplots_adjust(left=0.12, bottom=0.45, top=0.99, right=0.82)

        # ? Slider init values

        self.rad = 0.5  # * Radius
        self.edgy = 0.5  # * Edginess
        self.seeder = 50  # * Random Seed
        self.c = [-1, 1]  # * Translation co-ords
        self.scale = 10  # * Scale
        self.points = 4  # * Number of control points
        self.cluster_limit = (5, 10)  # * Cluster Limit

        # ? Images

        self.bg_index = 0  # * Background image pointer
        self.cluster_image = None  # * Generated Cluster image
        self.cluster_mask = None  # * Segmentation Mask (RGB)
        self.cluster_pil = None  # * Ground Truth Segmentation Mask
        self.cache = None  # * Reference params

        # ? Random Bezier Control Points
        self.a = (
            get_random_points(self.seeder, n=self.points, scale=self.scale) +
            self.c)

        # ? Bezier Curve coordinates and centre
        self.x, self.y, self.s = get_bezier_curve(self.a,
                                                  rad=self.rad,
                                                  edgy=self.edgy)
        self.centre = np.array([
            (np.max(self.x) + np.min(self.x)) / 2,
            (np.max(self.y) + np.min(self.y)) / 2,
        ])
        self.a_new = np.append(self.a, [self.centre], axis=0)

        self.ax_bez.set_xlim(self.limits)
        self.ax_bez.set_ylim(self.limits)

        # ? Curve View Image handler
        self.bezier_handler = self.ax_bez.imshow(plt.imread(
            self.bg_list[self.bg_index]),
                                                 extent=extent,
                                                 interpolation="none")

        self.ax_bez.set_aspect(1 / (aspect_ratio))
        self.ax_img.set_aspect(1 / (aspect_ratio))

        # ? Curve View Plot and Scatter handler
        (self.bezier_curve, ) = self.ax_bez.plot(self.x,
                                                 self.y,
                                                 linewidth=1,
                                                 color="w",
                                                 zorder=1)
        self.scatter_points = self.ax_bez.scatter(
            self.a_new[:, 0],
            self.a_new[:, 1],
            color="orangered",
            marker=".",
            alpha=1,
            zorder=2,
        )

        # ? Generator View Image handler
        self.cluster_handler = self.ax_img.imshow(
            np.flipud(np.array(plt.imread(self.bg_list[0]))),
            origin="lower",
            interpolation="none",
        )

        # ? State Indicator Text handler
        self.text_handler = plt.figtext(0.88,
                                        0.70,
                                        " Ready ",
                                        fontsize=14,
                                        backgroundcolor="#a3be8c")

        # ? Class distribution and its indicator text handlers
        self.class_dict = {
            "G:": (0.86, "#bdae93"),
            "M:": (0.901, "#81a1c1"),
            "P:": (0.942, "#b48ead"),
        }
        self.class_handlers = []
        self.class_count = Counter()
        for (cname, textarg) in self.class_dict.items():
            self.class_handlers.append(
                plt.figtext(
                    textarg[0],
                    0.80,
                    cname + "0".rjust(3),
                    fontsize=10,
                    backgroundcolor=textarg[1],
                ))

        # ? Saved image count and its indicator text handler
        self.count = len(
            [f for f in os.listdir(".") if f.startswith("label_")])
        self.count_handler = plt.figtext(
            0.86,
            0.76,
            f"Generated images: {self.count}",
            fontsize=10,
            backgroundcolor="#cf9f91",
        )

        undo_asset = plt.imread("./assets/undo.png")

        # ? Sliders

        rad_slider_ax = self.fig.add_axes([0.12, 0.42, 0.65, 0.03],
                                          facecolor=axis_color)
        self.rad_slider = Slider(rad_slider_ax,
                                 "Radius",
                                 0.0,
                                 1.0,
                                 valinit=self.rad,
                                 color=slider_color)

        edgy_slider_ax = self.fig.add_axes([0.12, 0.37, 0.65, 0.03],
                                           facecolor=axis_color)
        self.edgy_slider = Slider(edgy_slider_ax,
                                  "Edginess",
                                  0.0,
                                  5.0,
                                  valinit=self.edgy,
                                  color=slider_color)

        c0_slider_ax = self.fig.add_axes([0.12, 0.32, 0.65, 0.03],
                                         facecolor=axis_color)
        self.c0_slider = Slider(c0_slider_ax,
                                "Move X",
                                -7.0,
                                16.0,
                                valinit=self.c[0],
                                color=slider_color)

        c1_slider_ax = self.fig.add_axes([0.12, 0.27, 0.65, 0.03],
                                         facecolor=axis_color)
        self.c1_slider = Slider(c1_slider_ax,
                                "Move Y",
                                -7.0,
                                16.0,
                                valinit=self.c[1],
                                color=slider_color)

        scale_slider_ax = self.fig.add_axes([0.12, 0.22, 0.65, 0.03],
                                            facecolor=axis_color)
        self.scale_slider = Slider(scale_slider_ax,
                                   "Scale",
                                   1.0,
                                   20.0,
                                   valinit=self.scale,
                                   color=slider_color)

        points_slider_ax = self.fig.add_axes([0.12, 0.17, 0.65, 0.03],
                                             facecolor=axis_color)
        self.points_slider = Slider(
            points_slider_ax,
            "Points",
            3,
            10,
            valinit=self.points,
            valfmt="%d",
            color=slider_color,
        )

        seeder_slider_ax = self.fig.add_axes([0.12, 0.12, 0.65, 0.03],
                                             facecolor=axis_color)
        self.seeder_slider = Slider(
            seeder_slider_ax,
            "Seed",
            1,
            100,
            valinit=self.seeder,
            valfmt="%d",
            color=slider_color,
        )

        cluster_limit_slider_ax = self.fig.add_axes([0.12, 0.07, 0.65, 0.03],
                                                    facecolor=axis_color)
        self.cluster_limit_slider = RangeSlider(
            cluster_limit_slider_ax,
            "Cluster Count",
            1,
            20,
            valinit=self.cluster_limit,
            valfmt="%d",
            color=slider_color,
        )

        # ? Buttons

        save_button_ax = self.fig.add_axes([0.85, 0.05, 0.1, 0.06])
        self.save_button = Button(save_button_ax,
                                  "Save",
                                  color="#aee3f2",
                                  hovercolor="#85cade")

        reset_button_ax = self.fig.add_axes([0.85, 0.12, 0.1, 0.06])
        self.reset_button = Button(reset_button_ax,
                                   "Reset",
                                   color="#aee3f2",
                                   hovercolor="#85cade")

        background_button_ax = self.fig.add_axes([0.85, 0.19, 0.1, 0.06])
        self.background_button = Button(background_button_ax,
                                        "Background",
                                        color="#aee3f2",
                                        hovercolor="#85cade")

        generate_button_ax = self.fig.add_axes([0.85, 0.26, 0.1, 0.06])
        self.generate_button = Button(generate_button_ax,
                                      "Generate",
                                      color="#aee3f2",
                                      hovercolor="#85cade")

        add_new_button_ax = self.fig.add_axes([0.85, 0.33, 0.1, 0.06])
        self.add_new_button = Button(add_new_button_ax,
                                     "Add Cluster",
                                     color="#aee3f2",
                                     hovercolor="#85cade")

        update_button_ax = self.fig.add_axes([0.85, 0.40, 0.1, 0.06])
        self.update_button = Button(update_button_ax,
                                    "Update",
                                    color="#aee3f2",
                                    hovercolor="#85cade")

        undo_button_ax = self.fig.add_axes([0.875, 0.50, 0.05, 0.06])
        self.undo_button = Button(undo_button_ax,
                                  "",
                                  image=undo_asset,
                                  color="#aee3f2",
                                  hovercolor="#85cade")

        # ? Slider event triggers
        self.rad_slider.on_changed(self.curveplot)
        self.edgy_slider.on_changed(self.curveplot)
        self.c0_slider.on_changed(self.curveplot)
        self.c1_slider.on_changed(self.curveplot)
        self.scale_slider.on_changed(self.curveplot)
        self.points_slider.on_changed(self.curveplot)
        self.seeder_slider.on_changed(self.curveplot)
        self.cluster_limit_slider.on_changed(self.curveplot)

        # ? Button event triggers
        self.save_button.on_clicked(self.save)
        self.save_button.on_clicked(self.curveplot)
        self.reset_button.on_clicked(self.reset)
        self.reset_button.on_clicked(self.curveplot)
        self.background_button.on_clicked(self.curveplot)
        self.background_button.on_clicked(self.background)
        self.generate_button.on_clicked(self.curveplot)
        self.generate_button.on_clicked(self.generate)
        self.add_new_button.on_clicked(self.curveplot)
        self.add_new_button.on_clicked(self.add_new)
        self.update_button.on_clicked(self.curveplot)
        self.update_button.on_clicked(self.update)
        self.undo_button.on_clicked(self.curveplot)
        self.undo_button.on_clicked(self.undo)

        plt.show()

    # @profile
    def curveplot(self, _):

        self.cluster_limit = (
            int(self.cluster_limit_slider.val[0]),
            int(self.cluster_limit_slider.val[1]),
        )
        self.c = [self.c0_slider.val, self.c1_slider.val]
        self.scale = self.scale_slider.val
        self.a = (get_random_points(
            int(self.seeder_slider.val),
            n=int(self.points_slider.val),
            scale=self.scale,
        ) + self.c)
        self.x, self.y, _ = get_bezier_curve(self.a,
                                             rad=self.rad_slider.val,
                                             edgy=self.edgy_slider.val)
        self.centre = np.array([
            (np.max(self.x) + np.min(self.x)) / 2,
            (np.max(self.y) + np.min(self.y)) / 2,
        ])
        self.a_new = np.append(self.a, [self.centre], axis=0)

        self.bezier_curve.set_data(self.x, self.y)
        self.scatter_points.set_offsets(self.a_new)
        self.fig.canvas.draw_idle()

    # @profile
    def save(self, _):
        try:

            if self.cluster_image is None:
                raise ClusterNotGeneratedError

            save_generate(self.cluster_image, self.cluster_mask,
                          self.cluster_pil)
            self.cluster_image = None
            self.cluster_mask = None
            self.cluster_pil = None
            self.cache = None

        except ClusterNotGeneratedError:
            logger.warning("Generate cluster before saving.")
            self.text_handler.set_text("Generate new")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#ede5c0")
        except Exception:
            logger.error(traceback.print_exc())
            self.text_handler.set_text("Error. See logs")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#bf616a")
        else:
            logger.debug("Saved successfully.")
            self.text_handler.set_text("Saved")
            self.text_handler.set_position((0.89, 0.70))
            self.text_handler.set_backgroundcolor("#a3be8c")
            self.count += 1
            self.count_handler.set_text(f"Generated images: {self.count}")

    # @profile
    def reset(self, _):
        try:
            self.rad_slider.reset()
            self.edgy_slider.reset()
            self.c0_slider.reset()
            self.c1_slider.reset()
            self.scale_slider.reset()
            self.points_slider.reset()
            self.seeder_slider.reset()
            self.cluster_limit_slider.set_val((3, 7))
            self.bg_index = 0

            self.cluster_image = None
            self.cluster_mask = None
            self.cluster_pil = None

            self.cluster_handler.set_data(
                np.flipud(np.array(plt.imread(self.bg_list[0]))))
            self.bezier_handler.set_data(
                plt.imread(self.bg_list[self.bg_index]))

        except Exception:
            logger.error(traceback.print_exc())
            self.text_handler.set_text("Error. See logs")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#bf616a")
        else:
            logger.info("Reset state.")
            self.text_handler.set_text("Reset")
            self.text_handler.set_position((0.89, 0.70))
            self.text_handler.set_backgroundcolor("#a3be8c")
            for ind, cname in enumerate(self.class_dict):
                self.class_handlers[ind].set_text(cname + "0".rjust(3))

    # @profile
    def background(self, _):
        try:
            self.bg_index = (self.bg_index + 1) % len(self.bg_list)
            self.bezier_handler.set_data(
                plt.imread((self.bg_list[self.bg_index])))
        except Exception:
            logger.error(traceback.print_exc())
            self.text_handler.set_text("Error. See logs")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#bf616a")
        else:
            logger.info("Changed background.")
            self.text_handler.set_text("Changed")
            self.text_handler.set_position((0.88, 0.70))
            self.text_handler.set_backgroundcolor("#a3be8c")

    # @profile
    def generate(self, _):
        try:
            bg_image = np.array(plt.imread(self.bg_list[self.bg_index]))
            bg_mask = np.array(
                plt.imread(self.bg_list[self.bg_index].replace(
                    "images", "labels").replace("jpeg", "png")))
            params = list(zip(self.x, self.y))
            params.append(tuple(self.centre))
            (
                self.cluster_image,
                self.cluster_mask,
                self.cluster_pil,
                self.cache,
            ) = generate_cluster(
                bg_image,
                bg_mask,
                params,
                self.cluster_limit,
                self.limits,
                (self.dim_x, self.dim_y),
            )

            if not self.cluster_image:
                raise OutOfBoundsClusterError

            self.cluster_handler.set_data(np.flipud(self.cluster_image))

        except OutOfBoundsClusterError:
            logger.warning("Out of Bounds. Retry")
            self.text_handler.set_text("Out of Bounds")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#ede5c0")

        except Exception:
            logger.error(traceback.print_exc())
            self.text_handler.set_text("Error. See logs")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#bf616a")

        else:
            logger.info("Generated new cluster.")
            self.text_handler.set_text("Generated")
            self.text_handler.set_position((0.88, 0.70))
            self.text_handler.set_backgroundcolor("#a3be8c")

            self.class_count = Counter(self.cache[2])
            for ind, cname in enumerate(self.class_dict):
                self.class_handlers[ind].set_text(
                    cname + str(self.class_count[ind + 3]).rjust(3))

    # @profile
    def add_new(self, _):
        try:

            params = list(zip(self.x, self.y))
            params.append(tuple(self.centre))

            if self.cluster_image is None:
                raise ClusterNotGeneratedError

            (
                self.cluster_image,
                self.cluster_mask,
                self.cluster_pil,
                self.cache,
            ) = generate_cluster(
                np.array(self.cluster_image),
                self.cluster_mask,
                params,
                self.cluster_limit,
                self.limits,
                (self.dim_x, self.dim_y),
                new_cluster=False,
            )

            if np.array_equal(self.cluster_image, self.cache[0]):
                raise OutOfBoundsClusterError

            self.cluster_handler.set_data(np.flipud(self.cluster_image))

        except ClusterNotGeneratedError:
            logger.warning("Generate cluster before adding a new one.")
            self.text_handler.set_text("Generate new")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#ede5c0")

        except OutOfBoundsClusterError:
            logger.warning("Out of Bounds. Retry")
            self.text_handler.set_text("Out of Bounds")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#ede5c0")

        except Exception:
            logger.error(traceback.print_exc())
            self.text_handler.set_text("Error. See logs.")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#bf616a")

        else:
            logger.info("Added cluster.")
            self.text_handler.set_text("Added")
            self.text_handler.set_position((0.89, 0.70))
            self.text_handler.set_backgroundcolor("#a3be8c")

            self.class_count += Counter(self.cache[2])
            for ind, cname in enumerate(self.class_dict):
                self.class_handlers[ind].set_text(
                    cname + str(self.class_count[ind + 3]).rjust(3))

    # @profile
    def update(self, _):
        try:
            params = list(zip(self.x, self.y))
            params.append(tuple(self.centre))

            if self.cluster_image is None:
                raise ClusterNotGeneratedError

            bg_mask = np.array(
                plt.imread(self.bg_list[self.bg_index].replace(
                    "images", "labels").replace("jpeg", "png")))

            if np.array_equal(bg_mask, self.cache[1]):
                new_cluster = True
            else:
                new_cluster = False

            # old_class_list = cache[2][:]

            (
                self.cluster_image,
                self.cluster_mask,
                self.cluster_pil,
                self.cache,
            ) = update_cluster(*self.cache, params, self.limits,
                               (self.dim_x, self.dim_y), new_cluster)

            if np.array_equal(self.cluster_image, self.cache[0]):
                raise OutOfBoundsClusterError

            self.cluster_handler.set_data(np.flipud(self.cluster_image))

        except ClusterNotGeneratedError:
            logger.warning("Generate cluster before updating.")
            self.text_handler.set_text("Generate new")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#ede5c0")

        except OutOfBoundsClusterError:
            logger.warning("Out of Bounds. Retry")
            self.text_handler.set_text("Out of Bounds")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#ede5c0")

        except Exception:
            logger.error(traceback.print_exc())
            self.text_handler.set_text("Error. See logs")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#bf616a")

        else:
            logger.info("Updated cluster.")
            self.text_handler.set_text("Updated")
            self.text_handler.set_position((0.88, 0.70))
            self.text_handler.set_backgroundcolor("#a3be8c")

    # @profile
    def undo(self, _):
        try:

            if self.cluster_image is None:
                raise UndoError

            (
                self.cluster_image,
                self.cluster_mask,
                self.cluster_pil,
                self.cache,
            ) = undo_func()

            if self.cache is None:
                raise UndoError

            self.cluster_handler.set_data(np.flipud(self.cluster_image))

        except UndoError:
            logger.warning("Cannot undo as there is no previous state.")
            self.text_handler.set_text("Cannot undo")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#ede5c0")

        except Exception:
            logger.error(traceback.print_exc())
            self.text_handler.set_text("Error. See logs")
            self.text_handler.set_position((0.87, 0.70))
            self.text_handler.set_backgroundcolor("#bf616a")

        else:
            logger.info("Cluster undone.")
            self.text_handler.set_text("Undone")
            self.text_handler.set_position((0.88, 0.70))
            self.text_handler.set_backgroundcolor("#a3be8c")

            self.class_count -= Counter(self.cache[2])
            for ind, cname in enumerate(self.class_dict):
                self.class_handlers[ind].set_text(
                    cname + str(self.class_count[ind + 3]).rjust(3))
class my_Slider:
    def __init__(self, img, threshold=30, kernel=5, std=5):
        self.img = img
        self.threshold = threshold
        self.smooth = 'Gaussian smooth'
        self.k = kernel
        self.s = std
        self.fig = plt.figure()
        self.p = self.draw_plots(self.img, self.threshold, self.smooth, self.s)
        #set up sliders - location
        axcolor = 'lightgoldenrodyellow'
        ax_threshold = self.fig.add_axes([0.25, 0.01, 0.65, 0.02],
                                         facecolor=axcolor)
        ax_kernel = self.fig.add_axes([0.25, 0.03, 0.65, 0.02],
                                      facecolor=axcolor)
        ax_std = self.fig.add_axes([0.25, 0.05, 0.65, 0.02], facecolor=axcolor)
        #set up sliders - content, length, width
        self.s_threshold = Slider(ax_threshold,
                                  'Threshold',
                                  0.0,
                                  255.0,
                                  valinit=30.0,
                                  valstep=10.0)
        self.s_kenel = Slider(ax_kernel,
                              'Kernel',
                              3.0,
                              21.0,
                              valinit=5.0,
                              valstep=2.0)
        self.s_std = Slider(ax_std, 'Std', 1.0, 15.0, valinit=5.0, valstep=2.0)
        #set up buttons
        resetax = self.fig.add_axes([0.01, 0.025, 0.1, 0.04])
        self.button = Button(resetax,
                             'Reset',
                             color=axcolor,
                             hovercolor='0.975')
        rax = self.fig.add_axes([0.01, 0.5, 0.25, 0.25], facecolor=axcolor)
        self.radio = RadioButtons(rax, ('Gaussian smooth', 'median smooth'),
                                  active=0)

        self.s_threshold.on_changed(self.update)
        self.s_kenel.on_changed(self.update)
        self.s_std.on_changed(self.update)

        self.button.on_clicked(self.reset)
        self.radio.on_clicked(self.buttonfunc)

        self.p.show()

    def draw_plots(self,
                   img,
                   threshold_value,
                   smooth,
                   kernel=11,
                   std=1,
                   C=2,
                   maxVal=255,
                   onplot=None):
        threshold_value = int(threshold_value)
        kernel = int(kernel)
        img = cv2.imread(img, 0)

        if smooth == 'median smooth':
            img = cv2.medianBlur(img, kernel)
        elif smooth == 'Gaussian smooth':
            img = cv2.GaussianBlur(img, (kernel, kernel), std)

        #global
        ret, thresh1 = cv2.threshold(img, threshold_value, maxVal,
                                     cv2.THRESH_BINARY)

        #otsu
        ret2, thresh2 = cv2.threshold(img, 0, maxVal,
                                      cv2.THRESH_BINARY + cv2.THRESH_OTSU)

        #adaptive
        thresh3 = cv2.adaptiveThreshold(img, maxVal,
                                        cv2.ADAPTIVE_THRESH_MEAN_C,
                                        cv2.THRESH_BINARY, kernel, C)
        thresh4 = cv2.adaptiveThreshold(img, maxVal,
                                        cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
                                        cv2.THRESH_BINARY, kernel, C)
        titles = [
            'Binary', 'Otsu', 'Adaptive-mean', 'Adaptive-gaussian', 'histogram'
        ]
        images = [thresh1, thresh2, thresh3, thresh4]
        nrow = 2
        ncol = 2

        for i in range(4):
            self.fig.add_subplot(2, 2, i + 1)
            plt.imshow(images[i], 'gray')
            plt.title(titles[i], fontsize=8)
            plt.xticks([]), plt.yticks([])
            plt.tight_layout()
            plt.subplots_adjust(left=0.25,
                                bottom=0.1,
                                top=0.9,
                                right=0.95,
                                hspace=0.1,
                                wspace=0)
        return plt

    def update(self, val):
        self.threshold = int(self.s_threshold.val)
        self.k = int(self.s_kenel.val)
        self.s = int(self.s_std.val)

        p = self.draw_plots(self.img,
                            self.threshold,
                            self.smooth,
                            kernel=self.k,
                            std=self.s)
        p.show()
        self.fig.canvas.draw_idle()

    def reset(self, event):
        self.s_threshold.reset()
        self.s_kenel.reset()
        self.s_std.reset()

    def buttonfunc(self, label):
        self.smooth = label
        p2 = self.draw_plots(self.img,
                             self.threshold,
                             self.smooth,
                             kernel=self.k,
                             std=self.s)
        p2.show()
        self.fig.canvas.draw_idle()
Example #27
0
class AnimatedScatter(object):
    def __init__(self, bodies, axis_range, timescale):
        self.bodies = bodies
        self.axis_range = axis_range
        self.timescale = timescale
        self.stream = self.data_stream()
        fig = plt.figure()
        ax = fig.add_subplot(111, projection='3d')
        self.fig = fig
        self.ax = ax
        self.force_norm_factor = None
        self.ani = animation.FuncAnimation(self.fig,
                                           self.update,
                                           interval=INTERVAL,
                                           init_func=self.setup_plot,
                                           blit=False)

        self.x_ = []
        self.y_ = []
        self.z_ = []

    def setup_plot(self):
        xi, yi, zi, ui, vi, wi, x_, y_, z_ = next(self.stream)

        c = [np.random.rand(3, ) for i in range(len(xi))]

        self.ax.set_proj_type('ortho')
        self.scatter = self.ax.scatter(xi, yi, zi, c=c, s=10)
        self.quiver = self.ax.quiver(xi, yi, zi, ui, vi, wi, length=1)
        self.lines, = self.ax.plot([], [], [], ".", markersize=0.5)

        self.axtime = plt.axes([0.25, 0.1, 0.65, 0.03])
        self.stime = Slider(self.axtime, 'Time', 0.0, 10.0, valinit=0.0)

        def update(val):
            if val == 0: return
            print("Jumping e^{}={} frames".format(int(val), int(math.e**val)))
            for v in range(int(math.e**val)):
                x_i, y_i, z_i, u_i, v_i, w_i, x_, y_, z_ = next(self.stream)
            self.stime.reset()

        self.stime.on_changed(update)

        self.resetax = plt.axes([0.8, 0.025, 0.1, 0.04])
        self.button = Button(self.resetax, 'Reset', hovercolor='0.975')

        def reset(event):
            self.stime.reset()
            self.x_ = []
            self.y_ = []
            self.z_ = []

        self.button.on_clicked(reset)

        FLOOR = self.axis_range[0]
        CEILING = self.axis_range[1]
        self.ax.set_xlim3d(FLOOR, CEILING)
        self.ax.set_ylim3d(FLOOR, CEILING)
        self.ax.set_zlim3d(FLOOR, CEILING)
        self.ax.set_xlabel('X')
        self.ax.set_ylabel('Y')
        self.ax.set_zlabel('Z')

        return self.scatter, self.quiver

    def quiver_force_norm_factor(self):
        axis_length = np.abs(self.axis_range[1]) + np.abs(self.axis_range[0])
        return np.amax(np.array([b.f
                                 for b in self.bodies])) / (axis_length / 10)

    def data_stream(self):
        while True:
            move(self.bodies, self.timescale)
            if not self.force_norm_factor:
                self.force_norm_factor = self.quiver_force_norm_factor()
                # print('factor ', self.force_norm_factor)
            x, y, z = points_for_bodies(self.bodies)
            u, v, w = norm_forces_for_bodies(self.bodies,
                                             self.force_norm_factor)

            # rad = random.randint(0, TRACK_NUM-1)
            # x_.append(x[rad])
            # y_.append(y[rad])
            # z_.append(z[rad])

            self.x_.append(x[-1])
            self.y_.append(y[-1])
            self.z_.append(z[-1])
            yield x, y, z, u, v, w, self.x_, self.y_, self.z_

    def update(self, i):
        x_i, y_i, z_i, u_i, v_i, w_i, x_, y_, z_ = next(self.stream)

        self.scatter._offsets3d = (x_i, y_i, z_i)

        segments = np.array([(b.p, b.p + b.f / self.force_norm_factor)
                             for b in self.bodies])
        self.quiver.set_segments(segments)

        self.lines.set_data(np.array(x_), np.array(y_))
        self.lines.set_3d_properties(np.array(z_))

        plt.draw()
        return self.scatter, self.quiver, self.lines

    def show(self):
        plt.show()
Example #28
0
def plot_wid(
    self,
    X=[],
    Y=[],  # X-Y points in the graph.
    labels=[],  # Labels for tittle, axis and so on.
    legend=[],  # Legend for the curves plotted
    nf=1,  # New figure
    na=0,  # New axis. To plot in a new axis
    # Basic parameters that we can usually find in a plot
    color=None,  # Color
    lw=2,  # Line width
    alpha=1.0,  # Alpha
    fontsize=20,  # The font for the labels in the title
    fontsizeL=10,  # The font for the labels in the legeng
    fontsizeA=15,  # The font for the labels in the axis
    loc=1,
    scrolling=-1,  # Size of the window to visualize

    ### Super Special Shit !!
    fill=0  #  0 = No fill, 1 = Fill and line, 2 = Only fill
):

    ## Preprocess the data given so that it meets the right format
    self.preprocess_data(X, Y)
    X = self.X
    Y = self.Y

    NpX, NcX = X.shape
    NpY, NcY = Y.shape

    # Management of the figure
    self.figure_management(nf, na, labels, fontsize)

    plt.subplots_adjust(left=0.05, bottom=0.1)
    ##################################################################
    ############### CALL PLOTTING FUNCTION ###########################
    ##################################################################
    ## TODO. Second case where NcY = NcX !!

    ## This function is the encharged of the plotting itself !!
    ## We must have an "array" with the different plot scenarios that we make

    ax = self.axes
    fig = self.fig
    wsize = scrolling
    val = NpX - wsize
    for i in range(NcY):  # We plot once for every line to plot
        self.zorder = self.zorder + 1
        colorFinal = self.get_color(color)
        if (i >= len(legend)):
            ln, = plt.plot(X[val:val + wsize],
                           Y[val:val + wsize, i],
                           lw=lw,
                           alpha=alpha,
                           color=colorFinal,
                           zorder=self.zorder)
        else:
            #            print X.shape
            #            print Y[:,i].shape
            ln, = plt.plot(X[val:val + wsize],
                           Y[val:val + wsize:, i],
                           lw=lw,
                           alpha=alpha,
                           color=colorFinal,
                           label=legend[i],
                           zorder=self.zorder)

        if (fill == 1):  ## Fill this shit !!
            self.filler(X[val:val + wsize], Y[val:val + wsize:, i], colorFinal,
                        alpha)

    axcolor = 'lightgoldenrodyellow'
    # The canvas is small in the inferior part
    SmarginX = 0.05
    SmarginY = 0.05
    Sheight = 0.03
    axpos = plt.axes([SmarginX, SmarginY, 1.0 - 2 * SmarginX, Sheight],
                     axisbg=axcolor)
    sliderBar = Slider(axpos, 'Pos', 0, NpX - wsize, valinit=NpX - wsize)

    ## Init, graph
    ln.set_ydata(Y[val:val + wsize])
    ln.set_xdata(X[val:val + wsize])

    def slide(val):

        #            print "Pene"
        val = int(val)  # Init index of the time series.
        # We change the Y data shown
        ln.set_ydata(Y[val:val + wsize])
        ln.set_xdata(X[val:val + wsize])
        #            ln.set_color("red")
        #    ax.set_title(frame)

        # Set the new limits of Y axes
        ax.relim()
        ax.autoscale_view()
        #            # Draw the new signal
        #            plt.draw()
        fig.canvas.draw_idle()

    sliderBar.on_changed(slide)
    sliderBar.reset()

    self.slider = sliderBar
    self.update_legend(legend, NcY, loc=loc)
    self.format_axis(nf, fontsize=fontsizeA)

    if (na == 1 or nf == 1):
        self.format_plot()

    return 0
class PhasePlaneInteractive(object):
    """
    An interactive phase-plane plot generated from a TVB model object.

    A TVB integrator object will be use for generating sample trajectories
    -- not the phase-plane. This is mainly interesting for visualising
    the effect of noise on a trajectory.
    """
    def __init__(self, model, integrator):
        self.log = get_logger(self.__class__.__module__)
        self.model = model
        self.integrator = integrator
        #Make sure the model is fully configured...
        self.model.configure()
        self.model.update_derived_parameters()

    def get_required_memory_size(self, **kwargs):
        """
        Return the required memory to run this algorithm.
        """
        # Don't know how much memory is needed.
        return -1

    def draw_phase_plane(self):
        """Generate the interactive phase-plane figure."""
        self.log.debug("Plot started...")

        model_name = self.model.__class__.__name__
        msg = "Generating an interactive phase-plane plot for %s"
        self.log.info(msg % model_name)

        self.svx = self.model.state_variables[0]  # x-axis: 1st state variable
        self.svy = self.model.state_variables[1]  # y-axis: 2nd state variable
        self.mode = 0

        self._set_state_vector()

        #TODO: see how we can get the figure size from the UI to better 'fit' the encompassing div
        self.ipp_fig = pylab.figure(figsize=(10, 8))
        pylab.clf()
        self.pp_ax = self.ipp_fig.add_axes([0.265, 0.2, 0.7, 0.75])

        self.pp_splt = self.ipp_fig.add_subplot(212)
        self.ipp_fig.subplots_adjust(left=0.265,
                                     bottom=0.02,
                                     right=0.75,
                                     top=0.3,
                                     wspace=0.1,
                                     hspace=None)
        self.pp_splt.set_color_cycle(get_color(self.model.nvar))
        self.pp_splt.plot(
            numpy.arange(TRAJ_STEPS + 1) * self.integrator.dt,
            numpy.zeros((TRAJ_STEPS + 1, self.model.nvar)))
        if hasattr(self.pp_splt, 'autoscale'):
            self.pp_splt.autoscale(enable=True, axis='y', tight=True)
        self.pp_splt.legend(self.model.state_variables)

        #Selectors
        self._add_state_variable_selector()
        self._add_mode_selector()

        #Sliders
        self._add_axes_range_sliders()
        self._add_state_variable_sliders()
        if isinstance(self.integrator,
                      integrators_module.IntegratorStochastic):
            if self.integrator.noise.ntau > 0.0:
                self.integrator.noise.configure_coloured(
                    self.integrator.dt,
                    (1, self.model.nvar, 1, self.model.number_of_modes))
            else:
                self.integrator.noise.configure_white(
                    self.integrator.dt,
                    (1, self.model.nvar, 1, self.model.number_of_modes))

            self._add_noise_slider()
            self._add_reset_noise_button()
            self._add_reset_seed_button()

        #Reset buttons
        #self._add_reset_param_button()
        self._add_reset_sv_button()
        self._add_reset_axes_button()

        #Calculate the phase plane
        self._set_mesh_grid()
        self._calc_phase_plane()

        #Plot phase plane
        self._plot_phase_plane()

        # add mouse handler for trajectory clicking
        self.ipp_fig.canvas.mpl_connect('button_press_event',
                                        self._click_trajectory)
        self.ipp_fig.canvas.draw()

        return dict(serverIp=config.SERVER_IP,
                    serverPort=config.MPLH5_SERVER_PORT,
                    figureNumber=self.ipp_fig.number,
                    showFullToolbar=False)

    def _add_state_variable_selector(self):
        """
        Generate radio selector buttons to set which state variable is
        displayed on the x and y axis of the phase-plane plot.
        """
        svx_ind = self.model.state_variables.index(self.svx)
        svy_ind = self.model.state_variables.index(self.svy)

        #State variable for the x axis
        pos_shp = [0.08, 0.07, 0.065, 0.12 + 0.006 * self.model.nvar]
        rax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR, title="x-axis")
        self.state_variable_x = RadioButtons(rax,
                                             tuple(self.model.state_variables),
                                             active=svx_ind)
        self.state_variable_x.on_clicked(self._update_svx)

        #State variable for the y axis
        pos_shp = [0.16, 0.07, 0.065, 0.12 + 0.006 * self.model.nvar]
        rax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR, title="y-axis")
        self.state_variable_y = RadioButtons(rax,
                                             tuple(self.model.state_variables),
                                             active=svy_ind)
        self.state_variable_y.on_clicked(self._update_svy)

    def _add_mode_selector(self):
        """
        Add a radio button to the figure for selecting which mode of the model
        should be displayed.
        """
        pos_shp = [0.02, 0.07, 0.04, 0.1 + 0.002 * self.model.number_of_modes]
        rax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR, title="Mode")
        mode_tuple = tuple(range(self.model.number_of_modes))
        self.mode_selector = RadioButtons(rax, mode_tuple, active=0)
        self.mode_selector.on_clicked(self._update_mode)

    def _add_axes_range_sliders(self):
        """
        Add sliders to the figure to allow the phase-planes axes to be set.
        """
        self.axes_range_sliders = dict()

        default_range_x = (self.model.state_variable_range[self.svx][1] -
                           self.model.state_variable_range[self.svx][0])
        default_range_y = (self.model.state_variable_range[self.svy][1] -
                           self.model.state_variable_range[self.svy][0])
        min_val_x = self.model.state_variable_range[
            self.svx][0] - 4.0 * default_range_x
        max_val_x = self.model.state_variable_range[
            self.svx][1] + 4.0 * default_range_x
        min_val_y = self.model.state_variable_range[
            self.svy][0] - 4.0 * default_range_y
        max_val_y = self.model.state_variable_range[
            self.svy][1] + 4.0 * default_range_y

        sax = self.ipp_fig.add_axes([0.04, 0.835, 0.125, 0.025],
                                    axisbg=AXCOLOUR)
        sl_x_min = Slider(sax,
                          "xlo",
                          min_val_x,
                          max_val_x,
                          valinit=self.model.state_variable_range[self.svx][0])
        sl_x_min.on_changed(self._update_range)

        sax = self.ipp_fig.add_axes([0.04, 0.8, 0.125, 0.025], axisbg=AXCOLOUR)
        sl_x_max = Slider(sax,
                          "xhi",
                          min_val_x,
                          max_val_x,
                          valinit=self.model.state_variable_range[self.svx][1])
        sl_x_max.on_changed(self._update_range)

        sax = self.ipp_fig.add_axes([0.04, 0.765, 0.125, 0.025],
                                    axisbg=AXCOLOUR)
        sl_y_min = Slider(sax,
                          "ylo",
                          min_val_y,
                          max_val_y,
                          valinit=self.model.state_variable_range[self.svy][0])
        sl_y_min.on_changed(self._update_range)

        sax = self.ipp_fig.add_axes([0.04, 0.73, 0.125, 0.025],
                                    axisbg=AXCOLOUR)
        sl_y_max = Slider(sax,
                          "yhi",
                          min_val_y,
                          max_val_y,
                          valinit=self.model.state_variable_range[self.svy][1])
        sl_y_max.on_changed(self._update_range)

        self.axes_range_sliders["sl_x_min"] = sl_x_min
        self.axes_range_sliders["sl_x_max"] = sl_x_max
        self.axes_range_sliders["sl_y_min"] = sl_y_min
        self.axes_range_sliders["sl_y_max"] = sl_y_max

    def _add_state_variable_sliders(self):
        """
        Add sliders to the figure to allow default values for the models state
        variable to be set.
        """
        msv_range = self.model.state_variable_range
        offset = 0.0
        self.sv_sliders = dict()
        for sv in range(self.model.nvar):
            offset += 0.035
            pos_shp = [0.04, 0.6 - offset, 0.125, 0.025]
            sax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR)
            sv_str = self.model.state_variables[sv]
            self.sv_sliders[sv_str] = Slider(sax,
                                             sv_str,
                                             msv_range[sv_str][0],
                                             msv_range[sv_str][1],
                                             valinit=self.default_sv[sv, 0, 0])
            self.sv_sliders[sv_str].on_changed(self._update_state_variables)

    def _add_noise_slider(self):
        """
        Add a slider to the figure to allow the integrators noise strength to
        be set.
        """
        pos_shp = [0.04, 0.365, 0.125, 0.025]
        sax = self.ipp_fig.add_axes(pos_shp, axisbg=AXCOLOUR)

        self.noise_slider = Slider(sax,
                                   "Noise",
                                   0.0,
                                   1.0,
                                   valinit=self.integrator.noise.nsig)
        self.noise_slider.on_changed(self._update_noise)

    def _add_reset_sv_button(self):
        """
        Add a button to the figure for reseting the model state variables to
        their default values.
        """
        bax = self.ipp_fig.add_axes([0.04, 0.60, 0.125, 0.04])
        self.reset_sv_button = Button(bax,
                                      'Reset state-variables',
                                      color=BUTTONCOLOUR,
                                      hovercolor=HOVERCOLOUR)

        def reset_state_variables(event):
            for svsl in self.sv_sliders.itervalues():
                svsl.reset()

        self.reset_sv_button.on_clicked(reset_state_variables)

    def _add_reset_noise_button(self):
        """
        Add a button to the figure for reseting the noise to its default value.
        """
        bax = self.ipp_fig.add_axes([0.04, 0.4, 0.125, 0.04])
        self.reset_noise_button = Button(bax,
                                         'Reset noise strength',
                                         color=BUTTONCOLOUR,
                                         hovercolor=HOVERCOLOUR)

        def reset_noise(event):
            self.noise_slider.reset()

        self.reset_noise_button.on_clicked(reset_noise)

    def _add_reset_seed_button(self):
        """
        Add a button to the figure for reseting the random number generator to
        its intial state. For reproducible noise...
        """
        bax = self.ipp_fig.add_axes([0.04, 0.315, 0.125, 0.04])
        self.reset_seed_button = Button(bax,
                                        'Reset random stream',
                                        color=BUTTONCOLOUR,
                                        hovercolor=HOVERCOLOUR)

        def reset_seed(event):
            self.integrator.noise.trait["random_stream"].reset()

        self.reset_seed_button.on_clicked(reset_seed)

    def _add_reset_axes_button(self):
        """
        Add a button to the figure for reseting the phase-plane axes to their
        default ranges.
        """
        bax = self.ipp_fig.add_axes([0.04, 0.87, 0.125, 0.04])
        self.reset_axes_button = Button(bax,
                                        'Reset axes',
                                        color=BUTTONCOLOUR,
                                        hovercolor=HOVERCOLOUR)

        def reset_ranges(event):
            self.axes_range_sliders["sl_x_min"].reset()
            self.axes_range_sliders["sl_x_max"].reset()
            self.axes_range_sliders["sl_y_min"].reset()
            self.axes_range_sliders["sl_y_max"].reset()

        self.reset_axes_button.on_clicked(reset_ranges)

    ##------------------------------------------------------------------------##
    ##------------------- Functions for updating the figure ------------------##
    ##------------------------------------------------------------------------##

    #NOTE: All the ax.set_xlim, poly.xy, etc, garbage below is fragile. It works
    #      at the moment, but there are currently bugs in Slider and the hackery
    #      below takes these into account... If the bugs are fixed/changed then
    #      this could break. As an example, the Slider doc says poly is a
    #      Rectangle, but it's actually a Polygon. The Slider set_val method
    #      assumes a Rectangle even though this is not the case, so the array
    #      Slider.poly.xy is corrupted by that method. The corruption isn't
    #      visible in the plot, which is probably why it hasn't been fixed...

    def update_xrange_sliders(self):
        """
        """
        default_range_x = (self.model.state_variable_range[self.svx][1] -
                           self.model.state_variable_range[self.svx][0])
        min_val_x = self.model.state_variable_range[
            self.svx][0] - 4.0 * default_range_x
        max_val_x = self.model.state_variable_range[
            self.svx][1] + 4.0 * default_range_x
        self.axes_range_sliders[
            "sl_x_min"].valinit = self.model.state_variable_range[self.svx][0]
        self.axes_range_sliders["sl_x_min"].valmin = min_val_x
        self.axes_range_sliders["sl_x_min"].valmax = max_val_x
        self.axes_range_sliders["sl_x_min"].ax.set_xlim(min_val_x, max_val_x)
        self.axes_range_sliders["sl_x_min"].poly.axes.set_xlim(
            min_val_x, max_val_x)
        self.axes_range_sliders["sl_x_min"].poly.xy[[0, 1], 0] = min_val_x
        self.axes_range_sliders["sl_x_min"].vline.set_data(([
            self.axes_range_sliders["sl_x_min"].valinit,
            self.axes_range_sliders["sl_x_min"].valinit
        ], [0, 1]))
        self.axes_range_sliders[
            "sl_x_max"].valinit = self.model.state_variable_range[self.svx][1]
        self.axes_range_sliders["sl_x_max"].valmin = min_val_x
        self.axes_range_sliders["sl_x_max"].valmax = max_val_x
        self.axes_range_sliders["sl_x_max"].ax.set_xlim(min_val_x, max_val_x)
        self.axes_range_sliders["sl_x_max"].poly.axes.set_xlim(
            min_val_x, max_val_x)
        self.axes_range_sliders["sl_x_max"].poly.xy[[0, 1], 0] = min_val_x
        self.axes_range_sliders["sl_x_max"].vline.set_data(([
            self.axes_range_sliders["sl_x_max"].valinit,
            self.axes_range_sliders["sl_x_max"].valinit
        ], [0, 1]))
        self.axes_range_sliders["sl_x_min"].reset()
        self.axes_range_sliders["sl_x_max"].reset()

    def update_yrange_sliders(self):
        """
        """
        default_range_y = (self.model.state_variable_range[self.svy][1] -
                           self.model.state_variable_range[self.svy][0])
        min_val_y = self.model.state_variable_range[
            self.svy][0] - 4.0 * default_range_y
        max_val_y = self.model.state_variable_range[
            self.svy][1] + 4.0 * default_range_y
        self.axes_range_sliders[
            "sl_y_min"].valinit = self.model.state_variable_range[self.svy][0]
        self.axes_range_sliders["sl_y_min"].valmin = min_val_y
        self.axes_range_sliders["sl_y_min"].valmax = max_val_y
        self.axes_range_sliders["sl_y_min"].ax.set_xlim(min_val_y, max_val_y)
        self.axes_range_sliders["sl_y_min"].poly.axes.set_xlim(
            min_val_y, max_val_y)
        self.axes_range_sliders["sl_y_min"].poly.xy[[0, 1], 0] = min_val_y
        self.axes_range_sliders["sl_y_min"].vline.set_data(([
            self.axes_range_sliders["sl_y_min"].valinit,
            self.axes_range_sliders["sl_y_min"].valinit
        ], [0, 1]))
        self.axes_range_sliders[
            "sl_y_max"].valinit = self.model.state_variable_range[self.svy][1]
        self.axes_range_sliders["sl_y_max"].valmin = min_val_y
        self.axes_range_sliders["sl_y_max"].valmax = max_val_y
        self.axes_range_sliders["sl_y_max"].ax.set_xlim(min_val_y, max_val_y)
        self.axes_range_sliders["sl_y_max"].poly.axes.set_xlim(
            min_val_y, max_val_y)
        self.axes_range_sliders["sl_y_max"].poly.xy[[0, 1], 0] = min_val_y
        self.axes_range_sliders["sl_y_max"].vline.set_data(([
            self.axes_range_sliders["sl_y_max"].valinit,
            self.axes_range_sliders["sl_y_max"].valinit
        ], [0, 1]))
        self.axes_range_sliders["sl_y_min"].reset()
        self.axes_range_sliders["sl_y_max"].reset()

    def _update_svx(self, label):
        """
        Update state variable used for x-axis based on radio buttton selection.
        """
        self.svx = label
        self.update_xrange_sliders()
        self._set_mesh_grid()
        self._calc_phase_plane()
        self._update_phase_plane()

    def _update_svy(self, label):
        """
        Update state variable used for y-axis based on radio buttton selection.
        """
        self.svy = label
        self.update_yrange_sliders()
        self._set_mesh_grid()
        self._calc_phase_plane()
        self._update_phase_plane()

    def _update_mode(self, label):
        """ Update the visualised mode based on radio button selection. """
        self.mode = label
        self._update_phase_plane()

    def _update_noise(self, nsig):
        """ Update integrator noise based on the noise slider value. """
        self.integrator.noise.nsig = numpy.array([
            nsig,
        ])

    def _update_range(self, val):
        """
        Update the axes ranges based on the current axes slider values.

        NOTE: Haven't figured out how to update independently, so just update everything.
        """
        #TODO: Grab caller and use val directly, ie independent range update.
        self.axes_range_sliders["sl_x_min"].ax.set_axis_bgcolor(AXCOLOUR)
        self.axes_range_sliders["sl_x_max"].ax.set_axis_bgcolor(AXCOLOUR)
        self.axes_range_sliders["sl_y_min"].ax.set_axis_bgcolor(AXCOLOUR)
        self.axes_range_sliders["sl_y_max"].ax.set_axis_bgcolor(AXCOLOUR)
        if self.axes_range_sliders["sl_x_min"].val >= self.axes_range_sliders[
                "sl_x_max"].val:
            self.log.error("X-axis min must be less than max...")
            self.axes_range_sliders["sl_x_min"].ax.set_axis_bgcolor("Red")
            self.axes_range_sliders["sl_x_max"].ax.set_axis_bgcolor("Red")
            return
        if self.axes_range_sliders["sl_y_min"].val >= self.axes_range_sliders[
                "sl_y_max"].val:
            self.log.error("Y-axis min must be less than max...")
            self.axes_range_sliders["sl_y_min"].ax.set_axis_bgcolor("Red")
            self.axes_range_sliders["sl_y_max"].ax.set_axis_bgcolor("Red")
            return

        msv_range = self.model.state_variable_range
        msv_range[self.svx][0] = self.axes_range_sliders["sl_x_min"].val
        msv_range[self.svx][1] = self.axes_range_sliders["sl_x_max"].val
        msv_range[self.svy][0] = self.axes_range_sliders["sl_y_min"].val
        msv_range[self.svy][1] = self.axes_range_sliders["sl_y_max"].val
        self._set_mesh_grid()
        self._calc_phase_plane()
        self._update_phase_plane()

    def _update_phase_plane(self):
        """ Clear the axes and redraw the phase-plane. """
        self.pp_ax.clear()
        self.pp_splt.clear()
        self.pp_splt.set_color_cycle(get_color(self.model.nvar))
        self.pp_splt.plot(
            numpy.arange(TRAJ_STEPS + 1) * self.integrator.dt,
            numpy.zeros((TRAJ_STEPS + 1, self.model.nvar)))
        if hasattr(self.pp_splt, 'autoscale'):
            self.pp_splt.autoscale(enable=True, axis='y', tight=True)
        self.pp_splt.legend(self.model.state_variables)
        self._plot_phase_plane()

    def _update_state_variables(self, val):
        """
        Update the default state-variable values, used for non-visualised state
        variables, based of the current slider values.
        """
        for sv in self.sv_sliders:
            k = self.model.state_variables.index(sv)
            self.default_sv[k] = self.sv_sliders[sv].val

        self._calc_phase_plane()
        self._update_phase_plane()

    def _set_mesh_grid(self):
        """
        Generate the phase-plane gridding based on currently selected statevariables
        and their range values.
        """
        xlo = self.model.state_variable_range[self.svx][0]
        xhi = self.model.state_variable_range[self.svx][1]
        ylo = self.model.state_variable_range[self.svy][0]
        yhi = self.model.state_variable_range[self.svy][1]

        self.X = numpy.mgrid[xlo:xhi:(NUMBEROFGRIDPOINTS * 1j)]
        self.Y = numpy.mgrid[ylo:yhi:(NUMBEROFGRIDPOINTS * 1j)]

    def _set_state_vector(self):
        """
        """
        #import pdb; pdb.set_trace()
        svr = self.model.state_variable_range
        sv_mean = numpy.array(
            [svr[key].mean() for key in self.model.state_variables])
        sv_mean = sv_mean.reshape((self.model.nvar, 1, 1))
        self.default_sv = sv_mean.repeat(self.model.number_of_modes, axis=2)
        self.no_coupling = numpy.zeros(
            (self.model.nvar, 1, self.model.number_of_modes))

    def _calc_phase_plane(self):
        """ Calculate the vector field. """
        svx_ind = self.model.state_variables.index(self.svx)
        svy_ind = self.model.state_variables.index(self.svy)

        #Calculate the vector field discretely sampled at a grid of points
        grid_point = self.default_sv.copy()
        self.U = numpy.zeros((NUMBEROFGRIDPOINTS, NUMBEROFGRIDPOINTS,
                              self.model.number_of_modes))
        self.V = numpy.zeros((NUMBEROFGRIDPOINTS, NUMBEROFGRIDPOINTS,
                              self.model.number_of_modes))
        for ii in xrange(NUMBEROFGRIDPOINTS):
            grid_point[svy_ind] = self.Y[ii]
            for jj in xrange(NUMBEROFGRIDPOINTS):
                #import pdb; pdb.set_trace()
                grid_point[svx_ind] = self.X[jj]
                d = self.model.dfun(grid_point, self.no_coupling)

                for kk in range(self.model.number_of_modes):
                    self.U[ii, jj, kk] = d[svx_ind, 0, kk]
                    self.V[ii, jj, kk] = d[svy_ind, 0, kk]

        #self.UVmag = numpy.sqrt(self.U**2 + self.V**2)
        #import pdb; pdb.set_trace()
        if numpy.isnan(self.U).any() or numpy.isnan(self.V).any():
            self.log.error("NaN")

    def _plot_phase_plane(self):
        """ Plot the vector field and its nullclines. """
        # Set title and axis labels
        model_name = self.model.__class__.__name__
        self.pp_ax.set(title=model_name + " mode " + str(self.mode))
        self.pp_ax.set(xlabel="State Variable " + self.svx)
        self.pp_ax.set(ylabel="State Variable " + self.svy)
        #import pdb; pdb.set_trace()
        #Plot a discrete representation of the vector field
        if numpy.all(self.U[:, :, self.mode] + self.V[:, :, self.mode] == 0):
            self.pp_ax.set(title=model_name + " mode " + str(self.mode) +
                           ": NO MOTION IN THIS PLANE")
            X, Y = numpy.meshgrid(self.X, self.Y)
            self.pp_quivers = self.pp_ax.scatter(X, Y, s=8, marker=".", c="k")
        else:
            self.pp_quivers = self.pp_ax.quiver(
                self.X,
                self.Y,
                self.U[:, :, self.mode],
                self.V[:, :, self.mode],
                #self.UVmag[:, :, self.mode],
                width=0.001,
                headwidth=8)

        #Plot the nullclines
        self.nullcline_x = self.pp_ax.contour(self.X,
                                              self.Y,
                                              self.U[:, :, self.mode], [0],
                                              colors="r")
        self.nullcline_y = self.pp_ax.contour(self.X,
                                              self.Y,
                                              self.V[:, :, self.mode], [0],
                                              colors="g")
        self.ipp_fig.canvas.draw()

    def _plot_trajectory(self, x, y):
        """
        Plot a sample trajectory, starting at the position x,y in the phase-plane.
        """
        svx_ind = self.model.state_variables.index(self.svx)
        svy_ind = self.model.state_variables.index(self.svy)

        #Calculate an example trajectory
        state = self.default_sv.copy()
        state[svx_ind] = x
        state[svy_ind] = y
        scheme = self.integrator.scheme
        traj = numpy.zeros(
            (TRAJ_STEPS + 1, self.model.nvar, 1, self.model.number_of_modes))
        traj[0, :] = state
        for step in range(TRAJ_STEPS):
            #import pdb; pdb.set_trace()
            state = scheme(state, self.model.dfun, self.no_coupling, 0.0, 0.0)
            traj[step + 1, :] = state

        self.pp_ax.scatter(x, y, s=42, c='g', marker='o', edgecolor=None)
        self.pp_ax.plot(traj[:, svx_ind, 0, self.mode], traj[:, svy_ind, 0,
                                                             self.mode])

        #Plot the selected state variable trajectories as a function of time
        self.pp_splt.plot(
            numpy.arange(TRAJ_STEPS + 1) * self.integrator.dt, traj[:, :, 0,
                                                                    self.mode])

        pylab.draw()

    def _click_trajectory(self, event):
        """
        """
        if event.inaxes is self.pp_ax:
            x, y = event.xdata, event.ydata
            self.log.info('trajectory starting at (%f, %f)', x, y)
            self._plot_trajectory(x, y)

    def update_model_parameter(self, param_name, param_new_value):
        """
        Update model parameters based on the current parameter slider values.

        NOTE: Haven't figured out how to update independantly, so just update
            everything.
        """
        #TODO: Grab caller and use val directly, ie independent parameter update.
        setattr(self.model, param_name, numpy.array([param_new_value]))

        self.model.update_derived_parameters()
        self._calc_phase_plane()
        self._update_phase_plane()

    def update_all_model_parameters(self, model_instance):
        for key in model_instance.ui_configurable_parameters:
            attr = getattr(model_instance, key)
            if isinstance(attr, numpy.ndarray) and attr.size == 1:
                setattr(self.model, key, numpy.array([attr[0]]))

        self.model.update_derived_parameters()
        self._calc_phase_plane()
        self._update_phase_plane()

    def update_model_parameters_from_dict(self, parameters_dict):
        """
        NOTE: I expect that the given parameters exists on the current
        model and also that they are numpy arrays.

        Sets the parameters from the given dict on the current
        model instance and also updates the phase-plane.
        """
        for param_name in parameters_dict:
            setattr(self.model, param_name,
                    numpy.array([parameters_dict[param_name]]))

        self.model.update_derived_parameters()
        self._calc_phase_plane()
        self._update_phase_plane()
Example #30
0
def add_slider(self,
               plots_affected=[],
               name="slidy",
               func="timeSlide",
               args={}):
    ## This function adds a slider related to one of the plots
    ## Indicated by the index
    # plot_i = Indexes of the plot associated to the slider.
    # func = Set of functions that we want the slider to do.
    # Since we need to referenced inner things, we migh as well define the
    # updating functions inside this funciton.

    ## Shirnk the main axes. TODO, move this to another general func
    #    plt.subplots_adjust(left = 0.2, bottom=0.2)

    ## Limits of value of the slider.
    ## If nothig specified, they are the index of the selected plot

    if (len(plots_affected) == 0):
        plots_affected = range(len(self.plots_list))

    if (func == "timeSlide"):
        wsize = args["wsize"]
        NpX, NcY = (self.Data_list[plots_affected[0]][0]).shape

        valMin = 0
        valMax = NpX - wsize
        valInit = NpX - wsize

    # Create the Slider canvas
    axcolor = 'lightgoldenrodyellow'
    SmarginX = 0.05
    SmarginY = 0.05
    Sheight = 0.03
    Swidth = 0.8 - 2 * SmarginX

    axpos = plt.axes([SmarginX, SmarginY, Swidth, Sheight], axisbg=axcolor)
    sliderBar = Slider(axpos, name, valMin, valMax, valinit=valInit)

    def slideTime(val):
        ## Function to slide the time signal through time
        val = int(val)  # Init index of the time series.
        fig = self.fig
        #        print "FRGR"
        ## This will clear the axis !!
        #        plt.cla()
        # Now we iterate over all the necesary plots
        #        print "In bitch"
        for plot_i in plots_affected:
            lns = self.plots_list[plot_i]  # The reference to the plot
            # We might have more than one signal plotter though
            # We change the Y data shown
            #            print "In bitch 2"
            #            print self.plots_type[plot_i]
            for i in range(len(lns)):
                #                print "In bitch 3"
                # Type of plot will change the way to treat it
                ln_type = self.plots_type[plot_i][i]
                if (ln_type == "plot"):
                    ln = lns[i]
                    ln.set_ydata(self.Data_list[plot_i][1][val:val + wsize, i])
                    ln.set_xdata(self.Data_list[plot_i][0][val:val + wsize])

                elif (ln_type == "fill"):
                    ## We will remove and redraw !!
                    ln = lns[i]
                    #                    print ln
                    #                    print type(ln)
                    ln.remove()
                    #                    x = self.Data_list[plot_i][0][val:val + wsize]
                    #                    y1 = self.Data_list[plot_i][1][val:val + wsize]
                    #                    y2 = self.Data_list[plot_i][2]

                    x, y1, y2, where, ax, alpha, color, args, kwargs = self.Data_list[
                        plot_i]
                    #                    ln.set_xdata (self.Data_list[plot_i][0][val:val + wsize])

                    # TODO me estas puto diciendo que solo port seleccionar esto me jodes ?
                    x = x[val:val + wsize]
                    y1 = y1[val:val + wsize]

                    if where is None:
                        pass
                    else:
                        where = where[val:val + wsize]
#                    print len(x), len(y1), y2
#                    print type(x), type(y1)
#                    print kwargs

# We also need to resize "where" vector if needed.
#                    if "where" in kwargs
                    ln = ax.fill_between(x=x,
                                         y1=y1,
                                         y2=y2,
                                         where=where,
                                         color=color,
                                         alpha=0.3,
                                         *args,
                                         **kwargs)

                    self.plots_list[plot_i][i] = ln
#                    print XX
#                    ln.set_ydata(self.Data_list[plot_i][1][val:val + wsize,i])
#                    ln.set_xdata (self.Data_list[plot_i][0][val:val + wsize])

                elif (ln_type == "bar"):
                    ln = lns[i]
                    j = 0
                    for rect in ln:
                        rect.align = "center"
                        #                        print self.Data_list[plot_i][i]
                        rect.set_height(self.Data_list[plot_i][1][val + j - 1])
                        rect.set_x(self.Data_list[plot_i][0][val + j - 1])
                        rect.set_y(self.Data_list[plot_i][2][val + j - 1])
                        #                        rect.align = "center"
                        #                        print plt.getp(rect, "width")
                        j += 1
                elif (ln_type == "candlestick"):
                    lines = self.plots_list[plot_i][0][0]
                    rects = self.plots_list[plot_i][0][1]

                    axes_candlestick = self.Data_list[plot_i][1]
                    data = self.Data_list[plot_i][0]

                    for line in lines:
                        line.remove()
                    for rects in rects:
                        rects.remove()

                    plotting = candlestick_ohlc(axes_candlestick,
                                                data[val:val + wsize, :],
                                                width=0.7)
                    self.plots_list[plot_i][0] = plotting

#                    print "d2"
#            ln.set_color("red")
#    ax.set_title(frame)

# Set the new limits of Y axes

        self.format_axis(val=val, wsize=wsize)
        for ax in self.axes_list:
            ax.relim()
            ax.autoscale_view()


#            # Draw the new signal
#            plt.draw()
        fig.canvas.draw_idle()

    ## Set the slider
    if (func == "timeSlide"):
        sliderBar.on_changed(slideTime)

    sliderBar.reset()
    slideTime(valInit)
    self.widget_list.append(sliderBar)
    ########################################################
    ###### Buttons for sliding as well #####################
    ##########################################################

    Bheight = Sheight
    Bwidth = 0.03

    BmarginXleft = SmarginX - Bwidth - 0.001
    BmarginXright = SmarginX + Swidth + 0.001
    BmarginY = SmarginY

    BleftAx = plt.axes([BmarginXleft, BmarginY, Bwidth, Bheight])
    BrightAx = plt.axes([BmarginXright, BmarginY, Bwidth, Bheight])
    # Set the bottom into the axes, with some properties
    Bleft = Button2(BleftAx, '<', color=axcolor, hovercolor='0.975')
    Bright = Button2(BrightAx, '>', color=axcolor, hovercolor='0.975')

    # Create the function of the object
    def bleft_func(event, caca):
        #        print caca
        sliderBar.set_val(
            sliderBar.val -
            caca)  # Calls the on_changed func with the init value

    def bright_func(event, caca):
        sliderBar.set_val(
            sliderBar.val +
            caca)  # Calls the on_changed func with the init value

    Bleft.on_clicked(bleft_func)
    Bright.on_clicked(bright_func)

    self.widget_list.append(Bleft)
    self.widget_list.append(Bright)