diff --git a/src/aare/daq/operations/common/ml_bounding_box.py b/src/aare/daq/operations/common/ml_bounding_box.py index 41923fc0..7b42742c 100644 --- a/src/aare/daq/operations/common/ml_bounding_box.py +++ b/src/aare/daq/operations/common/ml_bounding_box.py @@ -198,21 +198,25 @@ def _box_to_raster_request( if grid_padding: # Pad the grid by a fraction of its size on each side (at least one cell), # extending *before* cell 0 as well, so the top-left moves outward and - # smargon_top_left shifts with it. + # smargon_top_left shifts with it. Y is asymmetric: the bottom (far end + # of the n_y scan) can be padded more than the top. frac_x = float(cfg_get("daq.auto_raster.grid_padding_fraction_x", 0.15)) - frac_y = float(cfg_get("daq.auto_raster.grid_padding_fraction_y", 0.15)) + frac_y_top = float(cfg_get("daq.auto_raster.grid_padding_fraction_y", 0.15)) + frac_y_bottom = float(cfg_get("daq.auto_raster.grid_padding_fraction_y_bottom", frac_y_top)) pad_x = max(1, int(ceil(frac_x * n_x))) - pad_y = max(1, int(ceil(frac_y * n_y))) + pad_y_top = max(1, int(ceil(frac_y_top * n_y))) + pad_y_bottom = max(1, int(ceil(frac_y_bottom * n_y))) x1 = x1 - pad_x * grid_size.x / geom.pixel_in_mm - y1 = y1 - pad_y * grid_size.y / geom.pixel_in_mm + y1 = y1 - pad_y_top * grid_size.y / geom.pixel_in_mm n_x = n_x + 2 * pad_x - n_y = n_y + 2 * pad_y + n_y = n_y + pad_y_top + pad_y_bottom logger.info( "Padded auto-center raster grid", extra=merge_log_context( sample_log_context(sample), {"sample_id": sample_id, "ml_image_name": filename, - "pad_cells_x": pad_x, "pad_cells_y": pad_y, "n_x": n_x, "n_y": n_y}, + "pad_cells_x": pad_x, "pad_cells_y_top": pad_y_top, + "pad_cells_y_bottom": pad_y_bottom, "n_x": n_x, "n_y": n_y}, ), ) diff --git a/tests/unit/daq/operations/test_ml_raster_plan.py b/tests/unit/daq/operations/test_ml_raster_plan.py index eeef603c..9a93c749 100644 --- a/tests/unit/daq/operations/test_ml_raster_plan.py +++ b/tests/unit/daq/operations/test_ml_raster_plan.py @@ -105,6 +105,26 @@ def test_grid_padding_grows_and_shifts_top_left(monkeypatch): assert pad.smargon_top_left.sh_mm.z != nopad.smargon_top_left.sh_mm.z +def test_grid_padding_y_bottom_asymmetric(monkeypatch): + box = (150, 150, 400, 450) # tall box + + def cfg(y_bottom): + return lambda k, d=None: ( + y_bottom if "grid_padding_fraction_y_bottom" in k + else (0.0 if "grid_padding_fraction" in k else d) + ) + + monkeypatch.setattr(mlb, "cfg_get", cfg(0.0)) # bottom == top (min 1 cell each) + sym = _grid(box, grid_padding=True) + monkeypatch.setattr(mlb, "cfg_get", cfg(0.6)) # much more padding at the bottom + bottom = _grid(box, grid_padding=True) + + assert bottom.n_y > sym.n_y # extra cells added at the bottom + assert bottom.n_x == sym.n_x # x unaffected + # top padding identical -> smargon_top_left (cell 0) unchanged + assert bottom.smargon_top_left == sym.smargon_top_left + + def test_grid_padding_fraction_scales(monkeypatch): box = (150, 150, 520, 420) monkeypatch.setattr(mlb, "cfg_get", lambda k, d=None: 0.0 if "grid_padding_fraction" in k else d)