Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FrameReceiver controllers, move FP controllers to odin_data.py #33

Merged
merged 1 commit into from
Sep 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion dev/one_node_fp/odin_server.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ adapters = fp, fr, mw
logging = error

[adapter.fr]
module = odin_data.control.frame_receiver_adapter.FrameReceiverAdapter
module = odin_data.control.odin_data_adapter.OdinDataAdapter
endpoints = 127.0.0.1:10000
update_interval = 0.2

Expand Down
2 changes: 1 addition & 1 deletion dev/two_node_fp/odin_server.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ adapters = fp, fr, mw
logging = error

[adapter.fr]
module = odin_data.control.frame_receiver_adapter.FrameReceiverAdapter
module = odin_data.control.odin_data_adapter.OdinDataAdapter
endpoints = 127.0.0.1:10000, 127.0.0.1:10010
update_interval = 0.2

Expand Down
4 changes: 1 addition & 3 deletions src/odin_fastcs/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@
from fastcs.backends.epics.gui import EpicsGUIOptions
from fastcs.connections.ip_connection import IPConnectionSettings

from odin_fastcs.odin_controller import (
OdinController,
)
from odin_fastcs.odin_controller import OdinController

from . import __version__

Expand Down
5 changes: 0 additions & 5 deletions src/odin_fastcs/frame_receiver.py

This file was deleted.

4 changes: 1 addition & 3 deletions src/odin_fastcs/odin_adapter_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@
from fastcs.util import snake_to_pascal

from odin_fastcs.http_connection import HTTPConnection
from odin_fastcs.util import (
OdinParameter,
)
from odin_fastcs.util import OdinParameter

types = {"float": Float(), "int": Int(), "bool": Bool(), "str": String()}

Expand Down
9 changes: 8 additions & 1 deletion src/odin_fastcs/odin_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,13 @@
from fastcs.datatypes import Bool, Float, Int, String

from odin_fastcs.eiger_fan import EigerFanAdapterController
from odin_fastcs.frame_processor import FrameProcessorAdapterController
from odin_fastcs.http_connection import HTTPConnection
from odin_fastcs.meta_writer import MetaWriterAdapterController
from odin_fastcs.odin_adapter_controller import OdinAdapterController
from odin_fastcs.odin_data import (
FrameProcessorAdapterController,
FrameReceiverAdapterController,
)
from odin_fastcs.util import OdinParameter, create_odin_parameters

types = {"float": Float(), "int": Int(), "bool": Bool(), "str": String()}
Expand Down Expand Up @@ -70,6 +73,10 @@
return FrameProcessorAdapterController(
connection, parameters, f"{self.API_PREFIX}/fp"
)
case "fr":
return FrameReceiverAdapterController(

Check warning on line 77 in src/odin_fastcs/odin_controller.py

View check run for this annotation

Codecov / codecov/patch

src/odin_fastcs/odin_controller.py#L76-L77

Added lines #L76 - L77 were not covered by tests
connection, parameters, f"{self.API_PREFIX}/fr"
)
case "mw":
return MetaWriterAdapterController(
connection, parameters, f"{self.API_PREFIX}/mw"
Expand Down
110 changes: 81 additions & 29 deletions src/odin_fastcs/frame_processor.py → src/odin_fastcs/odin_data.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import logging
import re
from collections.abc import Iterable, Sequence

Expand All @@ -12,27 +13,32 @@
)
from odin_fastcs.util import OdinParameter, partition

UNIQUE_FP_CONFIG = [
"rank",
"number",
"ctrl_endpoint",
"meta_endpoint",
"fr_ready_cnxn",
"fr_release_cnxn",
]

class OdinDataController(OdinAdapterController):
def _remove_metadata_fields_paths(self):
# paths ending in name or description are invalid in Odin's BaseParameterTree
self._parameters, invalid = partition(
self._parameters, lambda p: p.uri[-1] not in ["name", "description"]
)
if invalid:
invalid_names = ["/".join(param.uri) for param in invalid]
logging.warning(f"Removing parameters with invalid names: {invalid_names}")

class FrameProcessorAdapterController(OdinAdapterController):
def _process_parameters(self):
self._remove_metadata_fields_paths()
for parameter in self._parameters:
# Remove duplicate index from uri
parameter.uri = parameter.uri[1:]
# Remove redundant status/config from parameter path
parameter.set_path(parameter.uri[1:])


class OdinDataAdapterController(OdinAdapterController):
"""Sub controller for the frame processor adapter in an odin control server."""

frames_written: AttrR = AttrR(
Int(),
handler=StatusSummaryUpdater([re.compile("FP*"), "HDF"], "frames_written", sum),
)
writing: AttrR = AttrR(
Bool(),
handler=StatusSummaryUpdater([re.compile("FP*"), "HDF"], "writing", any),
)
_unique_config: list[str] = []
_subcontroller_label: str = "OD"
_subcontroller_cls: type[OdinDataController] = OdinDataController

async def initialise(self):
idx_parameters, self._parameters = partition(
Expand All @@ -45,12 +51,14 @@
idx_parameters, lambda p, idx=idx: p.uri[0] == idx
)

adapter_controller = FrameProcessorController(
adapter_controller = self._subcontroller_cls(
self._connection,
fp_parameters,
f"{self._api_prefix}/{idx}",
)
self.register_sub_controller(f"FP{idx}", adapter_controller)
self.register_sub_controller(
f"{self._subcontroller_label}{idx}", adapter_controller
)
await adapter_controller.initialise()

self._create_attributes()
Expand All @@ -62,11 +70,11 @@
for sub_controller in get_all_sub_controllers(self):
for parameter in sub_controller._parameters:
mode, key = parameter.uri[0], parameter.uri[-1]
if mode == "config" and key not in UNIQUE_FP_CONFIG:
if mode == "config" and key not in self._unique_config:
try:
attr = getattr(sub_controller, parameter.name)
except AttributeError:
print(
logging.warning(

Check warning on line 77 in src/odin_fastcs/odin_data.py

View check run for this annotation

Codecov / codecov/patch

src/odin_fastcs/odin_data.py#L77

Added line #L77 was not covered by tests
f"Controller has parameter {parameter}, "
f"but no corresponding attribute {parameter.name}"
)
Expand All @@ -88,7 +96,37 @@
)


class FrameProcessorController(OdinAdapterController):
class FrameReceiverController(OdinDataController):
async def initialise(self):
self._process_parameters()

def __decoder_parameter(parameter: OdinParameter):
return "decoder" in parameter.path[:-1]

decoder_parameters, self._parameters = partition(
self._parameters, __decoder_parameter
)
decoder_controller = FrameReceiverDecoderController(
self._connection, decoder_parameters, f"{self._api_prefix}"
)
self.register_sub_controller("DECODER", decoder_controller)
await decoder_controller.initialise()
self._create_attributes()


class FrameReceiverAdapterController(OdinDataAdapterController):
_subcontroller_label = "FR"
_subcontroller_cls = FrameReceiverController


class FrameReceiverDecoderController(OdinAdapterController):
def _process_parameters(self):
for parameter in self._parameters:
# remove redundant status/decoder part from path
parameter.set_path(parameter.uri[2:])


class FrameProcessorController(OdinDataController):
"""Sub controller for a frame processor application."""

async def initialise(self):
Expand All @@ -109,13 +147,6 @@
await self._create_plugin_sub_controllers(plugins)
self._create_attributes()

def _process_parameters(self):
for parameter in self._parameters:
# Remove duplicate index from uri
parameter.uri = parameter.uri[1:]
# Remove redundant status/config from parameter path
parameter.set_path(parameter.uri[1:])

async def _create_plugin_sub_controllers(self, plugins: Sequence[str]):
for plugin in plugins:

Expand All @@ -136,6 +167,27 @@
await plugin_controller.initialise()


class FrameProcessorAdapterController(OdinDataAdapterController):
frames_written: AttrR = AttrR(
Int(),
handler=StatusSummaryUpdater([re.compile("FP*"), "HDF"], "frames_written", sum),
)
writing: AttrR = AttrR(
Bool(),
handler=StatusSummaryUpdater([re.compile("FP*"), "HDF"], "writing", any),
)
_unique_config = [
"rank",
"number",
"ctrl_endpoint",
"meta_endpoint",
"fr_ready_cnxn",
"fr_release_cnxn",
]
_subcontroller_label = "FP"
_subcontroller_cls = FrameProcessorController


class FrameProcessorPluginController(OdinAdapterController):
"""SubController for a plugin in a frameProcessor application."""

Expand Down
154 changes: 154 additions & 0 deletions tests/input/two_node_fr_response.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
{
"api": {
"value": 0.1,
"writeable": false,
"type": "float"
},
"module": {
"value": "OdinDataAdapter",
"writeable": false,
"type": "str"
},
"endpoints": [
{
"ip_address": {
"value": "127.0.0.1",
"writeable": false,
"type": "str"
},
"port": {
"value": 10000,
"writeable": false,
"type": "int"
}
},
{
"ip_address": {
"value": "127.0.0.1",
"writeable": false,
"type": "str"
},
"port": {
"value": 10010,
"writeable": false,
"type": "int"
}
}
],
"count": {
"value": 2,
"writeable": false,
"type": "int"
},
"update_interval": {
"value": 0.2,
"writeable": false,
"type": "float"
},
"0": {
"status": {
"status": {
"ipc_configured": true,
"decoder_configured": true,
"buffer_manager_configured": true,
"rx_thread_configured": true,
"configuration_complete": true
},
"decoder": {
"name": "DummyUDPFrameDecoder",
"status_get_count": 7,
"packets_received": 0,
"packets_lost": 0,
"packets_dropped": 0
},
"buffers": {
"total": 292,
"empty": 292,
"mapped": 0
},
"frames": {
"timedout": 0,
"received": 0,
"released": 0,
"dropped": 0
},
"timestamp": "2024-08-29T13:56:17.796578",
"error": [],
"connected": true
},
"config": {
"ctrl_endpoint": "tcp://0.0.0.0:10000",
"rx_endpoint": "inproc://rx_channel",
"frame_ready_endpoint": "tcp://127.0.0.1:10001",
"frame_release_endpoint": "tcp://127.0.0.1:10002",
"decoder_path": "/scratch/hqv85942/scratchprojects/fast2/odin-data/prefix//lib",
"decoder_type": "DummyUDP",
"decoder_config": {
"enable_packet_logging": false,
"frame_timeout_ms": 1000,
"udp_packets_per_frame": 359,
"udp_packet_size": 8000
},
"shared_buffer_name": "OdinDataBuffer",
"max_buffer_mem": 840000000,
"rx_type": "udp",
"rx_address": "0.0.0.0",
"rx_ports": "61649",
"rx_recv_buffer_size": 30000000,
"frame_count": 1953718630
}
},
"1": {
"status": {
"status": {
"ipc_configured": true,
"decoder_configured": true,
"buffer_manager_configured": true,
"rx_thread_configured": true,
"configuration_complete": true
},
"decoder": {
"name": "DummyUDPFrameDecoder",
"status_get_count": 7,
"packets_received": 0,
"packets_lost": 0,
"packets_dropped": 0
},
"buffers": {
"total": 292,
"empty": 292,
"mapped": 0
},
"frames": {
"timedout": 0,
"received": 0,
"released": 0,
"dropped": 0
},
"timestamp": "2024-08-29T13:56:17.817041",
"error": [],
"connected": true
},
"config": {
"ctrl_endpoint": "tcp://0.0.0.0:10010",
"rx_endpoint": "inproc://rx_channel",
"frame_ready_endpoint": "tcp://127.0.0.1:10011",
"frame_release_endpoint": "tcp://127.0.0.1:10012",
"decoder_path": "/scratch/hqv85942/scratchprojects/fast2/odin-data/prefix//lib",
"decoder_type": "DummyUDP",
"decoder_config": {
"enable_packet_logging": false,
"frame_timeout_ms": 1000,
"udp_packets_per_frame": 359,
"udp_packet_size": 8000
},
"shared_buffer_name": "OdinDataBuffer",
"max_buffer_mem": 840000000,
"rx_type": "udp",
"rx_address": "0.0.0.0",
"rx_ports": "61650",
"rx_recv_buffer_size": 30000000,
"frame_count": 1953718630
}
}
}
Loading
Loading