diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ufo-roof-buffer.c | 34 | ||||
-rw-r--r-- | src/ufo-roof-buffer.h | 7 | ||||
-rw-r--r-- | src/ufo-roof-build-task.c | 86 | ||||
-rw-r--r-- | src/ufo-roof-config.c | 143 | ||||
-rw-r--r-- | src/ufo-roof-config.h | 43 | ||||
-rw-r--r-- | src/ufo-roof.h | 2 |
6 files changed, 243 insertions, 72 deletions
diff --git a/src/ufo-roof-buffer.c b/src/ufo-roof-buffer.c index 179d153..bac940c 100644 --- a/src/ufo-roof-buffer.c +++ b/src/ufo-roof-buffer.c @@ -9,15 +9,24 @@ // This is currently not thread safe. With dual-filter architecture this will be called sequentially. -UfoRoofBuffer *ufo_roof_buffer_new(UfoRoofConfig *cfg, guint max_datasets, GError **error) { +UfoRoofBuffer *ufo_roof_buffer_new(UfoRoofConfig *cfg, guint n_dims, guint max_datasets, GError **error) { + if ((n_dims < 1)||(n_dims > 2)) + roof_new_error(error, "Unsupported number of dimmensions %u (only plain and 2D ROOF structure is currently supported)", n_dims); + UfoRoofBuffer *buffer = (UfoRoofBuffer*)calloc(1, sizeof(UfoRoofBuffer)); if (!buffer) roof_new_error(error, "Can't allocate UfoRoofBuffer"); buffer->max_datasets = max_datasets; buffer->ring_size = cfg->buffer_size; buffer->drop_buffers = cfg->drop_buffers; - buffer->fragment_size = cfg->payload_size; + buffer->n_dims = n_dims; buffer->dataset_size = cfg->dataset_size; + buffer->dataset_dims[0] = cfg->fan_bins * cfg->bit_depth / 8; + buffer->dataset_dims[1] = cfg->fan_projections; + buffer->fragment_size = cfg->payload_size; + buffer->fragment_dims[0] = cfg->channels_per_module * cfg->bit_depth / 8; + buffer->fragment_dims[1] = buffer->fragment_size / buffer->fragment_dims[0]; + buffer->fragments_per_dataset = buffer->dataset_size / buffer->fragment_size; buffer->fragments_per_stream = buffer->fragments_per_dataset / cfg->n_streams; // printf("Configuration: dataset: %u - %u fragments (%u streams x %u) x %u bytes\n", buffer->dataset_size, buffer->fragments_per_dataset, cfg->n_streams, buffer->fragments_per_stream, buffer->fragment_size); @@ -96,15 +105,25 @@ gboolean ufo_roof_buffer_set_fragment(UfoRoofBuffer *buffer, guint stream_id, gu // The updates may happen after writting/reading is finished. } - // FIXME: This is builds events as it read from file in roof v.1 code. We can assemble fan projections directly here. - uint8_t *dataset_buffer = buffer->ring_buffer + buffer_id * buffer->dataset_size; - uint8_t *fragment_buffer = dataset_buffer + (stream_id * buffer->fragments_per_stream + fragment_id) * buffer->fragment_size; - /* printf("buffer: %u (%u), packet: %u (%ux%u %u), packet_size: %u [%x]\n", buffer_id, dataset_id, stream_id * buffer->fragments_per_stream + fragment_id, stream_id, buffer->fragments_per_stream, fragment_id, buffer->fragment_size, ((uint32_t*)fragment)[0] );*/ - memcpy(fragment_buffer, fragment, buffer->fragment_size); + + uint8_t *dataset_buffer = buffer->ring_buffer + buffer_id * buffer->dataset_size; + if (buffer->n_dims == 2) { + uint8_t *fragment_buffer = dataset_buffer + + stream_id * buffer->fragment_dims[0] + // x-coordinate + (fragment_id * buffer->fragment_dims[1]) * buffer->dataset_dims[0]; // y-coordinate + + for (int i = 0; i < buffer->fragment_dims[1]; ++i) { + memcpy(fragment_buffer + i * buffer->dataset_dims[0], fragment + i * buffer->fragment_dims[0], buffer->fragment_dims[0]); + } + } else { + // 1D stracture, simply putting fragment at the appropriate position in the stream + uint8_t *fragment_buffer = dataset_buffer + (stream_id * buffer->fragments_per_stream + fragment_id) * buffer->fragment_size; + memcpy(fragment_buffer, fragment, buffer->fragment_size); + } // FIXME: Sanity checks: verify is not a dublicate fragment? atomic_fetch_add(&buffer->n_fragments[buffer_id], 1); @@ -128,6 +147,7 @@ gboolean ufo_roof_buffer_get_dataset(UfoRoofBuffer *buffer, gpointer output_buff if (buffer->n_fragments[buffer_id] < buffer->fragments_per_dataset) return FALSE; memcpy(output_buffer, dataset_buffer, buffer->dataset_size); + buffer->n_fragments[buffer_id] = 0; buffer->current_id += 1; diff --git a/src/ufo-roof-buffer.h b/src/ufo-roof-buffer.h index c4c8474..7ebaec9 100644 --- a/src/ufo-roof-buffer.h +++ b/src/ufo-roof-buffer.h @@ -15,16 +15,19 @@ struct _UfoRoofBuffer { guint max_datasets; // Only the specified number of datasets will be buffered, the rest will be silently dropped + guint n_dims; // Indicates if we just assemble one fragment after another or there is 2D/3D data structure (ROOF) guint dataset_size; // Size (in bytes) of a full dataset + guint dataset_dims[2]; // x (in bytes), y (in rows) guint fragment_size; // Size (in bytes) of a single fragment (we expect fixed-size fragments at the moment) - + guint fragment_dims[2]; // x (in bytes), y (in rows) + guint fragments_per_dataset; // Number of packets in dataset (used to compute when dataset is ready) guint fragments_per_stream; // Number of packets in each of data streams (used to compute when dataset is ready) }; typedef struct _UfoRoofBuffer UfoRoofBuffer; -UfoRoofBuffer *ufo_roof_buffer_new(UfoRoofConfig *cfg, guint max_datasets, GError **error); +UfoRoofBuffer *ufo_roof_buffer_new(UfoRoofConfig *cfg, guint n_dims, guint max_datasets, GError **error); void ufo_roof_buffer_free(UfoRoofBuffer *buf); gboolean ufo_roof_buffer_set_fragment(UfoRoofBuffer *buffer, guint stream_id, guint fragment_id, gconstpointer fragment, GError **error); diff --git a/src/ufo-roof-build-task.c b/src/ufo-roof-build-task.c index e5e5518..8af44db 100644 --- a/src/ufo-roof-build-task.c +++ b/src/ufo-roof-build-task.c @@ -29,12 +29,19 @@ #include "ufo-roof-buffer.h" #include "ufo-roof-build-task.h" +typedef enum { + BUILD_AUTO = 0, + BUILD_RAW, + BUILD_SINO, + BUILD_UFO +} BuildType; struct _UfoRoofBuildTaskPrivate { gchar *config; // ROOF configuration file name UfoRoofConfig *cfg; // Parsed ROOF parameters UfoRoofBuffer *buf; // Ring buffer for incomming UDP packet + BuildType build; // What dataset do we build: ROOF sinogram or raw network data guint number; // Number of datasets to read gboolean stop; // Stop flag @@ -51,10 +58,21 @@ G_DEFINE_TYPE_WITH_CODE (UfoRoofBuildTask, ufo_roof_build_task, UFO_TYPE_TASK_NO #define UFO_ROOF_BUILD_TASK_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE((obj), UFO_TYPE_ROOF_BUILD_TASK, UfoRoofBuildTaskPrivate)) + + +static GEnumValue build_values[] = { + { BUILD_AUTO, "BUILD_AUTO", "auto" }, + { BUILD_RAW, "BUILD_RAW", "raw" }, + { BUILD_SINO, "BUILD_SINO", "sino" }, + { BUILD_UFO, "BUILD_UFO", "ufo" }, + { 0, NULL, NULL} +}; + enum { PROP_0, PROP_STOP, PROP_NUMBER, + PROP_BUILD, PROP_CONFIG, N_PROPERTIES }; @@ -83,8 +101,13 @@ ufo_roof_build_task_setup (UfoTask *task, if (!priv->cfg) roof_propagate_error(error, gerr, "roof-build-setup: "); + if (priv->build == BUILD_AUTO) { + if (priv->cfg->roof_mode) priv->build = BUILD_SINO; + else priv->build = BUILD_RAW; + g_object_notify_by_pspec (G_OBJECT(task), properties[PROP_BUILD]); + } - priv->buf = ufo_roof_buffer_new(priv->cfg, priv->number, &gerr); + priv->buf = ufo_roof_buffer_new(priv->cfg, (priv->build == BUILD_RAW)?1:2, priv->number, &gerr); if (!priv->buf) roof_propagate_error(error, gerr, "roof-build-setup: "); @@ -103,7 +126,7 @@ ufo_roof_build_task_finalize (GObject *object) if (priv->cfg) { ufo_roof_config_free(priv->cfg); - priv->cfg = NULL; + priv->cfg = NULL; } if (priv->config) { @@ -125,12 +148,21 @@ ufo_roof_build_task_get_requisition (UfoTask *task, { UfoRoofBuildTaskPrivate *priv = UFO_ROOF_BUILD_TASK_GET_PRIVATE (task); - guint bytes = priv->cfg->dataset_size; - - // FIXME: Can this be made more elegant? - requisition->n_dims = 1; - requisition->dims[0] = bytes / sizeof(float) + ((bytes%sizeof(float))?1:0); - + // FIXME: Can we handle data types more elegant? + if (priv->build == BUILD_RAW) { + guint bytes = priv->cfg->dataset_size; + requisition->n_dims = 1; + requisition->dims[0] = bytes / sizeof(float) + ((bytes%sizeof(float))?1:0); + } else if (priv->build == BUILD_SINO) { + guint bytes = priv->cfg->fan_bins * priv->cfg->bit_depth / 8; + requisition->n_dims = 2; + requisition->dims[0] = bytes / sizeof(float) + ((bytes%sizeof(float))?1:0); + requisition->dims[1] = priv->cfg->fan_projections; + } else if (priv->build == BUILD_UFO) { + requisition->n_dims = 2; + requisition->dims[0] = priv->cfg->fan_bins; + requisition->dims[1] = priv->cfg->fan_projections; + } } static guint @@ -222,9 +254,9 @@ ufo_roof_build_task_generate (UfoTask *task, { gboolean ready = FALSE; GError *gerr = NULL; - + UfoRoofBuildTaskPrivate *priv = UFO_ROOF_BUILD_TASK_GET_PRIVATE (task); -// UfoRoofConfig *cfg = priv->cfg; + UfoRoofConfig *cfg = priv->cfg; UfoRoofBuffer *buf = priv->buf; void *output_buffer = ufo_buffer_get_host_array(output, NULL); @@ -235,6 +267,20 @@ ufo_roof_build_task_generate (UfoTask *task, ready = ufo_roof_buffer_get_dataset(buf, output_buffer, &gerr); if (gerr) roof_print_error(gerr); + if (priv->build == BUILD_UFO) { + switch (cfg->bit_depth) { + case 8: + ufo_buffer_convert(output, UFO_BUFFER_DEPTH_8U); + break; + case 16: + ufo_buffer_convert(output, UFO_BUFFER_DEPTH_16U); + break; + case 32: + ufo_buffer_convert(output, UFO_BUFFER_DEPTH_32U); + break; + } + } + // FIXME: Or shall we start from counting from the ID of the first registerd dataset if ((priv->number)&&(buf->current_id >= priv->number)) { // printf("%u datasets processed, stopping\n", buf->current_id); @@ -242,8 +288,7 @@ ufo_roof_build_task_generate (UfoTask *task, g_object_notify_by_pspec (G_OBJECT(task), properties[PROP_STOP]); } - - if ((priv->number < 100)||((buf->current_id - priv->announced) > 1000)) { + if (((priv->number > 0)&&(priv->number <= 100))||((buf->current_id - priv->announced) > 1000)) { printf("Generating dataset %i (%s), next: %u out of %u)\n", buf->current_id, ready?"yes":" no", buf->n_fragments[buf->current_id%buf->ring_size], buf->fragments_per_dataset); priv->announced = buf->current_id; } @@ -270,6 +315,13 @@ ufo_roof_build_task_set_property (GObject *object, case PROP_NUMBER: priv->number = g_value_get_uint (value); break; + case PROP_BUILD: + priv->build = g_value_get_enum (value); + if ((priv->build == BUILD_AUTO)&&(priv->cfg)) { + if (priv->cfg->roof_mode) priv->build = BUILD_SINO; + else priv->build = BUILD_RAW; + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -294,6 +346,9 @@ ufo_roof_build_task_get_property (GObject *object, case PROP_NUMBER: g_value_set_uint (value, priv->number); break; + case PROP_BUILD: + g_value_set_enum (value, priv->build); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); break; @@ -342,6 +397,13 @@ ufo_roof_build_task_class_init (UfoRoofBuildTaskClass *klass) 0, G_MAXUINT, 0, G_PARAM_READWRITE); + properties[PROP_BUILD] = + g_param_spec_enum ("build", + "Build type (\"raw\", \"sino\", \"ufo\")", + "Build type (\"raw\" - raw data, \"sino\" - arrange in sinogram, \"ufo\" - arrange in sinogram and convert UFO floating-point format)", + g_enum_register_static ("build", build_values), + 0, G_PARAM_READWRITE); + for (guint i = PROP_0 + 1; i < N_PROPERTIES; i++) g_object_class_install_property (oclass, i, properties[i]); diff --git a/src/ufo-roof-config.c b/src/ufo-roof-config.c index 812d4a2..4788a2a 100644 --- a/src/ufo-roof-config.c +++ b/src/ufo-roof-config.c @@ -5,6 +5,7 @@ #include <ufo/ufo.h> +#include "ufo-roof.h" #include "ufo-roof-error.h" #include "ufo-roof-config.h" @@ -59,10 +60,13 @@ UfoRoofConfig *ufo_roof_config_new(const char *config, GError **error) { // JsonNode *node; JsonObject *root = NULL; JsonObject *hardware = NULL; + JsonObject *geometry = NULL; + JsonObject *optics = NULL; JsonObject *network = NULL; JsonObject *performance = NULL; JsonObject *simulation = NULL; - + JsonObject *reconstruction = NULL; + GError *gerr = NULL; priv = (UfoRoofConfigPrivate*)malloc(sizeof(UfoRoofConfigPrivate)); @@ -73,11 +77,20 @@ UfoRoofConfig *ufo_roof_config_new(const char *config, GError **error) { // Set defaults cfg = &priv->cfg; - cfg->port = 4000; + cfg->roof_mode = FALSE; + cfg->n_planes = 2; + cfg->n_modules = 16; + cfg->channels_per_module = 16; + cfg->bit_depth = 16; + cfg->samples_per_rotation = 1000; + cfg->sample_rate = 0; + cfg->imaging_rate = 0; + + cfg->port = 52067; cfg->n_streams = 1; cfg->protocol = "udp"; cfg->network_timeout = 10000000; - cfg->header_size = 0; + cfg->header_size = sizeof(UfoRoofPacketHeader); cfg->payload_size = 0; cfg->max_packet_size = 0; cfg->max_packets = 100; @@ -86,11 +99,12 @@ UfoRoofConfig *ufo_roof_config_new(const char *config, GError **error) { cfg->drop_buffers = 0; cfg->path = NULL; + // Read configuration priv->parser = json_parser_new_immutable (); json_parser_load_from_file (priv->parser, config, &gerr); - if (gerr != NULL) { + if (gerr != NULL) { g_propagate_prefixed_error(error, gerr, "Error parsing JSON file (%s) with ROOF configuration: ", config); ufo_roof_config_free(cfg); return NULL; @@ -100,75 +114,124 @@ UfoRoofConfig *ufo_roof_config_new(const char *config, GError **error) { if (root) { roof_config_node_get(hardware, root, object, "hardware"); + roof_config_node_get(geometry, root, object, "geometry"); + roof_config_node_get(optics, root, object, "optics"); roof_config_node_get(network, root, object, "network"); + roof_config_node_get(reconstruction, root, object, "reconstruction"); roof_config_node_get(simulation, root, object, "simulation"); roof_config_node_get(performance, root, object, "performance"); } if (hardware) { - // FIXME: Compute dataset size based on roof hardware + roof_config_node_get(cfg->n_planes, hardware, int, "planes"); + roof_config_node_get(cfg->n_modules, hardware, int, "modules"); + roof_config_node_get(cfg->channels_per_module, hardware, int, "channels_per_module"); + roof_config_node_get(cfg->bit_depth, hardware, int, "bit_depth"); + + roof_config_node_get(cfg->samples_per_rotation, hardware, int, "samples_per_rotation"); + roof_config_node_get(cfg->sample_rate, hardware, int, "sample_rate"); + roof_config_node_get(cfg->imaging_rate, hardware, int, "imaging_rate"); + + if ((cfg->sample_rate)||(cfg->imaging_rate)) { + if ((!cfg->sample_rate)||(!cfg->imaging_rate)||(cfg->sample_rate%cfg->imaging_rate)) { + ufo_roof_config_free(cfg); + roof_new_error(error, "Invalid sample (%u) and imaging (%u) rates are specified", cfg->sample_rate, cfg->imaging_rate); + } + + if ((json_object_get_member(hardware, "samples_per_rotation"))&&(cfg->samples_per_rotation != (cfg->sample_rate / cfg->imaging_rate))) { + ufo_roof_config_free(cfg); + roof_new_error(error, "The specified samples-per-rotation (%u) doesn't match sample/imaging rates (%u / %u)", cfg->samples_per_rotation, cfg->sample_rate, cfg->imaging_rate); + } + + cfg->samples_per_rotation = cfg->sample_rate / cfg->imaging_rate; + } + + if ((cfg->bit_depth%8)||(cfg->bit_depth > 32)) { + ufo_roof_config_free(cfg); + roof_new_error(error, "Invalid bit-depth (%u) is configured, only 8, 16, 24, 32 is currently supported", cfg->bit_depth); + } + + cfg->fan_projections = cfg->samples_per_rotation; + cfg->fan_bins = cfg->n_modules * cfg->channels_per_module; + + cfg->dataset_size = cfg->fan_projections * cfg->fan_bins * (cfg->bit_depth / 8); + cfg->n_streams = cfg->n_modules; + cfg->roof_mode = TRUE; } if (network) { -// int max_packet_size = 0; - roof_config_node_get(cfg->port, network, int, "port"); roof_config_node_get(cfg->n_streams, network, int, "streams"); - roof_config_node_get(cfg->max_packet_size, network, int, "max_packet_size"); - // FIXME: compute payload_size based on sample_size roof_config_node_get(cfg->payload_size, network, int, "payload_size"); roof_config_node_get(cfg->header_size, network, int, "header_size"); - roof_config_node_get(cfg->dataset_size, network, int, "dataset_size"); - } - - if (performance) { - roof_config_node_get(cfg->max_packets, performance, int, "packets_at_once"); - roof_config_node_get(cfg->buffer_size, performance, int, "buffer_size"); - roof_config_node_get(cfg->drop_buffers, performance, int, "drop_buffers"); + roof_config_node_get(cfg->max_packet_size, network, int, "max_packet_size"); + roof_config_node_get(cfg->dataset_size, network, int, "dataset_size"); + + if (!cfg->payload_size) { + ufo_roof_config_free(cfg); + roof_new_error(error, "Packet payload and header size must be set"); + } + + if ((cfg->header_size < sizeof(UfoRoofPacketHeader))&&(!strncmp(cfg->protocol, "udp", 3))) { + ufo_roof_config_free(cfg); + roof_new_error(error, "The header with packet id (%lu bytes) is expected for un-ordered protocols", sizeof(UfoRoofPacketHeader)); + } + + if (!cfg->dataset_size) + cfg->dataset_size = cfg->payload_size; } if (simulation) { roof_config_node_get_string(cfg->path, simulation, "path"); roof_config_node_get(cfg->first_file_number, simulation, int, "first_file_number"); + roof_config_node_get(cfg->header_size, simulation, int, "header_size"); + + if (!cfg->payload_size) + cfg->payload_size = cfg->dataset_size; } - // Check configuration consistency - if (!cfg->payload_size) { - ufo_roof_config_free(cfg); - roof_new_error(error, "Packet size is not set"); - } - - if ((!cfg->header_size)&&(!cfg->path)) { - if (!strncmp(cfg->protocol, "udp", 3)) { - // Error if 0 implicitely set, use default value otherwise - if ((network)&&(json_object_get_member(network, "header_size"))) { - ufo_roof_config_free(cfg); - roof_new_error(error, "The header with packet ids is required for un-ordered protocols"); - } else { - cfg->header_size = sizeof(uint32_t); - } - } + if (performance) { + roof_config_node_get(cfg->max_packets, performance, int, "packets_at_once"); + roof_config_node_get(cfg->buffer_size, performance, int, "buffer_size"); + roof_config_node_get(cfg->drop_buffers, performance, int, "drop_buffers"); } + + // Check configuration consistency guint fragments_per_dataset = cfg->dataset_size / cfg->payload_size; guint fragments_per_stream = fragments_per_dataset / cfg->n_streams; + // Dataset should be split in an integer number of network packets (we don't expect data from different datasets in one packet at the moment) if ((cfg->dataset_size % cfg->payload_size)||(fragments_per_dataset%cfg->n_streams)) { ufo_roof_config_free(cfg); roof_new_error(error, "Inconsistent ROOF configuration: dataset_size=%u, packet_size=%u, data_streams=%u", cfg->dataset_size, cfg->payload_size, cfg->n_streams); } - if (cfg->buffer_size * fragments_per_stream < cfg->max_packets) { - cfg->max_packets = cfg->buffer_size * fragments_per_stream / 2; + // Packet should contain an integer number of complete projections (their parts provided by a single module) + if ((cfg->roof_mode)&&(cfg->payload_size % (cfg->channels_per_module * (cfg->bit_depth / 8)))) { + ufo_roof_config_free(cfg); + roof_new_error(error, "Inconsistent ROOF configuration: packet_size=%u, projection_size=%u (%u channels x %u bits)", cfg->payload_size, cfg->channels_per_module * (cfg->bit_depth / 8), cfg->channels_per_module, cfg->bit_depth); } - - // Finalize configuration + if (!cfg->max_packet_size) - cfg->max_packet_size = cfg->header_size + cfg->payload_size; + cfg->max_packet_size = cfg->header_size + cfg->payload_size; + + if (hardware) { + if (cfg->n_modules != cfg->n_streams) { + ufo_roof_config_free(cfg); + roof_new_error(error, "Currently, number of ROOF modules (%u) is exepcted to be equal to number of independent data streams (%u)", cfg->n_modules, cfg->n_streams); + } + + if (cfg->dataset_size != (cfg->fan_projections * cfg->fan_bins * cfg->bit_depth / 8)) { + ufo_roof_config_free(cfg); + roof_new_error(error, "Specified dataset size (%u) does not match ROOF configuration (modules: %u, channels-per-module: %u, bit-depth: %u, samples-per-rotation: %u)", cfg->dataset_size, cfg->n_modules, cfg->channels_per_module, cfg->bit_depth, cfg->samples_per_rotation); + } + } - if (!cfg->dataset_size) - cfg->dataset_size = cfg->payload_size; + if ((cfg->buffer_size * fragments_per_stream) < cfg->max_packets) { + cfg->max_packets = cfg->buffer_size * fragments_per_stream / 2; + } if (cfg->buffer_size < 4) { cfg->drop_buffers = 0; @@ -176,5 +239,7 @@ UfoRoofConfig *ufo_roof_config_new(const char *config, GError **error) { cfg->drop_buffers = cfg->buffer_size / 2; } + printf("dataset size: %i\n", cfg->dataset_size); + return cfg; } diff --git a/src/ufo-roof-config.h b/src/ufo-roof-config.h index f90c5f3..b6ee748 100644 --- a/src/ufo-roof-config.h +++ b/src/ufo-roof-config.h @@ -4,30 +4,51 @@ #include <glib.h> typedef struct { + // ROOF Hardware + gboolean roof_mode; // Indicates if ROOF is configured (1), otherwise only networking is implemented + guint n_planes; // Number of detector planes, ROOF module serves a ring segment from all planes in a round-robin fashion + guint n_modules; // Number of ROOF modules + guint channels_per_module; // Number of pixels in each module + guint samples_per_rotation; // Number of samples (projections) in a full fan sinogram; computed from sample_rate & image_rate if given + guint sample_rate; // Number of samples (projections) acquired per second, 0 - if unknown + guint imaging_rate; // Number of complete datasets (images) acquired per second, 0 - if unknown + guint bit_depth; // Number of bits per pixel (we currently support only multiples of 8) + + // Geometry + guint fan_projections; // Number of fan projections = samples_per_rotation + guint fan_bins; // Number of fan detectors = n_modules * channels_per_module + guint parallel_projections; + guint parallel_bins; +// guint detector_diameter; + + // Optics + + + // Network Server / Reader gchar *path; // Location of data files for simmulation purposes (i.e. reading a sequence of files instead listening on the corresponding ports) guint first_file_number; // Indicates if the numbering of files starts at 0 or 1 gchar *protocol; // Protocols: tcp, udp, tcp6, udp6, ... guint port; // First port - guint n_streams; // Number of independent data streams (expected on sequential ports) + guint n_streams; // Number of independent data streams (expected on sequential ports), by default equal to number of ROOF modules guint header_size; // Expected size of the packet header, for dgram protocols we need at least 32-bit sequence number. Defaults to uint32_t for udp* and 0 - otherwise guint payload_size; // Expected size of TCP/UDP packet (without header) - guint dataset_size; // Size of a single dataset (image, sinogram, etc.). This is real size in bytes, excluding all technical headers used in communication protocol. + guint dataset_size; // Size of a single dataset (image, sinogram, etc.). This is real size in bytes, excluding all technical headers used in communication protocol. Normally, it is computed based on ROOF hardware parameters. + + // Performance parameters + guint max_packets; // limits maximum number of packets which are read at once + guint max_packet_size; // payload_size + header_size + ... (we don't care if tail is variable length provided that the complete packet does not exceed max_packet_size bytes) + guint buffer_size; // How many datasets we can buffer. There is no sense to have more than 2 for odered protocols (default), but having larger number could help for UDP if significant order disturbances are expected + guint drop_buffers; // If we are slow and lost some buffers, we may drop more than minimally necessary to catch up. + guint network_timeout; // Maximum time (us) to wait for data on the socket + -//? /* - guint pixels_per_module; guint planes_per_module; - guint samples_per_dataset; */ - guint max_packets; // limits maximum number of packets which are read at once - guint max_packet_size; // payload_size + header_size + ...? - guint buffer_size; // How many datasets we can buffer. There is no sense to have more than 2 for odered protocols (default), but having larger number could help for UDP if significant order disturbances are expected - guint drop_buffers; // If we are slow and lost some buffers, we may drop more than minimally necessary to catch up. - guint network_timeout; // Maximum time (us) to wait for data on the socket - + } UfoRoofConfig; diff --git a/src/ufo-roof.h b/src/ufo-roof.h index d9d3a57..9303045 100644 --- a/src/ufo-roof.h +++ b/src/ufo-roof.h @@ -8,7 +8,7 @@ #define UFO_ROOF_PACKET_BLOCK_HEADER(buf, cfg) ((UfoRoofPacketBlockHeader*)(((uint8_t*)buf) + cfg->max_packets * cfg->max_packet_size)) typedef struct { - uint32_t packet_id; // Sequential Packet ID (numbered from 0) + uint64_t packet_id; // Sequential Packet ID (numbered from 0) } UfoRoofPacketHeader; typedef struct { |