Unusual masking in Radar Mosaic

Hi, greetings to all,

I’m currently working on generating a radar mosaic that combines data from three radar sites — Baguio (S-BAG), Baler (S-BAL), and Daet (S-DAET) — using Py-ART’s grid_from_radars function.

When I use the following configuration:

grid = pyart.map.grid_from_radars(
(daet_radar, baguio_radar, baler_radar),
gatefilters=(gatefilter_daet, gatefilter_bag, gatefilter_bal),
grid_shape=(1, 8001, 8001),
grid_limits=((0, 2), (-1000000.0, 1000000.0), (-1000000.0, 1000000.0)),
fields=[“Reflectivity_CAPPI_2km”],
weighting_function=‘barnes2’,
gridding_algo=“map_gates_to_grid”,
roi_func=‘dist_beam’,
)

The output (Fig_1.png) appears to exclude or mask some of the S-BAG radar data. However, when I change the radar order as follows:

grid = pyart.map.grid_from_radars(
(baguio_radar, baler_radar, daet_radar),
gatefilters=(gatefilter_bag, gatefilter_bal, gatefilter_daet),
grid_shape=(1, 8001, 8001),
grid_limits=((0, 2), (-1000000.0, 1000000.0), (-1000000.0, 1000000.0)),
fields=[“Reflectivity_CAPPI_2km”],
weighting_function=‘barnes2’,
gridding_algo=“map_gates_to_grid”,
roi_func=‘dist_beam’,
)

It produces Fig_2.png, but this time the S-DAET radar data seems to be masked instead.

Is there a way to resolve this issue? It’s quite odd that one radar’s data seems to be excluded depending on the radar order in the configuration.

Hey. Again, doing some assuming here. It seems that the gridding itself works fine, and no critical errors are raised as the plots are drawn in both cases. The next idea is that the gate filters are introducing some weirdness.
From pyart source:

# find excluded gates from the gatefilter    
    if gatefilter is False:
        gatefilter = GateFilter(radar)  # include all gates
    elif gatefilter is None:
        gatefilter = moment_based_gate_filter(radar, **kwargs)
    excluded_gates = gatefilter.gate_excluded.astype("uint8")

Try setting gatefilters=False (or rather gatefilters = (False, False, False) in your grid_from_radars function) to see if this resolves the plotting issue. This would indicate if there is a problem with the plotting functions or your gate filter setups. Although without any actual troubleshooting, it’s difficult to pinpoint exactly where the issue lies.

Edit: Or change the first tuple in grid_limits, the z (altitude) component, as this might also play a role here. From docs:

grid_limits : 3-tuple of 2-tuples
Minimum and maximum grid location (inclusive) in meters for the
z, y, x coordinates.

While currently you are trying to grid from 0..2 meters? If I interpret the docs correctly here.

1 Like

Hi @jorahu! Thank you for your response. I tried to set the gatefilters to false for a while, including adjusting the grid limits; particularly to z (altitude) component into 2000 m.

Nothing has changed in the figures unfortunately. There is still some ‘sort of’ masking going on when I try to grid/mosaic the three radars.

I’m attaching here the 3 sample radar data that I’ve used to plot figures, for anyone who can try to trouble shoot.

Hi @gene_cgha,

It would be great if you could show the complete code to create the images. It would really help people to just play with your data. Especially as it’s not known how the gatefilters are created and how the radar objects are treated before.

To add something meaningful here, this could be an issue with grid_origin and/or how grid_origin is derived and handled under the hood. grid_origin defaults to None which in turn uses the location of the first radar. Not sure if and how this does affect gatefilter and gridding, though.

HTH,
Kai

1 Like

Hi @kmuehlbauer (and everyone), thanks for the response!

In the Google Drive link provided, I’ve updated and included the Python code used to generate the radar mosaic, along with the custom boundaries and topography layers.

Please kindly see the files included.

Hey

Sorry that it has taken so long time, but just didn’t have time to look into that. Thanks for the code, it helped a lot!

Now, I am by no means an expert with Pyart, maybe some others can give better explanations here and apologies in advance to them, if I say something wrong here. (I didn’t even have a solid env with Pyart installed before this issue.)

As much as I learned while trying to understand your issue, I did get the same result that you had, that the order changed the visualised image. I do not know, what’s the underlying issue, but seems that all the internal weighting and roi functions are doing too good of a work when trying to visualise a simple "one layer” (z→1 pixel) CAPPI product. Especially when the radars are far apart and even more with such big elevation differences (that’s the key here!).

Basically, what finally worked, was to set all elevations to the same exact value, in your case 2000 m seemed like an appropriate number, but I guess any constant work the same for the algorithm. This should ensure that the ROI function doesn’t take the beam elevation into account and just draws the “flat pancake” (i.e. the CAPPI).

The code snippet I used:

file1 = “20251103051105_SBAG_CAPPI_2km.nc”
file2 = “20251103051001_SBAL_CAPPI_2km.nc”
file3 = “20251103051038_SDAET_CAPPI_2km.nc”

baguio_radar = pyart.io.read_cfradial(file1)
baler_radar = pyart.io.read_cfradial(file2)
daet_radar = pyart.io.read_cfradial(file3)

# Just for visualisation and debugging, disable the mask:
shap = baguio_radar.fields[‘Reflectivity_CAPPI_2km’][‘data’].data.shape
shap2 = daet_radar.fields[‘Reflectivity_CAPPI_2km’][‘data’].data.shape
baguio_radar.fields[‘Reflectivity_CAPPI_2km’][‘data’].mask[:, :] = np.zeros(shap).astype(bool)
baler_radar.fields[‘Reflectivity_CAPPI_2km’][‘data’].mask[:, :] =  np.zeros(shap).astype(bool)
daet_radar.fields[‘Reflectivity_CAPPI_2km’][‘data’].mask[:, :] =   np.zeros(shap2).astype(bool)

#Set the altitude to 2000 (or whatever number, guess it just has to be same number for all radars)
baguio_radar.altitude[‘data’].data[0] = 2000
baler_radar.altitude[‘data’].data[0] = 2000
daet_radar.altitude[‘data’].data[0] = 2000

# Plot
grid = pyart.map.grid_from_radars(
    (daet_radar, baler_radar, baguio_radar),
    #(baler_radar, baguio_radar, daet_radar),
    
    grid_shape=(1, 450, 450),
    grid_limits=((0, 10_000), (-500_000, 500_000), (-500_000, 500_000)),
    grid_origin=(15.411, 121.725),
    fields=["Reflectivity_CAPPI_2km"],
    weighting_function="Barnes2",
    gridding_algo="map_gates_to_grid",
    roi_func='dist_beam',
)

refl = grid.fields[‘Reflectivity_CAPPI_2km’][‘data’][0]
lats = grid.point_latitude[‘data’][0].reshape(refl.shape)
lons = grid.point_longitude[‘data’][0].reshape(refl.shape)

plt.pcolormesh(lons, lats, refl)

This produces the following image, where you can see all three full circles of the radar measurement ranges. Also, adding the gatefilters distorted the image quite a bit, so you will have to play around some more with those, but this is the best I could come up with. Again, someone with better understanding of Pyart can maybe pitch in here and make this make sense (also to me).