1use crate::configuration::jsonable::JSONInputOutputDefinition;
2use crate::data_pipeline::per_channel_stream_caches::SensoryCorticalUnitCache;
3use crate::data_pipeline::{PipelineStageProperties, PipelineStagePropertyIndex};
4use crate::data_types::descriptors::PercentageChannelDimensionality;
5use crate::data_types::descriptors::{
6 ImageFrameProperties, MiscDataDimensions, SegmentedImageFrameProperties,
7};
8use crate::data_types::{
9 GazeProperties, ImageFrame, MiscData, Percentage, Percentage3D, SegmentedImageFrame,
10 SignedPercentage4D,
11};
12use crate::neuron_voxel_coding::xyzp::encoders::*;
13use crate::neuron_voxel_coding::xyzp::NeuronVoxelXYZPEncoder;
14use crate::wrapped_io_data::{WrappedIOData, WrappedIOType};
15use feagi_serialization::FeagiByteContainer;
16use feagi_structures::genomic::cortical_area::descriptors::{
17 CorticalChannelCount, CorticalChannelIndex, CorticalUnitIndex, NeuronDepth,
18};
19use feagi_structures::genomic::cortical_area::io_cortical_area_configuration_flag::{
20 FrameChangeHandling, PercentageNeuronPositioning,
21};
22use feagi_structures::genomic::cortical_area::CorticalID;
23use feagi_structures::genomic::SensoryCorticalUnit;
24use feagi_structures::neuron_voxels::xyzp::CorticalMappedXYZPNeuronVoxels;
25use feagi_structures::{sensor_cortical_units, FeagiDataError, FeagiSignal};
26use serde_json::json;
27use std::collections::HashMap;
28use std::fmt;
29use std::time::Instant;
30#[allow(unused_macros)] macro_rules! sensor_unit_functions {
36 (
37 SensoryCorticalUnit {
38 $(
39 $(#[doc = $doc:expr])?
40 $cortical_type_key_name:ident => {
41 friendly_name: $friendly_name:expr,
42 accepted_wrapped_io_data_type: $accepted_wrapped_io_data_type:ident,
43 cortical_id_unit_reference: $cortical_id_unit_reference:expr,
44 number_cortical_areas: $number_cortical_areas:expr,
45 cortical_type_parameters: {
46 $($param_name:ident: $param_type:ty),* $(,)?
47 },
48 $(allowed_frame_change_handling: [$($allowed_frame:ident),* $(,)?],)?
49 cortical_area_properties: {
50 $($area_index:tt => ($cortical_area_type_expr:expr, relative_position: [$rel_x:expr, $rel_y:expr, $rel_z:expr], channel_dimensions_default: [$dim_default_x:expr, $dim_default_y:expr, $dim_default_z:expr], channel_dimensions_min: [$dim_min_x:expr, $dim_min_y:expr, $dim_min_z:expr], channel_dimensions_max: [$dim_max_x:expr, $dim_max_y:expr, $dim_max_z:expr])),* $(,)?
51 }
52 }
53 ),* $(,)?
54 }
55 ) =>
56 {
57 $(
58 sensor_unit_functions!(@generate_functions
59 $cortical_type_key_name,
60 $accepted_wrapped_io_data_type
61 );
62 )*
63 };
64
65 (@generate_similar_functions
68 $cortical_type_key_name:ident,
69 $wrapped_data_type:ident
70 ) => {
71 ::paste::paste! {
72
73 pub fn [<$cortical_type_key_name:snake _write>](
74 &mut self,
75 unit: CorticalUnitIndex,
76 channel: CorticalChannelIndex,
77 data: WrappedIOData,
78 ) -> Result<(), FeagiDataError>
79 {
80 const SENSOR_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
81 let instant = Instant::now();
82
83 self.try_update_value(SENSOR_TYPE, unit, channel, data, instant)?;
84 Ok(())
85 }
86
87 pub fn [<$cortical_type_key_name:snake _read_postprocessed_cache_value>](
88 &mut self,
89 unit: CorticalUnitIndex,
90 channel: CorticalChannelIndex,
91 ) -> Result< $wrapped_data_type, FeagiDataError> {
92
93 const SENSOR_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
94 let wrapped = self.try_read_postprocessed_cached_value(SENSOR_TYPE, unit, channel)?;
95 let val: $wrapped_data_type = wrapped.try_into()?;
96 Ok(val)
97 }
98
99 pub fn [<$cortical_type_key_name:snake _get_single_stage_properties>](
100 &mut self,
101 unit: CorticalUnitIndex,
102 channel_index: CorticalChannelIndex,
103 stage_index: PipelineStagePropertyIndex
104 ) -> Result<PipelineStageProperties, FeagiDataError>
105 {
106 const SENSOR_UNIT_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
107 let stage = self.try_get_single_stage_properties(SENSOR_UNIT_TYPE, unit, channel_index, stage_index)?;
108 Ok(stage)
109 }
110
111 pub fn [<$cortical_type_key_name:snake _get_all_stage_properties>](
112 &mut self,
113 unit: CorticalUnitIndex,
114 channel_index: CorticalChannelIndex
115 ) -> Result<Vec<PipelineStageProperties>, FeagiDataError>
116 {
117 const SENSOR_UNIT_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
118 let stages = self.try_get_all_stage_properties(SENSOR_UNIT_TYPE, unit, channel_index)?;
119 Ok(stages)
120 }
121
122 pub fn [<$cortical_type_key_name:snake _update_single_stage_properties>](
123 &mut self,
124 unit: CorticalUnitIndex,
125 channel_index: CorticalChannelIndex,
126 pipeline_stage_property_index: PipelineStagePropertyIndex,
127 updating_property: PipelineStageProperties
128 ) -> Result<(), FeagiDataError>
129 {
130 const SENSOR_UNIT_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
131 self.try_update_single_stage_properties(SENSOR_UNIT_TYPE, unit, channel_index, pipeline_stage_property_index, updating_property)?;
132 Ok(())
133 }
134
135 pub fn [<$cortical_type_key_name:snake _update_all_stage_properties>](
136 &mut self,
137 unit: CorticalUnitIndex,
138 channel_index: CorticalChannelIndex,
139 updated_pipeline_stage_properties: Vec<PipelineStageProperties>
140 ) -> Result<(), FeagiDataError>
141 {
142 const SENSOR_UNIT_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
143 self.try_update_all_stage_properties(SENSOR_UNIT_TYPE, unit, channel_index, updated_pipeline_stage_properties)?;
144 Ok(())
145 }
146
147 pub fn [<$cortical_type_key_name:snake _replace_single_stage>](
148 &mut self,
149 unit: CorticalUnitIndex,
150 channel_index: CorticalChannelIndex,
151 pipeline_stage_property_index: PipelineStagePropertyIndex,
152 replacing_property: PipelineStageProperties
153 ) -> Result<(), FeagiDataError>
154 {
155 const SENSOR_UNIT_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
156 self.try_replace_single_stage(SENSOR_UNIT_TYPE, unit, channel_index, pipeline_stage_property_index, replacing_property)?;
157 Ok(())
158 }
159
160 pub fn [<$cortical_type_key_name:snake _replace_all_stages>](
161 &mut self,
162 unit: CorticalUnitIndex,
163 channel_index: CorticalChannelIndex,
164 new_pipeline_stage_properties: Vec<PipelineStageProperties>
165 ) -> Result<(), FeagiDataError>
166 {
167 const SENSOR_UNIT_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
168 self.try_replace_all_stages(SENSOR_UNIT_TYPE, unit, channel_index, new_pipeline_stage_properties)?;
169 Ok(())
170 }
171
172 pub fn [<$cortical_type_key_name:snake _removing_all_stages>](
173 &mut self,
174 unit: CorticalUnitIndex,
175 channel_index: CorticalChannelIndex
176 ) -> Result<(), FeagiDataError>
177 {
178 const SENSOR_UNIT_TYPE: SensoryCorticalUnit = SensoryCorticalUnit::$cortical_type_key_name;
179 self.try_removing_all_stages(SENSOR_UNIT_TYPE, unit, channel_index)?;
180 Ok(())
181 }
182 }
183 };
184 (@generate_functions
189 $sensory_unit:ident,
190 Boolean
191 ) => {
192 ::paste::paste! {
193 pub fn [<$sensory_unit:snake _register>](
194 &mut self,
195 unit: CorticalUnitIndex,
196 number_channels: CorticalChannelCount,
197 ) -> Result<(), FeagiDataError>
198 {
199 let cortical_id: CorticalID = SensoryCorticalUnit::[<get_cortical_ids_array_for_ $sensory_unit:snake _with_parameters>](unit)[0];
200 let encoder: Box<dyn NeuronVoxelXYZPEncoder + Sync + Send> = BooleanNeuronVoxelXYZPEncoder::new_box(cortical_id, number_channels)?;
201
202 let io_props: serde_json::Map<String, serde_json::Value> = json!({}).as_object().unwrap().clone();
203
204 let initial_val: WrappedIOData = false.into();
205 self.register(SensoryCorticalUnit::$sensory_unit, unit, encoder, io_props, number_channels, initial_val)?;
206 Ok(())
207 }
208 }
209
210 sensor_unit_functions!(@generate_similar_functions $sensory_unit, bool);
211 };
212
213 (@generate_functions
215 $sensory_unit:ident,
216 Percentage
217 ) => {
218 ::paste::paste! {
219 pub fn [<$sensory_unit:snake _register>](
220 &mut self,
221 unit: CorticalUnitIndex,
222 number_channels: CorticalChannelCount,
223 frame_change_handling: FrameChangeHandling,
224 z_neuron_resolution: NeuronDepth,
225 percentage_neuron_positioning: PercentageNeuronPositioning
226 ) -> Result<(), FeagiDataError>
227 {
228 let cortical_id: CorticalID = SensoryCorticalUnit::[<get_cortical_ids_array_for_ $sensory_unit:snake _with_parameters>](frame_change_handling, percentage_neuron_positioning, unit)[0];
229 let encoder: Box<dyn NeuronVoxelXYZPEncoder + Sync + Send> = PercentageNeuronVoxelXYZPEncoder::new_box(
230 cortical_id,
231 z_neuron_resolution,
232 number_channels,
233 percentage_neuron_positioning,
234 false,
235 PercentageChannelDimensionality::D1
236 )?;
237
238 let io_props: serde_json::Map<String, serde_json::Value> = json!({
239 "frame_change_handling": frame_change_handling,
240 "percentage_neuron_positioning": percentage_neuron_positioning
241 }).as_object().unwrap().clone();
242
243 let initial_val: WrappedIOData = WrappedIOData::Percentage(Percentage::new_zero());
244 self.register(SensoryCorticalUnit::$sensory_unit, unit, encoder, io_props, number_channels, initial_val)?;
245 Ok(())
246 }
247 }
248
249 sensor_unit_functions!(@generate_similar_functions $sensory_unit, Percentage);
250 };
251
252 (@generate_functions
254 $sensory_unit:ident,
255 Percentage_3D
256 ) => {
257 ::paste::paste! {
258 pub fn [<$sensory_unit:snake _register>](
259 &mut self,
260 unit: CorticalUnitIndex,
261 number_channels: CorticalChannelCount,
262 frame_change_handling: FrameChangeHandling,
263 z_neuron_resolution: NeuronDepth,
264 percentage_neuron_positioning: PercentageNeuronPositioning
265 ) -> Result<(), FeagiDataError>
266 {
267 let cortical_id: CorticalID = SensoryCorticalUnit::[<get_cortical_ids_array_for_ $sensory_unit:snake _with_parameters>](frame_change_handling, percentage_neuron_positioning, unit)[0];
268 let encoder: Box<dyn NeuronVoxelXYZPEncoder + Sync + Send> = PercentageNeuronVoxelXYZPEncoder::new_box(
269 cortical_id,
270 z_neuron_resolution,
271 number_channels,
272 percentage_neuron_positioning,
273 false,
274 PercentageChannelDimensionality::D3
275 )?;
276
277 let io_props: serde_json::Map<String, serde_json::Value> = json!({
278 "frame_change_handling": frame_change_handling,
279 "percentage_neuron_positioning": percentage_neuron_positioning
280 }).as_object().unwrap().clone();
281
282 let initial_val: WrappedIOData = WrappedIOData::Percentage(Percentage::new_zero());
283 self.register(SensoryCorticalUnit::$sensory_unit, unit, encoder, io_props, number_channels, initial_val)?;
284 Ok(())
285 }
286 }
287
288 sensor_unit_functions!(@generate_similar_functions $sensory_unit, Percentage3D);
289 };
290
291 (@generate_functions
293 $sensory_unit:ident,
294 SignedPercentage_4D
295 ) => {
296 ::paste::paste! {
297 pub fn [<$sensory_unit:snake _register>](
298 &mut self,
299 unit: CorticalUnitIndex,
300 number_channels: CorticalChannelCount,
301 frame_change_handling: FrameChangeHandling,
302 z_neuron_resolution: NeuronDepth,
303 percentage_neuron_positioning: PercentageNeuronPositioning
304 ) -> Result<(), FeagiDataError>
305 {
306 let cortical_id: CorticalID = SensoryCorticalUnit::[<get_cortical_ids_array_for_ $sensory_unit:snake _with_parameters>](frame_change_handling, percentage_neuron_positioning, unit)[0];
307 let encoder: Box<dyn NeuronVoxelXYZPEncoder + Sync + Send> = PercentageNeuronVoxelXYZPEncoder::new_box(
308 cortical_id,
309 z_neuron_resolution,
310 number_channels,
311 percentage_neuron_positioning,
312 true,
313 PercentageChannelDimensionality::D4
314 )?;
315
316 let io_props: serde_json::Map<String, serde_json::Value> = json!({
317 "frame_change_handling": frame_change_handling,
318 "percentage_neuron_positioning": percentage_neuron_positioning
319 }).as_object().unwrap().clone();
320
321 let initial_val: WrappedIOData = WrappedIOData::Percentage(Percentage::new_zero());
322 self.register(SensoryCorticalUnit::$sensory_unit, unit, encoder, io_props, number_channels, initial_val)?;
323 Ok(())
324 }
325 }
326
327 sensor_unit_functions!(@generate_similar_functions $sensory_unit, SignedPercentage4D);
328 };
329
330 (@generate_functions
332 $sensory_unit:ident,
333 SegmentedImageFrame
334 ) => {
335 ::paste::paste! {
336 pub fn [<$sensory_unit:snake _register>](
337 &mut self,
338 unit: CorticalUnitIndex,
339 number_channels: CorticalChannelCount,
340 frame_change_handling: FrameChangeHandling,
341 input_image_properties: ImageFrameProperties,
342 segmented_image_properties: SegmentedImageFrameProperties,
343 initial_gaze: GazeProperties
344 ) -> Result<(), FeagiDataError>
345 {
346 let cortical_ids: [CorticalID; 9] = SensoryCorticalUnit::[<get_cortical_ids_array_for_ $sensory_unit:snake _with_parameters>](frame_change_handling, unit);
348 let encoder: Box<dyn NeuronVoxelXYZPEncoder + Sync + Send> = SegmentedImageFrameNeuronVoxelXYZPEncoder::new_box(cortical_ids, segmented_image_properties, number_channels)?;
349
350 let io_props: serde_json::Map<String, serde_json::Value> = json!({
351 "frame_change_handling": frame_change_handling
352 }).as_object().unwrap().clone();
353
354 let initial_val: WrappedIOData = WrappedIOType::SegmentedImageFrame(Some(segmented_image_properties)).create_blank_data_of_type()?;
355 self.register(SensoryCorticalUnit::$sensory_unit, unit, encoder, io_props, number_channels, initial_val)?;
356
357 let stage_properties = PipelineStageProperties::new_image_frame_segmentator(input_image_properties.clone(), segmented_image_properties.clone(), initial_gaze.clone());
358
359 for channel_index in 0..*number_channels {
360 let segmentator_pipeline = vec![stage_properties.clone()];
361 self.[<$sensory_unit:snake _replace_all_stages>](unit, channel_index.into(), segmentator_pipeline);
362 }
363 Ok(())
364 }
365 }
366
367 sensor_unit_functions!(@generate_similar_functions $sensory_unit, SegmentedImageFrame);
368 };
369
370 (@generate_functions
372 $sensory_unit:ident,
373 MiscData
374 ) => {
375 ::paste::paste! {
376 pub fn [<$sensory_unit:snake _register>](
377 &mut self,
378 unit: CorticalUnitIndex,
379 number_channels: CorticalChannelCount,
380 frame_change_handling: FrameChangeHandling,
381 misc_data_dimensions: MiscDataDimensions
382 ) -> Result<(), FeagiDataError>
383 {
384 let cortical_id: CorticalID = SensoryCorticalUnit::[<get_cortical_ids_array_for_ $sensory_unit:snake _with_parameters>](frame_change_handling, unit)[0];
385 let encoder: Box<dyn NeuronVoxelXYZPEncoder + Sync + Send> = MiscDataNeuronVoxelXYZPEncoder::new_box(cortical_id, misc_data_dimensions, number_channels)?;
386
387 let io_props: serde_json::Map<String, serde_json::Value> = json!({
388 "frame_change_handling": frame_change_handling
389 }).as_object().unwrap().clone();
390
391 let initial_val: WrappedIOData = WrappedIOType::MiscData(Some(misc_data_dimensions)).create_blank_data_of_type()?;
392 self.register(SensoryCorticalUnit::$sensory_unit, unit, encoder, io_props, number_channels, initial_val)?;
393 Ok(())
394 }
395 }
396
397 sensor_unit_functions!(@generate_similar_functions $sensory_unit, MiscData);
398 };
399
400
401 (@generate_functions
403 $sensory_unit:ident,
404 ImageFrame
405 ) => {
406 ::paste::paste! {
407 pub fn [<$sensory_unit:snake _register>](
408 &mut self,
409 unit: CorticalUnitIndex,
410 number_channels: CorticalChannelCount,
411 frame_change_handling: FrameChangeHandling,
412 image_properties: ImageFrameProperties,
413 ) -> Result<(), FeagiDataError>
414 {
415 let cortical_id: CorticalID = SensoryCorticalUnit::[<get_cortical_ids_array_for_ $sensory_unit:snake _with_parameters>](frame_change_handling, unit)[0];
416 let encoder: Box<dyn NeuronVoxelXYZPEncoder + Sync + Send> = CartesianPlaneNeuronVoxelXYZPEncoder::new_box(cortical_id, &image_properties, number_channels)?;
417
418 let io_props: serde_json::Map<String, serde_json::Value> = json!({
419 "frame_change_handling": frame_change_handling
420 }).as_object().unwrap().clone();
421
422 let initial_val: WrappedIOData = WrappedIOType::ImageFrame(Some(image_properties)).create_blank_data_of_type()?;
423 self.register(SensoryCorticalUnit::$sensory_unit, unit, encoder, io_props, number_channels, initial_val)?;
424 Ok(())
425 }
426 }
427
428 sensor_unit_functions!(@generate_similar_functions $sensory_unit, ImageFrame);
429 };
430}
431
432pub struct SensorDeviceCache {
433 sensor_cortical_unit_caches:
434 HashMap<(SensoryCorticalUnit, CorticalUnitIndex), SensoryCorticalUnitCache>,
435 neuron_data: CorticalMappedXYZPNeuronVoxels,
436 byte_data: FeagiByteContainer,
437 previous_burst: Instant,
438 neurons_encoded_signal: FeagiSignal<CorticalMappedXYZPNeuronVoxels>,
439 bytes_encoded_signal: FeagiSignal<FeagiByteContainer>,
440}
441
442impl fmt::Debug for SensorDeviceCache {
443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444 f.debug_struct("SensorDeviceCache")
445 .field(
446 "stream_caches_count",
447 &self.sensor_cortical_unit_caches.len(),
448 )
449 .field("neuron_data", &self.neuron_data)
450 .field("byte_data", &self.byte_data)
451 .field("previous_burst", &self.previous_burst)
452 .finish()
453 }
454}
455
456impl Default for SensorDeviceCache {
457 fn default() -> Self {
458 Self::new()
459 }
460}
461
462#[allow(unused_must_use)]
463impl SensorDeviceCache {
464 pub fn new() -> Self {
465 SensorDeviceCache {
466 sensor_cortical_unit_caches: HashMap::new(),
467 neuron_data: CorticalMappedXYZPNeuronVoxels::new(),
468 byte_data: FeagiByteContainer::new_empty(),
469 previous_burst: Instant::now(),
470 neurons_encoded_signal: FeagiSignal::new(),
471 bytes_encoded_signal: FeagiSignal::new(),
472 }
473 }
474
475 pub fn reset(&mut self) {
477 self.sensor_cortical_unit_caches.clear();
478 self.neuron_data = CorticalMappedXYZPNeuronVoxels::new();
479 self.byte_data = FeagiByteContainer::new_empty();
480 self.previous_burst = Instant::now();
481 self.neurons_encoded_signal = FeagiSignal::new();
482 self.bytes_encoded_signal = FeagiSignal::new();
483 }
484 sensor_cortical_units!(sensor_unit_functions);
485
486 pub fn verify_existence(
487 &self,
488 sensory_cortical_unit: SensoryCorticalUnit,
489 unit_index: CorticalUnitIndex,
490 cortical_channel_index: CorticalChannelIndex,
491 ) -> Result<(), FeagiDataError> {
492 let sensor_stream_caches =
493 self.try_get_sensory_channel_stream_caches(sensory_cortical_unit, unit_index)?;
494 sensor_stream_caches.verify_channel_exists(cortical_channel_index)
495 }
496
497 pub fn try_get_index_of_first_stage_property_type_of(
498 &self,
499 sensory_cortical_unit: SensoryCorticalUnit,
500 unit_index: CorticalUnitIndex,
501 cortical_channel_index: CorticalChannelIndex,
502 property_example: &PipelineStageProperties,
503 ) -> Result<PipelineStagePropertyIndex, FeagiDataError> {
504 let sensor_stream_caches =
505 self.try_get_sensory_channel_stream_caches(sensory_cortical_unit, unit_index)?;
506 sensor_stream_caches
507 .try_get_first_index_of_stage_property_type(cortical_channel_index, property_example)
508 }
509
510 pub fn get_feagi_byte_container(&self) -> &FeagiByteContainer {
513 &self.byte_data
514 }
515
516 pub fn get_feagi_byte_container_mut(&mut self) -> &mut FeagiByteContainer {
517 &mut self.byte_data
518 }
519
520 pub fn get_neurons(&self) -> &CorticalMappedXYZPNeuronVoxels {
521 &self.neuron_data
522 }
523
524 pub fn encode_all_sensors_to_neurons(
537 &mut self,
538 time_of_burst: Instant,
539 ) -> Result<(), FeagiDataError> {
540 self.neuron_data.clear_neurons_only();
542
543 let previous_burst = self.previous_burst;
544
545 for ((_sensor_type, _unit_index), stream_cache) in
549 self.sensor_cortical_unit_caches.iter_mut()
550 {
551 stream_cache.update_neuron_data_with_recently_updated_cached_sensor_data(
552 &mut self.neuron_data,
553 previous_burst,
554 )?;
555 }
556
557 self.previous_burst = time_of_burst;
559
560 Ok(())
561 }
562
563 pub fn encode_neurons_to_bytes(&mut self) -> Result<(), FeagiDataError> {
572 self.byte_data
573 .overwrite_byte_data_with_single_struct_data(&self.neuron_data, 0)
574 .map_err(|e| {
575 FeagiDataError::BadParameters(format!(
576 "Failed to encode neuron data to bytes: {:?}",
577 e
578 ))
579 })?;
580 Ok(())
581 }
582
583 pub fn import_from_input_definition(
588 &mut self,
589 replacing_definition: &JSONInputOutputDefinition,
590 ) -> Result<(), FeagiDataError> {
591 self.reset();
592 let input_units_and_encoder_properties =
593 replacing_definition.get_input_units_and_encoder_properties();
594 for (sensory_unit, unit_and_encoder_definitions) in input_units_and_encoder_properties {
595 for unit_and_encoder_definition in unit_and_encoder_definitions {
596 let unit_definition = &unit_and_encoder_definition.0;
597 let encoder_definition = &unit_and_encoder_definition.1;
598
599 if self
600 .sensor_cortical_unit_caches
601 .contains_key(&(*sensory_unit, unit_definition.cortical_unit_index))
602 {
603 return Err(FeagiDataError::DeserializationError(format!(
604 "Already registered sensor {} of unit index {}!",
605 *sensory_unit, unit_definition.cortical_unit_index
606 )));
607 }
608
609 let new_unit = SensoryCorticalUnitCache::new_from_json(
610 sensory_unit,
611 unit_definition,
612 encoder_definition,
613 )?;
614 self.sensor_cortical_unit_caches.insert(
615 (*sensory_unit, unit_definition.cortical_unit_index),
616 new_unit,
617 );
618 }
619 }
620 Ok(())
621 }
622
623 pub fn export_to_input_definition(
624 &self,
625 filling_definition: &mut JSONInputOutputDefinition,
626 ) -> Result<(), FeagiDataError> {
627 for ((sensory_cortical_unit, cortical_unit_index), sensory_channel_stream_caches) in
628 self.sensor_cortical_unit_caches.iter()
629 {
630 let unit_and_encoder =
631 sensory_channel_stream_caches.export_as_jsons(*cortical_unit_index);
632 filling_definition.insert_sensor(
633 *sensory_cortical_unit,
634 unit_and_encoder.0,
635 unit_and_encoder.1,
636 );
637 }
638 Ok(())
639 }
640
641 fn register(
648 &mut self,
649 sensor_type: SensoryCorticalUnit,
650 unit_index: CorticalUnitIndex,
651 neuron_encoder: Box<dyn NeuronVoxelXYZPEncoder>,
652 io_configuration_flags: serde_json::Map<String, serde_json::Value>,
653 number_channels: CorticalChannelCount,
654 initial_cached_value: WrappedIOData,
655 ) -> Result<(), FeagiDataError> {
656 if self
657 .sensor_cortical_unit_caches
658 .contains_key(&(sensor_type, unit_index))
659 {
660 return Err(FeagiDataError::BadParameters(format!(
661 "Already registered sensor {} of unit index {}!",
662 sensor_type, unit_index
663 )));
664 }
665
666 self.sensor_cortical_unit_caches.insert(
667 (sensor_type, unit_index),
668 SensoryCorticalUnitCache::new(
669 neuron_encoder,
670 io_configuration_flags,
671 number_channels,
672 initial_cached_value,
673 )?,
674 );
675
676 Ok(())
677 }
678
679 fn try_update_value(
682 &mut self,
683 sensor_type: SensoryCorticalUnit,
684 unit_index: CorticalUnitIndex,
685 channel_index: CorticalChannelIndex,
686 value: WrappedIOData,
687 time_of_update: Instant,
688 ) -> Result<(), FeagiDataError> {
689 let sensor_stream_caches =
690 self.try_get_sensory_channel_stream_caches_mut(sensor_type, unit_index)?;
691 sensor_stream_caches.try_replace_input_channel_cache_value_and_run_pipeline(
692 channel_index,
693 value,
694 time_of_update,
695 )?; Ok(())
697 }
698
699 #[allow(dead_code)]
700 fn try_read_preprocessed_cached_value(
701 &self,
702 sensor_type: SensoryCorticalUnit,
703 unit_index: CorticalUnitIndex,
704 channel_index: CorticalChannelIndex,
705 ) -> Result<&WrappedIOData, FeagiDataError> {
706 let sensor_stream_caches =
707 self.try_get_sensory_channel_stream_caches(sensor_type, unit_index)?;
708 let value = sensor_stream_caches.try_get_channel_preprocessed_value(channel_index)?;
709 Ok(value)
710 }
711
712 fn try_read_postprocessed_cached_value(
713 &self,
714 sensor_type: SensoryCorticalUnit,
715 unit_index: CorticalUnitIndex,
716 channel_index: CorticalChannelIndex,
717 ) -> Result<&WrappedIOData, FeagiDataError> {
718 let sensor_stream_caches =
719 self.try_get_sensory_channel_stream_caches(sensor_type, unit_index)?;
720 let value =
721 sensor_stream_caches.try_get_channel_recent_postprocessed_value(channel_index)?;
722 Ok(value)
723 }
724
725 #[allow(dead_code)]
730 fn get_unit_friendly_name(
731 &self,
732 sensor_type: SensoryCorticalUnit,
733 unit_index: CorticalUnitIndex,
734 ) -> Result<&Option<String>, FeagiDataError> {
735 let sensor_stream_caches =
736 self.try_get_sensory_channel_stream_caches(sensor_type, unit_index)?;
737 Ok(sensor_stream_caches.get_friendly_name())
738 }
739
740 #[allow(dead_code)]
741 fn set_unit_friendly_name(
742 &mut self,
743 sensor_type: SensoryCorticalUnit,
744 unit_index: CorticalUnitIndex,
745 friendly_name: Option<String>,
746 ) -> Result<(), FeagiDataError> {
747 let sensor_stream_caches =
748 self.try_get_sensory_channel_stream_caches_mut(sensor_type, unit_index)?;
749 sensor_stream_caches.set_friendly_name(friendly_name);
750 Ok(())
751 }
752
753 fn try_get_single_stage_properties(
758 &self,
759 sensor_type: SensoryCorticalUnit,
760 unit_index: CorticalUnitIndex,
761 channel_index: CorticalChannelIndex,
762 pipeline_stage_property_index: PipelineStagePropertyIndex,
763 ) -> Result<PipelineStageProperties, FeagiDataError> {
764 let sensor_stream_caches =
765 self.try_get_sensory_channel_stream_caches(sensor_type, unit_index)?;
766 sensor_stream_caches
767 .try_get_single_stage_properties(channel_index, pipeline_stage_property_index)
768 }
769
770 fn try_get_all_stage_properties(
771 &self,
772 sensor_type: SensoryCorticalUnit,
773 unit_index: CorticalUnitIndex,
774 channel_index: CorticalChannelIndex,
775 ) -> Result<Vec<PipelineStageProperties>, FeagiDataError> {
776 let sensor_stream_caches =
777 self.try_get_sensory_channel_stream_caches(sensor_type, unit_index)?;
778 sensor_stream_caches.get_all_stage_properties(channel_index)
779 }
780
781 fn try_update_single_stage_properties(
782 &mut self,
783 sensor_type: SensoryCorticalUnit,
784 unit_index: CorticalUnitIndex,
785 channel_index: CorticalChannelIndex,
786 pipeline_stage_property_index: PipelineStagePropertyIndex,
787 replacing_property: PipelineStageProperties,
788 ) -> Result<(), FeagiDataError> {
789 let sensor_stream_caches =
790 self.try_get_sensory_channel_stream_caches_mut(sensor_type, unit_index)?;
791 sensor_stream_caches.try_update_single_stage_properties(
792 channel_index,
793 pipeline_stage_property_index,
794 replacing_property,
795 )
796 }
797
798 fn try_update_all_stage_properties(
799 &mut self,
800 sensor_type: SensoryCorticalUnit,
801 unit_index: CorticalUnitIndex,
802 channel_index: CorticalChannelIndex,
803 new_pipeline_stage_properties: Vec<PipelineStageProperties>,
804 ) -> Result<(), FeagiDataError> {
805 let sensor_stream_caches =
806 self.try_get_sensory_channel_stream_caches_mut(sensor_type, unit_index)?;
807 sensor_stream_caches
808 .try_update_all_stage_properties(channel_index, new_pipeline_stage_properties)
809 }
810
811 fn try_replace_single_stage(
812 &mut self,
813 sensor_type: SensoryCorticalUnit,
814 unit_index: CorticalUnitIndex,
815 channel_index: CorticalChannelIndex,
816 replacing_at_index: PipelineStagePropertyIndex,
817 new_pipeline_stage_properties: PipelineStageProperties,
818 ) -> Result<(), FeagiDataError> {
819 let sensor_stream_caches =
820 self.try_get_sensory_channel_stream_caches_mut(sensor_type, unit_index)?;
821 sensor_stream_caches.try_replace_single_stage(
822 channel_index,
823 replacing_at_index,
824 new_pipeline_stage_properties,
825 )
826 }
827
828 fn try_replace_all_stages(
829 &mut self,
830 sensor_type: SensoryCorticalUnit,
831 unit_index: CorticalUnitIndex,
832 channel_index: CorticalChannelIndex,
833 new_pipeline_stage_properties: Vec<PipelineStageProperties>,
834 ) -> Result<(), FeagiDataError> {
835 let sensor_stream_caches =
836 self.try_get_sensory_channel_stream_caches_mut(sensor_type, unit_index)?;
837 sensor_stream_caches.try_replace_all_stages(channel_index, new_pipeline_stage_properties)
838 }
839
840 fn try_removing_all_stages(
841 &mut self,
842 sensor_type: SensoryCorticalUnit,
843 unit_index: CorticalUnitIndex,
844 channel_index: CorticalChannelIndex,
845 ) -> Result<(), FeagiDataError> {
846 let sensor_stream_caches =
847 self.try_get_sensory_channel_stream_caches_mut(sensor_type, unit_index)?;
848 sensor_stream_caches.try_removing_all_stages(channel_index)?;
849 Ok(())
850 }
851
852 fn try_get_sensory_channel_stream_caches(
859 &self,
860 sensor_type: SensoryCorticalUnit,
861 unit_index: CorticalUnitIndex,
862 ) -> Result<&SensoryCorticalUnitCache, FeagiDataError> {
863 let check = self
864 .sensor_cortical_unit_caches
865 .get(&(sensor_type, unit_index));
866 if check.is_none() {
867 return Err(FeagiDataError::BadParameters(format!(
868 "Unable to find {} of cortical unit index {} in registered sensor's list!",
869 sensor_type, unit_index
870 )));
871 }
872 let check = check.unwrap();
873 Ok(check)
874 }
875
876 fn try_get_sensory_channel_stream_caches_mut(
877 &mut self,
878 sensor_type: SensoryCorticalUnit,
879 unit_index: CorticalUnitIndex,
880 ) -> Result<&mut SensoryCorticalUnitCache, FeagiDataError> {
881 let check = self
882 .sensor_cortical_unit_caches
883 .get_mut(&(sensor_type, unit_index));
884 if check.is_none() {
885 return Err(FeagiDataError::BadParameters(format!(
886 "Unable to find {} of cortical unit index {} in registered sensor's list!",
887 sensor_type, unit_index
888 )));
889 }
890 let check = check.unwrap();
891 Ok(check)
892 }
893
894 }
898
899impl fmt::Display for SensorDeviceCache {
900 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
901 Ok(writeln!(f, "Motor Device Cache:")?)
902 }
903}