beam centre: the FFT captures the whole detector, the walk refines what it captured
This commit is contained in:
1 parent
1d1d7fd686
commit
d75102b9b4
3 files changed
+106
-41
No files matched your search
@@ -82,7 +82,8 @@ float median_of(std::vector<float> &v) {
|
||||
|
||||
std::optional<BeamCenterEstimate>
|
||||
FindBeamCenterFromBackground(const DiffractionExperiment &experiment, const PixelMask &mask,
|
||||
const std::vector<float> &mean, size_t nthreads) {
|
||||
const std::vector<float> &mean, size_t nthreads,
|
||||
std::optional<std::pair<float, float>> start) {
|
||||
if (nthreads == 0)
|
||||
nthreads = std::max(1u, std::thread::hardware_concurrency());
|
||||
const auto W = static_cast<int>(experiment.GetXPixelsNumConv());
|
||||
@@ -106,8 +107,8 @@ FindBeamCenterFromBackground(const DiffractionExperiment &experiment, const Pixe
|
||||
const float pixel_size = geom.GetPixelSize_mm();
|
||||
const float distance = geom.GetDetectorDistance_mm();
|
||||
|
||||
float beam_x = geom.GetBeamX_pxl();
|
||||
float beam_y = geom.GetBeamY_pxl();
|
||||
float beam_x = start ? start->first : geom.GetBeamX_pxl();
|
||||
float beam_y = start ? start->second : geom.GetBeamY_pxl();
|
||||
|
||||
constexpr int n_cells = RADIAL_BINS * SECTORS;
|
||||
std::vector<int32_t> cell_of(n_pixels);
|
||||
@@ -359,3 +360,38 @@ FindBeamCenterFromBackground(const DiffractionExperiment &experiment, const Pixe
|
||||
return BeamCenterEstimate{beam_x, beam_y,
|
||||
std::max({sigma_x, sigma_y, std::hypot(step_x, step_y)})};
|
||||
}
|
||||
|
||||
std::optional<BeamCenterEstimate>
|
||||
FindBeamCenter(const DiffractionExperiment &experiment, const PixelMask &mask,
|
||||
const std::vector<float> &mean, size_t nthreads, BeamCenterFFTResult *capture) {
|
||||
// The image the capture scores: the projection with everything the mask excludes taken out.
|
||||
// The beam stop is in that mask by the time this runs, and it is the part that matters - an
|
||||
// opaque region on one side of the beam is centrosymmetric about ITS own centre, and where it
|
||||
// is large enough that preference beats the background's.
|
||||
std::vector<float> scored = mean;
|
||||
const auto &pixel_mask = mask.GetMask(experiment);
|
||||
if (pixel_mask.size() == scored.size())
|
||||
for (size_t i = 0; i < scored.size(); i++)
|
||||
if (pixel_mask[i] != 0)
|
||||
scored[i] = NAN;
|
||||
|
||||
const BeamCenterFFTResult fft = FindBeamCenterFFT(experiment, scored);
|
||||
if (capture)
|
||||
*capture = fft;
|
||||
if (fft.point.empty())
|
||||
return FindBeamCenterFromBackground(experiment, mask, mean, nthreads);
|
||||
|
||||
const std::pair<float, float> seed{fft.point[0].beam_x_pxl, fft.point[0].beam_y_pxl};
|
||||
if (auto refined = FindBeamCenterFromBackground(experiment, mask, mean, nthreads, seed))
|
||||
return refined;
|
||||
|
||||
// The walk has nothing to fit AT THE CAPTURE. That is a statement about the capture as much as
|
||||
// about the background: a centre far enough out leaves too few fully covered rings inside the
|
||||
// fitted band for the profile to exist at all. Measured on one small-molecule set whose capture
|
||||
// lands 536 px out - the walk from the file's centre answers there to 2.9 px, and taking the
|
||||
// capture instead would have been the composition's only regression on the corpus. So ask the
|
||||
// walk again where it used to be asked, and keep the capture only where neither start works.
|
||||
if (auto from_file = FindBeamCenterFromBackground(experiment, mask, mean, nthreads))
|
||||
return from_file;
|
||||
return BeamCenterEstimate{seed.first, seed.second, BEAM_CENTER_CAPTURE_SIGMA_PXL};
|
||||
}
|
||||
Reference in new issue
Block a user