コード例 #1
0
    def set_samples(self, xyz_input):
        """
        Set the observed data as [N,3] array, x,y, and depth
        """
        # Get the mapping of sample location to dual cell, with
        # potentially multiple samples mapping to the same cell.
        xyz_to_cell = np.zeros(len(xyz_input), np.int32) - 1

        for i, xyz in enumerate(xyz_input):
            if i % 1000 == 0:
                print("%d/%d" % (i, len(xyz_input)))
            # select by cell in the original grid to be sure that
            # samples fall within that "control volume"
            c = self.t_dual.select_cells_nearest(xyz[:2], inside=True)
            if c is not None:
                xyz_to_cell[i] = c

        # make sure we're starting clean
        self.t_net.nodes['value'][:] = np.nan
        # Install the averages onto the values field of the t_net nodes
        for c, hits in utils.enumerate_groups(xyz_to_cell):
            if c not in self.dual_to_net_node:
                continue  # not part of the clipped region
            n = self.dual_to_net_node[c]
            # This could be smarter about locally fitting a surface
            # and get a proper circumcenter value.
            self.t_net.nodes['value'][n] = xyz_input[:, 2][hits].mean()
コード例 #2
0
def recon(xy, k=1000, eps=0.5, interp='rbf'):
    target = [0, xy[0], xy[1]]
    nbr_dists, nbrs = kdt_txy.query(target, k=k)
    nbrs = np.array(nbrs)
    if 0:  # trim to a single, closest sample per track
        nbr_tracks = all_to_track_i[nbrs, 0]
        slim_nbrs = []
        for k, idxs in utils.enumerate_groups(nbr_tracks):
            best = np.argmin(nbr_dists[idxs])
            slim_nbrs.append(nbrs[idxs[best]])
        nbrs = np.array(slim_nbrs)

    nbr_z = xyzs[all_to_track_i[nbrs, 0], 2]
    if interp == 'rbf':
        try:
            rbf = Rbf(all_txy[nbrs, 0],
                      all_txy[nbrs, 1],
                      all_txy[nbrs, 2],
                      nbr_z,
                      epsilon=eps,
                      function='linear')
        except np.linalg.LinAlgError:
            print("Linear algebra error")
            return np.nan

        z_pred = rbf(*target)
    elif interp == 'mlr':
        clf = linear_model.LinearRegression()
        clf.fit(all_txy[nbrs, :], nbr_z)
        z_pred = clf.predict([target])[0]
    elif interp == 'griddata':
        z_pred = scipy.interpolate.griddata(all_txy[nbrs, :],
                                            nbr_z,
                                            target,
                                            rescale=True)
    elif interp == 'krige':
        points = all_txy[nbrs, :]
        values = nbr_z
        gp = GaussianProcess(theta0=0.1, thetaL=.001, thetaU=1., nugget=0.001)
        gp.fit(all_txy[nbrs, :], nbr_z)
        z_pred = gp.predict([target])[0]
    elif interp == 'idw':
        delta = all_txy[nbrs, :] - np.asarray(target)
        delta[:, 0] *= 10  # rescale streamdistance?
        dists = utils.mag(delta)
        weights = (dists + eps)**(-2)
        weights = weights / weights.sum()
        z_pred = (weights * nbr_z).sum()

    return z_pred
コード例 #3
0
def filter_fixes_by_speed(fish,max_speed=5.0):
    # pre-allocate, in case there are indices that
    # have no fixes.
    posns=[ [] ]*fish.dims['index']
    fix_xy=np.c_[ fish.fix_x.values,
                  fish.fix_y.values ]
    for key,grp in utils.enumerate_groups(fish.fix_idx.values):
        posns[key].append(fix_xy[grp])

    for idx in range(fish.dims['index']):
        if len(posns[idx])<2: continue # only filtering out multi-fixes
        
        for pxy in posns[idx]:
            for pxy_previous in posns[idx-1]:
                dist=utils.dist(pxy-pxy_previous)
                dt=HERE - but use YAPS instead
コード例 #4
0
def gen_aggregation_shp(model):
    pnts = model.grid.cells_centroid()

    # make this deterministic
    np.random.seed(37)

    centroids, labels = vq.kmeans2(pnts, k=20, iter=5, minit='points')
    permute = np.argsort(np.random.random(labels.max() + 1))
    # Make a shapefile out of that
    polys = []
    for k, grp in utils.enumerate_groups(labels):
        grp_poly = ops.cascaded_union(
            [model.grid.cell_polygon(i) for i in grp])
        assert grp_poly.type == 'Polygon', "Hmm - add code to deal with multipolygons"
        polys.append(grp_poly)

    agg_shp_fn = "dwaq_aggregation.shp"
    wkb2shp.wkb2shp(agg_shp_fn, polys, overwrite=True)
    return agg_shp_fn
コード例 #5
0
    def disp_array(self):
        hydro = self.hydro
        hydro.infer_2d_elements()
        hydro.infer_2d_links()

        K = np.zeros(self.hydro.n_exch, np.float64)

        Qaccum = np.zeros(hydro.n_2d_links, np.float64)
        Aaccum = np.zeros(hydro.n_2d_links, np.float64)
        accum_count = 0

        for ti in range(self.ti_start, self.ti_stop):
            t_sec = hydro.t_secs[ti]
            flows = [h.flows(t_sec) for h in [self.hydro_tidal, self.hydro]]
            flow_hp = flows[0] - flows[1]
            # depth-integrate
            flow_hor = flow_hp[:self.hydro_tidal.n_exch_x]
            link_flows = np.bincount(hydro.exch_to_2d_link['link'],
                                     hydro.exch_to_2d_link['sgn'] * flow_hor)

            Qaccum += link_flows**2
            Aaccum += np.bincount(hydro.exch_to_2d_link['link'],
                                  hydro.areas(t_sec)[:self.hydro.n_exch_x])
            accum_count += 1
        rms_flows = np.sqrt(Qaccum / accum_count)
        mean_A = Aaccum / accum_count

        Lexch = hydro.exchange_lengths.sum(axis=1)[:hydro.n_exch_x]
        L = [
            Lexch[exchs[0]] for l, exchs in utils.enumerate_groups(
                hydro.exch_to_2d_link['link'])
        ]

        # This is a rough scaling.
        # rms_flows has units of m3/s. normalize
        # by dividing by average flux area, and multiply by the distance
        # between cell centers.
        link_K = self.K_scale * rms_flows * L / mean_A
        K[:self.hydro.n_exch_x] = link_K[self.hydro.exch_to_2d_link['link']]

        log.info("Median dispersion coefficient: %g" % (np.median(K)))
        return K
コード例 #6
0
def match_log_likelihood(next_a,next_b,matches,
                         tnums_a,tnums_b,tags_a,tags_b,
                         verbose=False,
                         max_shift=20.0,max_drift=0.005,max_delta=0.500):
    """
    Estimate the likelihood of a given set of matches being 'correct'
    
    up to next_a and next_b, are possible.
    In the case that constraints are violated, if specific culprits
    can be identified return them as a tuple ( [bad a samples], [bad b samples] )
    otherwise, return False.

    matches: a list of tuples [ (a_idx,b_idx), ... ]
      noting which pings are potentially the same.

    next_a,next_b: index into tnums_a, tnums_b for the next detection
     not yet considered.
    
    tnums_a,tnums_b: timestamps for the pings.
    tags_a,tags_b:  tag ids (numbers, not strings) for the pings.

    max_shift: two clocks can never be more than this many seconds 
    apart, including both shift and drift. This is not 100% enforced,
    but in some cases this condition is used to prune the search.

    max_drift: unitless drift allowed. 0.001 would be a drift of 1ppt,
    such that every 1000 seconds, clock a is allowed to lose or gain 
    1 second relative to clock b.

    max_delta: the limit on how far apart detections can be and still be
    considered the same ping. This should be a generous upper bound on the
    travel time, probably scaled up by a factor of 2 (the sync between two 
    clocks might be driven by a ping from A->B, and then we look at the error
    of a ping B->A, so the expected error is twice the travel time).
    """
    
    # special case -- when nothing matches, at least disallow
    # the search from getting too far ahead on one side or the
    # other. Can't force exact chronological order.
    if len(matches)==0:
        # is a too far ahead of b?
        HERE
        if next_a>0 and next_b<len(tnums_b) and tnums_a[next_a-1]>tnums_b[next_b] + max_shift:
            # we already looked at an a that comes after the next b.
            return ([next_a-1],[next_b])
        if next_b>0 and next_a<len(tnums_a) and tnums_b[next_b-1]>tnums_a[next_a] + max_shift:
            # already looked at a b that comes after the next a
            return ([next_a],[next_b-1])
        # No matches to consider, and next_a and next_b are okay, so carry on.
        return True
    
    amatches=np.asarray(matches)

    # Keep us honest, that the caller didn't try to sneak a bad match in.
    assert np.all( tags_a[amatches[:,0]]==tags_b[amatches[:,1]] )

    # evaluate whether a matched sequence is within tolerance
    a_times=tnums_a[amatches[:,0]]
    b_times=tnums_b[amatches[:,1]]

    if len(a_times)>1:
        mb=np.polyfit(a_times,b_times,1)
        # Be a little smarter about the slope when fitting very short
        # series. 
    else:
        mb=[1.0,b_times[0]-a_times[0]]

    # Rather than treating too large a drift as an error, instead adjust
    # the fit to the max allowable slope, and below we'll see
    # if the max_error becomes too large.  Otherwise fits to short strings of
    # data may misconstrue noise as drift and get an erroneously large drift.
    max_slope=1+max_drift
    min_slope=1./max_slope
    recalc=False
    if mb[0]<min_slope:
        mb[0]=min_slope
        recalc=True
    elif mb[0]>max_slope:
        mb[0]=max_slope
        recalc=True
    if recalc:
        new_b=np.mean(b_times-mb[0]*a_times)
        if verbose:
            print(f"Adjusted slope to be within allowable range, intercept {mb[1]}=>{new_b}")
        mb[1]=new_b

    if verbose:
        print(f"Drift is {1-mb[0]:.4e}")
        print(f"Shift is {np.mean(a_times-b_times):.3f}")
        print("Max error is %.3f"%np.abs(np.polyval(mb,a_times)-b_times).max())
            
    # don't use the intercept -- it's the extrapolated time at tnum epoch.
    if not np.abs(np.mean(a_times-b_times))<max_shift:
        return False # shift is too much

    abs_errors=np.abs(np.polyval(mb,a_times)-b_times)
    if abs_errors.max() >= max_delta:
        bad_match=np.argmax(abs_errors)
        bad_pair=( [matches[bad_match][0]],
                   [matches[bad_match][1]] )
        # print("Abs error too great - bad_pair is ",bad_pair)
        return bad_pair # resulting travel times are too much.

    # to consider: instead of just going through next_a and next_b,
    #  this could go through the later of the adjusted times
    dtype=[('tnum',np.float64),
           ('matched',np.bool8),
           ('tag',np.int32),
           ('src','S1'),
           ('srci',np.int32)]
    a_full=np.zeros(next_a,dtype=dtype)
    b_full=np.zeros(next_b,dtype=dtype)
    
    a_full['tnum']=np.polyval(mb,tnums_a[:next_a])
    b_full['tnum']=tnums_b[:next_b]
    a_full['matched'][amatches[:,0]]=True
    b_full['matched'][amatches[:,1]]=True
    a_full['tag']=tags_a[:next_a]
    b_full['tag']=tags_b[:next_b]
    a_full['src']='a'
    b_full['src']='b'
    a_full['srci']=np.arange(next_a)
    b_full['srci']=np.arange(next_b)

    combined=np.concatenate([a_full,b_full])
    order=np.argsort(combined['tnum'])
    combined=combined[order]

    # This part has to be done per tag
    for tagn,idxs in utils.enumerate_groups(combined['tag']):
        if len(idxs)<2: continue
        deltas=np.diff( combined['tnum'][idxs] )
        matched=np.minimum( combined['matched'][idxs][:-1],
                            combined['matched'][idxs][1:] )

        if verbose:
            if np.any(~matched):
                min_delta=deltas[~matched].min()
            else:
                min_delta=np.nan
            print(f"[%s] %3d total detect. Min delta %.3f vs. interval %.3f for tag %s"%(all_tags[tagn],
                                                                                         len(idxs),
                                                                                         min_delta,
                                                                                         tagn_interval[tagn],
                                                                                         tagn))
        # evaluate all, sort, look at diff(time)
        if np.any(~matched):
            # the 0.8 is some slop. 
            bad=(~matched) & (deltas < 0.8*tagn_interval[tagn])
            bad_a=[]
            bad_b=[]
            
            for bad_idx in np.nonzero(bad)[0]:
                # deltas[bad_idx] is bad
                # That's from idxs[bad_idx],idxs[bad_idx+1]
                for bad_i in [bad_idx,bad_idx+1]:
                    i=idxs[bad_i]
                    if combined['src'][i]==b'a':
                        bad_a.append( combined['srci'][i] )
                    elif combined['src'][i]==b'b':
                        bad_b.append( combined['srci'][i] )
                    else:
                        assert False
                        
            if bad.sum()>0:
                bad_a=list(np.unique(bad_a))
                bad_b=list(np.unique(bad_b))
                # print("Per tag delta is bad.  Pair is ",(bad_a,bad_b))
                return (bad_a,bad_b)
    return True
コード例 #7
0
xyz_input = adcp_xyz.copy()
if src == 'dem':
    # Rather than use the ADCP data directly, during testing
    # use its horizontal distribution, but pull "truth" from the
    # DEM
    xyz_input[:, 2] = dem(xyz_input[:, :2])

if cluster:
    linkage = 'complete'
    n_clusters = 3000
    clustering = AgglomerativeClustering(linkage=linkage,
                                         n_clusters=n_clusters)
    clustering.fit(xyz_input[:, :2])

    group_xyz = np.zeros((n_clusters, 3))
    for grp, members in utils.enumerate_groups(clustering.labels_):
        group_xyz[grp] = xyz_input[members].mean(axis=0)
    xyz_input = group_xyz

##

# This is written out by merge_maps.py, currently just for one timestamp.
ds = xr.open_dataset('merged_map.nc')
g = unstructured_grid.UnstructuredGrid.from_ugrid(ds)

##

if 0:
    iz = InterpZhangDual(g,
                         u=ds.ucxa.values,
                         v=ds.ucya.values,
コード例 #8
0
    xyz_dense[:, 2] = dem(xyz_dense[:, :2])

##
from sklearn.cluster import AgglomerativeClustering

xyzs = xyz_dense.copy()

if cluster:
    linkage = 'complete'
    n_clusters = 3000
    clustering = AgglomerativeClustering(linkage=linkage,
                                         n_clusters=n_clusters)
    clustering.fit(xyzs[:, :2])

    group_xyz = np.zeros((n_clusters, 3))
    for grp, members in utils.enumerate_groups(clustering.labels_):
        group_xyz[grp] = xyzs[members].mean(axis=0)
    xyzs = group_xyz

if quant_xy:
    quant_scale = 1.0  # m

    # There are some repeated values in there, and the RBF is probably
    # poorly conditioned even for closely spaced samples.
    # round all coordinates to 10cm, and remove dupes.
    # go even further, round to 1m but average.
    xyz_quant = xyzs.copy()

    xyz_quant[:, 0] = quant_scale * np.round(xyz_quant[:, 0] / quant_scale)
    xyz_quant[:, 1] = quant_scale * np.round(xyz_dense[:, 1] / quant_scale)
    counts = np.zeros(len(xyz_quant), np.int32)
コード例 #9
0
    def disp_array(self):
        self.hydro.infer_2d_elements()
        self.hydro.infer_2d_links()

        # first calculate all time steps, just in 2D.

        Q = np.zeros((len(self.hydro.t_secs), self.hydro.n_2d_links),
                     np.float64)
        A = np.zeros((len(self.hydro.t_secs), self.hydro.n_2d_links),
                     np.float64)

        for ti in utils.progress(range(len(self.hydro.t_secs))):
            t_sec = self.hydro.t_secs[ti]
            flows = [
                hydro.flows(t_sec) for hydro in [self.hydro_tidal, self.hydro]
            ]
            flow_hp = flows[0] - flows[1]
            # depth-integrate
            flow_hor = flow_hp[:self.hydro_tidal.n_exch_x]
            link_flows = np.bincount(
                self.hydro.exch_to_2d_link['link'],
                self.hydro.exch_to_2d_link['sgn'] * flow_hor)

            Q[ti, :] = link_flows**2
            A[ti, :] = np.bincount(
                self.hydro.exch_to_2d_link['link'],
                self.hydro.areas(t_sec)[:self.hydro.n_exch_x])

        dt_s = np.median(np.diff(self.hydro.t_secs))

        winsize = int(self.lowpass_days * 86400 / dt_s)
        # These are a little slow.  10s?
        # could streamline this some since we later only use a fraction of the values.

        # clip here is because in some cases the values are very low and
        # and some roundoff is creating negatives.
        Qlp = filters.lowpass_fir(Q, winsize=winsize, axis=0).clip(0)
        Alp = filters.lowpass_fir(A, winsize=winsize, axis=0).clip(0)

        rms_flows = np.sqrt(Qlp)
        mean_A = Alp

        Lexch = self.hydro.exchange_lengths.sum(axis=1)[:self.hydro.n_exch_x]
        L = [
            Lexch[exchs[0]] for l, exchs in utils.enumerate_groups(
                self.hydro.exch_to_2d_link['link'])
        ]

        # This is just a placeholder. A proper scaling needs to account for
        # cell size. rms_flows has units of m3/s. probably that should be normalized
        # by dividing by average flux area, and possibly multiplying by the distance
        # between cell centers. that doesn't seem quite right.
        link_K = self.K_scale * rms_flows * L / mean_A

        # this is computed for every time step, but we can trim that down
        # it's lowpassed at winsize.  Try stride of half winsize.
        # That was used for the first round of tests, but it looks a bit
        # sparse.
        K_stride = winsize // 4
        K2D = link_K[::K_stride, :]
        K_t_secs = self.hydro.t_secs[::K_stride]

        if self.amp_factor != 1.0:
            Kbar = K2D.mean(axis=0)
            K2D = (Kbar[None, :] + self.amp_factor *
                   (K2D - Kbar[None, :])).clip(0)

        K = np.zeros((len(K_t_secs), self.hydro.n_exch), np.float64)

        # and then project to 3D
        K[:, :self.hydro.n_exch_x] = K2D[:, self.hydro.exch_to_2d_link['link']]

        if 0:  # DEBUGGING
            # verify that I can get back to the previous, constant in time
            # run.
            log.warning("Debugging K")
            Kconst = super(KautoUnsteady, self).disp_array()
            K[:, :] = Kconst[None, :]

        log.info("Median dispersion coefficient: %g" % (np.median(K)))

        return K_t_secs, K
コード例 #10
0
def test_matches(next_a,next_b,matches,
                 tnums_a,tnums_b,tags_a,tags_b,
                 verbose=False,
                 max_shift=20.0,max_drift=0.005,max_delta=0.500,
                 max_bad_pings=0):
    """
    return True if the matches so far, having considered
    up to next_a and next_b, are possible.

    Search state:
    matches: a list of tuples [ (a_idx,b_idx), ... ]
      noting which pings are potentially the same.

    next_a,next_b: index into tnums_a, tnums_b for the next detection
     not yet considered.
    
    tnums_a,tnums_b: timestamps for the pings.
    tags_a,tags_b:  tag ids (numbers, not strings) for the pings.

    max_shift: two clocks can never be more than this many seconds 
    apart, including both shift and drift. This is not 100% enforced,
    but in some cases this condition is used to prune the search.

    max_drift: unitless drift allowed. 0.001 would be a drift of 1ppt,
    such that every 1000 seconds, clock a is allowed to lose or gain 
    1 second relative to clock b.

    max_delta: the limit on how far apart detections can be and still be
    considered the same ping. This should be a generous upper bound on the
    travel time, probably scaled up by a factor of 2 (the sync between two 
    clocks might be driven by a ping from A->B, and then we look at the error
    of a ping B->A, so the expected error is twice the travel time).


    """
    # special case -- when nothing matches, at least disallow
    # the search from getting too far ahead on one side or the
    # other. Can't force exact chronological order.
    # proceed in raw chronological order
    if len(matches)==0:
        # is a too far ahead of b?
        if next_a>0 and next_b<len(tnums_b) and tnums_a[next_a-1]>tnums_b[next_b] + max_shift:
            # we already looked at an a that comes after the next b.
            return False
        if next_b>0 and next_a<len(tnums_a) and tnums_b[next_b-1]>tnums_a[next_a] + max_shift:
            # already looked at a b that comes after the next a
            return False
        # No matches to consider, and next_a and next_b are okay, so carry on.
        return True
    
    amatches=np.asarray(matches)

    # Keep us honest, that the caller didn't try to sneak a bad match in.
    assert np.all( tags_a[amatches[:,0]]==tags_b[amatches[:,1]] )

    # evaluate whether a matched sequence is within tolerance
    a_times=tnums_a[amatches[:,0]]
    b_times=tnums_b[amatches[:,1]]

    if len(a_times)>1:
        mb=np.polyfit(a_times,b_times,1)
        # Be a little smarter about the slope when fitting very short
        # series. 
    else:
        mb=[1.0,b_times[0]-a_times[0]]

    if 0:
        if not np.abs(np.log10(mb[0]))<np.log10(1+max_drift):
            return False # drift is too much
    else:
        # Rather than treating this as an error, instead adjust
        # the fit to the max allowable slope, and below we'll see
        # if the max_error becomes too large
        max_slope=1+max_drift
        min_slope=1./max_slope
        recalc=False
        if mb[0]<min_slope:
            mb[0]=min_slope
            recalc=True
        elif mb[0]>max_slope:
            mb[0]=max_slope
            recalc=True
        if recalc:
            new_b=np.mean(b_times-mb[0]*a_times)
            if verbose:
                print(f"Adjusted slope to be within allowable range, intercept {mb[1]}=>{new_b}")
            mb[1]=new_b

    if verbose:
        print(f"Drift is {1-mb[0]:.4e}")
        print(f"Shift is {np.mean(a_times-b_times):.3f}")
        print("Max error is %.3f"%np.abs(np.polyval(mb,a_times)-b_times).max())
            
    # don't use the intercept -- it's the extrapolated time at tnum epoch.
    if not np.abs(np.mean(a_times-b_times))<max_shift:
        return False # shift is too much

    max_error=np.abs(np.polyval(mb,a_times)-b_times).max()
    if not max_error < max_delta:
        return False # resulting travel times are too much.

    # to consider: instead of just going through next_a and next_b,
    #  this could go through the later of the adjusted times
    dtype=[('tnum',np.float64),
           ('matched',np.bool8),
           ('tag',np.int32)]
    a_full=np.zeros(next_a,dtype=dtype)
    b_full=np.zeros(next_b,dtype=dtype)
    
    a_full['tnum']=np.polyval(mb,tnums_a[:next_a])
    b_full['tnum']=tnums_b[:next_b]
    a_full['matched'][amatches[:,0]]=True
    b_full['matched'][amatches[:,1]]=True
    a_full['tag']=tags_a[:next_a]
    b_full['tag']=tags_b[:next_b]

    combined=np.concatenate([a_full,b_full])
    order=np.argsort(combined['tnum'])
    combined=combined[order]

    # This part has to be done per tag:
    n_bad=0 # running tally of number of bad pings
    for tagn,idxs in utils.enumerate_groups(combined['tag']):
        if len(idxs)<2: continue
        deltas=np.diff( combined['tnum'][idxs] )
        matched=np.minimum( combined['matched'][idxs][:-1],
                            combined['matched'][idxs][1:] )

        if verbose:
            if np.any(~matched):
                min_delta=deltas[~matched].min()
            else:
                min_delta=np.nan
            print(f"[%s] %3d total detect. Min delta %.3f vs. interval %.3f for tag %s"%(all_tags[tagn],
                                                                                         len(idxs),
                                                                                         min_delta,
                                                                                         tagn_interval[tagn],
                                                                                         tagn))
        # evaluate all, sort, look at diff(time)
        if np.any(~matched):
            n_bad+=(deltas[~matched] < 0.8*tagn_interval[tagn]).sum()
            if n_bad>max_bad_pings:
                # the 0.8 is some slop. 
                return False
            elif (n_bad>0) and verbose:
                print("%d bad pings, but that is allowed"%n_bad)
    return True
コード例 #11
0
ファイル: channel_gem.py プロジェクト: rustychris/part_disp
# Transition matrix

df['b0'] = xy_to_bin(df.loc[:, ['x0', 'y0']].values)
df['bN'] = xy_to_bin(df.loc[:, ['xN', 'yN']].values)

##
M = np.zeros((Nbins - 1, Nbins - 1), np.float64)

for idx, row in df.iterrows():
    M[int(row['b0']), int(row['bN'])] += 1

# normalize those by initial masses
bins0 = np.searchsorted(bins, parts0['x'][:, 0]) - 1
# initial mass in each bin
mass0 = np.array([len(idxs) for _, idxs in utils.enumerate_groups(bins0)])
# first column normalized by first mass, second by second etc.
M[:, :] *= (1. / mass0)[None, :]

##

fig = plt.figure(3)
fig.clf()
fig, ax = plt.subplots(1, 1, num=3)
img = ax.imshow(M)
plt.colorbar(img)

##

# that looks right.
# from here,
コード例 #12
0
##

# Fabricate a really basic aggregation
from scipy.cluster import vq

pnts = model.grid.cells_centroid()

# make this deterministic
np.random.seed(37)

centroids, labels = vq.kmeans2(pnts, k=20, iter=5, minit='points')
permute = np.argsort(np.random.random(labels.max() + 1))
# Make a shapefile out of that
polys = []
for k, grp in utils.enumerate_groups(labels):
    grp_poly = ops.cascaded_union([model.grid.cell_polygon(i) for i in grp])
    assert grp_poly.type == 'Polygon', "Hmm - add code to deal with multipolygons"
    polys.append(grp_poly)

agg_shp_fn = "dwaq_aggregation.shp"
wkb2shp.wkb2shp(agg_shp_fn, polys, overwrite=True)
##

import matplotlib.pyplot as plt
plt.figure(1).clf()
ax = plt.gca()
model.grid.plot_cells(values=permute[labels], ax=ax)
ax.axis('equal')

for poly in polys:
コード例 #13
0
            # enforce ordering of dimensions for safety
            scalar_value=scalar.isel(time=t_idx).transpose('layer','face').values
            volume=volumes.isel(time=t_idx).transpose('layer','face').values

            # need to filter out the -999 values first.
            valid=(scalar_value!=-999)
            num=(scalar_value*volume*valid).sum(axis=0)
            den=(volume*valid).sum(axis=0)

            #empty=(den<=0)
            #num[empty]=0
            #den[empty]=1.0
            #scalar_2d= num/den

            # And aggregate
            for agg_idx,members in utils.enumerate_groups(aggregator.elt_global_to_agg_2d):
                # print(".",end='')
                agg_num=num[members].sum()
                agg_den=den[members].sum()
                if agg_den<=0.0:
                    agg_scalar[t_idx,agg_idx]=0.0
                else:
                    agg_scalar[t_idx,agg_idx] = agg_num/agg_den

        ds=g_agg.write_to_xarray()
        ds['time']=('time',),scalar_map.time.values
        ds['scalar']=('time','face'),agg_scalar
        ds.attrs['name']=scalar_name
        ds.to_netcdf( nc_fn )

    # -with_bc2: the 2 indicates that it has concentrations, too.
コード例 #14
0
                dt=HERE - but use YAPS instead

##

this_fish=cleaned[ cleaned.TagID==fish_tag.lower() ]

##

# when there are two solutions, connect by a segment
# This happens 36 times for 7ADB, out of 155 fixes.

segs=[]
fix_xy=np.c_[ fish3.fix_x.values,
              fish3.fix_y.values ]

for key,grp in utils.enumerate_groups(fish3.fix_idx.values):
    if len(grp)==1: continue
    segs.append( fix_xy[grp,:] )

print(f"{len(segs)} locations have multiple solutions")

##

plt.figure(1).clf()
fig,ax=plt.subplots(1,1,num=1)
scat=ax.scatter(fix_xy[:,0],fix_xy[:,1],12,color='g')
ax.axis('equal')

ax.plot( this_fish.X_UTM, this_fish.Y_UTM, 'k.')

img.plot(ax=ax,zorder=-5)
コード例 #15
0
#   For each of these that is "sufficiently large",
#      pull a tile of low-bay-connected pixels, expand by 1.
#      overlap that with the new feature to get potential connecting pixels.
#      increment those pixels with the area of the connected feature

new_wet = (high_labels == high_bay_label) & (low_labels != low_bay_label)
new_labels, new_n_features = ndimage.label(new_wet)
new_labels_f = new_labels.astype(np.float64)
new_labels_f[~new_wet] = np.nan
new_labeled = field.SimpleGrid(extents=leveed_dem.extents, F=new_labels_f)
new_bay_label = new_labeled(seed_xy)

nrows, ncols = new_labels.shape
new_label_extents = np.zeros((new_n_features + 1, 4), np.int32)

for feat, idxs in utils.enumerate_groups(new_labels.ravel()):
    if feat == 0: continue
    r = idxs // ncols
    c = idxs % ncols
    new_label_extents[feat] = [r.min(), r.max(), c.min(), c.max()]

##

pad = 3
pad_extents = new_label_extents.copy()
pad_extents[:, 0] = np.maximum(0, new_label_extents[:, 0] - pad)
pad_extents[:, 1] = np.minimum(new_labels.shape[0],
                               new_label_extents[:, 1] + pad)
pad_extents[:, 2] = np.maximum(0, new_label_extents[:, 2] - pad)
pad_extents[:, 3] = np.minimum(new_labels.shape[1],
                               new_label_extents[:, 3] + pad)