Merge branch 'atg-arm-centre' into r4-integration
# Conflicts: # image_analysis/beam_stop/ShadowFinder.cpp # rugnux/Rugnux.cpp
This commit is contained in:
commit
0dab24241f
4 files changed
+28
-9
No files matched your search
@@ -834,7 +834,7 @@ std::vector<uint32_t> ShadowFinder::GetMask(size_t nthreads) const {
|
||||
for (int i = lo; i < hi; i++) {
|
||||
if (reflection_grown[i])
|
||||
region[i] = 0;
|
||||
mask[i] = region[i] ? 1 : 0;
|
||||
mask[i] = region[i] ? SHADOW : 0;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -885,7 +885,7 @@ std::vector<uint32_t> ShadowFinder::GetMask(size_t nthreads) const {
|
||||
if (n_dim >= MIN_SHADOW_PIXELS && n_low >= MIN_CORE_PIXELS)
|
||||
for (const int i : component)
|
||||
if (dim[i])
|
||||
mask[i] = 1;
|
||||
mask[i] = TRANSMITTING;
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
@@ -98,6 +98,9 @@ class ShadowFinder {
|
||||
[[nodiscard]] Projection Reduce() const;
|
||||
|
||||
public:
|
||||
static constexpr uint32_t SHADOW = 1;
|
||||
static constexpr uint32_t TRANSMITTING = 2;
|
||||
|
||||
ShadowFinder(const DiffractionExperiment &experiment, const PixelMask &mask);
|
||||
|
||||
// The centre the rings are drawn about. It starts as the file's, which is the only one there
|
||||
@@ -116,7 +119,9 @@ public:
|
||||
// decompression, reused across the calls of one worker.
|
||||
void AddImage(const DataMessage &data, std::vector<uint8_t> &buffer, size_t shard = 0);
|
||||
|
||||
// Compute the shadow mask (1 = shadow, 0 = keep), of the converted pixel count.
|
||||
// Compute the shadow mask (SHADOW, TRANSMITTING or 0 = keep), of the converted pixel count.
|
||||
// TRANSMITTING marks the pieces of hardware that let part of the beam through, added after the
|
||||
// shadow proper; both are masked, and a consumer that must not see those pieces can tell them apart.
|
||||
// Recomputed from the accumulators on each call - meant to be called once at the end.
|
||||
// nthreads = 0 asks for all hardware threads. The per-pixel passes over a 16M-pixel detector
|
||||
// dominate this, and they are all exactly parallel.
|
||||
|
||||
+17
-3
@@ -1310,6 +1310,7 @@ void Rugnux::PreScan(int start_image, int images_to_process, int frame_count, Ru
|
||||
|
||||
// Where the scattered background puts the beam, when the projection exists to say so.
|
||||
std::optional<std::pair<float, float>> ring_centre;
|
||||
std::vector<uint32_t> opaque_shadow;
|
||||
if (want_shadow) {
|
||||
// Every pixel is compared against the ring it sits on, so the rings have to be drawn about
|
||||
// the beam. A centre far enough out draws them across the background's own radial fall-off
|
||||
@@ -1337,8 +1338,12 @@ void Rugnux::PreScan(int start_image, int images_to_process, int frame_count, Ru
|
||||
experiment_.GetBeamX_pxl(), experiment_.GetBeamY_pxl());
|
||||
}
|
||||
const auto shadow = finder.GetMask(config_.nthreads);
|
||||
const auto shadowed = std::count(shadow.begin(), shadow.end(), 1u);
|
||||
const auto shadowed = std::count_if(shadow.begin(), shadow.end(), [](uint32_t v) { return v != 0; });
|
||||
pixel_mask_.LoadBeamStopMask(experiment_, shadow);
|
||||
opaque_shadow = shadow;
|
||||
for (auto &v : opaque_shadow)
|
||||
if (v == ShadowFinder::TRANSMITTING)
|
||||
v = 0;
|
||||
// Not "this beamline has no beam stop": it is also what a comparison drawn about the wrong
|
||||
// point returns, so an unexpected answer here is worth reading against the centre named
|
||||
// above first.
|
||||
@@ -1383,11 +1388,20 @@ void Rugnux::PreScan(int start_image, int images_to_process, int frame_count, Ru
|
||||
if (want_hot)
|
||||
MaskDefectivePixels(start_image, shadow_sample, ring_centre);
|
||||
|
||||
// The centre is fitted with the shadow masked but NOT the transmitting pieces the shadow finder
|
||||
// adds after it. Their dimming is multiplicative in azimuth, which the fit's per-sector amplitude
|
||||
// absorbs; masked, a thin arm running into the beam takes cells out of the rings it crosses, and
|
||||
// which rings stay covered then changes as the trial centre moves - a walk seeded beside such an
|
||||
// arm stalled on that edge 44 px from the centre it reaches with the arm left in.
|
||||
PixelMask centre_mask = pixel_mask_;
|
||||
if (!opaque_shadow.empty())
|
||||
centre_mask.LoadBeamStopMask(experiment_, opaque_shadow);
|
||||
|
||||
// It reads nothing the steps after it change, and nothing reads its answer before the first pass's
|
||||
// beam-centre check (RunPipeline), so it runs beside them - on copies of what it measures - and is
|
||||
// taken there (JoinBeamCenterCapture). It logs from its own thread.
|
||||
if (want_shadow && config_.beam_center_check)
|
||||
background_center_capture_ = std::async(std::launch::async, [x = experiment_, mask = pixel_mask_,
|
||||
background_center_capture_ = std::async(std::launch::async, [x = experiment_, mask = centre_mask,
|
||||
projection = finder.GetMeanProjection(),
|
||||
nthreads = config_.nthreads] {
|
||||
Logger logger("Rugnux");
|
||||
@@ -1593,7 +1607,7 @@ void Rugnux::PreScan(int start_image, int images_to_process, int frame_count, Ru
|
||||
// same geometry, same projection - so this asks for it again only where it was not run.
|
||||
estimate = background_center_
|
||||
? background_center_
|
||||
: FindBeamCenter(experiment_, pixel_mask_, finder.GetMeanProjection(),
|
||||
: FindBeamCenter(experiment_, centre_mask, finder.GetMeanProjection(),
|
||||
config_.nthreads);
|
||||
}
|
||||
if (!estimate) {
|
||||
|
||||
@@ -144,9 +144,9 @@ TEST_CASE("ShadowFinder_FindsAnArmThatLetsPartOfTheBeamThrough", "[ShadowFinder]
|
||||
|
||||
const auto mask = finder.GetMask();
|
||||
CHECK(mask[I(C, C)] == 1); // the stop
|
||||
CHECK(mask[I(GAP_X0 - 10, C)] == 1); // the arm where it transmits, before the gap
|
||||
CHECK(mask[I(GAP_X1 + 10, C + ARM_HALF_WIDE - 3)] == 1); // ... and after it
|
||||
CHECK(mask[I(W - 3, C)] == 1); // where it is opaque
|
||||
CHECK(mask[I(GAP_X0 - 10, C)] == ShadowFinder::TRANSMITTING); // the arm where it transmits, before the gap
|
||||
CHECK(mask[I(GAP_X1 + 10, C + ARM_HALF_WIDE - 3)] == ShadowFinder::TRANSMITTING); // ... and after it
|
||||
CHECK(mask[I(W - 3, C)] != 0); // where it is opaque
|
||||
CHECK(mask[I(GAP_X1 + 10, C + ARM_HALF_WIDE + 25)] == 0); // and nothing beside it
|
||||
CHECK(mask[I(0, 0)] == 0);
|
||||
CHECK(mask[I(C - 60, C)] == 0);
|
||||
|
||||
Reference in new issue
Block a user