Panel layout stage 3: per-panel spot finding (CPU+GPU, CCL) and raster algorithms on the plane raster
Spot finding works panel by panel, as the FPGA path does per JUNGFRAU module. PanelBoxes (common/) gives one box per DetectorModule; an empty table gives one box, the whole image, so every clamp reduces to the old image bounds in the same evaluation order (rotation sets, EIGER, CCDs, our JUNGFRAU unchanged). - ImageSpotFinder::SetPanels: the CPU local-box pass (dense, count-threshold and the DetectAt/candidate path of the adaptive finder) slides its windows inside each panel box; host CCL labels panel by panel; pixels on no panel are folded into the resolution mask. - GPU: analyze_pixel tiles each panel (warps numbered panel after panel), analyze_candidates and union_neighbours clip to the pixel's panel, the device spot carries its panel; the GPU list is put in panel order so it equals the host's. - DiffractionSpot carries its panel; SpotAnalyze maps by ImageToPlane(panel, ...) (d_A on the plane). - ImagePreprocessorBuffer::GatherTiles (CPU+GPU) clips each square to the panel of its centre. - MXAnalysisWithoutFPGA and the pre-scan workers hand the module table to finders and buffers. Raster algorithms: new common/AssembleToPlane.h (PlaneRasterOf, AssembleToPlane nearest-pixel gather with gaps, GatherFromPlane back to stored pixels; empty table = copy). With panels, ShadowFinder::GetMask runs on the projection assembled to the plane raster and gathers the mask back per stored pixel (CPU route); FindBeamCenterFFT scores the assembled projection and reports plane coordinates; the detector diagnostic JPEG shows the assembled plane. Without panels all three take their old path. Harness: PanelLayout_SpotsNeverCrossPanels enabled (count threshold and SNR on the edge scene), new PanelLayout_SpotFinderParity (CPU vs GPU, local box and adaptive, on the stacked layout), PanelLayout_AssembleToPlane, PanelLayout_ShadowFinder, PanelLayout_BeamCenterFFT, PanelLayout_DetectorDiagnostic (stacked vs assembled image cut to the raster). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015CeEGgpKdfkCTJb3YNMJcu
This commit is contained in:
1 parent
c8fb472f4d
commit
fd798cd665
26 files changed
+792
-184
No files matched your search
@@ -19,7 +19,8 @@ __global__ void gather_kernel(const int32_t *__restrict__ image,
|
||||
values[i] = image[npixel[i]];
|
||||
}
|
||||
|
||||
__global__ void gather_tiles_kernel(const int32_t *__restrict__ image, int width, int height,
|
||||
// centre holds six values per tile: its centre x, y and the box x0, y0, x1, y1 it is clipped to.
|
||||
__global__ void gather_tiles_kernel(const int32_t *__restrict__ image, int width,
|
||||
const int32_t *__restrict__ centre, int half,
|
||||
int32_t *__restrict__ tiles, size_t count) {
|
||||
const int side = 2 * half + 1;
|
||||
@@ -27,9 +28,10 @@ __global__ void gather_tiles_kernel(const int32_t *__restrict__ image, int width
|
||||
for (size_t i = blockIdx.x * blockDim.x + threadIdx.x; i < count; i += static_cast<size_t>(blockDim.x) * gridDim.x) {
|
||||
const size_t tile = i / area;
|
||||
const int p = static_cast<int>(i - tile * area);
|
||||
const int px = centre[2 * tile] - half + p % side;
|
||||
const int py = centre[2 * tile + 1] - half + p / side;
|
||||
tiles[i] = (px < 0 || py < 0 || px >= width || py >= height)
|
||||
const int32_t *c = centre + 6 * tile;
|
||||
const int px = c[0] - half + p % side;
|
||||
const int py = c[1] - half + p / side;
|
||||
tiles[i] = (px < c[2] || py < c[3] || px >= c[4] || py >= c[5])
|
||||
? INT32_MIN : image[static_cast<size_t>(py) * width + px];
|
||||
}
|
||||
}
|
||||
@@ -79,18 +81,24 @@ const int32_t *ImagePreprocessorBufferGPU::GatherTiles(const std::vector<int32_t
|
||||
gpu_tiles = CudaDevicePtr<int32_t>(tile_capacity);
|
||||
host_tiles.resize(tile_capacity);
|
||||
}
|
||||
if (2 * x.size() > tile_centre.size()) {
|
||||
tile_centre.resize(std::max(2 * x.size(), 2 * tile_centre.size()));
|
||||
if (6 * x.size() > tile_centre.size()) {
|
||||
tile_centre.resize(std::max(6 * x.size(), 2 * tile_centre.size()));
|
||||
gpu_tile_centre = CudaDevicePtr<int32_t>(tile_centre.size());
|
||||
}
|
||||
for (size_t i = 0; i < x.size(); i++) {
|
||||
tile_centre[2 * i] = x[i];
|
||||
tile_centre[2 * i + 1] = y[i];
|
||||
const PanelBox b = TileBox(x[i], y[i], width);
|
||||
int32_t *c = tile_centre.data() + 6 * i;
|
||||
c[0] = x[i];
|
||||
c[1] = y[i];
|
||||
c[2] = b.x0;
|
||||
c[3] = b.y0;
|
||||
c[4] = b.x1;
|
||||
c[5] = b.y1;
|
||||
}
|
||||
cuda_err(cudaMemcpyAsync(gpu_tile_centre.get(), tile_centre.data(), 2 * x.size() * sizeof(int32_t),
|
||||
cuda_err(cudaMemcpyAsync(gpu_tile_centre.get(), tile_centre.data(), 6 * x.size() * sizeof(int32_t),
|
||||
cudaMemcpyHostToDevice, gather_stream));
|
||||
const int blocks = static_cast<int>(std::min<size_t>((count + 255) / 256, 4096));
|
||||
gather_tiles_kernel<<<blocks, 256, 0, gather_stream>>>(gpu_image.get(), width, static_cast<int>(npixels / width),
|
||||
gather_tiles_kernel<<<blocks, 256, 0, gather_stream>>>(gpu_image.get(), width,
|
||||
gpu_tile_centre.get(), half, gpu_tiles.get(), count);
|
||||
cuda_err(cudaGetLastError());
|
||||
cuda_err(cudaMemcpyAsync(host_tiles.data(), gpu_tiles.get(), count * sizeof(int32_t),
|
||||
|
||||
Reference in new issue
Block a user