Esempio n. 1
0
    def dist2WTP_branch5(self, Ttimes):
        """
        calculate the distance to the WTP gate for branch 5
        """

        ## branch 5
        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID=5)

        dist_tem5 = WB.X[1:-1][::-1] * 3.28084  ## unit: ft

        ind5 = next((i for i, x in enumerate(Ttimes[1]) if x), None)
        dist_tem5[:ind5] = 0

        ## branch 1
        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID=1)
        dist_tem1 = WB.X[1:-1][::-1] * 3.28084  ## unit: ft

        dx = dist_tem1[-3] - dist_tem1[-2]

        ind1 = next((i for i, x in enumerate(Ttimes[0]) if x), None)
        dist_tem1[:ind1] = 0

        dist_tem5[ind5:] += dx + dist_tem1[ind1]

        return [dist_tem1, dist_tem5]
Esempio n. 2
0
    def Percentage_branch5(self, Np, Nt, starttime, location_x, x_combined,
                           Ttimes_avg):
        """
        At branch 5
        calculate the particle percentage for each transect at the corresponding travel time
        """

        Ttime_avg1 = Ttimes_avg[0]
        Ttime_avg5 = Ttimes_avg[1]

        #### read segment information for branch 5
        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID=5)

        x_branch5 = WB.X  #### segment x coordinates for branch 5

        #### read segment information for branch 1
        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID=1)

        x_branch1 = WB.X

        percentage5 = np.zeros_like(x_branch5)
        percentage1 = np.zeros_like(x_branch1)

        percentage_combined = np.zeros_like(x_combined)

        Ttime_avg_combined = Ttime_avg5.tolist() + Ttime_avg1.tolist(
        )[self.DHS5 - 1:]

        for ii, tt in enumerate(Ttime_avg_combined):
            tt = int(tt)
            if tt != 0:
                tt += starttime
                seg_id = ii + 2
                #print ('Calculate particle percentage for time step = %s, segment = %d\n'%(str(tt), seg_id))

                icount = 0
                for i in range(location_x.shape[0]):
                    if location_x[i, tt - starttime] >= x_combined[seg_id - 1]:
                        icount += 1
                percentage_combined[seg_id - 1] = float(icount) / Np

        percentage5[1:-1] = percentage_combined[1:len(x_branch5) - 1]
        percentage1[self.DHS5:] = percentage_combined[len(x_branch5) - 1:]

        #pdb.set_trace()
        return [percentage1, percentage5]
Esempio n. 3
0
    def Percentage_branch1(self, Np, Nt, starttime, location_x, Ttime_avg):
        """
        At branch 1
        calculate the particle percentage for each transect at the corresponding travel time
        """

        #### read bathymetry information
        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID=1)

        x_branch1 = WB.X

        ## from Ttime, find the segment index and travel time (time step) info for each
        percentage = np.zeros_like(
            x_branch1)  ## seg ID from 1 to 46 for branch 1

        for ii, tt in enumerate(Ttime_avg):
            tt = int(tt)
            if tt != 0:
                tt += starttime
                seg_id = ii + 2
                #print ('Calculate particle percentage for time step = %s, segment = %d\n'%(str(tt), seg_id))

                icount = 0
                for i in range(location_x.shape[0]):
                    if location_x[i, tt - starttime] >= x_branch1[seg_id - 1]:
                        icount += 1
                percentage[seg_id - 1] = float(icount) / Np

        #pdb.set_trace()
        return percentage
Esempio n. 4
0
    def dist2WTP_branch1(self, Ttime):
        """
        calculate the distance to the WTP gate for branch 1
        """

        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID=1)

        dist_tem = WB.X[1:-1][::-1] * 3.28084  ## unit: ft

        ind = next((i for i, x in enumerate(Ttime) if x), None)

        dist_tem[:ind] = 0

        return dist_tem
Esempio n. 5
0
    def readBathymetry(self):
        """
        read segment and layer info from the bathymetry file
        """
        WB = W2_Bathymetry(self.bathfile)
        WB.readVar()
        WB.readLyr()

        self.seg_length = WB.seg_length  #segment length
        self.seg_ori = WB.seg_ori  # segment orientation
        self.lyr_height = WB.lyr_height  # layer height or each segment

        self.lyrs_branchID = np.asarray(
            [int(float(ID)) for ID in WB.lyrs_branchID])
        self.lyrs_segID = np.asarray([int(float(ID)) for ID in WB.lyrs_segID])
        self.lyrs = WB.lyrs
Esempio n. 6
0
    def AnimateContour(self,
                       varname='Tracer',
                       timestep=0,
                       branchID=1,
                       days=100,
                       PlotGrid=False):
        """
        create animation 
        """
        import matplotlib.animation as animation
        from mpl_toolkits.axes_grid1 import make_axes_locatable

        Writer = animation.writers['ffmpeg']
        writer = Writer(fps=5, metadata=dict(artist='Me'), bitrate=1800)

        self.Readcpl()

        plt.rcParams.update({'font.size': 18})
        fig = plt.figure(figsize=(12.5, 8))
        ax = fig.add_subplot(111)

        if PlotGrid == True:
            from bathymetry import W2_Bathymetry
            filename = '%s\\%s' % (self.workdir, 'Bth_WB1.npt')
            WB = W2_Bathymetry(filename)
            pat = WB.VisBranch2(branchID)

        divider = make_axes_locatable(ax)
        cax = divider.append_axes("right", size="3%", pad=0.05)

        def animate(ii):
            ii += timestep
            ax.clear()
            ## search for index for each branch
            ## algorithm find the distance between two elements in self.X_flow that are large,
            ## this is where the two branches separate
            dist = np.diff(self.X_flow[ii])
            inds = np.where(dist > 1200)[0]
            ## this way is not necessary but clear
            if branchID == 1:
                ind0 = 0
                ind1 = inds[0]
            elif branchID == 2:
                ind0 = inds[0] + 1
                ind1 = inds[1]
            elif branchID == 3:
                ind0 = inds[1] + 1
                ind1 = inds[2]
            elif branchID == 4:
                ind0 = inds[2] + 1
                ind1 = inds[3]
            elif branchID == 5:
                ind0 = inds[3] + 1
                ind1 = len(self.X_flow[ii])

            X_flow = self.X_flow[ii][ind0:ind1 + 1]
            Z_flow = self.Z_flow[ii][ind0:ind1 + 1]
            X_flow = np.asarray(X_flow)
            Z_flow = np.asarray(Z_flow)

            if PlotGrid == True:
                for sq in pat:
                    ax.add_patch(sq)
                ax.autoscale_view()
                ## align each branch with grid
                dx = WB.X.max() - X_flow.max()
                X_flow += dx

            U = self.U[ii][ind0:ind1 + 1]
            W = self.W[ii][ind0:ind1 + 1]
            U = np.asarray(U)
            W = np.asarray(W)
            mask = np.logical_or(U != self.mask_value, W != self.mask_value)

            scale = 1.
            scale = 100. / scale
            Q = ax.quiver(X_flow[mask],
                          Z_flow[mask],
                          np.asarray(U[mask]) * 100.,
                          np.asarray(W[mask]) * 100.,
                          zorder=5,
                          width=0.001,
                          headwidth=4,
                          headlength=4.5,
                          scale=scale,
                          color='r')
            qk = ax.quiverkey(Q,
                              0.15,
                              0.15,
                              1,
                              r'$1 \frac{cm}{s}$',
                              labelpos='W',
                              fontproperties={
                                  'weight': 'bold',
                                  'size': 20
                              })

            var = self.var_output[varname]['value'][ii][ind0:ind1 + 1]
            var = np.asarray(var)

            #### quality control remove some very small values (spikes) ####
            var[(var == self.mask_value) & (var < 1e-15)] = 0

            #var = np.ma.masked_array(var,mask=var==self.mask_value)
            triang = tri.Triangulation(X_flow, Z_flow)
            isbad = np.equal(var, self.mask_value)
            mask = np.any(np.where(isbad[triang.triangles], True, False),
                          axis=1)
            triang.set_mask(mask)

            levels = np.linspace(var.min(), var.max(), 100)
            cmap = plt.set_cmap('bone_r')
            #cs = ax.tricontourf(X_flow, Z_flow, var, cmap=cmap, levels=levels)
            cs = ax.tricontourf(triang, var, cmap=cmap, levels=levels)

            cb = fig.colorbar(cs, cax=cax, orientation='vertical')
            cb.ax.tick_params(labelsize=12)
            cb.ax.yaxis.offsetText.set_fontsize(12)
            #cb.set_label('%s'%self.var_output[varname]['long_name'], fontsize=14)
            cb.set_label('Concentration (mg/L)', fontsize=14)

            timestr = datetime.strftime(self.runtimes[ii], '%Y-%m-%d')
            ax.title.set_text('Time: %s' % timestr)
            ax.set_ylim([135, 160])
            ax.set_xlabel('Distance from upstream (m)')
            ax.set_ylabel('Water Depth (m)')

            return cs, cax

        anim = animation.FuncAnimation(fig,
                                       animate,
                                       frames=days,
                                       interval=600,
                                       blit=False)
        anim.save('%s\\tracer.mp4' % self.workdir, writer=writer)
Esempio n. 7
0
    def VisContour(self,
                   varname='Tracer',
                   timestep=-1,
                   branchID=1,
                   Plotuv=False,
                   PlotGrid=False):
        """
        Create the contour plot of a variable given the variable name
        variable names are provided in cpl.opt
        e.g. 'U', 'W', 'Tracer'
        The python dictionary for variables can be found in vardict.py
        """

        self.Readcpl()

        ## search for index for each branch
        ## algorithm find the distance between two elements in self.X_flow that are large,
        ## this is where the two branches separate
        #dist = np.diff(self.X_flow[0])
        dist = np.diff(self.X_flow[timestep])
        inds = np.where(dist > 1200)[0]

        ## this way is not necessary but clear
        if branchID == 1:
            ind0 = 0
            ind1 = inds[0]
        elif branchID == 2:
            ind0 = inds[0] + 1
            ind1 = inds[1]
        elif branchID == 3:
            ind0 = inds[1] + 1
            ind1 = inds[2]
        elif branchID == 4:
            ind0 = inds[2] + 1
            ind1 = inds[3]
        elif branchID == 5:
            ind0 = inds[3] + 1
            #ind1 = len(self.X_flow[0])
            ind1 = len(self.X_flow[timestep]) - 1

        X_flow = self.X_flow[timestep][ind0:ind1 + 1]
        Z_flow = self.Z_flow[timestep][ind0:ind1 + 1]
        var = self.var_output[varname]['value'][timestep][ind0:ind1 + 1]

        pdb.set_trace()

        ###############   nested list ###############
        def has_list(inlist):
            return any(isinstance(el, list) for el in inlist)

        import collections

        def list_flatten(x):
            if isinstance(x, collections.abc.Iterable):
                return [a for i in x for a in list_flatten(i)]
            else:
                return [x]

        if has_list(X_flow):
            X_flow = list_flatten(X_flow)
        if has_list(Z_flow):
            Z_flow = list_flatten(Z_flow)
        if has_list(var):
            var = list_flatten(var)
        ##############################################
        pdb.set_trace()

        X_flow = np.asarray(X_flow)
        Z_flow = np.asarray(Z_flow)
        var = np.asarray(var)

        #### quality control remove some very small values (spikes) ####
        #var[(var.mask==False)&(var<1e-15)]=0
        var[(var == self.mask_value) & (var < 1e-15)] = 0

        plt.rcParams.update({'font.size': 18})
        fig = plt.figure(figsize=(11.5, 8))
        ax = fig.add_subplot(111)

        if PlotGrid == True:
            from bathymetry import W2_Bathymetry
            filename = '%s\\%s' % (self.workdir, 'Bth_WB1.npt')
            WB = W2_Bathymetry(filename)
            pat = WB.VisBranch2(branchID)
            for sq in pat:
                ax.add_patch(sq)
            ax.autoscale_view()
            ## align each branch with grid
            ## not sure how X is defined in the model
            ## algorithm starting from the end of the branch
            dx = WB.X.max() - X_flow.max()
            X_flow += dx

        if Plotuv:
            #X_flow = np.asarray(X_flow)
            #Z_flow = np.asarray(Z_flow)

            U = self.U[timestep][ind0:ind1 + 1]
            W = self.W[timestep][ind0:ind1 + 1]
            U = np.asarray(U)
            W = np.asarray(W)
            mask = np.logical_or(U != self.mask_value, W != self.mask_value)
            #U = np.ma.masked_array(U,mask=U==self.mask_value)
            #W = np.ma.masked_array(W,mask=W==self.mask_value)

            scale = 1.
            scale = 100. / scale
            Q = ax.quiver(X_flow[mask],
                          Z_flow[mask],
                          np.asarray(U[mask]) * 100.,
                          np.asarray(W[mask]) * 100.,
                          zorder=5,
                          width=0.001,
                          headwidth=4,
                          headlength=4.5,
                          scale=scale,
                          color='r')
            qk = ax.quiverkey(Q,
                              0.15,
                              0.15,
                              1,
                              r'$1 \frac{cm}{s}$',
                              labelpos='W',
                              fontproperties={
                                  'weight': 'bold',
                                  'size': 20
                              })

        #var = np.ma.masked_array(var,mask=var==self.mask_value)
        #### python3 does not allow for masked z values in tricontourf, a way to work around:
        triang = tri.Triangulation(X_flow, Z_flow)
        isbad = np.equal(var, self.mask_value)
        mask = np.any(np.where(isbad[triang.triangles], True, False), axis=1)
        triang.set_mask(mask)
        #pdb.set_trace()
        if var.min() == 0 and var.max() == 0:
            levels = np.linspace(self.var_output[varname]['limits'][0],
                                 self.var_output[varname]['limits'][1], 100)
        elif varname == 'T':
            #levels = np.linspace(23, 27, 100)  ## low WSE
            #levels = np.linspace(16, 21, 100)  ## high WSE
            levels = np.linspace(12, 17, 100)  ## medium WSE
        else:
            levels = np.linspace(var.min(), var.max(), 100)

        cmap = plt.set_cmap('bone_r')
        #cs = ax.tricontourf(X_flow, Z_flow, var, cmap=cmap, levels=levels)
        cs = ax.tricontourf(triang, var, cmap=cmap, levels=levels)
        from mpl_toolkits.axes_grid1 import make_axes_locatable
        divider = make_axes_locatable(ax)
        cax = divider.append_axes("right", size="3%", pad=0.05)
        cb = fig.colorbar(cs, cax=cax, orientation='vertical')
        cb.ax.tick_params(labelsize=12)
        cb.ax.yaxis.offsetText.set_fontsize(12)
        #cb.set_label('%s'%self.var_output[varname]['long_name'], fontsize=14)
        cb.set_label('Concentration (mg/L)', fontsize=14)

        timestr = datetime.strftime(self.runtimes[timestep], '%Y-%m-%d')
        ax.title.set_text('Time: %s' % timestr)
        #ax.set_xlim([0, 60000])
        ax.set_ylim([135, 160])
        ax.set_xlabel('Distance from upstream (m)')
        ax.set_ylabel('Water Depth (m)')
        #ax.yaxis.grid(True)
        #ax.xaxis.grid(True)
        plt.show()
Esempio n. 8
0
    def particle_animation(self,
                           Nt,
                           particle_location,
                           branchID=1,
                           verbose='surface'):
        """
        create animation for 1D particle tracking
        verbose: 'surface' or 'bottom'
        """
        import matplotlib.animation as animation

        Writer = animation.writers['ffmpeg']
        writer = Writer(fps=5, metadata=dict(artist='Me'), bitrate=1800)

        xx = np.arange(particle_location.shape[0]) + 1

        if branchID == 1:
            WB = W2_Bathymetry(self.Bthfile)
            pat = WB.VisBranch2(branchID)

            x_branch = WB.X

        elif branchID == 5:

            WB = W2_Bathymetry(self.Bthfile)
            pat = WB.VisBranch2(branchID)

            x_branch5 = WB.X  #### segment x coordinates for branch 5

            #### read segment information for branch 1
            WB = W2_Bathymetry(self.Bthfile)
            pat = WB.VisBranch2(branchID=1)

            x_branch1 = WB.X

            #### combine the two branch cells
            x_branch = x_branch5.tolist()[0:] + \
                        (x_branch1[self.DHS5-1:] - x_branch1[self.DHS5-1] + x_branch5[-2]).tolist()
            x_branch = np.asarray(x_branch)

        plt.rcParams.update({'font.size': 18})
        fig = plt.figure(figsize=(8, 12.5))
        ax = fig.add_subplot(111)

        def animate(ii):
            ax.clear()
            ### grid segments
            for yc in x_branch:
                ax.axhline(y=yc, color='gray', linestyle='-', linewidth=1)

            #### particle positions
            #for i in range(particle_location.shape[0]):
            cs = ax.plot(xx, particle_location[:, ii], 'ok',
                         markersize=3.5)  ## at 3rd time step

            ax.title.set_text('%s \n Time step = %d' % (verbose, ii))
            ax.set_ylim([-1500, 28500])
            ax.set_ylim(ax.get_ylim()[::-1])
            ax.set_xlabel('Particle ID')
            ax.set_ylabel('Distance from upstream (m)')

            return cs

        anim = animation.FuncAnimation(fig,
                                       animate,
                                       frames=Nt,
                                       interval=600,
                                       blit=False)
        anim.save(r'videos\particle\%s.mp4' % verbose, writer=writer)
Esempio n. 9
0
    def read_velocity(self, Nt, branchID=1):
        """
        read surface and bottom velocities, specific for each branch
        """

        #### read bathymetry information
        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID)

        X_surface = []  ## [time period, x grid points]
        Z_surface = []
        U_surface = []

        X_bottom = []
        Z_bottom = []
        U_bottom = []

        for tstep in range(self.starttime, self.starttime + Nt):

            print('Time step = %s \n' % str(tstep))
            ## search for index for each branch
            ## algorithm find the distance between two elements in self.X_flow that are large,
            ## this is where the two branches separate
            dist = np.diff(self.X_flow[tstep])
            inds = np.where(dist > 1200)[0]

            if branchID == 1:
                ind0 = 0
                ind1 = inds[0]
            elif branchID == 2:
                ind0 = inds[0] + 1
                ind1 = inds[1]
            elif branchID == 3:
                ind0 = inds[1] + 1
                ind1 = inds[2]
            elif branchID == 4:
                ind0 = inds[2] + 1
                ind1 = inds[3]
            elif branchID == 5:
                ind0 = inds[3] + 1
                ind1 = len(self.X_flow[tstep]
                           ) - 1  ## -1 remove the array size mismatch issue

            ## tracer locations
            X_flow = self.X_flow[tstep][ind0:ind1 + 1]
            Z_flow = self.Z_flow[tstep][ind0:ind1 + 1]
            X_flow = np.asarray(X_flow)
            Z_flow = np.asarray(Z_flow)

            ## align coordinates with the grid
            dx = WB.X.max() - X_flow.max()
            X_flow += dx

            ## read velocity
            U = self.U[tstep][ind0:ind1 + 1]
            W = self.W[tstep][ind0:ind1 + 1]
            U = np.asarray(U)
            W = np.asarray(W)

            #### find surface and bottom velocity at tstep
            X_surface_tem, Z_surface_tem, U_surface_tem,    \
            X_bottom_tem,  Z_bottom_tem,  U_bottom_tem  =   \
                            self.surface_bottom_velocity(X_flow, Z_flow, U, W)

            X_surface.append(X_surface_tem)
            Z_surface.append(Z_surface_tem)
            U_surface.append(U_surface_tem)

            X_bottom.append(X_bottom_tem)
            Z_bottom.append(Z_bottom_tem)
            U_bottom.append(U_bottom_tem)

            #pdb.set_trace()
        return X_surface, Z_surface, U_surface, X_bottom, Z_bottom, U_bottom
Esempio n. 10
0
    def particle_tracking_model_1D(self,
                                   Np,
                                   Nt,
                                   InitialSeg,
                                   starttime,
                                   branchID,
                                   flow_condition='high',
                                   dt=1,
                                   transportSurface=True,
                                   transportBottom=True,
                                   travelTime=True):
        """
        particle tracking with velocity 
        Np -- number of particles
        Nt -- particle tracking period (unit: day)
        InitialSeg -- initial spill release segment ID
        dt -- time interval, default 1 day, unit: day
        """

        dt *= 24 * 3600.  #### conversion from day to seconds

        self.starttime = starttime
        self.flow_condition = flow_condition

        #### read surface and bottom velocities
        if branchID == 1:
            self.X_surface, self.Z_surface, self.U_surface, \
            self.X_bottom, self.Z_bottom, self.U_bottom = self.read_velocity(Nt, branchID=1)

            ## contour plot of velocity
            self.plot_velocity(
                self.X_surface,
                self.U_surface,
                figname=r'figures\flow_rate\velocity\surface_branch%d_%s.png' %
                (branchID, flow_condition))  ## surface
            self.plot_velocity(
                self.X_bottom,
                self.U_bottom,
                figname=r'figures\flow_rate\velocity\bottom_branch%d_%s.png' %
                (branchID, flow_condition))  ## surface

        elif branchID == 5:
            X_surface1, Z_surface1, U_surface1, \
            X_bottom1, Z_bottom1, U_bottom1 = self.read_velocity(Nt, branchID=1)
            X_surface5, Z_surface5, U_surface5, \
            X_bottom5, Z_bottom5, U_bottom5 = self.read_velocity(Nt, branchID=5)

            ## contour plot of velocity
            self.plot_velocity(
                X_surface5,
                U_surface5,
                figname=r'figures\flow_rate\velocity\surface_branch%d_%s.png' %
                (branchID, flow_condition))  ## surface
            self.plot_velocity(
                X_bottom5,
                U_bottom5,
                figname=r'figures\flow_rate\velocity\bottom_branch%d_%s.png' %
                (branchID, flow_condition))  ## surface

            #### read bathymetry information
            WB = W2_Bathymetry(self.Bthfile)
            pat = WB.VisBranch2(branchID=1)
            #### adding branch 5 to main branch
            self.X_surface = []
            self.Z_surface = []
            self.U_surface = []

            self.X_bottom = []
            self.Z_bottom = []
            self.U_bottom = []

            for t in range(Nt):

                ## surface
                xind_surface = self.findNearest(WB.X[self.DHS5 - 1],
                                                X_surface1[t][:])
                xtem_surface_branch1 = np.asarray(X_surface1[t][xind_surface:]) - X_surface1[t][xind_surface-1] \
                                + X_surface5[t][-1]
                self.X_surface.append(X_surface5[t] +
                                      xtem_surface_branch1.tolist())
                self.Z_surface.append(Z_surface5[t] +
                                      Z_surface1[t][xind_surface:])
                self.U_surface.append(U_surface5[t] +
                                      U_surface1[t][xind_surface:])

                ## bottom
                xind_bottom = self.findNearest(WB.X[self.DHS5 - 1],
                                               X_bottom1[t][:])
                xtem_bottom_branch1 = np.asarray(X_bottom1[t][xind_bottom:]) - X_bottom1[t][xind_bottom-1] \
                                + X_bottom5[t][-1]
                self.X_bottom.append(X_bottom5[t] +
                                     xtem_bottom_branch1.tolist())
                self.Z_bottom.append(Z_bottom5[t] + Z_bottom1[t][xind_bottom:])
                self.U_bottom.append(U_bottom5[t] + U_bottom1[t][xind_bottom:])

        #### read bathymetry information
        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID)

        #### particle tracking calculation
        if transportSurface:

            #### particle location array
            self.location_x_surface = np.zeros(
                [Np, Nt])  ####[Number of particles, time period]
            self.grid_x_surface = np.zeros(
                [Nt])  #### surface water level at each x grid

            #### initial particle location
            self.location_x_surface[:, 0] = WB.X[InitialSeg - 1]

            #### first order Euler algorithm: x(t+1) = x(t) + U*dt + R*sqrt(6 * Dx *dt)
            for i in range(Np):
                for t in range(Nt - 1):
                    xtem = np.abs(self.X_surface[t] -
                                  self.location_x_surface[i, t])
                    #### check if
                    if xtem.min() < 1000:
                        #### query index
                        ind = np.argwhere(xtem == xtem.min())[0][0]
                        utem = self.U_surface[t][ind]
                        R = random.uniform(
                            0, 2) - 1  ## random number between [-1,1]
                        self.location_x_surface[
                            i, t + 1] = self.location_x_surface[
                                i,
                                t] + utem * dt + R * np.sqrt(6 * self.Dx * dt)
                    elif xtem.min(
                    ) > 1000:  ## there is no close grid point, water dries at this location
                        utem = 0
                        self.location_x_surface[
                            i,
                            t + 1] = self.location_x_surface[i, t] + utem * dt
                    #if t in range(236, 238):
                    ## at these steps, water at the first several cells dries, X_surface starts at 9659, while location_x_surface is 8440.
                    ## so particles do not move at these time steps

            #pdb.set_trace()
            for t in range(Nt):
                self.grid_x_surface[t] = self.Z_surface[t][0]

        if transportBottom:

            #### particle location array
            self.location_x_bottom = np.zeros([Np, Nt])
            self.grid_x_bottom = np.zeros(
                [Nt])  #### bottom water level at each x grid

            #### initial particle location
            self.location_x_bottom[:, 0] = WB.X[InitialSeg - 1]

            #### first order Euler algorithm
            for i in range(Np):
                for t in range(Nt - 1):
                    xtem = np.abs(self.X_bottom[t] -
                                  self.location_x_bottom[i, t])
                    #### check if
                    if xtem.min() < 1000:
                        #### query index
                        ind = np.argwhere(xtem == xtem.min())[0][0]
                        utem = self.U_bottom[t][ind]
                        R = random.uniform(
                            0, 2) - 1  ## random number between [-1,1]
                        self.location_x_bottom[
                            i, t + 1] = self.location_x_bottom[
                                i,
                                t] + utem * dt + R * np.sqrt(6 * self.Dx * dt)
                    elif xtem.min(
                    ) > 1000:  ## there is no close grid point, water dries at this location
                        utem = 0
                        self.location_x_bottom[
                            i,
                            t + 1] = self.location_x_bottom[i, t] + utem * dt

            for t in range(Nt):
                self.grid_x_bottom[t] = self.Z_bottom[t][0]

        ## first entry: Nt or self.period or self-defined depending on how long we need the video to be
        self.particle_animation(self.period,
                                self.location_x_surface,
                                branchID=branchID,
                                verbose='surface_branch%d_%s' %
                                (branchID, flow_condition))
        self.particle_animation(self.period,
                                self.location_x_bottom,
                                branchID=branchID,
                                verbose='bottom_branch%d_%s' %
                                (branchID, flow_condition))

        #        #### For testing only: visualize particle locations
        #        iy = 0
        #        plt.rcParams.update({'font.size': 16})
        #        fig = plt.figure(figsize=(14,10))
        #        ax = fig.add_subplot(211)
        #        for i in range(Np):
        #            ax.plot(self.location_x_surface[i], self.grid_x_surface+iy, 'o')
        #            iy+=5
        #
        #        ax2 = fig.add_subplot(212)
        #        for i in range(Np):
        #            ax2.plot(self.location_x_bottom[i], self.grid_x_bottom-iy, 'o')
        #            iy-=5
        #        plt.show()

        if travelTime and transportSurface:
            self.travel_time(
                Np,
                Nt,
                InitialSeg,
                starttime,
                branchID,
                self.location_x_surface,
                write2shp=False,
                density=0,
                excelfile=r'excel\particle_surface_branch%s_%s.xlsx' %
                (str(branchID), flow_condition))

        if travelTime and transportBottom:
            self.travel_time(
                Np,
                Nt,
                InitialSeg,
                starttime,
                branchID,
                self.location_x_bottom,
                write2shp=False,
                density=1,
                excelfile=r'excel\particle_bottom_branch%s_%s.xlsx' %
                (str(branchID), flow_condition))
Esempio n. 11
0
    def Concentrate(self,
                    starttime,
                    endtime,
                    Ttime,
                    branchID,
                    water_level=True):
        """
        calculate the concentrate at each segment 
        if water_level is True, save the water level data too
        """

        #### read bathymetry information
        WB = W2_Bathymetry(self.Bthfile)
        pat = WB.VisBranch2(branchID)

        ## from Ttime, find the segment index and travel time (time step) info for each
        concentrate = np.zeros_like(WB.X)  ## seg ID from 1 to 46 for branch 1

        elevation = np.zeros_like(WB.X)

        for ii, tt in enumerate(Ttime):
            tt = int(tt)
            if tt != 0:
                tt += starttime
                seg_id = ii + 2
                print(
                    'Calculate concentration for time step = %s, segment = %d\n'
                    % (str(tt), seg_id))

                ## read grid info
                dist = np.diff(self.X_flow[tt])
                inds = np.where(dist > 1200)[0]

                if branchID == 1:
                    ind0 = 0
                    ind1 = inds[0]
                elif branchID == 5:
                    ind0 = inds[3] + 1
                    ind1 = len(
                        self.X_flow[tt]
                    ) - 1  ## -1 remove the array size mismatch issue

                X_flow = self.X_flow[tt][ind0:ind1 + 1]
                Z_flow = self.Z_flow[tt][ind0:ind1 + 1]
                X_flow = np.asarray(X_flow)
                Z_flow = np.asarray(Z_flow)

                ## align coordinates with the grid
                dx = WB.X.max() - X_flow.max()
                X_flow += dx

                ## no concentrate data for particle tracking, concentration is zero instead
                #                ## read tracer data
                #                vartem = np.asarray( self.var_output['Tracer']['value'][tt][ind0:ind1+1] )
                #
                #                #### quality control if X_flow, vartem not in the same shape, resize
                #                if X_flow.shape != vartem.shape:
                #                    #pdb.set_trace()
                #                    Lmin = np.min([X_flow.shape[0], vartem.shape[0]])
                #                    if X_flow.shape[0] > vartem.shape[0]:
                #                        X_flow = np.delete(X_flow, np.arange(Lmin, X_flow.shape[0]))
                #                    elif X_flow.shape[0] < vartem.shape[0]:
                #                        vartem = np.delete(vartem, np.arange(Lmin, vartem.shape[0]))
                #
                #                ## segment location : WB.X[seg_id-1]
                #
                #                ## find index
                #                ## There are two options
                #                ## Option 1: the concentrate at the exact segment
                #                inds = self.find_seg_index_exact(WB.X[seg_id-1], X_flow, vartem)
                #                ## Option 2: the concentrate beyond the segment
                #                #inds_beyond = self.find_seg_index_beyond(WB.X[seg_id-1], X_flow, vartem)
                #
                #                concentrate[seg_id-1] = vartem[inds[0]]

                if water_level:

                    eta = np.asarray(
                        self.var_output['Elevation']['value'][tt][ind0:ind1 +
                                                                  1])

                    if X_flow.shape != eta.shape:
                        Lmin = np.min([X_flow.shape[0], eta.shape[0]])
                        if X_flow.shape[0] > eta.shape[0]:
                            X_flow = np.delete(
                                X_flow, np.arange(Lmin, X_flow.shape[0]))
                        elif X_flow.shape[0] < eta.shape[0]:
                            eta = np.delete(eta, np.arange(Lmin, eta.shape[0]))

                    inds_eta = self.find_seg_index_exact(
                        WB.X[seg_id - 1], X_flow, eta)

                    elevation[seg_id - 1] = eta[inds_eta[0]]

        if water_level:
            return concentrate[1:-1], elevation[1:-1] / 0.3048
Esempio n. 12
0
    def travel_time(self, Np, Nt, InitialSeg, starttime, branchID, location_x,
                    write2shp, density, excelfile):
        """
        calculate travel time based on the particle tracking
        """

        if branchID == 1:

            #### read segment information
            WB = W2_Bathymetry(self.Bthfile)
            pat = WB.VisBranch2(branchID)

            #### create empty array for travel time
            Ttime = np.zeros([Np, WB.X.shape[0]])

            #### calculate travel time
            for i in range(Np):
                for tstep in range(Nt):
                    location_x_tem = location_x[i, tstep]

                    ind = self.Xsearch(location_x_tem, WB.X)

                    if tstep == 0:
                        Ttime[i, InitialSeg - 1:ind + 1] = tstep + 1
                        ind_tem = ind
                    else:
                        ind_nonzero = np.nonzero(Ttime[i, :])[0].max(
                        )  ## only add travel time to zero elements
                        if ind > max(ind_tem, ind_nonzero):
                            Ttime[i,
                                  max(ind_tem + 1, ind_nonzero + 1):ind +
                                  1] = tstep + 1
                            print(Ttime[i, :])
                        ind_tem = ind

            #### calculate the average among particles
            #### be careful about this average among particles
            #Ttime = np.mean(Ttime, axis=0, dtype=np.int)
            #### simply average may yield smaller travel time at the downstream end
            #### because some particle may not travel to the last segment, which has zero travel time there
            #### so only average among non-zero values.
            Ttime_avg = np.zeros([WB.X.shape[0]])
            for i in range(WB.X.shape[0]):
                if i >= InitialSeg - 1:
                    Ttime_avg[i] = np.median(Ttime[:, i][np.nonzero(Ttime[:,
                                                                          i])])

            #pdb.set_trace()
            Ttime_avg = Ttime_avg[1:-1]

            ## calculate concentrate/water_level based on the travel time
            concentrate, water_level = self.Concentrate_branch1(
                Nt, starttime, Ttime_avg)

            ## calculate distance to WTP gate
            dist = self.dist2WTP_branch1(Ttime_avg)

            ## calculate particle percentage
            percentage = self.Percentage_branch1(Np, Nt, starttime, location_x,
                                                 Ttime_avg)

            Ttime_avg[
                Ttime_avg != 0] = Ttime_avg[-1] - Ttime_avg[Ttime_avg != 0]

            #### call segment class for segment information
            WS = W2_Segmentation(self.Bthfile)
            WS.VisSeg2()

            #### save travel time data to txt file ####
            #self.savetxt_Traveltime_branch1(WS, Ttime_avg, density, self.flows[self.flow_condition], txtfile)
            save_excel_Traveltime_branch1(WS, Ttime_avg, density, self.solubility, self.flows[self.flow_condition], \
                                               concentrate, water_level, dist, excelfile)

            if write2shp:
                from myshapefile import writeShpLines_one_branch

                writeShpLines_one_branch(
                    WS,
                    Ttime_avg,
                    shpname='particle_surface_traveltime_branch1')

        if branchID == 5:
            """
            Under development
            """
            #### read segment information for branch 5
            WB = W2_Bathymetry(self.Bthfile)
            pat = WB.VisBranch2(branchID)

            x_branch5 = WB.X  #### segment x coordinates for branch 5

            #### read segment information for branch 1
            WB = W2_Bathymetry(self.Bthfile)
            pat = WB.VisBranch2(branchID=1)

            x_branch1 = WB.X

            #### create empty array for travel time
            #### should not include the inactive cell at the end of branch5 when combining
            #            x_combined = x_branch5.tolist()[0:-1] + \
            #                        (x_branch1[self.DHS5-1:] - x_branch1[self.DHS5-1] + x_branch5[-2]).tolist()
            x_combined = x_branch5.tolist()[0:-1] + \
                        (x_branch1[self.DHS5-1:] - x_branch1[self.DHS5-1] + x_branch5[-2]).tolist()[1:]
            x_combined = np.asarray(x_combined)
            Ttime = np.zeros([Np, x_combined.shape[0]])

            #### calculate travel time
            for i in range(Np):
                for tstep in range(Nt):
                    location_x_tem = location_x[i, tstep]

                    ind = self.Xsearch(location_x_tem, x_combined)

                    if tstep == 0:
                        Ttime[i, InitialSeg - 1:ind + 1] = tstep + 1
                        ind_tem = ind
                    else:
                        ind_nonzero = np.nonzero(Ttime[i, :])[0].max(
                        )  ## only add travel time to zero elements
                        if ind > max(ind_tem, ind_nonzero):
                            Ttime[i,
                                  max(ind_tem + 1, ind_nonzero + 1):ind +
                                  1] = tstep + 1
                            print(Ttime[i, :])
                        ind_tem = ind

            #### separate the travel time to branch 1 segments and branch 5 segments
            Ttime5 = Ttime[:, 0:len(x_branch5[0:-1]) + 1]

            Ttime1 = np.zeros([Np, len(x_branch1)])
            #Ttime1[:, self.DHS5:] = Ttime[:, len(x_branch5[0:-1])+1:]
            Ttime1[:, self.DHS5:-1] = Ttime[:, len(x_branch5[0:-1]) + 1:]

            #pdb.set_trace()
            #### calculate the average among particles
            Ttime_avg1 = np.zeros([Ttime1.shape[1]])
            for i in range(Ttime1.shape[1]):
                if i >= self.DHS5 and len(Ttime1[:, i].nonzero()[0]) != 0:
                    Ttime_avg1[i] = np.median(Ttime1[:,
                                                     i][np.nonzero(Ttime1[:,
                                                                          i])])

            Ttime_avg5 = np.zeros([Ttime5.shape[1]])
            for i in range(Ttime5.shape[1]):
                if i >= InitialSeg - 1:
                    Ttime_avg5[i] = np.median(Ttime5[:,
                                                     i][np.nonzero(Ttime5[:,
                                                                          i])])

            Ttime_avg1 = Ttime_avg1[1:-1]
            Ttime_avg5 = Ttime_avg5[1:-1]

            Ttimes_avg = [Ttime_avg1, Ttime_avg5]

            ## calculate concentrate/water level based on the travel time
            concentrates, water_levels = self.Concentrate_branch5(
                Nt, starttime, Ttimes_avg)

            ## calculate distance to WTP gate
            dists = self.dist2WTP_branch5(Ttimes_avg)

            ## calculate particle percentage
            percentages = self.Percentage_branch5(Np, Nt, starttime,
                                                  location_x, x_combined,
                                                  Ttimes_avg)

            MaxTime = Ttimes_avg[0][-1]
            for Ttime in Ttimes_avg:
                Ttime[Ttime != 0] = MaxTime - Ttime[Ttime != 0]

            #### call segment class for segment information
            WS = W2_Segmentation(self.Bthfile)
            WS.VisSeg2()

            #### save travel time data to txt file ####
            #self.savetxt_Traveltime_branch5(WS, Ttimes_avg, density, self.flows[self.flow_condition], txtfile)
            save_excel_Traveltime_branch5(WS, Ttimes_avg, density, self.solubility, self.flows[self.flow_condition], \
                                          concentrates, water_levels, dists, excelfile)

            if write2shp:
                from myshapefile import writeShpLines

                writeShpLines(WS,
                              Ttimes_avg,
                              shpname='particle_bottom_traveltime_branch5')
 def travel_time(self, starttime=0, endtime=1460, branchID=1):
     """
     calculate the travel time (or median arrival time) for conservative tracers
     timestep - when to calculate the travel time 
     branchID - the travel time of which branch
     """
     print ("Calculate travel time for branch %s ... \n"%str(branchID))
     
     #### read bathymetry information
     WB = W2_Bathymetry(self.Bthfile)
     pat = WB.VisBranch2(branchID)
     
     #### create empty array for travel time
     Ttime = np.zeros_like(WB.X)
     
     #### calculate travel time ####
     #### loop over all time steps ####
     #### starttime to endtime, during which period to search for tracer travel time
     for tstep in range(starttime, endtime): 
         print ('Time step = %s \n'%str(tstep))
         
         ## search for index for each branch 
         ## algorithm find the distance between two elements in self.X_flow that are large, 
         ## this is where the two branches separate
         dist = np.diff(self.X_flow[tstep])
         inds = np.where(dist>1200)[0]
         if branchID == 1:
             ind0 = 0
             ind1 = inds[0]
         elif branchID == 2:
             ind0 = inds[0]+1
             ind1 = inds[1]
         elif branchID == 3:
             ind0 = inds[1]+1
             ind1 = inds[2]
         elif branchID == 4:
             ind0 = inds[2]+1
             ind1 = inds[3]
         elif branchID == 5:
             ind0 = inds[3]+1
             ind1 = len(self.X_flow[tstep]) - 1   ## -1 remove the array size mismatch issue
         
         ## tracer locations
         X_flow = self.X_flow[tstep][ind0:ind1+1]
         Z_flow = self.Z_flow[tstep][ind0:ind1+1]
         X_flow = np.asarray(X_flow)
         Z_flow = np.asarray(Z_flow)
         
         ## align coordinates with the grid
         dx =  WB.X.max() - X_flow.max()
         X_flow += dx
         
         vartem = np.asarray( self.var_output['Tracer']['value'][tstep][ind0:ind1+1] )
         
         #### quality control if X_flow, vartem not in the same shape, resize
         if X_flow.shape != vartem.shape:
             #pdb.set_trace()
             Lmin = np.min([X_flow.shape[0], vartem.shape[0]])
             if X_flow.shape[0] > vartem.shape[0]:
                 X_flow = np.delete(X_flow, np.arange(Lmin, X_flow.shape[0]))
             elif X_flow.shape[0] < vartem.shape[0]:
                 vartem = np.delete(vartem, np.arange(Lmin, vartem.shape[0]))
                 
         
         ## search nonzero X coordinates
         X_nonzero = self.Xsearch(X_flow, Z_flow, vartem)  
         ## search nonzero X index
         ind_nonzero = self.GridSearch(WB.X, X_nonzero, branchID)  ## output is segID
         
         #### if tracer is released at day 385.9 at segment 18, the tracer would travel to segment 22 at day 386
         #### so it is important to record the initial segment in the travel time array
         if tstep == starttime and starttime >= 1:
             #Ttime[np.min(ind_nonzero)-1] = tstep - 1
             if self.initialBranch == 1 and branchID == 1:
                 Ttime[self.initialSeg-1] = tstep - 1
             elif self.initialBranch == 5 and branchID == 5:
                 Ttime[self.initialSeg-85] = tstep - 1
         
         
         if ind_nonzero.size != 0:     #### there is nonzero tracer in the branch
             
             if branchID in [1,5]:
                 
                 ind_max = np.max(ind_nonzero)
                 ## add the travel time to the pre-defined 1D array
                 if Ttime[ind_max] == 0:
                     if len(Ttime.nonzero()[0]) != 0:
                         ind_tem = np.where(Ttime==Ttime.max())[0][-1]
                         Ttime[ind_tem+1: ind_max] = tstep
                     else:
                         Ttime[ind_max] = tstep
                         
                         
             elif branchID in [2,3,4]:
                 if len(Ttime.nonzero()[0])==0 and len(ind_nonzero) == 1:
                     Ttime[ind_nonzero[0]] = tstep
                 else:
                     ind_min = np.min(ind_nonzero)
                     ## add the travel time to the pre-defined 1D array
                     if Ttime[ind_min] == 0:
                         if len(Ttime.nonzero()[0]) != 0:
                             ind_tem = np.where(Ttime==Ttime.max())[0][0]
                             Ttime[ind_min:ind_tem] = tstep
                         else:
                             Ttime[ind_min] = tstep
         
         print (Ttime)
         #pdb.set_trace()
         
     if branchID in [1, 5]:
         Ttime[-2] = Ttime[-3] + 1
     
     return Ttime
Esempio n. 14
0
    def travel_time(self, endtime=1460, branchID=1):
        """
        calculate the travel time (or earliest arrival time) for conservative tracers
        timestep - when to calculate the travel time 
        branchID - the travel time of which branch
        """
        print "Calculate travel time for branch %s ... \n" % str(branchID)

        #### read bathymetry information
        Bthfile = '%s\\%s' % (self.workdir, 'Bth_WB1.npt')
        WB = W2_Bathymetry(Bthfile)
        pat = WB.VisBranch2(branchID)

        #### create empty array for travel time
        Ttime = np.zeros_like(WB.X)

        #### calculate travel time ####
        #### loop over all time steps ####
        for tstep in range(endtime):
            print 'Time step = %s \n' % str(tstep)

            ## search for index for each branch
            ## algorithm find the distance between two elements in self.X_flow that are large,
            ## this is where the two branches separate
            dist = np.diff(self.X_flow[tstep])
            inds = np.where(dist > 1200)[0]
            if branchID == 1:
                ind0 = 0
                ind1 = inds[0]
            elif branchID == 2:
                ind0 = inds[0] + 1
                ind1 = inds[1]
            elif branchID == 3:
                ind0 = inds[1] + 1
                ind1 = inds[2]
            elif branchID == 4:
                ind0 = inds[2] + 1
                ind1 = inds[3]
            elif branchID == 5:
                ind0 = inds[3] + 1
                ind1 = len(self.X_flow[tstep]
                           ) - 1  ## -1 remove the array size mismatch issue

            ## tracer locations
            X_flow = self.X_flow[tstep][ind0:ind1 + 1]
            Z_flow = self.Z_flow[tstep][ind0:ind1 + 1]
            X_flow = np.asarray(X_flow)
            Z_flow = np.asarray(Z_flow)

            ## align coordinates with the grid
            dx = WB.X.max() - X_flow.max()
            X_flow += dx

            vartem = np.asarray(
                self.var_output['Tracer']['value'][tstep][ind0:ind1 + 1])

            #### quality control if X_flow, vartem not in the same shape, resize
            if X_flow.shape != vartem.shape:
                #pdb.set_trace()
                Lmin = np.min([X_flow.shape[0], vartem.shape[0]])
                if X_flow.shape[0] > vartem.shape[0]:
                    X_flow = np.delete(X_flow,
                                       np.arange(Lmin, X_flow.shape[0]))
                elif X_flow.shape[0] < vartem.shape[0]:
                    vartem = np.delete(vartem,
                                       np.arange(Lmin, vartem.shape[0]))

            ## search nonzero X coordinates
            X_nonzero = self.Xsearch(X_flow, Z_flow, vartem)
            ## search nonzero X index
            ind_nonzero = self.GridSearch(WB.X, X_nonzero, branchID)

            if ind_nonzero.size != 0:  #### there is nonzero tracer in the branch

                if branchID == 1:
                    ind_max = np.max(ind_nonzero)
                    ## add the travel time to the pre-defined 1D array
                    if Ttime[ind_max] == 0:
                        if len(Ttime.nonzero()[0]) != 0:
                            ind_tem = np.where(Ttime == Ttime.max())[0][-1]
                            Ttime[ind_tem + 1:ind_max] = tstep
                        else:
                            Ttime[ind_max] = tstep
                elif branchID in [2, 3, 4, 5]:
                    if len(Ttime.nonzero()[0]) == 0 and len(ind_nonzero) == 1:
                        Ttime[ind_nonzero[0]] = tstep
                    else:
                        ind_min = np.min(ind_nonzero)
                        ## add the travel time to the pre-defined 1D array
                        if Ttime[ind_min] == 0:
                            if len(Ttime.nonzero()[0]) != 0:
                                ind_tem = np.where(Ttime == Ttime.max())[0][0]
                                Ttime[ind_min:ind_tem] = tstep
                            else:
                                Ttime[ind_min] = tstep
            print Ttime
            #pdb.set_trace()

        if branchID == 1:
            Ttime[-2] = Ttime[-3] + 1

        return Ttime
Esempio n. 15
0
    def VisParticles(self,
                     timestep=-1,
                     branchID=1,
                     PlotFlow=True,
                     PlotTemp=True,
                     PlotGrid=True):
        """
        visualize the particle trajectories at a given time step
        set PlotTemp == False for now, need to figure out how to contour plot 1D array
        """
        self.ReadParticles(branchID)

        X = self.X[timestep]
        Z = self.Z[timestep]

        if PlotFlow == True or PlotTemp == True:
            self.ReadBackground(branchID)
            X_flow = self.X_flow[timestep]
            Z_flow = self.Z_flow[timestep]

        plt.rcParams.update({'font.size': 18})
        fig = plt.figure(figsize=(11.5, 8))
        ax = fig.add_subplot(111)
        ax.plot(X, Z, '.', color='r')
        if PlotFlow == True:
            U = self.U[timestep]
            W = self.W[timestep]

            ## mask data
            X_flow = np.asarray(X_flow)
            Z_flow = np.asarray(Z_flow)
            U = np.asarray(U)
            W = np.asarray(W)
            maskuv = np.logical_or(U != 0, W != 0)

            scale = 1.
            scale = 100. / scale
            Q = ax.quiver(X_flow[maskuv],
                          Z_flow[maskuv],
                          U[maskuv] * 100.,
                          W[maskuv] * 100.,
                          zorder=5,
                          width=0.001,
                          headwidth=4,
                          headlength=4.5,
                          scale=scale,
                          color='b')
            qk = ax.quiverkey(Q,
                              0.15,
                              0.15,
                              1,
                              r'$1 \frac{cm}{s}$',
                              labelpos='W',
                              fontproperties={
                                  'weight': 'bold',
                                  'size': 20
                              })

        if PlotTemp == True:
            import matplotlib.tri as tri
            #from scipy.interpolate import griddata
            T = self.T[timestep]
            U = np.asarray(self.U[timestep])
            W = np.asarray(self.W[timestep])

            ## mask data
            X_flow = np.asarray(X_flow)
            Z_flow = np.asarray(Z_flow)
            T = np.asarray(T)

            triang = tri.Triangulation(X_flow, Z_flow)
            isbad = np.less_equal(np.asarray(self.T[0]), 0)
            #isbad = np.equal(U, 0) & np.equal(W, 0)
            mask = np.any(np.where(isbad[triang.triangles], True, False),
                          axis=1)
            triang.set_mask(mask)

            #T[T==0] = self.mask_value
            #T = np.ma.masked_array(T,mask=T==self.mask_value)

            #T_limits = [0,35]
            T_limits = [T.min(), T.max()]
            levels = np.linspace(T_limits[0], T_limits[1], 100)
            cs = ax.tricontourf(triang, T, cmap=plt.cm.bone, levels=levels)
            #cs = ax.tricontourf(X_flow, Z_flow, T, cmap=plt.cm.bone, levels=levels)

            from mpl_toolkits.axes_grid1 import make_axes_locatable
            divider = make_axes_locatable(ax)
            cax = divider.append_axes("right", size="3%", pad=0.05)
            cb = fig.colorbar(cs, cax=cax, orientation='vertical')
            cb.ax.tick_params(labelsize=12)
            cb.ax.yaxis.offsetText.set_fontsize(12)
            cb.set_label('Temperature', fontsize=14)

        if PlotGrid == True:
            from bathymetry import W2_Bathymetry
            filename = '%s\\%s' % (self.workdir, 'Bth_WB1.npt')
            WB = W2_Bathymetry(filename)
            pat = WB.VisBranch2(branchID)
            for sq in pat:
                ax.add_patch(sq)
            ax.autoscale_view()

        timestr = datetime.strftime(self.runtimes[timestep], '%Y-%m-%d')
        ax.title.set_text('Time: %s' % timestr)
        #ax.set_xlim([4000, 12000])
        #ax.set_ylim([135, 150])
        ax.set_ylim([135, 160])
        ax.set_xlabel('Distance from upstream (m)')
        ax.set_ylabel('Water Depth (m)')
        #ax.yaxis.grid(True)
        #ax.xaxis.grid(True)
        #plt.show()
        #plt.savefig('particle_tracks_%s.png'%str(timestep))
        #plt.savefig('%s\\particle_tracks_%s.png'%(self.workdir, str(timestep)))
        #plt.close()
        plt.show()