Ejemplo n.º 1
0
def gridcell_areas(lat,
                   lon,
                   mask=None,
                   radius=6372000.,
                   lat_edges_in=False,
                   lon_edges_in=False):

    ### assume uniform longitude spacing
    lat_edges, lon_edges = get_gridcell_edges(lat, lon)
    if lon_edges_in:
        IM = lon.shape[0] - 1
        lon_edges = lon[:]
        res_lon = lon_edges[1] - lon_edges[0]
    else:
        IM = lon.shape[0]
        res_lon = lon[1] - lon[0]
        #
    if lat_edges_in:
        JM = lat.shape[0] - 1
        lat_edges = lat[:]
    else:
        JM = lat.shape[0]
    southern_edge = np.fmax(lat_edges[0:JM], np.ones(JM) * -89.99)
    northern_edge = np.fmin(lat_edges[1:], np.ones(JM) * 89.99)
    #
    area = Ngl.gc_qarea(southern_edge,np.zeros(JM)-res_lon/2.,\
                        northern_edge,np.zeros(JM)-res_lon/2.,\
                        northern_edge,np.zeros(JM)+res_lon/2.,\
                        southern_edge,np.zeros(JM)+res_lon/2.,\
                        radius=radius) ### 1-D array in meters sq.
    area_array = np.array(np.reshape(np.repeat(area, IM), [JM, IM]))
    if not mask == None:
        area_array = np.ma.array(area_array, mask=mask)
    return area_array
Ejemplo n.º 2
0
def gridcell_areas(lat, lon, mask=None, radius=6372000., lat_edges_in=False, lon_edges_in=False):

    ### assume uniform longitude spacing
    lat_edges, lon_edges = get_gridcell_edges(lat, lon)
    if lon_edges_in:
        IM = lon.shape[0] - 1
        lon_edges = lon[:]
        res_lon = lon_edges[1] - lon_edges[0]
    else:
        IM = lon.shape[0]
        res_lon = lon[1]-lon[0]
        #
    if lat_edges_in:
        JM = lat.shape[0] - 1       
        lat_edges = lat[:] 
    else:
        JM = lat.shape[0]
    southern_edge = np.fmax(lat_edges[0:JM], np.ones(JM)*-89.99)
    northern_edge = np.fmin(lat_edges[1:], np.ones(JM)*89.99)
    #
    area = Ngl.gc_qarea(southern_edge,np.zeros(JM)-res_lon/2.,\
                        northern_edge,np.zeros(JM)-res_lon/2.,\
                        northern_edge,np.zeros(JM)+res_lon/2.,\
                        southern_edge,np.zeros(JM)+res_lon/2.,\
                        radius=radius) ### 1-D array in meters sq.
    area_array = np.array(np.reshape(np.repeat(area,IM), [JM,IM]))
    if not mask==None:
        area_array = np.ma.array(area_array, mask=mask)
    return area_array
Ejemplo n.º 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
Ejemplo n.º 4
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