Skip to content

Sample detection#570

Open
tfarago wants to merge 15 commits intomasterfrom
sample-detection
Open

Sample detection#570
tfarago wants to merge 15 commits intomasterfrom
sample-detection

Conversation

@tfarago
Copy link
Copy Markdown
Contributor

@tfarago tfarago commented Nov 21, 2025

Wat's new

  1. zmq's receiver can wait until stop() really stops
  2. We can have zmq.PUB/zmq.SUB addons
  3. We have SampleDetector addon
  4. viewer can display a rectangle around an object

Why so much

Adding sample detection addon which tracks the sample and at the end creates the larges bounding box does not need to be zmq.PUSH/zmq.PULL, but the "unreliable" zmq.PUB/zmq.SUB, because we do not need to analyze every image and thus drain resources. That in turn means that we have to be able to wait for ZmqReceiver.stop(), which turns all zmq business to asyncio and that means all classes ZmqBase, ZmqReceiver, ..., have to subclass AsyncObject. And that means, all code that uses them and their new asyncio functions had to be changed.

TODOS

  • test underlying network changes - request stop of receiver mostly
  • test sample detection
  • test imageprocessing's image conversion
  • test storage's write_image
  • update docs

Example session

import asyncio
import logging
import os
import numpy as np
import zmq
from inspect import iscoroutinefunction
import concert
concert.require("0.34.0")

from concert.coroutines.base import background
from concert.devices.cameras.dummy import FileCamera
from concert.helpers import CommData
from concert.readers import TiffSequenceReader
from concert.quantities import q
from concert.networking.base import get_tango_device, ZmqReceiver
from concert.session.utils import ddoc, dstate, pdoc, code_of
from concert.ext.viewers import PyQtGraphViewer

LOG = logging.getLogger(__name__)
MULTIINSTANCE = False


async def detect(image):
    encoding = f"{image.shape[1]}/{image.shape[0]}/{image.dtype}"
    blob = image.tobytes()

    return await device.sample_detect((encoding, blob))


device = get_tango_device(f'{os.uname()[1]}:1239/concert/tango/sampledetect#dbase=no', timeout=1000 * q.s)
await device.write_attribute("model_path", "/mnt/fast3/best.pt")    # This is the AI model
viewer = await PyQtGraphViewer(show_refresh_rate=True)

com = CommData(host="localhost", port=18999, protocol="tcp", socket_type=zmq.PUB, sndhwm=1)
com_viewer = CommData(host="localhost", port=18998, protocol="tcp", socket_type=zmq.PUB, sndhwm=1)
camera = await FileCamera(YOU_REPLACE_WITH_PATH_TO_RADIOS)
await camera.register_endpoint(com)
await camera.register_endpoint(com_viewer)
await device.write_attribute("receiver_reliable", False)
await device.write_attribute("receiver_rcvhwm", 1)
await device.write_attribute("endpoint", com.client_endpoint)
if (await device.read_attribute("sending_port")).value != 19000:
    await device.write_attribute("sending_port", 19000)
await camera.start_recording()
viewer.subscribe("tcp://localhost:18998", "image")
viewer.subscribe("tcp://localhost:19000", "metadata")

Example usage

sampledetect > f = device.stream_detect(); await camera.grab_send(1500)
sampledetect > await viewer.draw_rectangle(await device.get_maximum_rectangle())

which allows us to wait for stopping receiver's subscription, which in
turn enables us to have unreliable tango processing servers
(unreliable=zmq.PUB/SUB)
E.g. sample's bounding box is broadcasted as metadata.
@codecov
Copy link
Copy Markdown

codecov bot commented Nov 21, 2025

Codecov Report

❌ Patch coverage is 28.65014% with 259 lines in your changes missing coverage. Please review.
✅ Project coverage is 81.79%. Comparing base (f59ded9) to head (e1d2bce).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
concert/ext/tangoservers/sampledetect.py 0.00% 99 Missing ⚠️
concert/ext/tangoservers/base.py 0.00% 38 Missing ⚠️
concert/experiments/addons/tango.py 0.00% 23 Missing ⚠️
concert/experiments/addons/base.py 25.00% 18 Missing ⚠️
concert/ext/tangoservers/reco.py 0.00% 17 Missing ⚠️
concert/ext/tangoservers/walker.py 0.00% 16 Missing ⚠️
concert/imageprocessing.py 6.66% 14 Missing ⚠️
concert/storage.py 37.50% 10 Missing ⚠️
concert/experiments/addons/local.py 38.46% 8 Missing ⚠️
concert/networking/base.py 85.45% 8 Missing ⚠️
... and 3 more
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #570      +/-   ##
==========================================
- Coverage   83.52%   81.79%   -1.73%     
==========================================
  Files         133      134       +1     
  Lines       10718    10993     +275     
==========================================
+ Hits         8952     8992      +40     
- Misses       1766     2001     +235     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants