When regridding for example on target grid with 2.5 degree resolution, the resulting meridional grid points are always centered at e.g. 1.25N, 3.75N ... 88.75N. For computing blocking in the MiLES diagnostic (by @oloapinivad) we need a grid resolution of 2.50 degree but also grid points centered at 60N (which is not included in the list above) (see for example the Tibaldi and Molteni 1990 definition). So we need meridional grid points centered at 0, 2.5N ... 87.5N.
The problem is that the meridional centers are defined at line 109 of _regrid.py as follows
ydata = np.linspace(_LAT_MIN + mid_dy, _LAT_MAX - mid_dy, _LAT_RANGE / dy)
so it assumes that the bounding box always starts at latitude 0 (0 cannot be a center of the meridional grid) ( mid_dy is half of the meridional spacing and LAT_MINis -90)
In this case something like this would be needed instead
ydata = np.linspace(_LAT_MIN, _LAT_MAX, _LAT_RANGE / dy + 1)
I think it is not a good idea to change the behaviour of a preprocessor module to address a specific requirement of a diagnostic.
The mid-points defined at 1.25, 3.75... 88.75N for a 2.5-degree grid also make perfect sense to me.
For this specific case, I would suggest to perform the regridding at the diagnostic level in order to get the grid you need for your analysis.
I think we could fairly easily allow specifying the grid offset in the recipe in addition to the step size.
That would a better option, if the default behaviour remains the current one.
@bouweandela solution is elegant, I agree with @mattiarighi to move the regridding at diagnostic level but then again even at diagnostic level one should still import the esmvaltool regridding module rather than do their own regridding algorithm, so by importing the regridder Jost is back to square A. Another option is to apply a shift of the centers in the diagnostic after the regridding has been done in the preprocessor?
Adding an offset would be useful but actually the desired grid in this case is not only offset, it also has more points. E.g. currently "target_grid: 2.5x2.5" provides an output grid with latitudes centered at -88.75, -86.25 ... -1.25, 1.25, ... 88.75. What would be needed is the possibility to get also grids where the equator is a grid center, that is with centers: -90, -87.50, ... -2.50, 0, 2.50, .. 87.50, 90. Please notice that this grid has one latitude more than the previous one in the meridional direction.
My suggestion is to allow specifying an additional "centered" regular target grid type, so that "target_grid: 2.5x2.5c" (where the additional "c" is for "centered on latitude 0") gives the desired grid. This simply extends the functionality and does not touch the default behavior.
Please give a look at branch https://github.com/ESMValGroup/ESMValTool/tree/fix_preproc_meridional_grid which implements exactly this (it only modifies _regrid.py parsing also a possible c after the latitudinal resolution). I also profited from the occasion to add an additional horizontal interpolation scheme "linear_extrapolate" which uses the iris extrapolation_mode="extrapolate" to avoid getting missing values close to the pole in some situations (this solves issue https://github.com/ESMValGroup/ESMValTool/issues/806)
Thanks for the detailed explanation.
Please give a look at branch https://github.com/ESMValGroup/ESMValTool/tree/fix_preproc_meridional_grid which implements exactly this.
Can you put this change (and only it) in a separate branch and open a PR?
We can quickly review it and test it.
I am going to be a pain in the arse and suggest that we should probably not use a target grid specified with a letter in it and rather add a keyword argument to the regrid function like centered=False and set it true if the preprocessor regrid has a key centered_grid: True in the recipe. Just to keep things clear: a target grid is always specified by an MxN string
Well, I actually thought about that, but in my opinion since the end target grid is really a different grid, it is better to give it also a different name. This way the target_grid specification contains all the information to identify univocally the target grid.
To clarify: imagine that one day for some reason in esmvaltool you wanted also to allow Gaussian grids as a target. In that case too you would modify the code to be able to parse different target_grid keys like "n36", "n80" etc, no?
By the way, actually here the centering refers to the meridional direction, so if an additional keyword is really preferred, this should rather be something like center_lat_grid ....
Also notice that if you try and code this, adding parsing the additional "c" in the target string requires only minimal modifications to _regrid.py. Additional keywords would instead imply additional arguments for the regrid function, so also from this point of view "2.5x2.5c" seems a simpler solution to me.
Final argument: it is not needed now, but in theory this notation could be extended to specify also centering in the lon direction (containing lon=0 as a grid center) by adding a "c" after the first resolution in the target_grid key.