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