예제 #1
0
    def plot(self):
        """
        plot residual phase tensor
        """

        #get residual phase tensor for plotting
        self._compute_residual_pt()

        #filter data if desired
        if self.med_filt_kernel is not None:
            self._apply_median_filter(kernel=self.med_filt_kernel)

        #set position properties for the plot
        plt.rcParams['font.size'] = self.font_size
        plt.rcParams['figure.subplot.left'] = self.subplot_left
        plt.rcParams['figure.subplot.right'] = self.subplot_right
        plt.rcParams['figure.subplot.bottom'] = self.subplot_bottom
        plt.rcParams['figure.subplot.top'] = self.subplot_top
        plt.rcParams['figure.subplot.wspace'] = self.subplot_wspace
        plt.rcParams['figure.subplot.hspace'] = self.subplot_hspace

        #make figure instance
        self.fig = plt.figure(self.fig_num, self.fig_size, dpi=self.fig_dpi)

        #create axis instance, be sure to make aspect equal or ellipses will
        #look funny.
        self.ax = self.fig.add_subplot(1, 1, 1, aspect='equal')

        #set local parameters with shorter names
        es = self.ellipse_size
        ck = self.ellipse_colorby
        cmap = self.ellipse_cmap
        ckmin = float(self.ellipse_range[0])
        ckmax = float(self.ellipse_range[1])

        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            ckstep = 3
        #set the number of segments in case a segmented map is desired
        nseg = float((ckmax - ckmin) / (2 * ckstep))

        if cmap == 'mt_seg_bl2wh2rd':
            bounds = np.arange(ckmin, ckmax + ckstep, ckstep)

        #get largest ellipse
        emax = self.ellipse_scale
        #emax = self.rpt_array['phimax'].max()

        #plot phase tensor ellipses
        for ii, rpt in enumerate(self.rpt_array):

            phimax = rpt['phimax']
            phimin = rpt['phimin']
            azimuth = rpt['azimuth']

            #get the properties to color the ellipses by
            try:
                color_array = rpt[self.ellipse_colorby]
            except ValueError:
                raise NameError('{0} is not supported'.format(
                    self.ellipse_colorby))

            for jj, ff in enumerate(self.freq_list):
                if phimin[jj] == 0.0 or phimax[jj] == 0.0:
                    pass
                else:
                    #make sure the ellipses will be visable
                    eheight = phimin[jj] / emax * es
                    ewidth = phimax[jj] / emax * es

                    #create an ellipse scaled by phimin and phimax and orient
                    #the ellipse so that north is up and east is right
                    #need to add 90 to do so instead of subtracting
                    if self.rot90 == True:
                        ellipd = patches.Ellipse(
                            (rpt['offset'] * self.xstretch,
                             np.log10(ff) * self.ystretch),
                            width=ewidth,
                            height=eheight,
                            angle=azimuth[jj] - 90)
                    else:
                        ellipd = patches.Ellipse(
                            (rpt['offset'] * self.xstretch,
                             np.log10(ff) * self.ystretch),
                            width=ewidth,
                            height=eheight,
                            angle=azimuth[jj])

                    #get ellipse color
                    if cmap.find('seg') > 0:
                        ellipd.set_facecolor(
                            mtcl.get_plot_color(color_array[jj],
                                                self.ellipse_colorby,
                                                cmap,
                                                ckmin,
                                                ckmax,
                                                bounds=bounds))
                    else:
                        ellipd.set_facecolor(
                            mtcl.get_plot_color(color_array[jj],
                                                self.ellipse_colorby, cmap,
                                                ckmin, ckmax))

                    # == =add the ellipse to the plot == ========
                    self.ax.add_artist(ellipd)

        #--> Set plot parameters
        #need to sort the offsets and station labels so they plot correctly
        sdtype = [('offset', np.float), ('station', '|S10')]
        slist = np.array([(oo, ss) for oo, ss in zip(
            self.rpt_array['offset'], self.rpt_array['station'])],
                         dtype=sdtype)

        offset_sort = np.sort(slist, order='offset')

        self.offset_list = offset_sort['offset']
        self.station_list = offset_sort['station']

        #min and max frequency of the plot
        pmin = int(np.floor(np.log10(self.freq_list.min())))
        pmax = int(np.ceil(np.log10(self.freq_list.max())))

        #set y-axis major ticks to be on each power of 10
        self.ax.yaxis.set_ticks(
            np.arange(pmin * self.ystretch, (pmax + 1) * self.ystretch,
                      self.ystretch))
        #set y-ticklabels to coincide with the desired label
        if self.tscale == 'period':
            #make tick labels that will represent period
            yticklabels = [
                mtpl.labeldict[-ii] for ii in range(pmin, pmax + 1, 1)
            ]
            self.ax.set_ylabel('Period (s)',
                               fontsize=self.font_size + 2,
                               fontweight='bold')

        elif self.tscale == 'frequency':
            yticklabels = [
                mtpl.labeldict[ii] for ii in range(pmin, pmax + 1, 1)
            ]
            self.ax.set_ylabel('Frequency (Hz)',
                               fontsize=self.font_size + 2,
                               fontweight='bold')
        #--> set y-limits
        if self.ylimits == None:
            self.ax.set_ylim(pmin * self.ystretch, pmax * self.ystretch)
        else:
            pmin = np.log10(self.ylimits[0]) * self.ystretch
            pmax = np.log10(self.ylimits[1]) * self.ystretch
            self.ax.set_ylim(pmin, pmax)

        #--> set y-axis tick labels
        self.ax.set_yticklabels(yticklabels)

        #--> set x-axis label
        self.ax.set_xlabel('Station',
                           fontsize=self.font_size + 2,
                           fontweight='bold')

        #set x-axis ticks
        self.ax.set_xticks(self.offset_list * self.xstretch)

        #set x-axis tick labels as station names
        xticklabels = self.station_list
        if self.xstep != 1:
            xticklabels = np.zeros(len(self.station_list),
                                   dtype=self.station_list.dtype)
            for xx in range(0, len(self.station_list), self.xstep):
                xticklabels[xx] = self.station_list[xx]
        self.ax.set_xticklabels(xticklabels)

        #--> set x-limits
        if self.xlimits == None:
            self.ax.set_xlim(self.offset_list.min() * self.xstretch - es * 2,
                             self.offset_list.max() * self.xstretch + es * 2)
        else:
            self.ax.set_xlim(self.xlimits)

        #--> set title of the plot
        if self.plot_title == None:
            pass
        else:
            self.ax.set_title(self.plot_title, fontsize=self.font_size + 2)

        #put a grid on the plot
        self.ax.grid(alpha=.25, which='both', color=(.25, .25, .25))

        #==> make a colorbar with appropriate colors
        if self.cb_position == None:
            self.ax2, kw = mcb.make_axes(self.ax,
                                         orientation=self.cb_orientation,
                                         shrink=.35)
        else:
            self.ax2 = self.fig.add_axes(self.cb_position)

        if cmap == 'mt_seg_bl2wh2rd':
            #make a color list
            self.clist = [(cc, cc, 1)
                         for cc in np.arange(0, 1+1./(nseg), 1./(nseg))]+\
                        [(1, cc, cc)
                         for cc in np.arange(1, -1./(nseg), -1./(nseg))]

            #make segmented colormap
            mt_seg_bl2wh2rd = colors.ListedColormap(self.clist)

            #make bounds so that the middle is white
            bounds = np.arange(ckmin - ckstep, ckmax + 2 * ckstep, ckstep)

            #normalize the colors
            norms = colors.BoundaryNorm(bounds, mt_seg_bl2wh2rd.N)

            #make the colorbar
            self.cb = mcb.ColorbarBase(self.ax2,
                                       cmap=mt_seg_bl2wh2rd,
                                       norm=norms,
                                       orientation=self.cb_orientation,
                                       ticks=bounds[1:-1])
        else:
            self.cb = mcb.ColorbarBase(self.ax2,
                                       cmap=mtcl.cmapdict[cmap],
                                       norm=colors.Normalize(vmin=ckmin,
                                                             vmax=ckmax),
                                       orientation=self.cb_orientation)

        #label the color bar accordingly
        self.cb.set_label(mtpl.ckdict[ck],
                          fontdict={
                              'size': self.font_size,
                              'weight': 'bold'
                          })

        #place the label in the correct location
        if self.cb_orientation == 'horizontal':
            self.cb.ax.xaxis.set_label_position('top')
            self.cb.ax.xaxis.set_label_coords(.5, 1.3)

        elif self.cb_orientation == 'vertical':
            self.cb.ax.yaxis.set_label_position('right')
            self.cb.ax.yaxis.set_label_coords(1.5, .5)
            self.cb.ax.yaxis.tick_left()
            self.cb.ax.tick_params(axis='y', direction='in')

        plt.show()
예제 #2
0
파일: plotpt.py 프로젝트: azeezkk/mtpy
    def plot(self):
        """
        plots the phase tensor elements
        """
        
        #Set plot parameters
        plt.rcParams['font.size'] = self.font_size
        plt.rcParams['figure.subplot.left'] = .1
        plt.rcParams['figure.subplot.right'] = .98
        plt.rcParams['figure.subplot.bottom'] = .1
        plt.rcParams['figure.subplot.top'] = .95
        plt.rcParams['figure.subplot.wspace'] = .21
        plt.rcParams['figure.subplot.hspace'] = .5
        
        font_dict = {'size':self.font_size, 'weight':'bold'}
        font_dictt = {'size':self.font_size+2, 'weight':'bold'}
        
        #--> create plot instance
        self.fig = plt.figure(self.fig_num, self.fig_size, dpi=self.fig_dpi)
        plt.clf()
        
        #get phase tensor instance
        try:
            self.pt
            self.pt.rotate(self.rot_z)
        except AttributeError:
            self.pt = self._mt.get_PhaseTensor()
            self.pt.rotate(self.rot_z)
            self.zinv = self._mt.get_Zinvariants()
            self.zinv.rotate(self.rot_z)
        
        cmap = self.ellipse_cmap
        ckmin = self.ellipse_range[0]
        ckmax = self.ellipse_range[1]
        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            ckstep = 3
            
        if cmap == 'mt_seg_bl2wh2rd':
            bounds = np.arange(ckmin, ckmax+ckstep, ckstep)
            nseg = float((ckmax-ckmin)/(2*ckstep))

        #get the properties to color the ellipses by
        if self.ellipse_colorby == 'phiminang' or \
           self.ellipse_colorby == 'phimin':
            colorarray = self.pt.phimin[0]
    
                                           
        elif self.ellipse_colorby == 'phidet':
            colorarray = np.sqrt(abs(self.pt.det[0]))*(180/np.pi)
             
            
        elif self.ellipse_colorby == 'skew' or\
             self.ellipse_colorby == 'skew_seg':
            colorarray = self.pt.beta[0]
            
        elif self.ellipse_colorby == 'ellipticity':
            colorarray = self.pt.ellipticity[0]
            
        else:
            raise NameError(self.ellipse_colorby+' is not supported')
     
        #-------------plotPhaseTensor-----------------------------------
        self.ax1 = self.fig.add_subplot(3, 1, 1, aspect='equal')
        for ii, ff in enumerate(self._mt.period):
            #make sure the ellipses will be visable
            eheight = self.pt.phimin[0][ii]/self.pt.phimax[0][ii]*\
                                                              self.ellipse_size
            ewidth = self.pt.phimax[0][ii]/self.pt.phimax[0][ii]*\
                                                              self.ellipse_size
        
            #create an ellipse scaled by phimin and phimax and oriented along
            #the azimuth which is calculated as clockwise but needs to 
            #be plotted counter-clockwise hence the negative sign.
            ellipd = patches.Ellipse((np.log10(ff)*self.ellipse_spacing, 0),
                                     width=ewidth,
                                     height=eheight,
                                     angle=90-self.pt.azimuth[0][ii])
                                     
            self.ax1.add_patch(ellipd)
            
        
            #get ellipse color
            if cmap.find('seg') > 0:
                ellipd.set_facecolor(mtcl.get_plot_color(colorarray[ii],
                                                         self.ellipse_colorby,
                                                         cmap,
                                                         ckmin,
                                                         ckmax,
                                                         bounds=bounds))
            else:
                ellipd.set_facecolor(mtcl.get_plot_color(colorarray[ii],
                                                         self.ellipse_colorby,
                                                         cmap,
                                                         ckmin,
                                                         ckmax))
            
    
        #----set axes properties-----------------------------------------------
        #--> set tick labels and limits
        xlimits = (np.floor(np.log10(self._mt.period[0])),
                   np.ceil(np.log10(self._mt.period[-1])))


        self.ax1.set_xlim(xlimits)
        tklabels = []
        xticks = []
        for tk in self.ax1.get_xticks():
            try:
                tklabels.append(mtpl.labeldict[tk])
                xticks.append(tk)
            except KeyError:
                pass
        self.ax1.set_xticks(xticks)
        self.ax1.set_xticklabels(tklabels, fontdict={'size':self.font_size})
        self.ax1.set_xlabel('Period (s)', fontdict=font_dict)
        self.ax1.set_ylim(ymin=-1.5*self.ellipse_size, 
                          ymax=1.5*self.ellipse_size)
        
        self.ax1.grid(True, 
                     alpha=.25, 
                     which='major', 
                     color=(.25,.25,.25),
                     lw=.25)
        
        plt.setp(self.ax1.get_yticklabels(), visible=False)
        #add colorbar for PT
        self.cbax = self.fig.add_axes(self.cb_position)
        if cmap == 'mt_seg_bl2wh2rd':
            #make a color list
            clst = [(cc, cc, 1) for cc in np.arange(0,1+1./(nseg),1./(nseg))]+\
                   [(1, cc, cc) for cc in np.arange(1,-1./(nseg),-1./(nseg))]
            
            #make segmented colormap
            mt_seg_bl2wh2rd = colors.ListedColormap(clst)

            #make bounds so that the middle is white
            bounds = np.arange(ckmin-ckstep, ckmax+2*ckstep, ckstep)
            
            #normalize the colors
            norms = colors.BoundaryNorm(bounds, mt_seg_bl2wh2rd.N)
            
            #make the colorbar
            self.cbpt = mcb.ColorbarBase(self.cbax,
                                       cmap=mt_seg_bl2wh2rd,
                                       norm=norms,
                                       orientation='vertical',
                                       ticks=bounds[1:-1])
        else:
            self.cbpt = mcb.ColorbarBase(self.cbax,
                                       cmap=mtcl.cmapdict[cmap],
                                       norm=colors.Normalize(vmin=ckmin,
                                                             vmax=ckmax),
                                        orientation='vertical')
        self.cbpt.set_ticks([ckmin, ckmax])
        self.cbpt.set_ticklabels(['{0:.0f}'.format(ckmin),
                                  '{0:.0f}'.format(ckmax)])
        self.cbpt.ax.yaxis.set_label_position('left')
        self.cbpt.ax.yaxis.set_label_coords(-1.05, .5)
        self.cbpt.ax.yaxis.tick_right()
        self.cbpt.ax.tick_params(axis='y', direction='in')
        self.cbpt.set_label(mtpl.ckdict[self.ellipse_colorby], 
                            fontdict={'size':self.font_size, 'weight':'bold'})
        
        #---------------plotStrikeAngle-----------------------------------
        self.ax2 = self.fig.add_subplot(3, 2, 3)
        az = self.pt.azimuth[0]
        azerr = self.pt.azimuth[1]
        
        #put the strike into a coordinate system that goes from -90 to 90
        az[np.where(az > 90)] -= 180
        az[np.where(az < -90)] += 180
        
        stlst = []
        stlabel = []
        
        #plot phase tensor strike
        ps2 = self.ax2.errorbar(self._mt.period, 
                                az, 
                                marker=self.strike_pt_marker, 
                                ms=self.marker_size, 
                                mfc=self.strike_pt_color, 
                                mec=self.strike_pt_color, 
                                mew=self.marker_lw,
                                ls='none', 
                                yerr=azerr, 
                                ecolor=self.strike_pt_color,
                                capsize=self.marker_size,
                                elinewidth=self.marker_lw)
                                
        stlst.append(ps2[0])
        stlabel.append('PT')
        try:
            strike = self.zinv.strike
            strikeerr = np.nan_to_num(self.zinv.strike_err)
            #put the strike into a coordinate system that goes from -90 to 90
            strike[np.where(strike>90)] = strike[np.where(strike>90)]-180
            strike[np.where(strike<-90)] = strike[np.where(strike<-90)]+180
            
            #plot invariant strike
            erxy = self.ax2.errorbar(self._mt.period, 
                                    strike, 
                                    marker=self.strike_inv_marker, 
                                    ms=self.marker_size, 
                                    mfc=self.strike_inv_color, 
                                    mec=self.strike_inv_color, 
                                    mew=self.marker_lw,
                                    ls='none', 
                                    yerr=strikeerr, 
                                    ecolor=self.strike_inv_color,
                                    capsize=self.marker_size,
                                    elinewidth=self.marker_lw)
                              
            stlst.append(erxy[0])
            stlabel.append('Z_inv')
        except AttributeError:
            print 'Could not get z_invariants from pt, input z if desired.'
            
        if self._mt.tipper is not None:
            #strike from tipper
            tp = self._mt.get_Tipper()
            s3 = tp.ang_real+90
            
            #fold to go from -90 to 90
            s3[np.where(s3>90)] = s3[np.where(s3>90)]-180
            s3[np.where(s3<-90)] = s3[np.where(s3<-90)]+180
            
            #plot strike with error bars
            ps3 = self.ax2.errorbar(self._mt.period, 
                                    s3, 
                                    marker=self.strike_tp_marker, 
                                    ms=self.marker_size, 
                                    mfc=self.strike_tp_color, 
                                    mec=self.strike_tp_color, 
                                    mew=self.marker_lw,
                                    ls='none', 
                                    yerr=np.zeros_like(s3), 
                                    ecolor=self.strike_tp_color,
                                    capsize=self.marker_size,
                                    elinewidth=self.marker_lw)
                                    
            stlst.append(ps3[0])
            stlabel.append('Tipper')
        
             
        self.ax2.legend(stlst,
                        stlabel,
                        loc='lower left',
                        markerscale=.5*self.marker_size,
                        borderaxespad=.01,
                        labelspacing=.1,
                        handletextpad=.2,
                        ncol=len(stlst),
                        borderpad=.1,
                        columnspacing=.1)
                   
        leg = plt.gca().get_legend()
        ltext  = leg.get_texts()  # all the text.Text instance in the legend
        plt.setp(ltext, fontsize=6)    # the legend text fontsize

        if self.strike_limits == None:
            self.strike_limits = (-89.99, 89.99)
        
        self.ax2.set_yscale('linear')
        self.ax2.set_xscale('log')
        self.ax2.set_xlim(xmax=10**xlimits[-1], xmin=10**xlimits[0])
        self.ax2.set_ylim(self.strike_limits)
        self.ax2.yaxis.set_major_locator(MultipleLocator(20))
        self.ax2.yaxis.set_minor_locator(MultipleLocator(5))
        self.ax2.grid(True, alpha=.25, which='both', color=(.25, .25, .25),
                      lw=.25)
        self.ax2.set_ylabel('Angle (deg)', fontdict=font_dict)
        self.ax2.set_title('Strike', fontdict=font_dictt)
        
        #---------plot Min & Max Phase-----------------------------------------
        minphi = self.pt.phimin[0]
        minphierr = self.pt.phimin[1]
        maxphi = self.pt.phimax[0]
        maxphierr = self.pt.phimax[1]

        self.ax3 = self.fig.add_subplot(3, 2, 4, sharex=self.ax2)
        
        ermin = self.ax3.errorbar(self._mt.period,
                                  minphi,
                                  marker=self.ptmin_marker,
                                  ms=self.marker_size,
                                  mfc='None',
                                  mec=self.ptmin_color,
                                  mew=self.marker_lw,
                                  ls='None',
                                  yerr=minphierr,
                                  ecolor=self.ptmin_color,
                                  capsize=self.marker_size,
                                  elinewidth=self.marker_lw)
                                
        ermax = self.ax3.errorbar(self._mt.period,
                                  maxphi,
                                  marker=self.ptmax_marker,
                                  ms=self.marker_size,
                                  mfc='None',
                                  mec=self.ptmax_color,
                                  mew=self.marker_lw,
                                  ls='None',
                                  yerr=maxphierr,
                                  ecolor=self.ptmax_color,
                                  capsize=self.marker_size,
                                  elinewidth=self.marker_lw)
                           
                
        if self.pt_limits == None:
            self.pt_limits = [min([self.pt.phimax[0].min(), 
                                   self.pt.phimin[0].min()])-3, 
                              max([self.pt.phimax[0].max(), 
                                   self.pt.phimin[0].max()])+3]
            if self.pt_limits[0] < -10:
                self.pt_limits[0] = -9.9
            if self.pt_limits[1] > 100:
                self.pt_limits[1] = 99.99
        
        self.ax3.set_xscale('log')
        self.ax3.set_yscale('linear')
        
        self.ax3.legend((ermin[0], ermax[0]),
                        ('$\phi_{min}$','$\phi_{max}$'),
                        loc='lower left',
                        markerscale=.5*self.marker_size,
                        borderaxespad=.01,
                        labelspacing=.1,
                        handletextpad=.2,
                        ncol=2,
                        borderpad=.01,
                        columnspacing=.01)
        
        leg = plt.gca().get_legend()
        ltext  = leg.get_texts()  # all the text.Text instance in the legend
        plt.setp(ltext, fontsize=6.5)    # the legend text fontsize
        
        self.ax3.set_ylim(self.pt_limits)
        self.ax3.grid(True, alpha=.25, which='both', color=(.25, .25, .25),
                      lw=.25)

        self.ax3.set_ylabel('Phase (deg)', fontdict=font_dict)
        self.ax3.set_title('$\mathbf{\phi_{min}}$ and $\mathbf{\phi_{max}}$',
                           fontdict=font_dictt)

        #-----------------------plotSkew---------------------------------------
        
        skew = self.pt.beta[0]
        skewerr = self.pt.beta[1]

        self.ax4 = self.fig.add_subplot(3, 2, 5, sharex=self.ax2)
        erskew = self.ax4.errorbar(self._mt.period,
                                   skew,
                                   marker=self.skew_marker,
                                   ms=self.marker_size,
                                   mfc='None',
                                   mec=self.skew_color,
                                   mew=self.marker_lw,
                                   ls='None',
                                   yerr=skewerr,
                                   ecolor=self.skew_color,
                                   capsize=self.marker_size,
                                   elinewidth=self.marker_lw)
        
        #plot lines indicating not 3d
        self.ax4.plot([10**xlimits[0], 10**xlimits[-1]],
                      [self.skew_cutoff, self.skew_cutoff],
                      ls='--',
                      color=self.skew_color,
                      lw=1)
                      
        self.ax4.plot([10**xlimits[0], 10**xlimits[-1]],
                      [-self.skew_cutoff, -self.skew_cutoff],
                      ls='--',
                      color=self.skew_color,
                      lw=1)

        
        self.ax4.set_xscale('log')
        self.ax4.set_yscale('linear')
        self.ax4.yaxis.set_major_locator(MultipleLocator(ckstep))

        if self.skew_limits is None:
            self.skew_limits=(-10, 10)
        self.ax4.set_ylim(self.skew_limits)
        self.ax4.grid(True, alpha=.25, which='both', color=(.25, .25, .25),
                      lw=.25)
        self.ax4.set_xlabel('Period (s)',fontdict=font_dict)
        self.ax4.set_ylabel('Skew Angle (deg)',fontdict=font_dict)
        self.ax4.set_title('Skew Angle',fontdict=font_dictt)
        
        #----------------------plotEllipticity--------------------------------
        ellipticity = self.pt.ellipticity[0]
        ellipticityerr = self.pt.ellipticity[1]

        self.ax5 = self.fig.add_subplot(3, 2, 6, sharex=self.ax2)
        erskew = self.ax5.errorbar(self._mt.period,
                                   ellipticity,
                                   marker=self.ellip_marker,
                                   ms=self.marker_size,
                                   mfc='None',
                                   mec=self.ellip_color,
                                   mew=self.marker_lw,
                                   ls='None',
                                   yerr=ellipticityerr,
                                   ecolor=self.ellip_color,
                                   capsize=self.marker_size,
                                   elinewidth=self.marker_lw)
        
        #draw a line where the ellipticity is not 2d                           
        self.ax5.plot([10**xlimits[0], 10**xlimits[-1]],
                      [self.ellip_cutoff, self.ellip_cutoff],
                      ls='--',
                      color=self.ellip_color,
                      lw=1)
                      
        self.ax5.set_xscale('log')
        self.ax5.set_yscale('linear')

        self.ax5.yaxis.set_major_locator(MultipleLocator(.1))

        self.ax5.set_ylim(ymin=0,ymax=1)
        self.ax5.grid(True, alpha=.25, which='both', color=(.25,.25,.25),
                      lw=.25)
        self.ax5.set_xlabel('Period (s)',fontdict=font_dict)
        self.ax5.set_ylabel('$\mathbf{\phi_{max}-\phi_{min}/\phi_{max}+\phi_{min}}$',
                            fontdict=font_dict)
        self.ax5.set_title('Ellipticity',fontdict=font_dictt)
        
        self.fig.suptitle('Phase Tensor Elements for: '+self._mt.station,
                          fontdict={'size':self.font_size+3, 'weight':'bold'})
예제 #3
0
    def plot(self):
        """
        plot residual phase tensor
        """
        # get residual phase tensor for plotting
        self._compute_residual_pt()

        # filter data if desired
        if self.med_filt_kernel is not None:
            self._apply_median_filter(kernel=self.med_filt_kernel)

        # set position properties for the plot
        plt.rcParams["font.size"] = self.font_size
        plt.rcParams["figure.subplot.left"] = self.subplot_left
        plt.rcParams["figure.subplot.right"] = self.subplot_right
        plt.rcParams["figure.subplot.bottom"] = self.subplot_bottom
        plt.rcParams["figure.subplot.top"] = self.subplot_top
        plt.rcParams["figure.subplot.wspace"] = self.subplot_wspace
        plt.rcParams["figure.subplot.hspace"] = self.subplot_hspace

        # make figure instance
        self.fig = plt.figure(self.fig_num, self.fig_size, dpi=self.fig_dpi)

        self.ax = self.fig.add_subplot(1, 1, 1, aspect="equal")

        # create empty lists to put things into
        self.stationlist = []
        self.offsetlist = []
        minlist = []
        maxlist = []
        plot_periodlist = None

        # set local parameters with shorter names
        es = self.ellipse_size
        ck = self.ellipse_colorby
        cmap = self.ellipse_cmap
        ckmin = float(self.ellipse_range[0])
        ckmax = float(self.ellipse_range[1])
        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            ckstep = 3

        nseg = float((ckmax - ckmin) / (2 * ckstep))

        if cmap == "mt_seg_bl2wh2rd":
            bounds = np.arange(ckmin, ckmax + ckstep, ckstep)

        # get largest ellipse
        emax = self._get_ellipse_size_max()

        # plot phase tensor ellipses
        for ii, rpt in enumerate(self.residual_pt_list):
            self.stationlist.append(rpt.station[self.station_id[0] : self.station_id[1]])

            # set the an arbitrary origin to compare distance to all other
            # stations.
            if ii == 0:
                east0 = rpt.lon
                north0 = rpt.lat
                offset = 0.0
            else:
                east = rpt.lon
                north = rpt.lat
                if self.linedir == "ew":
                    if east0 < east:
                        offset = np.sqrt((east0 - east) ** 2 + (north0 - north) ** 2)
                    elif east0 > east:
                        offset = -1 * np.sqrt((east0 - east) ** 2 + (north0 - north) ** 2)
                    else:
                        offset = 0
                elif self.linedir == "ns":
                    if north0 < north:
                        offset = np.sqrt((east0 - east) ** 2 + (north0 - north) ** 2)
                    elif north0 > north:
                        offset = -1 * np.sqrt((east0 - east) ** 2 + (north0 - north) ** 2)
                    else:
                        offset = 0

            self.offsetlist.append(offset)

            periodlist = 1.0 / rpt.freq[::-1]
            phimax = rpt.residual_pt.phimax[0][::-1]
            phimin = rpt.residual_pt.phimin[0][::-1]
            azimuth = rpt.residual_pt.azimuth[0][::-1]

            # get the properties to color the ellipses by
            if self.ellipse_colorby == "phimin":
                colorarray = rpt.residual_pt.phimin[0][::-1]

            elif self.ellipse_colorby == "phimax":
                colorarray = rpt.residual_pt.phimin[0][::-1]

            elif self.ellipse_colorby == "phidet":
                colorarray = np.sqrt(abs(rpt.residual_pt.det[::-1])) * (180 / np.pi)

            elif self.ellipse_colorby == "skew" or self.ellipse_colorby == "skew_seg":
                colorarray = rpt.residual_pt.beta[0][::-1]

            elif self.ellipse_colorby == "ellipticity":
                colorarray = rpt.residual_pt.ellipticity[::-1]

            else:
                raise NameError(self.ellipse_colorby + " is not supported")

            # get the number of periods
            n = len(periodlist)

            if ii == 0:
                plot_periodlist = periodlist

            else:
                if n > len(plot_periodlist):
                    plot_periodlist = periodlist

            # get min and max of the color array for scaling later
            minlist.append(min(colorarray))
            maxlist.append(max(colorarray))

            for jj, ff in enumerate(periodlist):

                # make sure the ellipses will be visable
                eheight = phimin[jj] / emax * es
                ewidth = phimax[jj] / emax * es

                # create an ellipse scaled by phimin and phimax and orient
                # the ellipse so that north is up and east is right
                # need to add 90 to do so instead of subtracting
                ellipd = patches.Ellipse(
                    (offset * self.xstretch, np.log10(ff) * self.ystretch),
                    width=ewidth,
                    height=eheight,
                    angle=azimuth[jj] - 90,
                )

                # get ellipse color
                if cmap.find("seg") > 0:
                    ellipd.set_facecolor(
                        mtcl.get_plot_color(colorarray[jj], self.ellipse_colorby, cmap, ckmin, ckmax, bounds=bounds)
                    )
                else:
                    ellipd.set_facecolor(mtcl.get_plot_color(colorarray[jj], self.ellipse_colorby, cmap, ckmin, ckmax))

                # == =add the ellipse to the plot == ========
                self.ax.add_artist(ellipd)

        # --> Set plot parameters
        self._plot_periodlist = plot_periodlist
        n = len(plot_periodlist)

        # calculate minimum period and maximum period with a stretch factor
        pmin = np.log10(plot_periodlist.min()) * self.ystretch
        pmax = np.log10(plot_periodlist.max()) * self.ystretch

        # need to sort the offsets and station labels so they plot correctly
        sdtype = [("offset", np.float), ("station", "|S10")]
        slist = np.array([(oo, ss) for oo, ss in zip(self.offsetlist, self.stationlist)], dtype=sdtype)
        offset_sort = np.sort(slist, order="offset")

        self.offsetlist = offset_sort["offset"]
        self.stationlist = offset_sort["station"]

        # set y-ticklabels
        if self.tscale == "period":
            yticklabels = [
                "{0:>4}".format("{0: .1e}".format(plot_periodlist[ll])) for ll in np.arange(0, n, self.ystep)
            ] + ["{0:>4}".format("{0: .1e}".format(plot_periodlist[-1]))]

            self.ax.set_ylabel("Period (s)", fontsize=self.font_size + 2, fontweight="bold")

        elif self.tscale == "frequency":
            yticklabels = [
                "{0:>4}".format("{0: .1e}".format(1.0 / plot_periodlist[ll])) for ll in np.arange(0, n, self.ystep)
            ] + ["{0:>4}".format("{0: .1e}".format(1.0 / plot_periodlist[-1]))]

            self.ax.set_ylabel("Frequency (Hz)", fontsize=self.font_size + 2, fontweight="bold")
        # set x-axis label
        self.ax.set_xlabel("Station", fontsize=self.font_size + 2, fontweight="bold")

        # --> set tick locations and labels
        # set y-axis major ticks
        self.ax.yaxis.set_ticks([np.log10(plot_periodlist[ll]) * self.ystretch for ll in np.arange(0, n, self.ystep)])

        # set y-axis minor ticks
        self.ax.yaxis.set_ticks(
            [np.log10(plot_periodlist[ll]) * self.ystretch for ll in np.arange(0, n, 1)], minor=True
        )
        # set y-axis tick labels
        self.ax.set_yticklabels(yticklabels)

        # set x-axis ticks
        self.ax.set_xticks(self.offsetlist * self.xstretch)

        # set x-axis tick labels as station names
        xticklabels = self.stationlist
        if self.xstep != 1:
            xticklabels = np.zeros(len(self.stationlist), dtype=self.stationlist.dtype)
            for xx in range(0, len(self.stationlist), self.xstep):
                xticklabels[xx] = self.stationlist[xx]
        self.ax.set_xticklabels(xticklabels)

        # --> set x-limits
        if self.xlimits == None:
            self.ax.set_xlim(
                self.offsetlist.min() * self.xstretch - es * 2, self.offsetlist.max() * self.xstretch + es * 2
            )
        else:
            self.ax.set_xlim(self.xlimits)

        # --> set y-limits
        if self.ylimits == None:
            self.ax.set_ylim(pmax + es * 2, pmin - es * 2)
        else:
            pmin = np.log10(self.ylimits[0]) * self.ystretch
            pmax = np.log10(self.ylimits[1]) * self.ystretch
            self.ax.set_ylim(pmax + es * 2, pmin - es * 2)

        # --> set title of the plot
        if self.plot_title == None:
            pass
        else:
            self.ax.set_title(self.plot_title, fontsize=self.font_size + 2)

        # put a grid on the plot
        self.ax.grid(alpha=0.25, which="both", color=(0.25, 0.25, 0.25))

        # print out the min an max of the parameter plotted
        print "-" * 25
        print ck + " min = {0:.2f}".format(min(minlist))
        print ck + " max = {0:.2f}".format(max(maxlist))
        print "-" * 25

        # ==> make a colorbar with appropriate colors
        if self.cb_position == None:
            self.ax2, kw = mcb.make_axes(self.ax, orientation=self.cb_orientation, shrink=0.35)
        else:
            self.ax2 = self.fig.add_axes(self.cb_position)

        if cmap == "mt_seg_bl2wh2rd":
            # make a color list
            self.clist = [(cc, cc, 1) for cc in np.arange(0, 1 + 1.0 / (nseg), 1.0 / (nseg))] + [
                (1, cc, cc) for cc in np.arange(1, -1.0 / (nseg), -1.0 / (nseg))
            ]

            # make segmented colormap
            mt_seg_bl2wh2rd = colors.ListedColormap(self.clist)

            # make bounds so that the middle is white
            bounds = np.arange(ckmin - ckstep, ckmax + 2 * ckstep, ckstep)

            # normalize the colors
            norms = colors.BoundaryNorm(bounds, mt_seg_bl2wh2rd.N)

            # make the colorbar
            self.cb = mcb.ColorbarBase(
                self.ax2, cmap=mt_seg_bl2wh2rd, norm=norms, orientation=self.cb_orientation, ticks=bounds[1:-1]
            )
        else:
            self.cb = mcb.ColorbarBase(
                self.ax2,
                cmap=mtcl.cmapdict[cmap],
                norm=colors.Normalize(vmin=ckmin, vmax=ckmax),
                orientation=self.cb_orientation,
            )

        # label the color bar accordingly
        self.cb.set_label(mtpl.ckdict[ck], fontdict={"size": self.font_size, "weight": "bold"})

        # place the label in the correct location
        if self.cb_orientation == "horizontal":
            self.cb.ax.xaxis.set_label_position("top")
            self.cb.ax.xaxis.set_label_coords(0.5, 1.3)

        elif self.cb_orientation == "vertical":
            self.cb.ax.yaxis.set_label_position("right")
            self.cb.ax.yaxis.set_label_coords(1.5, 0.5)
            self.cb.ax.yaxis.tick_left()
            self.cb.ax.tick_params(axis="y", direction="in")

        plt.show()
예제 #4
0
    def add_pt_patch(self, pt_dict):
        """
        Add patches to plot
        """

        plot_x = pt_dict["lon"]
        plot_y = pt_dict["lat"]
        w1 = Wedge(
            (plot_x, plot_y),
            self.ellipse_size,
            90 - pt_dict["azimuth"] - self.wedge_width,
            90 - pt_dict["azimuth"] + self.wedge_width,
            color=mtcolors.get_plot_color(
                pt_dict["phi_max"],
                "phimax",
                self.phimax_cmap,
                self.phase_limits[0],
                self.phase_limits[1],
            ),
        )
        w2 = Wedge(
            (plot_x, plot_y),
            self.ellipse_size,
            270 - pt_dict["azimuth"] - self.wedge_width,
            270 - pt_dict["azimuth"] + self.wedge_width,
            color=mtcolors.get_plot_color(
                pt_dict["phi_max"],
                "phimax",
                self.phimax_cmap,
                self.phase_limits[0],
                self.phase_limits[1],
            ),
        )

        w3 = Wedge(
            (plot_x, plot_y),
            self.ellipse_size * pt_dict["phi_min"] / pt_dict["phi_max"],
            -1 * pt_dict["azimuth"] - self.wedge_width,
            -1 * pt_dict["azimuth"] + self.wedge_width,
            color=mtcolors.get_plot_color(
                pt_dict["phi_min"],
                "phimin",
                self.phimin_cmap,
                self.phase_limits[0],
                self.phase_limits[1],
            ),
        )
        w4 = Wedge(
            (plot_x, plot_y),
            self.ellipse_size * pt_dict["phi_min"] / pt_dict["phi_max"],
            180 - pt_dict["azimuth"] - self.wedge_width,
            180 - pt_dict["azimuth"] + self.wedge_width,
            color=mtcolors.get_plot_color(
                pt_dict["phi_min"],
                "phimin",
                self.phimin_cmap,
                self.phase_limits[0],
                self.phase_limits[1],
            ),
        )

        if pt_dict["tip_mag_re"] > 0:
            txr = (pt_dict["tip_mag_re"] * self.arrow_size *
                   np.sin(np.deg2rad(pt_dict["tip_ang_re"])))
            tyr = (pt_dict["tip_mag_re"] * self.arrow_size *
                   np.cos(np.deg2rad(pt_dict["tip_ang_re"])))

            self.ax.arrow(
                plot_x,
                plot_y,
                txr,
                tyr,
                width=self.arrow_lw,
                facecolor=self.arrow_color_real,
                edgecolor=(0, 0, 0),
                length_includes_head=False,
                head_width=self.arrow_head_width,
                head_length=self.arrow_head_length,
            )

            txi = (pt_dict["tip_mag_im"] * self.arrow_size *
                   np.sin(np.deg2rad(pt_dict["tip_ang_im"])))
            tyi = (pt_dict["tip_mag_im"] * self.arrow_size *
                   np.cos(np.deg2rad(pt_dict["tip_ang_im"])))

            self.ax.arrow(
                plot_x,
                plot_y,
                txi,
                tyi,
                width=self.arrow_lw,
                facecolor=self.arrow_color_imag,
                edgecolor=(0, 0, 0),
                length_includes_head=False,
                head_width=self.arrow_head_width,
                head_length=self.arrow_head_length,
            )

        # make an ellipse
        e1 = Ellipse(
            (plot_x, plot_y),
            width=2 * self.ellipse_size,
            height=2 * self.ellipse_size * pt_dict["phi_min"] /
            pt_dict["phi_max"],
            angle=90 - pt_dict["azimuth"],
        )

        gm = np.sqrt(abs(pt_dict["phi_min"])**2 + abs(pt_dict["phi_max"])**2)
        e1.set_facecolor(
            mtcolors.get_plot_color(
                gm,
                "geometric_mean",
                self.gm_cmap,
                self.phase_limits[0],
                self.phase_limits[1],
            ))
        e1.set_edgecolor(
            mtcolors.get_plot_color(
                abs(pt_dict["skew"]),
                "skew_seg",
                self.skew_cmap,
                self.skew_limits[0],
                self.skew_limits[1],
                np.arange(
                    self.skew_limits[0],
                    self.skew_limits[1] + self.skew_step,
                    self.skew_step,
                ),
            ))
        e1.set_linewidth(self.skew_lw)
        e1.set_alpha(self.ellipse_alpha)
        ### add patches
        for patch in [e1, w1, w2, w3, w4]:
            self.ax.add_patch(patch)
예제 #5
0
    def plot(self):
        """
        plot residual phase tensor
        """ 
                           
        #get residual phase tensor for plotting        
        self._compute_residual_pt()
        
        #filter data if desired
        if self.med_filt_kernel is not None:
            self._apply_median_filter(kernel=self.med_filt_kernel)
        
        #set position properties for the plot
        plt.rcParams['font.size']=self.font_size
        plt.rcParams['figure.subplot.left'] = self.subplot_left
        plt.rcParams['figure.subplot.right'] = self.subplot_right
        plt.rcParams['figure.subplot.bottom'] = self.subplot_bottom
        plt.rcParams['figure.subplot.top'] = self.subplot_top
        plt.rcParams['figure.subplot.wspace'] = self.subplot_wspace
        plt.rcParams['figure.subplot.hspace'] = self.subplot_hspace
        
        #make figure instance
        self.fig = plt.figure(self.fig_num, self.fig_size, dpi=self.fig_dpi)
        
        #create axis instance, be sure to make aspect equal or ellipses will
        #look funny.
        self.ax = self.fig.add_subplot(1, 1, 1, aspect='equal')

        #set local parameters with shorter names
        es = self.ellipse_size
        ck = self.ellipse_colorby
        cmap = self.ellipse_cmap
        ckmin = float(self.ellipse_range[0])
        ckmax = float(self.ellipse_range[1])
        
        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            ckstep = 3
        #set the number of segments in case a segmented map is desired        
        nseg = float((ckmax-ckmin)/(2*ckstep))

        if cmap == 'mt_seg_bl2wh2rd':
            bounds = np.arange(ckmin, ckmax+ckstep, ckstep)
            
        #get largest ellipse
        emax = self.ellipse_scale
        #emax = self.rpt_array['phimax'].max()
        
        #plot phase tensor ellipses
        for ii, rpt in enumerate(self.rpt_array):

            phimax = rpt['phimax']
            phimin = rpt['phimin']
            azimuth = rpt['azimuth']
                
            #get the properties to color the ellipses by
            try:
                color_array = rpt[self.ellipse_colorby]
            except ValueError:
                raise NameError('{0} is not supported'.format(
                                                        self.ellipse_colorby))

            for jj, ff in enumerate(self.freq_list):
                if phimin[jj] == 0.0 or phimax[jj] == 0.0:
                    pass
                else:
                    #make sure the ellipses will be visable
                    eheight = phimin[jj]/emax*es
                    ewidth = phimax[jj]/emax*es
            
                    #create an ellipse scaled by phimin and phimax and orient
                    #the ellipse so that north is up and east is right
                    #need to add 90 to do so instead of subtracting
                    if self.rot90 == True:
                        ellipd = patches.Ellipse((rpt['offset']*self.xstretch,
                                                  np.log10(ff)*self.ystretch),
                                                  width=ewidth,
                                                  height=eheight,
                                                  angle=azimuth[jj]-90)
                    else:
                        ellipd = patches.Ellipse((rpt['offset']*self.xstretch,
                                                  np.log10(ff)*self.ystretch),
                                                  width=ewidth,
                                                  height=eheight,
                                                  angle=azimuth[jj])
                                                
                    #get ellipse color
                    if cmap.find('seg')>0:
                        ellipd.set_facecolor(mtcl.get_plot_color(color_array[jj],
                                             self.ellipse_colorby,
                                             cmap,
                                             ckmin,
                                             ckmax,
                                             bounds=bounds))
                    else:
                        ellipd.set_facecolor(mtcl.get_plot_color(color_array[jj],
                                             self.ellipse_colorby,
                                             cmap,
                                             ckmin,
                                             ckmax))
                        
                    # == =add the ellipse to the plot == ========
                    self.ax.add_artist(ellipd)
                    
                
        #--> Set plot parameters
        #need to sort the offsets and station labels so they plot correctly
        sdtype = [('offset', np.float), ('station','|S10')]
        slist = np.array([(oo, ss) for oo, ss in zip(self.rpt_array['offset'], 
                         self.rpt_array['station'])], dtype=sdtype)
        
        offset_sort = np.sort(slist, order='offset')
     
        self.offset_list = offset_sort['offset']
        self.station_list = offset_sort['station']
        
        #min and max frequency of the plot
        pmin = int(np.floor(np.log10(self.freq_list.min())))
        pmax = int(np.ceil(np.log10(self.freq_list.max())))

        #set y-axis major ticks to be on each power of 10
        self.ax.yaxis.set_ticks(np.arange(pmin*self.ystretch, 
                                          (pmax+1)*self.ystretch, 
                                          self.ystretch))
        #set y-ticklabels to coincide with the desired label
        if self.tscale == 'period':
            #make tick labels that will represent period
            yticklabels = [mtpl.labeldict[-ii] for ii in range(pmin, pmax+1, 1)]
            self.ax.set_ylabel('Period (s)',
                               fontsize=self.font_size+2,
                               fontweight='bold')

        elif self.tscale == 'frequency': 
            yticklabels = [mtpl.labeldict[ii] for ii in range(pmin, pmax+1, 1)]
            self.ax.set_ylabel('Frequency (Hz)',
                               fontsize=self.font_size+2,
                               fontweight='bold')
        #--> set y-limits
        if self.ylimits == None:
            self.ax.set_ylim(pmin*self.ystretch, pmax*self.ystretch)
        else:
            pmin = np.log10(self.ylimits[0])*self.ystretch
            pmax = np.log10(self.ylimits[1])*self.ystretch
            self.ax.set_ylim(pmin, pmax)
            
        #--> set y-axis tick labels
        self.ax.set_yticklabels(yticklabels)
    
        #--> set x-axis label                       
        self.ax.set_xlabel('Station',
                           fontsize=self.font_size+2,
                           fontweight='bold')

        #set x-axis ticks
        self.ax.set_xticks(self.offset_list*self.xstretch)
        
        #set x-axis tick labels as station names
        xticklabels = self.station_list
        if self.xstep != 1:
            xticklabels = np.zeros(len(self.station_list), 
                                   dtype=self.station_list.dtype)
            for xx in range(0,len(self.station_list),self.xstep):
                xticklabels[xx] = self.station_list[xx]
        self.ax.set_xticklabels(xticklabels)
        
        #--> set x-limits
        if self.xlimits == None:
            self.ax.set_xlim(self.offset_list.min()*self.xstretch-es*2,
                             self.offset_list.max()*self.xstretch+es*2)
        else:
            self.ax.set_xlim(self.xlimits)
            
        
            
        #--> set title of the plot
        if self.plot_title == None:
            pass
        else:
            self.ax.set_title(self.plot_title, fontsize=self.font_size+2)
        
        #put a grid on the plot
        self.ax.grid(alpha=.25, which='both', color=(.25, .25, .25))

        #==> make a colorbar with appropriate colors
        if self.cb_position == None:
            self.ax2, kw = mcb.make_axes(self.ax,
                                         orientation=self.cb_orientation,
                                         shrink=.35)
        else:
            self.ax2 = self.fig.add_axes(self.cb_position)
        
        if cmap == 'mt_seg_bl2wh2rd':
            #make a color list
            self.clist = [(cc, cc, 1) 
                         for cc in np.arange(0, 1+1./(nseg), 1./(nseg))]+\
                        [(1, cc, cc) 
                         for cc in np.arange(1, -1./(nseg), -1./(nseg))]
            
            #make segmented colormap
            mt_seg_bl2wh2rd = colors.ListedColormap(self.clist)

            #make bounds so that the middle is white
            bounds = np.arange(ckmin-ckstep, ckmax+2*ckstep, ckstep)
            
            #normalize the colors
            norms = colors.BoundaryNorm(bounds, mt_seg_bl2wh2rd.N)
            
            #make the colorbar
            self.cb = mcb.ColorbarBase(self.ax2,
                                       cmap=mt_seg_bl2wh2rd,
                                       norm=norms,
                                       orientation=self.cb_orientation,
                                       ticks=bounds[1:-1])
        else:
            self.cb = mcb.ColorbarBase(self.ax2,
                                       cmap=mtcl.cmapdict[cmap],
                                       norm=colors.Normalize(vmin=ckmin,
                                                             vmax=ckmax),
                                       orientation=self.cb_orientation)

        #label the color bar accordingly
        self.cb.set_label(mtpl.ckdict[ck],
                          fontdict={'size':self.font_size,'weight':'bold'})
            
        #place the label in the correct location                   
        if self.cb_orientation == 'horizontal':
            self.cb.ax.xaxis.set_label_position('top')
            self.cb.ax.xaxis.set_label_coords(.5, 1.3)
            
            
        elif self.cb_orientation == 'vertical':
            self.cb.ax.yaxis.set_label_position('right')
            self.cb.ax.yaxis.set_label_coords(1.5, .5)
            self.cb.ax.yaxis.tick_left()
            self.cb.ax.tick_params(axis='y', direction='in')
            
        #--> add reference ellipse
        ref_ellip = patches.Ellipse((0, .0),
                                       width=es,
                                       height=es,
                                       angle=0)
        ref_ellip.set_facecolor((0, 0, 0))
        ref_ax_loc = list(self.ax2.get_position().bounds)
        ref_ax_loc[0] *= .95
        ref_ax_loc[1] -= .17
        ref_ax_loc[2] = .1
        ref_ax_loc[3] = .1
        self.ref_ax = self.fig.add_axes(ref_ax_loc, aspect='equal')
        self.ref_ax.add_artist(ref_ellip)
        self.ref_ax.set_xlim(-es/2.*1.05, es/2.*1.05)
        self.ref_ax.set_ylim(-es/2.*1.05, es/2.*1.05)
        plt.setp(self.ref_ax.xaxis.get_ticklabels(), visible=False)
        plt.setp(self.ref_ax.yaxis.get_ticklabels(), visible=False)
        self.ref_ax.set_title(r'$\Delta \Phi$ = 1')
          
        # put the grid lines behind 
#        [line.set_zorder(10000) for line in self.ax.lines]
        self.ax.set_axisbelow(True)
        
        plt.show()
예제 #6
0
    def plot(self, period=0, save2file=None, **kwargs):
        """ Plot phase tensor maps for data and or response, each figure is of a
        different period.  If response is input a third column is added which is
        the residual phase tensor showing where the model is not fitting the data
        well.  The data is plotted in km.

        Args:
            period: the period index to plot, default=0

        Returns:

        """

        print("The input parameter period is", period)

        # --> read in data first
        if self.data_obj is None:
            self._read_files()

        # set plot properties
        plt.rcParams['font.size'] = self.font_size
        plt.rcParams['figure.subplot.left'] = self.subplot_left
        plt.rcParams['figure.subplot.right'] = self.subplot_right
        plt.rcParams['figure.subplot.bottom'] = self.subplot_bottom
        plt.rcParams['figure.subplot.top'] = self.subplot_top
        font_dict = {'size': self.font_size + 2, 'weight': 'bold'}

        # make a grid of subplots
        gs = gridspec.GridSpec(1,
                               3,
                               hspace=self.subplot_hspace,
                               wspace=self.subplot_wspace)

        # set some parameters for the colorbar
        ckmin = float(self.ellipse_range[0])
        ckmax = float(self.ellipse_range[1])
        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            if self.ellipse_cmap == 'mt_seg_bl2wh2rd':
                raise ValueError('Need to input range as (min, max, step)')
            else:
                ckstep = 3
        bounds = np.arange(ckmin, ckmax + ckstep, ckstep)

        # set plot limits to be the station area
        if self.ew_limits is None:
            east_min = self.data_obj.data_array['rel_east'].min() - \
                self.pad_east
            east_max = self.data_obj.data_array['rel_east'].max() + \
                self.pad_east
            self.ew_limits = (east_min / self.dscale, east_max / self.dscale)

        if self.ns_limits is None:
            north_min = self.data_obj.data_array['rel_north'].min() - \
                self.pad_north
            north_max = self.data_obj.data_array['rel_north'].max() + \
                self.pad_north
            self.ns_limits = (north_min / self.dscale, north_max / self.dscale)

        # -------------plot phase tensors------------------------------------
        if period > len(self.plot_period_list) - 1:
            print("Error: the period exceeds the max value:",
                  len(self.plot_period_list) - 1)

        # FZ: changed below to plot a given period index
        # for ff, per in enumerate(self.plot_period_list):
        for ff, per in enumerate(self.plot_period_list[period:period + 1]):
            # FZ
            print(ff, per)
            print(self.plot_period_list)

            data_ii = self.period_dict[per]

            print 'Plotting Period: {0:.5g}'.format(per)
            fig = plt.figure('{0:.5g}'.format(per),
                             figsize=self.fig_size,
                             dpi=self.fig_dpi)
            fig.clf()

            if self.resp_fn is not None:
                axd = fig.add_subplot(gs[0, 0], aspect='equal')
                axm = fig.add_subplot(gs[0, 1], aspect='equal')
                axr = fig.add_subplot(gs[0, 2], aspect='equal')
                ax_list = [axd, axm, axr]

            else:
                axd = fig.add_subplot(gs[0, :], aspect='equal')
                ax_list = [axd]

            # plot model below the phase tensors
            if self.model_fn is not None:
                gridzcentre = np.mean(
                    [self.model_obj.grid_z[1:], self.model_obj.grid_z[:-1]],
                    axis=0)
                if self.d_index is not None:
                    approx_depth, d_index = ws.estimate_skin_depth(
                        self.model_obj.res_model.copy(),
                        gridzcentre / self.dscale,
                        per,
                        dscale=self.dscale)
                else:
                    d_index = self.d_index
                    approx_depth = self.model_obj.grid_z[d_index]

                # need to add an extra row and column to east and north to make sure
                # all is plotted see pcolor for details.
                plot_east = np.append(self.model_obj.grid_east,
                                      self.model_obj.grid_east[-1] * 1.25) / \
                    self.dscale
                plot_north = np.append(self.model_obj.grid_north,
                                       self.model_obj.grid_north[-1] * 1.25) / \
                    self.dscale

                # make a mesh grid for plotting
                # the 'ij' makes sure the resulting grid is in east, north
                try:
                    self.mesh_east, self.mesh_north = np.meshgrid(
                        plot_east, plot_north, indexing='ij')
                except TypeError:
                    self.mesh_east, self.mesh_north = [
                        arr.T for arr in np.meshgrid(plot_east, plot_north)
                    ]

                for ax in ax_list:
                    plot_res = np.log10(self.model_obj.res_model[:, :,
                                                                 d_index].T)
                    ax.pcolormesh(self.mesh_east,
                                  self.mesh_north,
                                  plot_res,
                                  cmap=self.res_cmap,
                                  vmin=self.res_limits[0],
                                  vmax=self.res_limits[1])

            # --> plot data phase tensors
            for pt in self.pt_data_arr[data_ii]:
                eheight = pt['phimin'] / \
                    self.pt_data_arr[data_ii]['phimax'].max() * \
                    self.ellipse_size
                ewidth = pt['phimax'] / \
                    self.pt_data_arr[data_ii]['phimax'].max() * \
                    self.ellipse_size

                ellipse = Ellipse((pt['east'], pt['north']),
                                  width=ewidth,
                                  height=eheight,
                                  angle=90 - pt['azimuth'],
                                  **kwargs)

                # get ellipse color
                if self.ellipse_cmap.find('seg') > 0:
                    ellipse.set_facecolor(
                        mtcl.get_plot_color(pt[self.ellipse_colorby],
                                            self.ellipse_colorby,
                                            self.ellipse_cmap,
                                            ckmin,
                                            ckmax,
                                            bounds=bounds))
                else:
                    ellipse.set_facecolor(
                        mtcl.get_plot_color(pt[self.ellipse_colorby],
                                            self.ellipse_colorby,
                                            self.ellipse_cmap, ckmin, ckmax))

                axd.add_artist(ellipse)

            # -----------plot response phase tensors---------------
            if self.resp_fn is not None:
                rcmin = np.floor(self.pt_resid_arr['geometric_mean'].min())
                rcmax = np.floor(self.pt_resid_arr['geometric_mean'].max())
                for mpt, rpt in zip(self.pt_resp_arr[data_ii],
                                    self.pt_resid_arr[data_ii]):
                    eheight = mpt['phimin'] / \
                        self.pt_resp_arr[data_ii]['phimax'].max() * \
                        self.ellipse_size
                    ewidth = mpt['phimax'] / \
                        self.pt_resp_arr[data_ii]['phimax'].max() * \
                        self.ellipse_size

                    ellipsem = Ellipse((mpt['east'], mpt['north']),
                                       width=ewidth,
                                       height=eheight,
                                       angle=90 - mpt['azimuth'],
                                       **kwargs)

                    # get ellipse color
                    if self.ellipse_cmap.find('seg') > 0:
                        ellipsem.set_facecolor(
                            mtcl.get_plot_color(mpt[self.ellipse_colorby],
                                                self.ellipse_colorby,
                                                self.ellipse_cmap,
                                                ckmin,
                                                ckmax,
                                                bounds=bounds))
                    else:
                        ellipsem.set_facecolor(
                            mtcl.get_plot_color(mpt[self.ellipse_colorby],
                                                self.ellipse_colorby,
                                                self.ellipse_cmap, ckmin,
                                                ckmax))

                    axm.add_artist(ellipsem)

                    # -----------plot residual phase tensors---------------
                    eheight = rpt['phimin'] / \
                        self.pt_resid_arr[data_ii]['phimax'].max() * \
                        self.ellipse_size
                    ewidth = rpt['phimax'] / \
                        self.pt_resid_arr[data_ii]['phimax'].max() * \
                        self.ellipse_size

                    ellipser = Ellipse((rpt['east'], rpt['north']),
                                       width=ewidth,
                                       height=eheight,
                                       angle=rpt['azimuth'],
                                       **kwargs)

                    # get ellipse color
                    rpt_color = np.sqrt(abs(rpt['phimin'] * rpt['phimax']))
                    if self.ellipse_cmap.find('seg') > 0:
                        ellipser.set_facecolor(
                            mtcl.get_plot_color(rpt_color,
                                                'geometric_mean',
                                                self.residual_cmap,
                                                ckmin,
                                                ckmax,
                                                bounds=bounds))
                    else:
                        ellipser.set_facecolor(
                            mtcl.get_plot_color(rpt_color, 'geometric_mean',
                                                self.residual_cmap, ckmin,
                                                ckmax))

                    axr.add_artist(ellipser)

            # --> set axes properties
            # data
            axd.set_xlim(self.ew_limits)
            axd.set_ylim(self.ns_limits)
            axd.set_xlabel('Easting ({0})'.format(self.map_scale),
                           fontdict=font_dict)
            axd.set_ylabel('Northing ({0})'.format(self.map_scale),
                           fontdict=font_dict)
            # make a colorbar for phase tensors
            # bb = axd.axes.get_position().bounds
            bb = axd.get_position().bounds
            y1 = .25 * (2 + (self.ns_limits[1] - self.ns_limits[0]) /
                        (self.ew_limits[1] - self.ew_limits[0]))
            cb_location = (3.35 * bb[2] / 5 + bb[0], y1 * self.cb_pt_pad,
                           .295 * bb[2], .02)
            cbaxd = fig.add_axes(cb_location)
            cbd = mcb.ColorbarBase(cbaxd,
                                   cmap=mtcl.cmapdict[self.ellipse_cmap],
                                   norm=Normalize(vmin=ckmin, vmax=ckmax),
                                   orientation='horizontal')
            cbd.ax.xaxis.set_label_position('top')
            cbd.ax.xaxis.set_label_coords(.5, 1.75)
            cbd.set_label(mtplottools.ckdict[self.ellipse_colorby])
            cbd.set_ticks(
                np.arange(ckmin, ckmax + self.cb_tick_step, self.cb_tick_step))

            axd.text(self.ew_limits[0] * .95,
                     self.ns_limits[1] * .95,
                     'Data',
                     horizontalalignment='left',
                     verticalalignment='top',
                     bbox={'facecolor': 'white'},
                     fontdict={'size': self.font_size + 1})

            # Model and residual
            if self.resp_fn is not None:
                for aa, ax in enumerate([axm, axr]):
                    ax.set_xlim(self.ew_limits)
                    ax.set_ylim(self.ns_limits)
                    ax.set_xlabel('Easting ({0})'.format(self.map_scale),
                                  fontdict=font_dict)
                    plt.setp(ax.yaxis.get_ticklabels(), visible=False)
                    # make a colorbar ontop of axis
                    bb = ax.axes.get_position().bounds
                    y1 = .25 * (2 + (self.ns_limits[1] - self.ns_limits[0]) /
                                (self.ew_limits[1] - self.ew_limits[0]))
                    cb_location = (3.35 * bb[2] / 5 + bb[0],
                                   y1 * self.cb_pt_pad, .295 * bb[2], .02)
                    cbax = fig.add_axes(cb_location)
                    if aa == 0:
                        cb = mcb.ColorbarBase(
                            cbax,
                            cmap=mtcl.cmapdict[self.ellipse_cmap],
                            norm=Normalize(vmin=ckmin, vmax=ckmax),
                            orientation='horizontal')
                        cb.ax.xaxis.set_label_position('top')
                        cb.ax.xaxis.set_label_coords(.5, 1.75)
                        cb.set_label(mtplottools.ckdict[self.ellipse_colorby])
                        cb.set_ticks(
                            np.arange(ckmin, ckmax + self.cb_tick_step,
                                      self.cb_tick_step))
                        ax.text(self.ew_limits[0] * .95,
                                self.ns_limits[1] * .95,
                                'Model',
                                horizontalalignment='left',
                                verticalalignment='top',
                                bbox={'facecolor': 'white'},
                                fontdict={'size': self.font_size + 1})
                    else:
                        cb = mcb.ColorbarBase(
                            cbax,
                            cmap=mtcl.cmapdict[self.residual_cmap],
                            norm=Normalize(vmin=rcmin, vmax=rcmax),
                            orientation='horizontal')
                        cb.ax.xaxis.set_label_position('top')
                        cb.ax.xaxis.set_label_coords(.5, 1.75)
                        cb.set_label(r"$\sqrt{\Phi_{min} \Phi_{max}}$")
                        cb_ticks = [rcmin, (rcmax - rcmin) / 2, rcmax]
                        cb.set_ticks(cb_ticks)
                        ax.text(self.ew_limits[0] * .95,
                                self.ns_limits[1] * .95,
                                'Residual',
                                horizontalalignment='left',
                                verticalalignment='top',
                                bbox={'facecolor': 'white'},
                                fontdict={'size': self.font_size + 1})

            if self.model_fn is not None:
                for ax in ax_list:
                    ax.tick_params(direction='out')
                    bb = ax.axes.get_position().bounds
                    y1 = .25 * (2 - (self.ns_limits[1] - self.ns_limits[0]) /
                                (self.ew_limits[1] - self.ew_limits[0]))
                    cb_position = (3.0 * bb[2] / 5 + bb[0],
                                   y1 * self.cb_res_pad, .35 * bb[2], .02)
                    cbax = fig.add_axes(cb_position)
                    cb = mcb.ColorbarBase(cbax,
                                          cmap=self.res_cmap,
                                          norm=Normalize(
                                              vmin=self.res_limits[0],
                                              vmax=self.res_limits[1]),
                                          orientation='horizontal')
                    cb.ax.xaxis.set_label_position('top')
                    cb.ax.xaxis.set_label_coords(.5, 1.5)
                    cb.set_label('Resistivity ($\Omega \cdot$m)')
                    cb_ticks = np.arange(np.floor(self.res_limits[0]),
                                         np.ceil(self.res_limits[1] + 1), 1)
                    cb.set_ticks(cb_ticks)
                    cb.set_ticklabels(
                        [mtplottools.labeldict[ctk] for ctk in cb_ticks])

            if save2file is not None:
                fig.savefig(save2file, dpi=self.fig_dpi, bbox_inches='tight')

            plt.show()
            self.fig_list.append(fig)

            return fig
예제 #7
0
파일: plotpt.py 프로젝트: umma-zannat/mtpy
    def plot(self):
        """
        plots the phase tensor elements
        """

        # Set plot parameters
        plt.rcParams['font.size'] = self.font_size
        plt.rcParams['figure.subplot.left'] = .1
        plt.rcParams['figure.subplot.right'] = .98
        plt.rcParams['figure.subplot.bottom'] = .1
        plt.rcParams['figure.subplot.top'] = .95
        plt.rcParams['figure.subplot.wspace'] = .21
        plt.rcParams['figure.subplot.hspace'] = .5

        font_dict = {'size': self.font_size, 'weight': 'bold'}
        font_dictt = {'size': self.font_size + 2, 'weight': 'bold'}

        #--> create plot instance
        self.fig = plt.figure(self.fig_num, self.fig_size, dpi=self.fig_dpi)
        plt.clf()

        # get phase tensor instance
        try:
            self.pt
            self.pt.rotate(self.rot_z)
        except AttributeError:
            self.pt = self._mt.pt
            self.pt.rotate(self.rot_z)
            self.zinv = self._mt.Z.invariants
            self.zinv.rotate(self.rot_z)

        cmap = self.ellipse_cmap
        ckmin = self.ellipse_range[0]
        ckmax = self.ellipse_range[1]
        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            ckstep = 3

        if cmap == 'mt_seg_bl2wh2rd':
            bounds = np.arange(ckmin, ckmax + ckstep, ckstep)
            nseg = float((ckmax - ckmin) / (2 * ckstep))

        # get the properties to color the ellipses by
        if self.ellipse_colorby == 'phiminang' or \
           self.ellipse_colorby == 'phimin':
            colorarray = self.pt.phimin[0]

        elif self.ellipse_colorby == 'phidet':
            colorarray = np.sqrt(abs(self.pt.det[0])) * (180 / np.pi)

        elif self.ellipse_colorby == 'skew' or\
                self.ellipse_colorby == 'skew_seg':
            colorarray = self.pt.beta[0]

        elif self.ellipse_colorby == 'ellipticity':
            colorarray = self.pt.ellipticity[0]

        else:
            raise NameError(self.ellipse_colorby + ' is not supported')

        #-------------plotPhaseTensor-----------------------------------
        self.ax1 = self.fig.add_subplot(3, 1, 1, aspect='equal')
        self._mt._period = 1. / self._mt.freq

        for ii, ff in enumerate(self._mt.period):
            # make sure the ellipses will be visable
            if self.pt.phimax[0][ii] != 0:
                eheight = self.pt.phimin[0][ii] / self.pt.phimax[0][ii] *\
                    self.ellipse_size

                ewidth = self.ellipse_size

            else:
                # tiny instead of nothing
                eheight = 0.01 * self.ellipse_size
                ewidth = 0.01 * self.ellipse_size

            # ewidth = self.pt.phimax[0][ii]/self.pt.phimax[0][ii]*\
            #                                                  self.ellipse_size

            # alternative scaling
            # eheight = self.pt.phimin[0][ii]/max(np.abs(self.pt.phimax[0]))*\
            #                                                   self.ellipse_size
            # ewidth = self.pt.phimax[0][ii]/max(np.abs(self.pt.phimax[0]))*\
            #                                                   self.ellipse_size

            # create an ellipse scaled by phimin and phimax and oriented along
            # the azimuth which is calculated as clockwise but needs to
            # be plotted counter-clockwise hence the negative sign.
            ellipd = patches.Ellipse((np.log10(ff) * self.ellipse_spacing, 0),
                                     width=ewidth,
                                     height=eheight,
                                     angle=90 - self.pt.azimuth[0][ii])

            self.ax1.add_patch(ellipd)

            # get ellipse color
            if cmap.find('seg') > 0:
                ellipd.set_facecolor(
                    mtcl.get_plot_color(colorarray[ii],
                                        self.ellipse_colorby,
                                        cmap,
                                        ckmin,
                                        ckmax,
                                        bounds=bounds))
            else:
                ellipd.set_facecolor(
                    mtcl.get_plot_color(colorarray[ii], self.ellipse_colorby,
                                        cmap, ckmin, ckmax))

        #----set axes properties-----------------------------------------------
        #--> set tick labels and limits
        xlimits = (np.floor(np.log10(self._mt.period[0])),
                   np.ceil(np.log10(self._mt.period[-1])))

        self.ax1.set_xlim(xlimits)
        tklabels = []
        xticks = []
        for tk in self.ax1.get_xticks():
            try:
                tklabels.append(mtpl.labeldict[tk])
                xticks.append(tk)
            except KeyError:
                pass
        self.ax1.set_xticks(xticks)
        self.ax1.set_xticklabels(tklabels, fontdict={'size': self.font_size})
        self.ax1.set_xlabel('Period (s)', fontdict=font_dict)
        self.ax1.set_ylim(ymin=-1.5 * self.ellipse_size,
                          ymax=1.5 * self.ellipse_size)

        self.ax1.grid(True,
                      alpha=.25,
                      which='major',
                      color=(.25, .25, .25),
                      lw=.25)

        plt.setp(self.ax1.get_yticklabels(), visible=False)
        # add colorbar for PT
        self.cbax = self.fig.add_axes(self.cb_position)
        if cmap == 'mt_seg_bl2wh2rd':
            # make a color list
            clist = [(cc, cc, 1) for cc in np.arange(0, 1 + 1. / (nseg), 1. / (nseg))] +\
                [(1, cc, cc)
                 for cc in np.arange(1, -1. / (nseg), -1. / (nseg))]

            # make segmented colormap
            mt_seg_bl2wh2rd = colors.ListedColormap(clist)

            # make bounds so that the middle is white
            bounds = np.arange(ckmin - ckstep, ckmax + 2 * ckstep, ckstep)

            # normalize the colors
            norms = colors.BoundaryNorm(bounds, mt_seg_bl2wh2rd.N)

            # make the colorbar
            self.cbpt = mcb.ColorbarBase(self.cbax,
                                         cmap=mt_seg_bl2wh2rd,
                                         norm=norms,
                                         orientation='vertical',
                                         ticks=bounds[1:-1])
        else:
            self.cbpt = mcb.ColorbarBase(self.cbax,
                                         cmap=mtcl.cmapdict[cmap],
                                         norm=colors.Normalize(vmin=ckmin,
                                                               vmax=ckmax),
                                         orientation='vertical')
        self.cbpt.set_ticks([ckmin, ckmax])
        self.cbpt.set_ticklabels(
            ['{0:.0f}'.format(ckmin), '{0:.0f}'.format(ckmax)])
        self.cbpt.ax.yaxis.set_label_position('left')
        self.cbpt.ax.yaxis.set_label_coords(-1.05, .5)
        self.cbpt.ax.yaxis.tick_right()
        self.cbpt.ax.tick_params(axis='y', direction='in')
        self.cbpt.set_label(mtpl.ckdict[self.ellipse_colorby],
                            fontdict={
                                'size': self.font_size,
                                'weight': 'bold'
                            })

        #---------------plotStrikeAngle-----------------------------------
        self.ax2 = self.fig.add_subplot(3, 2, 3)
        az = self.pt.azimuth[0]
        az_err = self.pt.azimuth[1]

        # put the strike into a coordinate system that goes from -90 to 90
        az[np.where(az > 90)] -= 180
        az[np.where(az < -90)] += 180

        stlist = []
        stlabel = []

        # plot phase tensor strike
        ps2 = self.ax2.errorbar(self._mt.period,
                                az,
                                marker=self.strike_pt_marker,
                                ms=self.marker_size,
                                mfc=self.strike_pt_color,
                                mec=self.strike_pt_color,
                                mew=self.marker_lw,
                                ls='none',
                                yerr=az_err,
                                ecolor=self.strike_pt_color,
                                capsize=self.marker_size,
                                elinewidth=self.marker_lw)

        stlist.append(ps2[0])
        stlabel.append('PT')
        try:
            strike = self.zinv.strike
            strikeerr = np.nan_to_num(self.zinv.strike_err)
            # put the strike into a coordinate system that goes from -90 to 90
            strike[np.where(strike > 90)] = strike[np.where(strike > 90)] - 180
            strike[np.where(
                strike < -90)] = strike[np.where(strike < -90)] + 180

            # plot invariant strike
            erxy = self.ax2.errorbar(self._mt.period,
                                     strike,
                                     marker=self.strike_inv_marker,
                                     ms=self.marker_size,
                                     mfc=self.strike_inv_color,
                                     mec=self.strike_inv_color,
                                     mew=self.marker_lw,
                                     ls='none',
                                     yerr=strikeerr,
                                     ecolor=self.strike_inv_color,
                                     capsize=self.marker_size,
                                     elinewidth=self.marker_lw)

            stlist.append(erxy[0])
            stlabel.append('Z_inv')
        except AttributeError:
            print 'Could not get z_invariants from pt, input z if desired.'

        if self._mt.tipper is not None:
            # strike from tipper
            tp = self._mt.Tipper
            s3 = tp.angle_real + 90

            # fold to go from -90 to 90
            s3[np.where(s3 > 90)] = s3[np.where(s3 > 90)] - 180
            s3[np.where(s3 < -90)] = s3[np.where(s3 < -90)] + 180

            # plot strike with error bars
            ps3 = self.ax2.errorbar(self._mt.period,
                                    s3,
                                    marker=self.strike_tp_marker,
                                    ms=self.marker_size,
                                    mfc=self.strike_tp_color,
                                    mec=self.strike_tp_color,
                                    mew=self.marker_lw,
                                    ls='none',
                                    yerr=np.zeros_like(s3),
                                    ecolor=self.strike_tp_color,
                                    capsize=self.marker_size,
                                    elinewidth=self.marker_lw)

            stlist.append(ps3[0])
            stlabel.append('Tipper')

        self.ax2.legend(stlist,
                        stlabel,
                        loc='lower left',
                        markerscale=.5 * self.marker_size,
                        borderaxespad=.01,
                        labelspacing=.1,
                        handletextpad=.2,
                        ncol=len(stlist),
                        borderpad=.1,
                        columnspacing=.1)

        leg = plt.gca().get_legend()
        ltext = leg.get_texts()  # all the text.Text instance in the legend
        plt.setp(ltext, fontsize=6)  # the legend text fontsize

        if self.strike_limits is None:
            self.strike_limits = (-89.99, 89.99)

        self.ax2.set_yscale('linear')
        self.ax2.set_xscale('log', nonposx='clip')
        self.ax2.set_xlim(xmax=10**xlimits[-1], xmin=10**xlimits[0])
        self.ax2.set_ylim(self.strike_limits)
        self.ax2.yaxis.set_major_locator(MultipleLocator(20))
        self.ax2.yaxis.set_minor_locator(MultipleLocator(5))
        self.ax2.grid(True,
                      alpha=.25,
                      which='both',
                      color=(.25, .25, .25),
                      lw=.25)
        self.ax2.set_ylabel('Angle (deg)', fontdict=font_dict)
        self.ax2.set_title('Strike', fontdict=font_dictt)

        #---------plot Min & Max Phase-----------------------------------------
        minphi = self.pt.phimin[0]
        minphierr = self.pt.phimin[1]
        maxphi = self.pt.phimax[0]
        maxphierr = self.pt.phimax[1]

        self.ax3 = self.fig.add_subplot(3, 2, 4, sharex=self.ax2)

        ermin = self.ax3.errorbar(self._mt.period,
                                  minphi,
                                  marker=self.ptmin_marker,
                                  ms=self.marker_size,
                                  mfc='None',
                                  mec=self.ptmin_color,
                                  mew=self.marker_lw,
                                  ls='None',
                                  yerr=minphierr,
                                  ecolor=self.ptmin_color,
                                  capsize=self.marker_size,
                                  elinewidth=self.marker_lw)

        ermax = self.ax3.errorbar(self._mt.period,
                                  maxphi,
                                  marker=self.ptmax_marker,
                                  ms=self.marker_size,
                                  mfc='None',
                                  mec=self.ptmax_color,
                                  mew=self.marker_lw,
                                  ls='None',
                                  yerr=maxphierr,
                                  ecolor=self.ptmax_color,
                                  capsize=self.marker_size,
                                  elinewidth=self.marker_lw)

        if self.pt_limits is None:
            self.pt_limits = [
                min([self.pt.phimax[0].min(), self.pt.phimin[0].min()]) - 3,
                max([self.pt.phimax[0].max(), self.pt.phimin[0].max()]) + 3
            ]
            if self.pt_limits[0] < -10:
                self.pt_limits[0] = -9.9
            if self.pt_limits[1] > 100:
                self.pt_limits[1] = 99.99

        self.ax3.set_xscale('log', nonposx='clip')
        self.ax3.set_yscale('linear')

        self.ax3.legend((ermin[0], ermax[0]), ('$\phi_{min}$', '$\phi_{max}$'),
                        loc='lower left',
                        markerscale=.5 * self.marker_size,
                        borderaxespad=.01,
                        labelspacing=.1,
                        handletextpad=.2,
                        ncol=2,
                        borderpad=.01,
                        columnspacing=.01)

        leg = plt.gca().get_legend()
        ltext = leg.get_texts()  # all the text.Text instance in the legend
        plt.setp(ltext, fontsize=6.5)  # the legend text fontsize

        self.ax3.set_ylim(self.pt_limits)
        self.ax3.grid(True,
                      alpha=.25,
                      which='both',
                      color=(.25, .25, .25),
                      lw=.25)

        self.ax3.set_ylabel('Phase (deg)', fontdict=font_dict)
        self.ax3.set_title('$\mathbf{\phi_{min}}$ and $\mathbf{\phi_{max}}$',
                           fontdict=font_dictt)

        #-----------------------plotSkew---------------------------------------

        skew = self.pt.beta[0]
        skewerr = self.pt.beta[1]

        self.ax4 = self.fig.add_subplot(3, 2, 5, sharex=self.ax2)
        erskew = self.ax4.errorbar(self._mt.period,
                                   skew,
                                   marker=self.skew_marker,
                                   ms=self.marker_size,
                                   mfc='None',
                                   mec=self.skew_color,
                                   mew=self.marker_lw,
                                   ls='None',
                                   yerr=skewerr,
                                   ecolor=self.skew_color,
                                   capsize=self.marker_size,
                                   elinewidth=self.marker_lw)

        # plot lines indicating not 3d
        self.ax4.plot([10**xlimits[0], 10**xlimits[-1]],
                      [self.skew_cutoff, self.skew_cutoff],
                      ls='--',
                      color=self.skew_color,
                      lw=1)

        self.ax4.plot([10**xlimits[0], 10**xlimits[-1]],
                      [-self.skew_cutoff, -self.skew_cutoff],
                      ls='--',
                      color=self.skew_color,
                      lw=1)

        self.ax4.set_xscale('log', nonposx='clip')
        self.ax4.set_yscale('linear')
        self.ax4.yaxis.set_major_locator(MultipleLocator(ckstep))

        if self.skew_limits is None:
            self.skew_limits = (-10, 10)
        self.ax4.set_ylim(self.skew_limits)
        self.ax4.grid(True,
                      alpha=.25,
                      which='both',
                      color=(.25, .25, .25),
                      lw=.25)
        self.ax4.set_xlabel('Period (s)', fontdict=font_dict)
        self.ax4.set_ylabel('Skew Angle (deg)', fontdict=font_dict)
        self.ax4.set_title('Skew Angle', fontdict=font_dictt)

        #----------------------plotEllipticity--------------------------------
        ellipticity = self.pt.ellipticity[0]
        ellipticityerr = self.pt.ellipticity[1]

        self.ax5 = self.fig.add_subplot(3, 2, 6, sharex=self.ax2)
        erskew = self.ax5.errorbar(self._mt.period,
                                   ellipticity,
                                   marker=self.ellip_marker,
                                   ms=self.marker_size,
                                   mfc='None',
                                   mec=self.ellip_color,
                                   mew=self.marker_lw,
                                   ls='None',
                                   yerr=ellipticityerr,
                                   ecolor=self.ellip_color,
                                   capsize=self.marker_size,
                                   elinewidth=self.marker_lw)

        # draw a line where the ellipticity is not 2d
        self.ax5.plot([10**xlimits[0], 10**xlimits[-1]],
                      [self.ellip_cutoff, self.ellip_cutoff],
                      ls='--',
                      color=self.ellip_color,
                      lw=1)

        self.ax5.set_xscale('log', nonposx='clip')
        self.ax5.set_yscale('linear')

        self.ax5.yaxis.set_major_locator(MultipleLocator(.1))

        self.ax5.set_ylim(ymin=0, ymax=1)
        self.ax5.grid(True,
                      alpha=.25,
                      which='both',
                      color=(.25, .25, .25),
                      lw=.25)
        self.ax5.set_xlabel('Period (s)', fontdict=font_dict)
        self.ax5.set_ylabel(
            '$\mathbf{\phi_{max}-\phi_{min}/\phi_{max}+\phi_{min}}$',
            fontdict=font_dict)
        self.ax5.set_title('Ellipticity', fontdict=font_dictt)

        try:
            self.fig.suptitle('Phase Tensor Elements for: ' + self._mt.station,
                              fontdict={
                                  'size': self.font_size + 3,
                                  'weight': 'bold'
                              })
        except:
            self.fig.suptitle('Phase Tensor Elements for Station "unknown"',
                              fontdict={
                                  'size': self.font_size + 3,
                                  'weight': 'bold'
                              })
예제 #8
0
    def plot(self):
        """
        plot residual phase tensor
        """                            
        #get residual phase tensor for plotting        
        self._compute_residual_pt()
        
        #filter data if desired
        if self.med_filt_kernel is not None:
            self._apply_median_filter(kernel=self.med_filt_kernel)
        
        
        #set position properties for the plot
        plt.rcParams['font.size']=self.font_size
        plt.rcParams['figure.subplot.left'] = self.subplot_left
        plt.rcParams['figure.subplot.right'] = self.subplot_right
        plt.rcParams['figure.subplot.bottom'] = self.subplot_bottom
        plt.rcParams['figure.subplot.top'] = self.subplot_top
        plt.rcParams['figure.subplot.wspace'] = self.subplot_wspace
        plt.rcParams['figure.subplot.hspace'] = self.subplot_hspace
        
        #make figure instance
        if self.tscale == 'period':
            titlefreq = '{0:.5g} (s)'.format(1./self.plot_freq)
        else:
            titlefreq='{0:.5g} (Hz)'.format(self.plot_freq)
            
        self.fig = plt.figure(titlefreq,
                              self.fig_size, dpi=self.fig_dpi)
        
        #clear the figure if there is already one up
        plt.clf()
        
        #make an axes instance
        self.ax = self.fig.add_subplot(1, 1, 1, aspect='equal')
        
        #--> plot the background image if desired-----------------------
        try:
            im = plt.imread(self.image_file)
            self.ax.imshow(im, origin='lower', extent=self.image_extent, 
                           aspect='auto')
        except AttributeError:
            pass
        
        #get the reference point
        refpoint = self.plot_reference_point
            
        #set some local parameters
        es = float(self.ellipse_size)
        cmap = self.ellipse_cmap
        ckmin = float(self.ellipse_range[0])
        ckmax = float(self.ellipse_range[1])
        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            if cmap == 'mt_seg_bl2wh2rd':
                raise ValueError('Need to input range as (min, max, step)')
            else:
                ckstep = 3
        nseg = float((ckmax-ckmin)/(2*ckstep))
        ck = self.ellipse_colorby


        #--> set the bounds on the segmented colormap
        if cmap == 'mt_seg_bl2wh2rd':
            bounds = np.arange(ckmin, ckmax+ckstep, ckstep) 
            
        #set tick parameters depending on the mapscale
        if self.mapscale == 'latlon':
            self.tickstrfmt = '%.3f'
            
        elif self.mapscale == 'eastnorth' or self.mapscale == 'eastnorthkm':
            self.tickstrfmt = '%.0f'
        
        #make some empty arrays
        elliplist=[]
        latlist = np.zeros(len(self.residual_pt_list))
        lonlist = np.zeros(len(self.residual_pt_list))
        self.plot_xarr = np.zeros(len(self.residual_pt_list))
        self.plot_yarr = np.zeros(len(self.residual_pt_list))
        
        
        for ii, rpt in enumerate(self.residual_pt_list):
            #try to find the freq in the freq list of each file
            freqfind = [ff for ff, f2 in enumerate(rpt.freq) 
                         if f2 > self.plot_freq*(1-self.ftol) and
                            f2 < self.plot_freq*(1+self.ftol)]
            try:
                self.jj = freqfind[0]
                jj = self.jj
                
                #--> get size of largest ellipse for this frequency for 
                #    normalization to give an indication of the size of 
                #    change.
                emax = self._get_ellipse_size_max(jj)
                
                #if map scale is lat lon set parameters                
                if self.mapscale == 'latlon':
                    latlist[ii] = rpt.lat
                    lonlist[ii] = rpt.lon
                    plotx = rpt.lon-refpoint[0]
                    ploty = rpt.lat-refpoint[1]
                
                #if map scale is in meters easting and northing
                elif self.mapscale == 'eastnorth':
                    zone, east, north = utm2ll.LLtoUTM(23, rpt.lat, rpt.lon)
                    
                    #set the first point read in as a refernce other points                    
                    if ii == 0:
                        zone1 = zone
                        plotx = east-refpoint[0]
                        ploty = north-refpoint[1]
                        
                    #read in all the other point
                    else:
                        #check to make sure the zone is the same this needs
                        #to be more rigorously done
                        if zone1!=zone:
                            print 'Zone change at station '+rpt.station
                            if zone1[0:2] == zone[0:2]:
                                pass
                            elif int(zone1[0:2])<int(zone[0:2]):
                                east += 500000
                            else:
                                east -= -500000
                            latlist[ii] = north-refpoint[1]
                            lonlist[ii] = east-refpoint[0]
                            plotx = east-refpoint[0]
                            ploty = north-refpoint[1]
                        else:
                            latlist[ii] = north-refpoint[1]
                            lonlist[ii] = east-refpoint[0]
                            plotx = east-refpoint[0]
                            ploty = north-refpoint[1]
                
                #if mapscale is in km easting and northing
                elif self.mapscale == 'eastnorthkm':
                    zone,east,north = utm2ll.LLtoUTM(23, rpt.lat, rpt.lon)
                    if ii == 0:
                        zone1 = zone
                        plotx = (east-refpoint[0])/1000.
                        ploty = (north-refpoint[1])/1000.
                    
                    else:
                        if zone1!=zone:
                            print 'Zone change at station '+rpt.station
                            if zone1[0:2] == zone[0:2]:
                                pass
                            elif int(zone1[0:2])<int(zone[0:2]):
                                east += 500000
                            else:
                                east -= 500000
                            latlist[ii] = (north-refpoint[1])/1000.
                            lonlist[ii] = (east-refpoint[0])/1000.
                            plotx = (east-refpoint[0])/1000.
                            ploty = (north-refpoint[1])/1000.
                        else:
                            latlist[ii] = (north-refpoint[1])/1000.
                            lonlist[ii] = (east-refpoint[0])/1000.
                            plotx = (east-refpoint[0])/1000.
                            ploty = (north-refpoint[1])/1000.
                else:
                    raise NameError('mapscale not recognized')
                
                #put the location of each ellipse into an array in x and y
                self.plot_xarr[ii] = plotx
                self.plot_yarr[ii] = ploty
                
                #--> set local variables
                phimin = np.nan_to_num(rpt.residual_pt.phimin[0][jj])
                phimax = np.nan_to_num(rpt.residual_pt.phimax[0][jj])
                eangle = np.nan_to_num(rpt.residual_pt.azimuth[0][jj])
                
                if cmap == 'mt_seg_bl2wh2rd':
                    bounds = np.arange(ckmin, ckmax+ckstep, ckstep)
                    nseg = float((ckmax-ckmin)/(2*ckstep))
        
                #get the properties to color the ellipses by
                if self.ellipse_colorby == 'phiminang' or \
                   self.ellipse_colorby == 'phimin':
                    colorarray = rpt.residual_pt.phimin[0][jj]
            
                                                   
                elif self.ellipse_colorby == 'phidet':
                     colorarray = np.sqrt(abs(rpt.det[0][jj]))*(180/np.pi)
                     
                    
                elif self.ellipse_colorby == 'skew' or\
                     self.ellipse_colorby == 'skew_seg':
                    colorarray = rpt.residual_pt.beta[0][jj]
                    
                elif self.ellipse_colorby == 'ellipticity':
                    colorarray = rpt.residual_pt.ellipticity[0][jj]
                    
                else:
                    raise NameError(self.ellipse_colorby+' is not supported')
                
                #--> get ellipse properties
                #if the ellipse size is not physically correct make it a dot
                if phimax == 0 or phimax>100 or phimin == 0 or phimin>100:
                    eheight=.0000001*es
                    ewidth=.0000001*es
                    print rpt.station
                else:
                    scaling = es/emax
                    eheight = phimin*scaling
                    ewidth = phimax*scaling
                
                #make an ellipse
                ellipd=patches.Ellipse((plotx,ploty),
                                       width=ewidth,
                                       height=eheight,
                                       angle=90-eangle)
                
                #get ellipse color
                if cmap.find('seg')>0:
                    ellipd.set_facecolor(mtcl.get_plot_color(colorarray,
                                                             self.ellipse_colorby,
                                                             cmap,
                                                             ckmin,
                                                             ckmax,
                                                             bounds=bounds))
                else:
                    ellipd.set_facecolor(mtcl.get_plot_color(colorarray,
                                                             self.ellipse_colorby,
                                                             cmap,
                                                             ckmin,
                                                             ckmax))
                
                #==> add ellipse to the plot
                elliplist.append(ellipd)
                self.ax.add_artist(ellipd)
                        
                #------------Plot station name------------------------------
                try:
                    self.ax.text(plotx,
                            ploty+self.station_pad,
                            rpt.station[self.station_id[0]:self.station_id[1]],
                            horizontalalignment='center',
                            verticalalignment='baseline',
                            fontdict=self.station_font_dict)
                except AttributeError:
                    pass
                
            #==> print a message if couldn't find the freq
            except IndexError:
                print 'Did not find {0:.5g} Hz for station {1}'.format(
                                               self.plot_freq, rpt.station)
        
        #--> set axes properties depending on map scale------------------------
        if self.mapscale == 'latlon':    
            self.ax.set_xlabel('longitude',
                               fontsize=self.font_size+2,
                               fontweight='bold')
            self.ax.set_ylabel('latitude',
                               fontsize=self.font_size+2,
                               fontweight='bold')
            
        elif self.mapscale == 'eastnorth':
            self.ax.set_xlabel('Easting (m)',
                               fontsize=self.font_size+2,
                               fontweight='bold')
            self.ax.set_ylabel('Northing (m)',
                               fontsize=self.font_size+2,
                               fontweight='bold')
      
        elif self.mapscale == 'eastnorthkm':
            self.ax.set_xlabel('Easting (km)',
                               fontsize=self.font_size+2,
                               fontweight='bold')
            self.ax.set_ylabel('Northing (km)',
                               fontsize=self.font_size+2,
                               fontweight='bold')

        
        #--> set plot limits
        self.ax.set_xlim(self.plot_xarr.min()-self.xpad,
                             self.plot_xarr.max()+self.xpad)
        self.ax.set_ylim(self.plot_yarr.min()-self.xpad,
                         self.plot_yarr.max()+self.xpad)
                         
        #--> set tick label format
        self.ax.xaxis.set_major_formatter(FormatStrFormatter(self.tickstrfmt))
        self.ax.yaxis.set_major_formatter(FormatStrFormatter(self.tickstrfmt))
        
        #--> set title in period or freq
        if self.tscale == 'period':
            titlefreq = '{0:.5g} (s)'.format(1./self.plot_freq)
        else:
            titlefreq='{0:.5g} (Hz)'.format(self.plot_freq)
        
        if not self.plot_title:
            self.ax.set_title('Phase Tensor Map for '+titlefreq,
                              fontsize=self.font_size+2,fontweight='bold')
        else:
            self.ax.set_title(self.plot_title+titlefreq,
                              fontsize=self.font_size+2,fontweight='bold')
                              
        #make a grid with gray lines
        self.ax.grid(alpha=.25)
        
        #==> make a colorbar with appropriate colors
        if self.cb_position == None:
            self.ax2, kw = mcb.make_axes(self.ax,
                                         orientation=self.cb_orientation,
                                         shrink=.35)
        else:
            self.ax2 = self.fig.add_axes(self.cb_position)
        
        if cmap == 'mt_seg_bl2wh2rd':
            #make a color list
            self.clist = [(cc, cc ,1) 
                         for cc in np.arange(0, 1+1./(nseg), 1./(nseg))]+\
                       [(1, cc, cc) 
                         for cc in np.arange(1, -1./(nseg), -1./(nseg))]
            
            #make segmented colormap
            mt_seg_bl2wh2rd = colors.ListedColormap(self.clist)

            #make bounds so that the middle is white
            bounds = np.arange(ckmin-ckstep, ckmax+2*ckstep, ckstep)
            
            #normalize the colors
            norms = colors.BoundaryNorm(bounds, mt_seg_bl2wh2rd.N)
            
            #make the colorbar
            self.cb=mcb.ColorbarBase(self.ax2,
                                     cmap=mt_seg_bl2wh2rd,
                                     norm=norms,
                                     orientation=self.cb_orientation,
                                     ticks=bounds[1:-1])
        else:
            self.cb=mcb.ColorbarBase(self.ax2,
                                     cmap=mtcl.cmapdict[cmap],
                                     norm=colors.Normalize(vmin=ckmin,
                                                           vmax=ckmax),
                                     orientation=self.cb_orientation)

        #label the color bar accordingly
        self.cb.set_label(mtpl.ckdict[ck],
                          fontdict={'size':self.font_size,'weight':'bold'})
            
        #place the label in the correct location                   
        if self.cb_orientation == 'horizontal':
            self.cb.ax.xaxis.set_label_position('top')
            self.cb.ax.xaxis.set_label_coords(.5, 1.3)
            
            
        elif self.cb_orientation == 'vertical':
            self.cb.ax.yaxis.set_label_position('right')
            self.cb.ax.yaxis.set_label_coords(1.25, .5)
            self.cb.ax.yaxis.tick_left()
            self.cb.ax.tick_params(axis='y', direction='in')
            
        plt.show()
예제 #9
0
    def plot(self):
        """
        plot residual phase tensor
        """
        # get residual phase tensor for plotting
        self._get_plot_freq_data()

        # filter data if desired
        if self.med_filt_kernel is not None:
            self._apply_median_filter()

        # set position properties for the plot
        plt.rcParams["font.size"] = self.font_size
        plt.rcParams["figure.subplot.left"] = self.subplot_left
        plt.rcParams["figure.subplot.right"] = self.subplot_right
        plt.rcParams["figure.subplot.bottom"] = self.subplot_bottom
        plt.rcParams["figure.subplot.top"] = self.subplot_top
        plt.rcParams["figure.subplot.wspace"] = self.subplot_wspace
        plt.rcParams["figure.subplot.hspace"] = self.subplot_hspace

        # make figure instance
        if self.tscale == "period":
            titlefreq = "{0:.5g} (s)".format(1.0 / self.plot_freq)
        else:
            titlefreq = "{0:.5g} (Hz)".format(self.plot_freq)

        self.fig = plt.figure(titlefreq, self.fig_size, dpi=self.fig_dpi)

        # clear the figure if there is already one up
        plt.clf()

        # make an axes instance
        self.ax = self.fig.add_subplot(1, 1, 1, aspect="equal")

        # --> plot the background image if desired-----------------------
        try:
            im = plt.imread(self.image_file)
            self.ax.imshow(im, origin="lower", extent=self.image_extent, aspect="auto")
        except AttributeError:
            pass

        # get the reference point
        refpoint = self.plot_reference_point

        # set some local parameters
        es = float(self.ellipse_size)
        cmap = self.ellipse_cmap
        ckmin = float(self.ellipse_range[0])
        ckmax = float(self.ellipse_range[1])
        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            if cmap == "mt_seg_bl2wh2rd":
                raise ValueError("Need to input range as (min, max, step)")
            else:
                ckstep = 3
        nseg = float((ckmax - ckmin) / (2 * ckstep))
        ck = self.ellipse_colorby

        # --> set the bounds on the segmented colormap
        if cmap == "mt_seg_bl2wh2rd":
            bounds = np.arange(ckmin, ckmax + ckstep, ckstep)
            nseg = float((ckmax - ckmin) / (2 * ckstep))

        # set tick parameters depending on the map_scale
        if self.map_scale == "deg":
            self.tickstrfmt = "%.3f"

        elif self.map_scale == "m" or self.map_scale == "km":
            self.tickstrfmt = "%.0f"

        # make some empty arrays
        elliplist = []
        self.plot_xarr = np.zeros(len(self.plot_data))
        self.plot_yarr = np.zeros(len(self.plot_data))

        # --> get size of largest ellipse for this frequency for
        #    normalization to give an indication of the size of
        #    change.
        emax = self.plot_data[self.ellipse_colorby].max()
        for ii, rpt in enumerate(self.plot_data):
            # if map scale is lat lon set parameters
            if self.map_scale == "deg":
                plotx = rpt["lon"] - refpoint[0]
                ploty = rpt["lat"] - refpoint[1]

            # if map scale is in meters easting and northing
            elif self.map_scale == "m":
                zone, east, north = utm2ll.LLtoUTM(23, rpt["lat"], rpt["lon"])

                # set the first point read in as a refernce other points
                if ii == 0:
                    zone1 = zone
                    plotx = east - refpoint[0]
                    ploty = north - refpoint[1]

                # read in all the other point
                else:
                    # check to make sure the zone is the same this needs
                    # to be more rigorously done
                    if zone1 != zone:
                        print "Zone change at station {0}".format(rpt["station"])
                        if zone1[0:2] == zone[0:2]:
                            pass
                        elif int(zone1[0:2]) < int(zone[0:2]):
                            east += 500000
                        else:
                            east -= -500000
                        plotx = east - refpoint[0]
                        ploty = north - refpoint[1]
                    else:
                        plotx = east - refpoint[0]
                        ploty = north - refpoint[1]

            # if map_scale is in km easting and northing
            elif self.map_scale == "km":
                zone, east, north = utm2ll.LLtoUTM(23, rpt["lat"], rpt["lon"])
                if ii == 0:
                    zone1 = zone
                    plotx = (east - refpoint[0]) / 1000.0
                    ploty = (north - refpoint[1]) / 1000.0

                else:
                    if zone1 != zone:
                        print "Zone change at station {0}".format(rpt["station"])
                        if zone1[0:2] == zone[0:2]:
                            pass
                        elif int(zone1[0:2]) < int(zone[0:2]):
                            east += 500000
                        else:
                            east -= 500000

                        plotx = (east - refpoint[0]) / 1000.0
                        ploty = (north - refpoint[1]) / 1000.0
                    else:
                        plotx = (east - refpoint[0]) / 1000.0
                        ploty = (north - refpoint[1]) / 1000.0

            # put the location of each ellipse into an array in x and y
            self.plot_xarr[ii] = plotx
            self.plot_yarr[ii] = ploty

            # --> get ellipse properties
            # if the ellipse size is not physically correct make it a dot
            if rpt["phimax"] == 0 or rpt["phimax"] > 100 or rpt["phimin"] == 0 or rpt["phimin"] > 100:
                eheight = 0.0000001 * es
                ewidth = 0.0000001 * es
                print "Bad data at {0}".format(rpt["station"])
            else:
                scaling = es / emax
                eheight = rpt["phimin"] * scaling
                ewidth = rpt["phimax"] * scaling

            # make an ellipse
            ellipd = patches.Ellipse((plotx, ploty), width=ewidth, height=eheight, angle=self.rot90 - rpt["azimuth"])

            # get ellipse color
            if cmap.find("seg") > 0:
                ellipd.set_facecolor(
                    mtcl.get_plot_color(
                        rpt[self.ellipse_colorby], self.ellipse_colorby, cmap, ckmin, ckmax, bounds=bounds
                    )
                )
            else:
                ellipd.set_facecolor(
                    mtcl.get_plot_color(rpt[self.ellipse_colorby], self.ellipse_colorby, cmap, ckmin, ckmax)
                )

            # ==> add ellipse to the plot
            elliplist.append(ellipd)
            self.ax.add_artist(ellipd)

            # ------------Plot station name------------------------------
            try:
                self.ax.text(
                    plotx,
                    ploty + self.station_pad,
                    rpt["station"][self.station_id[0] : self.station_id[1]],
                    horizontalalignment="center",
                    verticalalignment="baseline",
                    fontdict=self.station_font_dict,
                )
            except AttributeError:
                pass

        # --> set axes properties depending on map scale------------------------
        if self.map_scale == "deg":
            self.ax.set_xlabel("Longitude", fontsize=self.font_size + 2, fontweight="bold")
            self.ax.set_ylabel("Latitude", fontsize=self.font_size + 2, fontweight="bold")

        elif self.map_scale == "m":
            self.ax.set_xlabel("Easting (m)", fontsize=self.font_size + 2, fontweight="bold")
            self.ax.set_ylabel("Northing (m)", fontsize=self.font_size + 2, fontweight="bold")

        elif self.map_scale == "km":
            self.ax.set_xlabel("Easting (km)", fontsize=self.font_size + 2, fontweight="bold")
            self.ax.set_ylabel("Northing (km)", fontsize=self.font_size + 2, fontweight="bold")

        # --> set plot limits
        self.ax.set_xlim(self.plot_xarr.min() - self.xpad, self.plot_xarr.max() + self.xpad)
        self.ax.set_ylim(self.plot_yarr.min() - self.xpad, self.plot_yarr.max() + self.xpad)

        # --> set tick label format
        self.ax.xaxis.set_major_formatter(FormatStrFormatter(self.tickstrfmt))
        self.ax.yaxis.set_major_formatter(FormatStrFormatter(self.tickstrfmt))

        # --> set title in period or freq
        if self.tscale == "period":
            titlefreq = "{0:.5g} (s)".format(1.0 / self.plot_freq)
        else:
            titlefreq = "{0:.5g} (Hz)".format(self.plot_freq)

        if not self.plot_title:
            self.ax.set_title(
                "Phase Tensor Map for {0}".format(titlefreq), fontsize=self.font_size + 2, fontweight="bold"
            )
        else:
            self.ax.set_title(self.plot_title + titlefreq, fontsize=self.font_size + 2, fontweight="bold")

        # make a grid with gray lines
        self.ax.grid(alpha=0.25)

        # ==> make a colorbar with appropriate colors
        if self.cb_position == None:
            self.ax2, kw = mcb.make_axes(self.ax, orientation=self.cb_orientation, shrink=0.35)
        else:
            self.ax2 = self.fig.add_axes(self.cb_position)

        if cmap == "mt_seg_bl2wh2rd":
            # make a color list
            self.clist = [(cc, cc, 1) for cc in np.arange(0, 1 + 1.0 / (nseg), 1.0 / (nseg))] + [
                (1, cc, cc) for cc in np.arange(1, -1.0 / (nseg), -1.0 / (nseg))
            ]

            # make segmented colormap
            mt_seg_bl2wh2rd = colors.ListedColormap(self.clist)

            # make bounds so that the middle is white
            bounds = np.arange(ckmin - ckstep, ckmax + 2 * ckstep, ckstep)

            # normalize the colors
            norms = colors.BoundaryNorm(bounds, mt_seg_bl2wh2rd.N)

            # make the colorbar
            self.cb = mcb.ColorbarBase(
                self.ax2, cmap=mt_seg_bl2wh2rd, norm=norms, orientation=self.cb_orientation, ticks=bounds[1:-1]
            )
        else:
            self.cb = mcb.ColorbarBase(
                self.ax2,
                cmap=mtcl.cmapdict[cmap],
                norm=colors.Normalize(vmin=ckmin, vmax=ckmax),
                orientation=self.cb_orientation,
            )

        # label the color bar accordingly
        self.cb.set_label(mtpl.ckdict[ck], fontdict={"size": self.font_size, "weight": "bold"})

        # place the label in the correct location
        if self.cb_orientation == "horizontal":
            self.cb.ax.xaxis.set_label_position("top")
            self.cb.ax.xaxis.set_label_coords(0.5, 1.3)

        elif self.cb_orientation == "vertical":
            self.cb.ax.yaxis.set_label_position("right")
            self.cb.ax.yaxis.set_label_coords(1.25, 0.5)
            self.cb.ax.yaxis.tick_left()
            self.cb.ax.tick_params(axis="y", direction="in")

        plt.show()
예제 #10
0
    def plot(self):
        """
        plot residual phase tensor
        """                            
        #get residual phase tensor for plotting        
        self._compute_residual_pt()
        
        #filter data if desired
        if self.med_filt_kernel is not None:
            self._apply_median_filter(kernel=self.med_filt_kernel)
        
        
        #set position properties for the plot
        plt.rcParams['font.size']=self.font_size
        plt.rcParams['figure.subplot.left'] = self.subplot_left
        plt.rcParams['figure.subplot.right'] = self.subplot_right
        plt.rcParams['figure.subplot.bottom'] = self.subplot_bottom
        plt.rcParams['figure.subplot.top'] = self.subplot_top
        plt.rcParams['figure.subplot.wspace'] = self.subplot_wspace
        plt.rcParams['figure.subplot.hspace'] = self.subplot_hspace
        
        #make figure instance
        self.fig = plt.figure(self.fig_num, self.fig_size, dpi=self.fig_dpi)
        
        self.ax = self.fig.add_subplot(1, 1, 1, aspect='equal')
        
        #create empty lists to put things into
        self.stationlist = []
        self.offsetlist = []
        minlist = []
        maxlist = []
        plot_period_list = []
        
        #set local parameters with shorter names
        es = self.ellipse_size
        ck = self.ellipse_colorby
        cmap = self.ellipse_cmap
        ckmin = float(self.ellipse_range[0])
        ckmax = float(self.ellipse_range[1])
        try:
            ckstep = float(self.ellipse_range[2])
        except IndexError:
            ckstep = 3
                
        nseg = float((ckmax-ckmin)/(2*ckstep))

        if cmap == 'mt_seg_bl2wh2rd':
            bounds = np.arange(ckmin, ckmax+ckstep, ckstep)
            
        #get largest ellipse
        emax = self._get_ellipse_size_max()
            
        #plot phase tensor ellipses
        for ii, rpt in enumerate(self.residual_pt_list):
            self.stationlist.append(
                              rpt.station[self.station_id[0]:self.station_id[1]])
            
            #set the an arbitrary origin to compare distance to all other 
            #stations.
            if ii == 0:
                east0 = rpt.lon
                north0 = rpt.lat
                offset = 0.0
            else:
                east = rpt.lon
                north = rpt.lat
                if self.linedir == 'ew': 
                    if east0 < east:
                        offset = np.sqrt((east0-east)**2+(north0-north)**2)
                    elif east0 > east:
                        offset = -1*np.sqrt((east0-east)**2+(north0-north)**2)
                    else:
                        offset = 0
                elif self.linedir == 'ns':
                    if north0 < north:
                        offset = np.sqrt((east0-east)**2+(north0-north)**2)
                    elif north0 > north:
                        offset = -1*np.sqrt((east0-east)**2+(north0-north)**2)
                    else:
                        offset = 0
                        
            self.offsetlist.append(offset)
            
            period_list = 1./rpt.freq[::-1]
            phimax = rpt.residual_pt.phimax[0][::-1]
            phimin = rpt.residual_pt.phimin[0][::-1]
            azimuth = rpt.residual_pt.azimuth[0][::-1]
                
            #get the properties to color the ellipses by
            if self.ellipse_colorby == 'phimin':
                colorarray = rpt.residual_pt.phimin[0][::-1]
                
            elif self.ellipse_colorby == 'phimax':
                colorarray = rpt.residual_pt.phimin[0][::-1]
                
            elif self.ellipse_colorby == 'phidet':
                colorarray = np.sqrt(abs(rpt.residual_pt.det[::-1]))*(180/np.pi)
                
            elif self.ellipse_colorby == 'skew' or\
                 self.ellipse_colorby == 'skew_seg':
                colorarray = rpt.residual_pt.beta[0][::-1]
                
            elif self.ellipse_colorby == 'ellipticity':
                colorarray = rpt.residual_pt.ellipticity[::-1]
                
            else:
                raise NameError(self.ellipse_colorby+' is not supported')
            
            #get the number of periods
            n = len(period_list)
            
            plot_period_list.extend(list(period_list))
            
            #get min and max of the color array for scaling later
            minlist.append(min(colorarray))
            maxlist.append(max(colorarray))

            for jj, ff in enumerate(period_list):
                
                #make sure the ellipses will be visable
                eheight = phimin[jj]/emax*es
                ewidth = phimax[jj]/emax*es
            
                #create an ellipse scaled by phimin and phimax and orient
                #the ellipse so that north is up and east is right
                #need to add 90 to do so instead of subtracting
                if self.rot90 == True:
                    ellipd = patches.Ellipse((offset*self.xstretch,
                                              np.log10(ff)*self.ystretch),
                                                width=ewidth,
                                                height=eheight,
                                                angle=azimuth[jj]-90)
                else:
                    ellipd = patches.Ellipse((offset*self.xstretch,
                                              np.log10(ff)*self.ystretch),
                                                width=ewidth,
                                                height=eheight,
                                                angle=azimuth[jj])
                                            
                #get ellipse color
                if cmap.find('seg')>0:
                    ellipd.set_facecolor(mtcl.get_plot_color(colorarray[jj],
                                                             self.ellipse_colorby,
                                                             cmap,
                                                             ckmin,
                                                             ckmax,
                                                             bounds=bounds))
                else:
                    ellipd.set_facecolor(mtcl.get_plot_color(colorarray[jj],
                                                             self.ellipse_colorby,
                                                             cmap,
                                                             ckmin,
                                                             ckmax))
                    
                # == =add the ellipse to the plot == ========
                self.ax.add_artist(ellipd)
                
                
        #--> Set plot parameters
        plot_period_list = np.array(sorted(list(set(plot_period_list))))
        self._plot_period_list = plot_period_list
        n = len(plot_period_list)
        
        
        #calculate minimum period and maximum period with a stretch factor
        pmin = int(np.floor(np.log10(self._plot_period_list.min())))
        pmax = int(np.ceil(np.log10(self._plot_period_list.max())))
        
        #need to sort the offsets and station labels so they plot correctly
        sdtype = [('offset', np.float), ('station','|S10')]
        slist = np.array([(oo, ss) for oo, ss in zip(self.offsetlist, 
                         self.stationlist)], dtype=sdtype)
        offset_sort = np.sort(slist, order='offset')
     
        self.offsetlist = offset_sort['offset']
        self.stationlist = offset_sort['station']
        
        #set y-ticklabels
        if self.tscale == 'period':
            yticklabels = [mtpl.labeldict[ii] for ii in range(pmin, pmax+1, 1)]
#            yticklabels = ['{0:>4}'.format('{0: .1e}'.format(plot_period_list[ll])) 
#                            for ll in np.arange(0, n, self.ystep)]+\
#                        ['{0:>4}'.format('{0: .1e}'.format(plot_period_list[-1]))]
            
            self.ax.set_ylabel('Period (s)',
                               fontsize=self.font_size+2,
                               fontweight='bold')
                               
        elif self.tscale == 'frequency':
#            yticklabels = ['{0:>4}'.format('{0: .1e}'.format(1./plot_period_list[ll])) 
#                            for ll in np.arange(0, n, self.ystep)]+\
#                            ['{0:>4}'.format('{0: .1e}'.format(1./plot_period_list[-1]))]
#            
            yticklabels = [mtpl.labeldict[-ii] for ii in range(pmin, pmax+1, 1)]
            self.ax.set_ylabel('Frequency (Hz)',
                               fontsize=self.font_size+2,
                               fontweight='bold')
        #set x-axis label                       
        self.ax.set_xlabel('Station',
                           fontsize=self.font_size+2,
                           fontweight='bold')
         
        #--> set tick locations and labels
        #set y-axis major ticks
        self.ax.yaxis.set_ticks(np.arange(pmin*self.ystretch, 
                                          (pmax+1)*self.ystretch, 
                                          self.ystretch))
#        self.ax.yaxis.set_ticks([np.log10(plot_period_list[ll])*self.ystretch 
#                             for ll in np.arange(0, n, self.ystep)])
        
        #set y-axis minor ticks                     
#        self.ax.yaxis.set_ticks([np.log10(plot_period_list[ll])*self.ystretch 
#                             for ll in np.arange(0, n, 1)],minor=True)
        #set y-axis tick labels
        self.ax.set_yticklabels(yticklabels)
        
        #set x-axis ticks
        self.ax.set_xticks(self.offsetlist*self.xstretch)
        
        #set x-axis tick labels as station names
        xticklabels = self.stationlist
        if self.xstep != 1:
            xticklabels = np.zeros(len(self.stationlist), 
                                   dtype=self.stationlist.dtype)
            for xx in range(0,len(self.stationlist),self.xstep):
                xticklabels[xx] = self.stationlist[xx]
        self.ax.set_xticklabels(xticklabels)
        
        #--> set x-limits
        if self.xlimits == None:
            self.ax.set_xlim(self.offsetlist.min()*self.xstretch-es*2,
                             self.offsetlist.max()*self.xstretch+es*2)
        else:
            self.ax.set_xlim(self.xlimits)
            
        #--> set y-limits
        if self.ylimits == None:
            self.ax.set_ylim(pmax*self.ystretch, pmin*self.ystretch)
        else:
            pmin = np.log10(self.ylimits[0])*self.ystretch
            pmax = np.log10(self.ylimits[1])*self.ystretch
            self.ax.set_ylim(pmax, pmin)
            
        #--> set title of the plot
        if self.plot_title == None:
            pass
        else:
            self.ax.set_title(self.plot_title, fontsize=self.font_size+2)
        
        #put a grid on the plot
        self.ax.grid(alpha=.25, which='both', color=(.25, .25, .25))
        
        #print out the min an max of the parameter plotted
        print '-'*25
        print ck+' min = {0:.2f}'.format(min(minlist))
        print ck+' max = {0:.2f}'.format(max(maxlist))
        print '-'*25

        #==> make a colorbar with appropriate colors
        if self.cb_position == None:
            self.ax2, kw = mcb.make_axes(self.ax,
                                         orientation=self.cb_orientation,
                                         shrink=.35)
        else:
            self.ax2 = self.fig.add_axes(self.cb_position)
        
        if cmap == 'mt_seg_bl2wh2rd':
            #make a color list
            self.clist = [(cc, cc, 1) 
                         for cc in np.arange(0, 1+1./(nseg), 1./(nseg))]+\
                        [(1, cc, cc) 
                         for cc in np.arange(1, -1./(nseg), -1./(nseg))]
            
            #make segmented colormap
            mt_seg_bl2wh2rd = colors.ListedColormap(self.clist)

            #make bounds so that the middle is white
            bounds = np.arange(ckmin-ckstep, ckmax+2*ckstep, ckstep)
            
            #normalize the colors
            norms = colors.BoundaryNorm(bounds, mt_seg_bl2wh2rd.N)
            
            #make the colorbar
            self.cb = mcb.ColorbarBase(self.ax2,
                                       cmap=mt_seg_bl2wh2rd,
                                       norm=norms,
                                       orientation=self.cb_orientation,
                                       ticks=bounds[1:-1])
        else:
            self.cb = mcb.ColorbarBase(self.ax2,
                                       cmap=mtcl.cmapdict[cmap],
                                       norm=colors.Normalize(vmin=ckmin,
                                                             vmax=ckmax),
                                       orientation=self.cb_orientation)

        #label the color bar accordingly
        self.cb.set_label(mtpl.ckdict[ck],
                          fontdict={'size':self.font_size,'weight':'bold'})
            
        #place the label in the correct location                   
        if self.cb_orientation == 'horizontal':
            self.cb.ax.xaxis.set_label_position('top')
            self.cb.ax.xaxis.set_label_coords(.5, 1.3)
            
            
        elif self.cb_orientation == 'vertical':
            self.cb.ax.yaxis.set_label_position('right')
            self.cb.ax.yaxis.set_label_coords(1.5, .5)
            self.cb.ax.yaxis.tick_left()
            self.cb.ax.tick_params(axis='y', direction='in')
        
        plt.show()