0

I'm trying to perform a relative normalization between two images in Google Earth Engine using Python, but am running into issues mapping a function over an image collection due to client-server issues. The code below provides the error 'Exception: A mapped function's arguments cannot be used in client-side operations'.

The PIF_sample is sampled pseudo invariant features storied inside a feature collection. The code is intended to determine the relationship between a parent image and a child image, and to apply the corrections to each band in a child image. I wanted to then map this over the whole image collection (ps).

I've read the documentation on issues with .map but am struggling to implement a fix.

import statsmodels.api as sm

def rn(image):


    rep_sample = image.sample(PIF_sample, 30, 'EPSG:32612', geometries=True)


    rep_sample_df = geemap.ee_to_geopandas(rep_sample)
    merged_df = rep_sample_df.merge(PIF_df, on='geometry')


    x = merged_df['b1']
    y = merged_df['B1p']
    x = sm.add_constant(x)

    regression_model = sm.OLS(y, x).fit()

    regression_const = regression_model.params['const']
    band_coeff = regression_model.params['b1']

    b1 = image.select('b1')

    normB1 = b1.multiply(band_coeff).add(regression_const).rename('normb1')
    image = image.addBands(normB1)

    return image

ps2 = ps2.map(rn)

I've started to rewrite this to run through GEE reducers following the format from regression on feature collections here. After mapping the function over my image collecetion, when I try and .getInfo on the collection afterwards I get an error that 'EEException: Error in map(ID=20170727): Array: Parameter 'values' is required'. I suspect I'm not sampling the locations properly - the sample locations are derived from a larger area composite, but in the single images only a few will be present.

def rngee(image):

     aoi = image.geometry().intersection(ps2_cloudfree_median.geometry())  
     subSamp = PIF_sample.filterBounds(aoi)
     imgSamp = bands.sampleRegions(subSamp, scale= 30)
    bands = image.select('B1').addBands(ps2_cloudfree_median.select('B1')).rename(['t_B1', 'P_B1'])

    imgSamp = bands.sampleRegions(sample, scale= 30)

    def func_psb(feature):
        return feature.set('constant', 1).map(func_psb)

    linearRegression = ee.Dictionary(imgSamp.reduceColumns(ee.Reducer.linearRegression(**{
    'numX': 2,
    'numY': 1
  }),
    selectors = ['constant', 't_B1', 'P_B1']))

    coefList = ee.Array(linearRegression.get('coefficients')).toList()

    yInt = ee.List(coefList.get(0)).get(0) # y-intercept
    slope = ee.List(coefList.get(1)).get(0) # slope

    props = ee.List(['t_B1', 'P_B1'])


    regressionVarsList = ee.List(imgSamp.reduceColumns(ee.Reducer.toList().repeat(props.size()),
      selectors = props).get('list'));
    x = ee.Array(ee.List(regressionVarsList.get(0)))
    y1 = ee.Array(ee.List(regressionVarsList.get(1)))

  yInt = ee.Number(yInt)
    slope = ee.Number(slope)


    b1 = image.select('B1')

    normB1 = b1.multiply(slope).add(yInt).rename('normb1')


return image.addBands(normB1)
2
  • 2
    Have you tried regression reducers? sm.OLS is a client-side function
    – aldo_tapia
    Commented Jan 19, 2023 at 17:30
  • I have tried to follow the ee.FeatureCollection example from that page, though I'm definitely doing something wrong. I'll edit the original post and add the code. Thanks!
    – Guest
    Commented Jan 19, 2023 at 18:51

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.