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)