コード例 #1
0
def natgrid_interp(data_in, lats_in, lons_in, lats_out, lons_out, valid_range=None, wrapping_overlap_interval=10.):
    IM_i = len(lons_in)
    JM_i = len(lats_in)
    IM_o = len(lons_out)
    JM_o = len(lats_out)
    lons_in_interval1 = np.zeros(IM_i)
    lons_in_interval2 = np.zeros(IM_i)
    lons_out_interval1 = np.zeros(IM_o)
    lons_out_interval2 = np.zeros(IM_o)
    for i in range(IM_i):
        lons_in_interval1[i] = Ngl.normalize_angle(lons_in[i], 0)
        lons_in_interval2[i] = Ngl.normalize_angle(lons_in[i], 1)
    for i in range(IM_o):
        lons_out_interval1[i] = Ngl.normalize_angle(lons_out[i], 0)
    if valid_range == None:
        valid_range = [data_in.min(), data_in.max()]
    x_in_interval1 = np.tile(lons_in_interval1,JM_i)
    y_in = np.repeat(lats_in, IM_i)
    z_in = data_in.flatten()
    if lons_in_interval1.max() - lons_in_interval1.min() > 180. and lons_in_interval2.max() - lons_in_interval2.min() > 180.:
        wrap = True
        ## span of lons is greater than 180; assume that it is a global run and therefore needs to be wrapped
        logical_wrapping = np.logical_and(lons_in_interval2[:] > -wrapping_overlap_interval, lons_in_interval2[:] < 0.)
        lons_wrapped = lons_in_interval2[logical_wrapping]
        data_in_wrapped = data_in[:,logical_wrapping]
        IM_wrapped = len(lons_wrapped)
        lons_wrapped_vector = np.tile(lons_wrapped,JM_i)
        lats_wrapped_vector = np.repeat(lats_in, IM_wrapped)
        data_in_wrapped_vector = data_in_wrapped.flatten()
        ### and add them together
        x_in_interval1 = np.concatenate((x_in_interval1, lons_wrapped_vector))
        y_in = np.concatenate((y_in, lats_wrapped_vector))
        z_in = np.concatenate((z_in, data_in_wrapped_vector))
        #
        logical_wrapping = np.logical_and(lons_in_interval2[:] < wrapping_overlap_interval, lons_in_interval2[:] > 0.)
        lons_wrapped = lons_in_interval1[logical_wrapping] + 360.
        data_in_wrapped = data_in[:,logical_wrapping]
        IM_wrapped = len(lons_wrapped)
        lons_wrapped_vector = np.tile(lons_wrapped,JM_i)
        lats_wrapped_vector = np.repeat(lats_in, IM_wrapped)
        data_in_wrapped_vector = data_in_wrapped.flatten()
        ### and add them together
        x_in_interval1 = np.concatenate((x_in_interval1, lons_wrapped_vector))
        y_in = np.concatenate((y_in, lats_wrapped_vector))
        z_in = np.concatenate((z_in, data_in_wrapped_vector))
        # ### reorder output lons
        # lons_out_interval1_unsorted = lons_out_interval1
        # lons_out_interval1 = lons_out_interval1[lons_out_interval1.argsort()]
    output1 = Ngl.natgrid(x_in_interval1, y_in, z_in, lons_out_interval1, lats_out).transpose()
    output_masked = np.ma.masked_array(output1, mask=np.logical_or(output1 < min(valid_range), output1 > max(valid_range)))
    return(output_masked)
コード例 #2
0
def bilinear_interp(data_in, lats_in, lons_in, lats_out, lons_out):
    IM_i = len(lons_in)
    JM_i = len(lats_in)
    IM_o = len(lons_out)
    JM_o = len(lats_out)
    #
    #
    ## find four points from old grid that surround each point on new grid
    J_index_below = np.zeros(JM_o, dtype=np.int)
    J_index_above = np.zeros(JM_o, dtype=np.int)
    for j in range(JM_o):
        J_index_below[j] = np.sum(lats_in[:] <= lats_out[j]) - 1
        J_index_above[j] = JM_i - max(np.sum(lats_in[:] >= lats_out[j]), 1)
    #
    I_index_below = np.zeros(IM_o, dtype=np.int)
    I_index_above = np.zeros(IM_o, dtype=np.int)
    for i in range(IM_o):
        found = False
        for ii in range(IM_i):
            if not found:
                if Ngl.normalize_angle(lons_in[ii],0) == Ngl.normalize_angle(lons_out[i],0):
                    I_index_below[i] = ii
                    I_index_above[i] = ii
                    found = True
        for ii in range(IM_i-1):
            if not found:      
                if Ngl.normalize_angle(lons_in[ii],0) < Ngl.normalize_angle(lons_out[i],0) and Ngl.normalize_angle(lons_in[ii+1],0) > Ngl.normalize_angle(lons_out[i],0):
                    I_index_below[i] = ii
                    I_index_above[i] = ii+1
                    found = True
                elif Ngl.normalize_angle(lons_in[ii],1) < Ngl.normalize_angle(lons_out[i],1) and Ngl.normalize_angle(lons_in[ii+1],1) > Ngl.normalize_angle(lons_out[i],1):
                    I_index_below[i] = ii
                    I_index_above[i] = ii+1
                    found = True
        if not found:
            if Ngl.normalize_angle(lons_in[IM_i-1],1) < Ngl.normalize_angle(lons_out[i],1) and Ngl.normalize_angle(lons_in[0],1) > Ngl.normalize_angle(lons_out[i],1):
                    I_index_below[i] = IM_i-1
                    I_index_above[i] = 0
                    found = True
            elif Ngl.normalize_angle(lons_in[IM_i-1],0) < Ngl.normalize_angle(lons_out[i],0) and Ngl.normalize_angle(lons_in[0],0) > Ngl.normalize_angle(lons_out[i],0):
                    I_index_below[i] = IM_i-1
                    I_index_above[i] = 0
                    found = True
        if not found:
            raise RuntimeError
    #
    # print(J_index_below)
    # print(J_index_above)

    # print(I_index_below)
    # print(I_index_above)
    #
    #
    if type(data_in) == np.ma.masked_array:
        masked_in = True
        data_out = np.ma.masked_all([JM_o,IM_o])
    else:
        masked_in = False
        data_out = np.zeros([JM_o,IM_o])
    #
    #
    ### now loop to do the interpolation
    if masked_in:
        for i in range(IM_o):
            for j in range(JM_o):
                if I_index_below[i] != I_index_above[i] and J_index_below[j] != J_index_above[j]:
                    weights = np.ma.masked_all([4])
                    values = np.ma.masked_all([4])
                    weights[0] = absdeltalon(lons_in[I_index_below[i]], lons_out[i]) * abs(lats_in[J_index_below[j]] - lats_out[j])
                    weights[1] = absdeltalon(lons_in[I_index_above[i]], lons_out[i]) * abs(lats_in[J_index_below[j]] - lats_out[j])
                    weights[2] = absdeltalon(lons_in[I_index_below[i]], lons_out[i]) * abs(lats_in[J_index_above[j]] - lats_out[j])
                    weights[3] = absdeltalon(lons_in[I_index_above[i]], lons_out[i]) * abs(lats_in[J_index_above[j]] - lats_out[j])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_below[j], I_index_above[i]]
                    values[2] = data_in[J_index_above[j], I_index_below[i]]
                    values[3] = data_in[J_index_above[j], I_index_above[i]]
                    weights.mask = values.mask
                    data_out[j,i] = np.sum(weights * values) / np.sum(weights)
                elif I_index_below[i] == I_index_above[i] and J_index_below[j] != J_index_above[j]:
                    weights = np.ma.masked_all([2])
                    values = np.ma.masked_all([2])
                    weights[0] =  abs(lats_in[J_index_below[j]] - lats_out[j])
                    weights[1] =  abs(lats_in[J_index_above[j]] - lats_out[j])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_above[j], I_index_above[i]]
                    weights.mask = values.mask
                    data_out[j,i] = np.sum(weights * values) / np.sum(weights)
                elif J_index_below[j] == J_index_above[j] and I_index_below[i] != I_index_above[i]:
                    weights = np.ma.masked_all([2])
                    values = np.ma.masked_all([2])
                    weights[0] = absdeltalon(lons_in[I_index_below[i]], lons_out[i])
                    weights[1] = absdeltalon(lons_in[I_index_above[i]], lons_out[i])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_above[j], I_index_above[i]]
                    weights.mask = values.mask
                    data_out[j,i] = np.sum(weights * values) / np.sum(weights)
                else:
                    data_out[j,i] = data_in[J_index_below[j], I_index_below[i]]
    else:
        for i in range(IM_o):
            for j in range(JM_o):
                if I_index_below[i] != I_index_above[i] and J_index_below[j] != J_index_above[j]:
                    weights = np.zeros([4])
                    values = np.zeros([4])
                    weights[0] = absdeltalon(lons_in[I_index_below[i]], lons_out[i]) * abs(lats_in[J_index_below[j]] - lats_out[j])
                    weights[1] = absdeltalon(lons_in[I_index_above[i]], lons_out[i]) * abs(lats_in[J_index_below[j]] - lats_out[j])
                    weights[2] = absdeltalon(lons_in[I_index_below[i]], lons_out[i]) * abs(lats_in[J_index_above[j]] - lats_out[j])
                    weights[3] = absdeltalon(lons_in[I_index_above[i]], lons_out[i]) * abs(lats_in[J_index_above[j]] - lats_out[j])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_below[j], I_index_above[i]]
                    values[2] = data_in[J_index_above[j], I_index_below[i]]
                    values[3] = data_in[J_index_above[j], I_index_above[i]]
                    data_out[j,i] = np.sum(weights * values) / np.sum(weights)
                elif I_index_below[i] == I_index_above[i] and J_index_below[j] != J_index_above[j]:
                    weights = np.zeros([2])
                    values = np.zeros([2])
                    weights[0] =  abs(lats_in[J_index_below[j]] - lats_out[j])
                    weights[1] =  abs(lats_in[J_index_above[j]] - lats_out[j])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_above[j], I_index_above[i]]
                    data_out[j,i] = np.sum(weights * values) / np.sum(weights)
                elif J_index_below[j] == J_index_above[j] and I_index_below[i] != I_index_above[i]:
                    weights = np.zeros([2])
                    values = np.zeros([2])
                    weights[0] = absdeltalon(lons_in[I_index_below[i]], lons_out[i])
                    weights[1] = absdeltalon(lons_in[I_index_above[i]], lons_out[i])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_above[j], I_index_above[i]]
                    data_out[j,i] = np.sum(weights * values) / np.sum(weights)
                else:
                    data_out[j,i] = data_in[J_index_below[j], I_index_below[i]]
    #
    #
    return(data_out)
コード例 #3
0
def conservative_regrid(data_in, lats_in, lons_in, lats_out, lons_out, centers_out=True, weights_in=None, spherical=True, radius=6372000., dilute_w_masked_data=True, return_frac_input_masked=False):
    #
    """ do a conservative remapping from one 2-d grid to another.  assumes that input coordinate arrays are monotonic increasing (but handles lon jump across meridian) and that lat and lon are second-to last and last dimensions
        possible to mask the input data either by using a masked array or by setting weights array to zero for masked gridcells
        option dilute_w_masked_data means that where the input data is masked, a value of zero is averaged into the output grid, so that global integrals equal.
        setting this false will mean that global integrals do not equal, hoe=wever this could be back-calculated out using the fraction masked if return_frac_input_masked is set to true
        using the weights_in argument will also lead to non-equal global integrals """
    #
    shape = data_in.shape
    ndims = len(shape)
    JM_i = shape[ndims-2]
    IM_i = shape[ndims-1]
    maxlat = 89.9
    if weights_in == None:
        weights_in = np.ones([JM_i,IM_i])
        weights_mask = np.zeros([JM_i,IM_i], dtype=np.bool)
    else:
        weights_mask = weights_in[:] == 0.
    if type(data_in) == np.ma.core.MaskedArray:
        if ndims == 2:
            mask_in = np.logical_or(data_in[:].mask, weights_mask)
        elif ndims == 3:
            mask_in = np.logical_or(data_in[0,:].mask, weights_mask)
        elif ndims == 4:
            mask_in = np.logical_or(data_in[0,0,:].mask, weights_mask)
    else:
        mask_in = np.logical_or(np.zeros([JM_i,IM_i], dtype=np.bool), weights_mask)
    ## check to see if coordinates input are for gridcell centers or edges.  assume that if edges, length of vector will be one longer than length of data
    #
    #
    #
    #
    ####### lats_in
    if len(lats_in) == JM_i:
        if spherical:
            lat_edges_in = np.zeros(JM_i+1)
            lat_edges_in[0] = max(-maxlat, lats_in[0] - 0.5*(lats_in[1] - lats_in[0]))
            lat_edges_in[JM_i] = min(maxlat, lats_in[JM_i-1] + 0.5*(lats_in[JM_i-1] - lats_in[JM_i-2]))
            lat_edges_in[1:JM_i] = (lats_in[0:JM_i-1] + lats_in[1:JM_i])/2.
        else:
            lat_edges_in = np.zeros(JM_i+1)
            lat_edges_in[0] = lats_in[0] - 0.5*(lats_in[1] - lats_in[0])
            lat_edges_in[JM_i] = lats_in[JM_i-1] + 0.5*(lats_in[JM_i-1] - lats_in[JM_i-2])
            lat_edges_in[1:JM_i] = (lats_in[0:JM_i-1] + lats_in[1:JM_i])/2.                
    elif len(lats_in) == JM_i+1:
        lat_edges_in = lats_in
    else:
        raise RuntimeError
    #
    ####### lats_out
    if centers_out:
        JM_o = len(lats_out)
        if spherical:
            lat_edges_out = np.zeros(JM_o+1)
            lat_edges_out[0] = max(-maxlat, lats_out[0] - 0.5*(lats_out[1] - lats_out[0]))
            lat_edges_out[JM_o] = min(maxlat, lats_out[JM_o-1] + 0.5*(lats_out[JM_o-1] - lats_out[JM_o-2]))
            lat_edges_out[1:JM_o] = (lats_out[0:JM_o-1] + lats_out[1:JM_o])/2.
        else:
            lat_edges_out = np.zeros(JM_o+1)
            lat_edges_out[0] = lats_out[0] - 0.5*(lats_out[1] - lats_out[0])
            lat_edges_out[JM_o] = lats_out[JM_o-1] + 0.5*(lats_out[JM_o-1] - lats_out[JM_o-2])
            lat_edges_out[1:JM_o] = (lats_out[0:JM_o-1] + lats_out[1:JM_o])/2.                
    else:
        JM_o = len(lats_out) -1
        lat_edges_out = lats_out
    #
    ####### lons_in
    if len(lons_in) == IM_i:
        lon_edges_in = np.zeros(IM_i+1)
        lon_edges_in[0] = lons_in[0] - 0.5*(lons_in[1] - lons_in[0])
        lon_edges_in[IM_i] = lons_in[IM_i-1] + 0.5*(lons_in[IM_i-1] - lons_in[IM_i-2])
        lon_edges_in[1:IM_i] = (lons_in[0:IM_i-1] + lons_in[1:IM_i])/2.                
    elif len(lons_in) == IM_i+1:
        lon_edges_in = lons_in
    else:
        raise RuntimeError
    #
    ####### lons_out
    if centers_out:
        IM_o = len(lons_out)
        lon_edges_out = np.zeros(IM_o+1)
        lon_edges_out[0] = lons_out[0] - 0.5*(lons_out[1] - lons_out[0])
        lon_edges_out[IM_o] = lons_out[IM_o-1] + 0.5*(lons_out[IM_o-1] - lons_out[IM_o-2])
        lon_edges_out[1:IM_o] = (lons_out[0:IM_o-1] + lons_out[1:IM_o])/2.                
    else:
        IM_o = len(lons_out) -1
        lon_edges_out = lons_out
    #
    #
    #
    ### first define ranges to loop over that map overlapping lat and lons
    lon_looplist = [[]]
    for i in range(IM_o):
        if i > 0:
            lon_looplist.append([])
        ### figure out which lon quadrant to normalize the data to.  if -90<lon<90 then normalize to option 1, otherwise to zero
        if (Ngl.normalize_angle(lon_edges_out[i], 1) < 90.) and (Ngl.normalize_angle(lon_edges_out[i], 1) > -90.):
            lon_sector = 1
        else:
            lon_sector = 0
        min_cell_lon_o = Ngl.normalize_angle(lon_edges_out[i], lon_sector)
        max_cell_lon_o = Ngl.normalize_angle(lon_edges_out[i+1], lon_sector)
        for ii in range(IM_i):
            min_cell_lon_i = Ngl.normalize_angle(lon_edges_in[ii], lon_sector)
            max_cell_lon_i = Ngl.normalize_angle(lon_edges_in[ii+1], lon_sector)
            overlap_interval_lon = min(max_cell_lon_i, max_cell_lon_o) - max(min_cell_lon_i,min_cell_lon_o)
            if overlap_interval_lon > 0.:
                lon_looplist[i].append(ii)
    #
    #
    #
    lat_looplist = [[]]
    for j in range(JM_o):
        if j > 0:
            lat_looplist.append([])
        min_cell_lat_o = lat_edges_out[j]
        max_cell_lat_o = lat_edges_out[j+1]
        for jj in range(JM_i):
            min_cell_lat_i = lat_edges_in[jj]
            max_cell_lat_i = lat_edges_in[jj+1]
            overlap_interval_lat = min(max_cell_lat_i, max_cell_lat_o) - max(min_cell_lat_i,min_cell_lat_o)
            if overlap_interval_lat > 0.:
                lat_looplist[j].append(jj)
    #
    #
    #            
    ### now begin looping over output grid
    total_weights = np.zeros([JM_o,IM_o])
    total_weights_inputmasked = np.zeros([JM_o,IM_o])
    if ndims == 2:
        total_value = np.zeros([JM_o,IM_o])
    elif ndims == 3:
        total_value = np.zeros([shape[0],JM_o,IM_o])
    elif ndims == 4:
        total_value = np.zeros([shape[0],shape[1],JM_o,IM_o])
    else:
        raise RuntimeError
    for i in range(IM_o):
        ### figure out which lon quadrant to normalize the data to.  if -90<lon<90 then normalize to option 1, otherwise to zero
        if (Ngl.normalize_angle(lon_edges_out[i], 1) < 90.) and (Ngl.normalize_angle(lon_edges_out[i], 1) > -90.):
            lon_sector = 1
        else:
            lon_sector = 0
        min_cell_lon_o = Ngl.normalize_angle(lon_edges_out[i], lon_sector)
        max_cell_lon_o = Ngl.normalize_angle(lon_edges_out[i+1], lon_sector)
        for j in range(JM_o):
            min_cell_lat_o = lat_edges_out[j]
            max_cell_lat_o = lat_edges_out[j+1]
            for ii in lon_looplist[i]:
                for jj in lat_looplist[j]:
                    if not(mask_in[jj,ii]) or dilute_w_masked_data:
                        min_cell_lat_i = lat_edges_in[jj]
                        max_cell_lat_i = lat_edges_in[jj+1]
                        min_cell_lon_i = Ngl.normalize_angle(lon_edges_in[ii], lon_sector)
                        max_cell_lon_i = Ngl.normalize_angle(lon_edges_in[ii+1], lon_sector)
                        overlap_interval_lat = min(max_cell_lat_i, max_cell_lat_o) - max(min_cell_lat_i,min_cell_lat_o)
                        overlap_interval_lon = min(max_cell_lon_i, max_cell_lon_o) - max(min_cell_lon_i,min_cell_lon_o)
                        if overlap_interval_lat > 0. and overlap_interval_lon > 0.:
                            fractional_overlap_lat = overlap_interval_lat / (max_cell_lat_i - min_cell_lat_i)
                            fractional_overlap_lon = overlap_interval_lon / (max_cell_lon_i - min_cell_lon_i)
                            fractional_overlap_total = fractional_overlap_lat * fractional_overlap_lon
                            if spherical:
                                weight = fractional_overlap_total * weights_in[jj,ii] * Ngl.gc_qarea(min_cell_lat_i,min_cell_lon_i,max_cell_lat_i,min_cell_lon_i,max_cell_lat_i,max_cell_lon_i,min_cell_lat_i,max_cell_lon_i,radius=radius)
                            else:
                                weight = fractional_overlap_total * weights_in[jj,ii]
                            total_weights[j,i] = total_weights[j,i] + weight
                            if not(mask_in[jj,ii]):
                                total_weights_inputmasked[j,i] = total_weights_inputmasked[j,i] + weight
                                if ndims == 2:
                                    total_value[j,i] = total_value[j,i] + weight * data_in[jj,ii]
                                elif ndims == 3:
                                    total_value[:,j,i] = total_value[:,j,i] + weight * data_in[:,jj,ii]
                                elif ndims == 4:
                                    total_value[:,:,j,i] = total_value[:,:,j,i] + weight * data_in[:,:,jj,ii]
    #
    if ndims > 2:
        total_weights_bc, total_value_bc = np.broadcast_arrays(total_weights, total_value)
        total_weights_inputmasked_bc, total_value_bc = np.broadcast_arrays(total_weights_inputmasked, total_value)
    else:
        total_weights_bc = total_weights
        total_weights_inputmasked_bc = total_weights_inputmasked
    #
    if total_weights_inputmasked.min() > 0.:
        mean_value = total_value[:] / total_weights_bc[:]
        fraction_maskedinput = total_weights_inputmasked[:] / total_weights[:]
    else:
        mean_value = np.ma.masked_array(total_value[:] / total_weights_bc[:], mask=total_weights_inputmasked_bc[:] == 0.)
        fraction_maskedinput = np.ma.masked_array(total_weights_inputmasked[:] / total_weights[:], mask=total_weights_inputmasked[:] == 0.)
    #
    #
    if not return_frac_input_masked:
        return mean_value
    else:
        return mean_value, fraction_maskedinput
コード例 #4
0
ファイル: interp_regrid_lib.py プロジェクト: ckoven/ckplotlib
def bilinear_interp(data_in, lats_in, lons_in, lats_out, lons_out):
    IM_i = len(lons_in)
    JM_i = len(lats_in)
    IM_o = len(lons_out)
    JM_o = len(lats_out)
    #
    #
    ## find four points from old grid that surround each point on new grid
    J_index_below = np.zeros(JM_o, dtype=np.int)
    J_index_above = np.zeros(JM_o, dtype=np.int)
    for j in range(JM_o):
        J_index_below[j] = np.sum(lats_in[:] <= lats_out[j]) - 1
        J_index_above[j] = JM_i - max(np.sum(lats_in[:] >= lats_out[j]), 1)
    #
    I_index_below = np.zeros(IM_o, dtype=np.int)
    I_index_above = np.zeros(IM_o, dtype=np.int)
    for i in range(IM_o):
        found = False
        for ii in range(IM_i):
            if not found:
                if Ngl.normalize_angle(lons_in[ii], 0) == Ngl.normalize_angle(
                        lons_out[i], 0):
                    I_index_below[i] = ii
                    I_index_above[i] = ii
                    found = True
        for ii in range(IM_i - 1):
            if not found:
                if Ngl.normalize_angle(lons_in[ii], 0) < Ngl.normalize_angle(
                        lons_out[i], 0) and Ngl.normalize_angle(
                            lons_in[ii + 1], 0) > Ngl.normalize_angle(
                                lons_out[i], 0):
                    I_index_below[i] = ii
                    I_index_above[i] = ii + 1
                    found = True
                elif Ngl.normalize_angle(lons_in[ii], 1) < Ngl.normalize_angle(
                        lons_out[i], 1) and Ngl.normalize_angle(
                            lons_in[ii + 1], 1) > Ngl.normalize_angle(
                                lons_out[i], 1):
                    I_index_below[i] = ii
                    I_index_above[i] = ii + 1
                    found = True
        if not found:
            if Ngl.normalize_angle(lons_in[IM_i - 1], 1) < Ngl.normalize_angle(
                    lons_out[i], 1) and Ngl.normalize_angle(
                        lons_in[0], 1) > Ngl.normalize_angle(lons_out[i], 1):
                I_index_below[i] = IM_i - 1
                I_index_above[i] = 0
                found = True
            elif Ngl.normalize_angle(
                    lons_in[IM_i - 1], 0) < Ngl.normalize_angle(
                        lons_out[i], 0) and Ngl.normalize_angle(
                            lons_in[0], 0) > Ngl.normalize_angle(
                                lons_out[i], 0):
                I_index_below[i] = IM_i - 1
                I_index_above[i] = 0
                found = True
        if not found:
            raise RuntimeError
    #
    # print(J_index_below)
    # print(J_index_above)

    # print(I_index_below)
    # print(I_index_above)
    #
    #
    if type(data_in) == np.ma.masked_array:
        masked_in = True
        data_out = np.ma.masked_all([JM_o, IM_o])
    else:
        masked_in = False
        data_out = np.zeros([JM_o, IM_o])
    #
    #
    ### now loop to do the interpolation
    if masked_in:
        for i in range(IM_o):
            for j in range(JM_o):
                if I_index_below[i] != I_index_above[i] and J_index_below[
                        j] != J_index_above[j]:
                    weights = np.ma.masked_all([4])
                    values = np.ma.masked_all([4])
                    weights[0] = absdeltalon(
                        lons_in[I_index_below[i]],
                        lons_out[i]) * abs(lats_in[J_index_below[j]] -
                                           lats_out[j])
                    weights[1] = absdeltalon(
                        lons_in[I_index_above[i]],
                        lons_out[i]) * abs(lats_in[J_index_below[j]] -
                                           lats_out[j])
                    weights[2] = absdeltalon(
                        lons_in[I_index_below[i]],
                        lons_out[i]) * abs(lats_in[J_index_above[j]] -
                                           lats_out[j])
                    weights[3] = absdeltalon(
                        lons_in[I_index_above[i]],
                        lons_out[i]) * abs(lats_in[J_index_above[j]] -
                                           lats_out[j])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_below[j], I_index_above[i]]
                    values[2] = data_in[J_index_above[j], I_index_below[i]]
                    values[3] = data_in[J_index_above[j], I_index_above[i]]
                    weights.mask = values.mask
                    data_out[j, i] = np.sum(weights * values) / np.sum(weights)
                elif I_index_below[i] == I_index_above[
                        i] and J_index_below[j] != J_index_above[j]:
                    weights = np.ma.masked_all([2])
                    values = np.ma.masked_all([2])
                    weights[0] = abs(lats_in[J_index_below[j]] - lats_out[j])
                    weights[1] = abs(lats_in[J_index_above[j]] - lats_out[j])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_above[j], I_index_above[i]]
                    weights.mask = values.mask
                    data_out[j, i] = np.sum(weights * values) / np.sum(weights)
                elif J_index_below[j] == J_index_above[
                        j] and I_index_below[i] != I_index_above[i]:
                    weights = np.ma.masked_all([2])
                    values = np.ma.masked_all([2])
                    weights[0] = absdeltalon(lons_in[I_index_below[i]],
                                             lons_out[i])
                    weights[1] = absdeltalon(lons_in[I_index_above[i]],
                                             lons_out[i])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_above[j], I_index_above[i]]
                    weights.mask = values.mask
                    data_out[j, i] = np.sum(weights * values) / np.sum(weights)
                else:
                    data_out[j, i] = data_in[J_index_below[j],
                                             I_index_below[i]]
    else:
        for i in range(IM_o):
            for j in range(JM_o):
                if I_index_below[i] != I_index_above[i] and J_index_below[
                        j] != J_index_above[j]:
                    weights = np.zeros([4])
                    values = np.zeros([4])
                    weights[0] = absdeltalon(
                        lons_in[I_index_below[i]],
                        lons_out[i]) * abs(lats_in[J_index_below[j]] -
                                           lats_out[j])
                    weights[1] = absdeltalon(
                        lons_in[I_index_above[i]],
                        lons_out[i]) * abs(lats_in[J_index_below[j]] -
                                           lats_out[j])
                    weights[2] = absdeltalon(
                        lons_in[I_index_below[i]],
                        lons_out[i]) * abs(lats_in[J_index_above[j]] -
                                           lats_out[j])
                    weights[3] = absdeltalon(
                        lons_in[I_index_above[i]],
                        lons_out[i]) * abs(lats_in[J_index_above[j]] -
                                           lats_out[j])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_below[j], I_index_above[i]]
                    values[2] = data_in[J_index_above[j], I_index_below[i]]
                    values[3] = data_in[J_index_above[j], I_index_above[i]]
                    data_out[j, i] = np.sum(weights * values) / np.sum(weights)
                elif I_index_below[i] == I_index_above[
                        i] and J_index_below[j] != J_index_above[j]:
                    weights = np.zeros([2])
                    values = np.zeros([2])
                    weights[0] = abs(lats_in[J_index_below[j]] - lats_out[j])
                    weights[1] = abs(lats_in[J_index_above[j]] - lats_out[j])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_above[j], I_index_above[i]]
                    data_out[j, i] = np.sum(weights * values) / np.sum(weights)
                elif J_index_below[j] == J_index_above[
                        j] and I_index_below[i] != I_index_above[i]:
                    weights = np.zeros([2])
                    values = np.zeros([2])
                    weights[0] = absdeltalon(lons_in[I_index_below[i]],
                                             lons_out[i])
                    weights[1] = absdeltalon(lons_in[I_index_above[i]],
                                             lons_out[i])
                    values[0] = data_in[J_index_below[j], I_index_below[i]]
                    values[1] = data_in[J_index_above[j], I_index_above[i]]
                    data_out[j, i] = np.sum(weights * values) / np.sum(weights)
                else:
                    data_out[j, i] = data_in[J_index_below[j],
                                             I_index_below[i]]
    #
    #
    return (data_out)
コード例 #5
0
ファイル: interp_regrid_lib.py プロジェクト: ckoven/ckplotlib
def natgrid_interp(data_in,
                   lats_in,
                   lons_in,
                   lats_out,
                   lons_out,
                   valid_range=None,
                   wrapping_overlap_interval=10.):
    IM_i = len(lons_in)
    JM_i = len(lats_in)
    IM_o = len(lons_out)
    JM_o = len(lats_out)
    lons_in_interval1 = np.zeros(IM_i)
    lons_in_interval2 = np.zeros(IM_i)
    lons_out_interval1 = np.zeros(IM_o)
    lons_out_interval2 = np.zeros(IM_o)
    for i in range(IM_i):
        lons_in_interval1[i] = Ngl.normalize_angle(lons_in[i], 0)
        lons_in_interval2[i] = Ngl.normalize_angle(lons_in[i], 1)
    for i in range(IM_o):
        lons_out_interval1[i] = Ngl.normalize_angle(lons_out[i], 0)
    if valid_range == None:
        valid_range = [data_in.min(), data_in.max()]
    x_in_interval1 = np.tile(lons_in_interval1, JM_i)
    y_in = np.repeat(lats_in, IM_i)
    z_in = data_in.flatten()
    if lons_in_interval1.max() - lons_in_interval1.min(
    ) > 180. and lons_in_interval2.max() - lons_in_interval2.min() > 180.:
        wrap = True
        ## span of lons is greater than 180; assume that it is a global run and therefore needs to be wrapped
        logical_wrapping = np.logical_and(
            lons_in_interval2[:] > -wrapping_overlap_interval,
            lons_in_interval2[:] < 0.)
        lons_wrapped = lons_in_interval2[logical_wrapping]
        data_in_wrapped = data_in[:, logical_wrapping]
        IM_wrapped = len(lons_wrapped)
        lons_wrapped_vector = np.tile(lons_wrapped, JM_i)
        lats_wrapped_vector = np.repeat(lats_in, IM_wrapped)
        data_in_wrapped_vector = data_in_wrapped.flatten()
        ### and add them together
        x_in_interval1 = np.concatenate((x_in_interval1, lons_wrapped_vector))
        y_in = np.concatenate((y_in, lats_wrapped_vector))
        z_in = np.concatenate((z_in, data_in_wrapped_vector))
        #
        logical_wrapping = np.logical_and(
            lons_in_interval2[:] < wrapping_overlap_interval,
            lons_in_interval2[:] > 0.)
        lons_wrapped = lons_in_interval1[logical_wrapping] + 360.
        data_in_wrapped = data_in[:, logical_wrapping]
        IM_wrapped = len(lons_wrapped)
        lons_wrapped_vector = np.tile(lons_wrapped, JM_i)
        lats_wrapped_vector = np.repeat(lats_in, IM_wrapped)
        data_in_wrapped_vector = data_in_wrapped.flatten()
        ### and add them together
        x_in_interval1 = np.concatenate((x_in_interval1, lons_wrapped_vector))
        y_in = np.concatenate((y_in, lats_wrapped_vector))
        z_in = np.concatenate((z_in, data_in_wrapped_vector))
        # ### reorder output lons
        # lons_out_interval1_unsorted = lons_out_interval1
        # lons_out_interval1 = lons_out_interval1[lons_out_interval1.argsort()]
    output1 = Ngl.natgrid(x_in_interval1, y_in, z_in, lons_out_interval1,
                          lats_out).transpose()
    output_masked = np.ma.masked_array(output1,
                                       mask=np.logical_or(
                                           output1 < min(valid_range),
                                           output1 > max(valid_range)))
    return (output_masked)
コード例 #6
0
ファイル: interp_regrid_lib.py プロジェクト: ckoven/ckplotlib
def conservative_regrid(data_in,
                        lats_in,
                        lons_in,
                        lats_out,
                        lons_out,
                        centers_out=True,
                        weights_in=None,
                        spherical=True,
                        radius=6372000.,
                        dilute_w_masked_data=True,
                        return_frac_input_masked=False):
    #
    """ do a conservative remapping from one 2-d grid to another.  assumes that input coordinate arrays are monotonic increasing (but handles lon jump across meridian) and that lat and lon are second-to last and last dimensions
        possible to mask the input data either by using a masked array or by setting weights array to zero for masked gridcells
        option dilute_w_masked_data means that where the input data is masked, a value of zero is averaged into the output grid, so that global integrals equal.
        setting this false will mean that global integrals do not equal, hoe=wever this could be back-calculated out using the fraction masked if return_frac_input_masked is set to true
        using the weights_in argument will also lead to non-equal global integrals """
    #
    shape = data_in.shape
    ndims = len(shape)
    JM_i = shape[ndims - 2]
    IM_i = shape[ndims - 1]
    maxlat = 89.9
    if weights_in == None:
        weights_in = np.ones([JM_i, IM_i])
        weights_mask = np.zeros([JM_i, IM_i], dtype=np.bool)
    else:
        weights_mask = weights_in[:] == 0.
    if type(data_in) == np.ma.core.MaskedArray:
        if ndims == 2:
            mask_in = np.logical_or(data_in[:].mask, weights_mask)
        elif ndims == 3:
            mask_in = np.logical_or(data_in[0, :].mask, weights_mask)
        elif ndims == 4:
            mask_in = np.logical_or(data_in[0, 0, :].mask, weights_mask)
    else:
        mask_in = np.logical_or(np.zeros([JM_i, IM_i], dtype=np.bool),
                                weights_mask)
    ## check to see if coordinates input are for gridcell centers or edges.  assume that if edges, length of vector will be one longer than length of data
    #
    #
    #
    #
    ####### lats_in
    if len(lats_in) == JM_i:
        if spherical:
            lat_edges_in = np.zeros(JM_i + 1)
            lat_edges_in[0] = max(-maxlat,
                                  lats_in[0] - 0.5 * (lats_in[1] - lats_in[0]))
            lat_edges_in[JM_i] = min(
                maxlat, lats_in[JM_i - 1] + 0.5 *
                (lats_in[JM_i - 1] - lats_in[JM_i - 2]))
            lat_edges_in[1:JM_i] = (lats_in[0:JM_i - 1] + lats_in[1:JM_i]) / 2.
        else:
            lat_edges_in = np.zeros(JM_i + 1)
            lat_edges_in[0] = lats_in[0] - 0.5 * (lats_in[1] - lats_in[0])
            lat_edges_in[JM_i] = lats_in[JM_i - 1] + 0.5 * (lats_in[JM_i - 1] -
                                                            lats_in[JM_i - 2])
            lat_edges_in[1:JM_i] = (lats_in[0:JM_i - 1] + lats_in[1:JM_i]) / 2.
    elif len(lats_in) == JM_i + 1:
        lat_edges_in = lats_in
    else:
        raise RuntimeError
    #
    ####### lats_out
    if centers_out:
        JM_o = len(lats_out)
        if spherical:
            lat_edges_out = np.zeros(JM_o + 1)
            lat_edges_out[0] = max(
                -maxlat, lats_out[0] - 0.5 * (lats_out[1] - lats_out[0]))
            lat_edges_out[JM_o] = min(
                maxlat, lats_out[JM_o - 1] + 0.5 *
                (lats_out[JM_o - 1] - lats_out[JM_o - 2]))
            lat_edges_out[1:JM_o] = (lats_out[0:JM_o - 1] +
                                     lats_out[1:JM_o]) / 2.
        else:
            lat_edges_out = np.zeros(JM_o + 1)
            lat_edges_out[0] = lats_out[0] - 0.5 * (lats_out[1] - lats_out[0])
            lat_edges_out[JM_o] = lats_out[
                JM_o - 1] + 0.5 * (lats_out[JM_o - 1] - lats_out[JM_o - 2])
            lat_edges_out[1:JM_o] = (lats_out[0:JM_o - 1] +
                                     lats_out[1:JM_o]) / 2.
    else:
        JM_o = len(lats_out) - 1
        lat_edges_out = lats_out
    #
    ####### lons_in
    if len(lons_in) == IM_i:
        lon_edges_in = np.zeros(IM_i + 1)
        lon_edges_in[0] = lons_in[0] - 0.5 * (lons_in[1] - lons_in[0])
        lon_edges_in[IM_i] = lons_in[IM_i - 1] + 0.5 * (lons_in[IM_i - 1] -
                                                        lons_in[IM_i - 2])
        lon_edges_in[1:IM_i] = (lons_in[0:IM_i - 1] + lons_in[1:IM_i]) / 2.
    elif len(lons_in) == IM_i + 1:
        lon_edges_in = lons_in
    else:
        raise RuntimeError
    #
    ####### lons_out
    if centers_out:
        IM_o = len(lons_out)
        lon_edges_out = np.zeros(IM_o + 1)
        lon_edges_out[0] = lons_out[0] - 0.5 * (lons_out[1] - lons_out[0])
        lon_edges_out[IM_o] = lons_out[IM_o - 1] + 0.5 * (lons_out[IM_o - 1] -
                                                          lons_out[IM_o - 2])
        lon_edges_out[1:IM_o] = (lons_out[0:IM_o - 1] + lons_out[1:IM_o]) / 2.
    else:
        IM_o = len(lons_out) - 1
        lon_edges_out = lons_out
    #
    #
    #
    ### first define ranges to loop over that map overlapping lat and lons
    lon_looplist = [[]]
    for i in range(IM_o):
        if i > 0:
            lon_looplist.append([])
        ### figure out which lon quadrant to normalize the data to.  if -90<lon<90 then normalize to option 1, otherwise to zero
        if (Ngl.normalize_angle(lon_edges_out[i], 1) <
                90.) and (Ngl.normalize_angle(lon_edges_out[i], 1) > -90.):
            lon_sector = 1
        else:
            lon_sector = 0
        min_cell_lon_o = Ngl.normalize_angle(lon_edges_out[i], lon_sector)
        max_cell_lon_o = Ngl.normalize_angle(lon_edges_out[i + 1], lon_sector)
        for ii in range(IM_i):
            min_cell_lon_i = Ngl.normalize_angle(lon_edges_in[ii], lon_sector)
            max_cell_lon_i = Ngl.normalize_angle(lon_edges_in[ii + 1],
                                                 lon_sector)
            overlap_interval_lon = min(max_cell_lon_i, max_cell_lon_o) - max(
                min_cell_lon_i, min_cell_lon_o)
            if overlap_interval_lon > 0.:
                lon_looplist[i].append(ii)
    #
    #
    #
    lat_looplist = [[]]
    for j in range(JM_o):
        if j > 0:
            lat_looplist.append([])
        min_cell_lat_o = lat_edges_out[j]
        max_cell_lat_o = lat_edges_out[j + 1]
        for jj in range(JM_i):
            min_cell_lat_i = lat_edges_in[jj]
            max_cell_lat_i = lat_edges_in[jj + 1]
            overlap_interval_lat = min(max_cell_lat_i, max_cell_lat_o) - max(
                min_cell_lat_i, min_cell_lat_o)
            if overlap_interval_lat > 0.:
                lat_looplist[j].append(jj)
    #
    #
    #
    ### now begin looping over output grid
    total_weights = np.zeros([JM_o, IM_o])
    total_weights_inputmasked = np.zeros([JM_o, IM_o])
    if ndims == 2:
        total_value = np.zeros([JM_o, IM_o])
    elif ndims == 3:
        total_value = np.zeros([shape[0], JM_o, IM_o])
    elif ndims == 4:
        total_value = np.zeros([shape[0], shape[1], JM_o, IM_o])
    else:
        raise RuntimeError
    for i in range(IM_o):
        ### figure out which lon quadrant to normalize the data to.  if -90<lon<90 then normalize to option 1, otherwise to zero
        if (Ngl.normalize_angle(lon_edges_out[i], 1) <
                90.) and (Ngl.normalize_angle(lon_edges_out[i], 1) > -90.):
            lon_sector = 1
        else:
            lon_sector = 0
        min_cell_lon_o = Ngl.normalize_angle(lon_edges_out[i], lon_sector)
        max_cell_lon_o = Ngl.normalize_angle(lon_edges_out[i + 1], lon_sector)
        for j in range(JM_o):
            min_cell_lat_o = lat_edges_out[j]
            max_cell_lat_o = lat_edges_out[j + 1]
            for ii in lon_looplist[i]:
                for jj in lat_looplist[j]:
                    if not (mask_in[jj, ii]) or dilute_w_masked_data:
                        min_cell_lat_i = lat_edges_in[jj]
                        max_cell_lat_i = lat_edges_in[jj + 1]
                        min_cell_lon_i = Ngl.normalize_angle(
                            lon_edges_in[ii], lon_sector)
                        max_cell_lon_i = Ngl.normalize_angle(
                            lon_edges_in[ii + 1], lon_sector)
                        overlap_interval_lat = min(
                            max_cell_lat_i, max_cell_lat_o) - max(
                                min_cell_lat_i, min_cell_lat_o)
                        overlap_interval_lon = min(
                            max_cell_lon_i, max_cell_lon_o) - max(
                                min_cell_lon_i, min_cell_lon_o)
                        if overlap_interval_lat > 0. and overlap_interval_lon > 0.:
                            fractional_overlap_lat = overlap_interval_lat / (
                                max_cell_lat_i - min_cell_lat_i)
                            fractional_overlap_lon = overlap_interval_lon / (
                                max_cell_lon_i - min_cell_lon_i)
                            fractional_overlap_total = fractional_overlap_lat * fractional_overlap_lon
                            if spherical:
                                weight = fractional_overlap_total * weights_in[
                                    jj, ii] * Ngl.gc_qarea(min_cell_lat_i,
                                                           min_cell_lon_i,
                                                           max_cell_lat_i,
                                                           min_cell_lon_i,
                                                           max_cell_lat_i,
                                                           max_cell_lon_i,
                                                           min_cell_lat_i,
                                                           max_cell_lon_i,
                                                           radius=radius)
                            else:
                                weight = fractional_overlap_total * weights_in[
                                    jj, ii]
                            total_weights[j, i] = total_weights[j, i] + weight
                            if not (mask_in[jj, ii]):
                                total_weights_inputmasked[
                                    j,
                                    i] = total_weights_inputmasked[j,
                                                                   i] + weight
                                if ndims == 2:
                                    total_value[j, i] = total_value[
                                        j, i] + weight * data_in[jj, ii]
                                elif ndims == 3:
                                    total_value[:, j,
                                                i] = total_value[:, j,
                                                                 i] + weight * data_in[:,
                                                                                       jj,
                                                                                       ii]
                                elif ndims == 4:
                                    total_value[:, :, j,
                                                i] = total_value[:, :, j,
                                                                 i] + weight * data_in[:, :,
                                                                                       jj,
                                                                                       ii]
    #
    if ndims > 2:
        total_weights_bc, total_value_bc = np.broadcast_arrays(
            total_weights, total_value)
        total_weights_inputmasked_bc, total_value_bc = np.broadcast_arrays(
            total_weights_inputmasked, total_value)
    else:
        total_weights_bc = total_weights
        total_weights_inputmasked_bc = total_weights_inputmasked
    #
    if total_weights_inputmasked.min() > 0.:
        mean_value = total_value[:] / total_weights_bc[:]
        fraction_maskedinput = total_weights_inputmasked[:] / total_weights[:]
    else:
        mean_value = np.ma.masked_array(
            total_value[:] / total_weights_bc[:],
            mask=total_weights_inputmasked_bc[:] == 0.)
        fraction_maskedinput = np.ma.masked_array(
            total_weights_inputmasked[:] / total_weights[:],
            mask=total_weights_inputmasked[:] == 0.)
    #
    #
    if not return_frac_input_masked:
        return mean_value
    else:
        return mean_value, fraction_maskedinput