From 3047ccd13e449870a5c2b7d19e5d2fd19c9e2676 Mon Sep 17 00:00:00 2001 From: Filip Leonarski Date: Sun, 8 Nov 2026 09:56:11 +0100 Subject: [PATCH] Receivers and pullers: comments as plain sentences, with the reasons put back Rewrites the one-line comments that did not parse (JFJochReceiverStream::ExpectedImages, ImagePuller's ring and republish cap) and restores what the comment-shortening pass dropped: the ZeroMQ pusher drops an image after one second, so a ring too small costs images; RugnuxStructure::Map's margin where the model reaches beyond the cell, and the header's mean and RMS being the cell's; RugnuxLiveStatus' time base, the START message preceding the first image by start_to_first_image_s, and the frame-rate formula. Code does not change. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01HVeDQsU5a8AJUdJPgWevAK --- image_puller/ImagePuller.h | 6 ++++-- image_puller/ZMQImagePuller.cpp | 3 ++- receiver/JFJochReceiverStream.cpp | 2 +- receiver/RugnuxLiveStatus.h | 4 +++- receiver/RugnuxStructure.h | 4 +++- 5 files changed, 13 insertions(+), 6 deletions(-) diff --git a/image_puller/ImagePuller.h b/image_puller/ImagePuller.h index dd91fcb5a..fec35d311 100644 --- a/image_puller/ImagePuller.h +++ b/image_puller/ImagePuller.h @@ -48,10 +48,12 @@ struct ImagePullerStatistics { class ImagePuller { protected: ThreadSafeFIFO outside_fifo; // assuming 1 file is <1000 files, this should be enough to buffer - // Bounds the bytes of received messages until consumed; size 0: on the heap, bounded by the queues alone + // Holds every received message until it is consumed. The queues count messages, the ring bounds bytes. + // With size 0 there is no ring: messages are held on the heap, bounded by the queues alone. ReceiveRingBuffer ring; - // Bytes republish holds now: capped at a share of the ring, as a slow republish consumer pins all received after + // Bytes republish holds now. Republish keeps the oldest unsent images and the ring is reclaimed in arrival order, + // so a slow republish consumer would pin everything received after them. That is why it is capped at a share of the ring. std::atomic repub_bytes{0}; bool RepubCanHold(size_t bytes) const { return ring.GetCapacity() == 0 || repub_bytes.load() + bytes <= ring.GetCapacity() / 4; diff --git a/image_puller/ZMQImagePuller.cpp b/image_puller/ZMQImagePuller.cpp index 533d392d2..377e88906 100644 --- a/image_puller/ZMQImagePuller.cpp +++ b/image_puller/ZMQImagePuller.cpp @@ -84,7 +84,8 @@ void ZMQImagePuller::PullerThread() { ret.raw = std::shared_ptr(new ReceiveBufferRegion{const_cast(msg->data()), msg->size()}, [msg](ReceiveBufferRegion *r) { delete r; }); } else { - // When the ring is full this waits, and the socket is not read: the sender's send blocks for as long as it waits + // When the ring is full this waits and the socket is not read, so the sender's send blocks. + // The broker's ZeroMQ pusher waits one second, then drops the image, so a ring too small for the writer's stalls costs images. ret.raw = ring.Allocate(msg->size()); if (!ret.raw) { // Stop() - the puller is being disconnected. diff --git a/receiver/JFJochReceiverStream.cpp b/receiver/JFJochReceiverStream.cpp index 7e843b6b0..d673a766c 100644 --- a/receiver/JFJochReceiverStream.cpp +++ b/receiver/JFJochReceiverStream.cpp @@ -256,7 +256,7 @@ void JFJochReceiverStream::AddToEndMessage(EndMessage &message) { message.adu_histogram = end_adu_histogram; } -// With the card summing, an image is many frames. +// The collection is counted in images, not frames. When the card sums frames, one image is many frames. int64_t JFJochReceiverStream::ExpectedImages() const { return experiment.GetImageNum(); } diff --git a/receiver/RugnuxLiveStatus.h b/receiver/RugnuxLiveStatus.h index a73c1ee2d..5c372c286 100644 --- a/receiver/RugnuxLiveStatus.h +++ b/receiver/RugnuxLiveStatus.h @@ -14,7 +14,9 @@ class RugnuxStructure; // RugnuxStructure.h struct ProcessResult; // rugnux/Rugnux.h -// Where the live rugnux run of the last collection is; times in seconds since the first image arrived +// Where the live rugnux run of the last collection is. +// Times come from the image puller (when a message came off the socket) and are in seconds since the first image arrived. +// The START message comes earlier, by start_to_first_image_s. The frame rate is (images_received - 1) / last_image_s. enum class RugnuxLiveState { Idle, Running, Done, Failed, Cancelled, Skipped }; struct RugnuxLiveStep { diff --git a/receiver/RugnuxStructure.h b/receiver/RugnuxStructure.h index d27129d85..39dd82183 100644 --- a/receiver/RugnuxStructure.h +++ b/receiver/RugnuxStructure.h @@ -42,7 +42,9 @@ public: // The coefficients include the anomalous difference map (ANOM/PHANOM): the merge kept the Bijvoet pairs. bool HasAnomalousMap() const; std::string ModelCif() const; - // A CCP4 map sampled every d_min/3, on one unit cell around the model; empty where there are no coefficients + // A CCP4 map sampled every d_min/3, on one unit cell centred on the model. + // Along an axis where the model reaches further than the cell, the map covers the model plus MAP_MARGIN_A instead. + // The mean and RMS in the header are those of the cell. Empty where there are no coefficients. std::string Map(RugnuxMapType type) const; };