feagi_structures/genomic/
sensory_cortical_unit.rs1use crate::genomic::cortical_area::descriptors::CorticalSubUnitIndex;
2use crate::genomic::cortical_area::descriptors::CorticalUnitIndex;
3use crate::genomic::cortical_area::io_cortical_area_configuration_flag::{
4 FrameChangeHandling, PercentageNeuronPositioning,
5};
6use crate::genomic::cortical_area::{
7 CorticalAreaType, CorticalID, IOCorticalAreaConfigurationFlag,
8};
9use crate::sensor_cortical_units;
10use paste;
11use serde_json::{Map, Value};
12use std::collections::HashMap;
13use std::fmt::{Display, Formatter};
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub struct UnitTopology {
17 pub relative_position: [i32; 3],
18 pub channel_dimensions_default: [u32; 3],
19 pub channel_dimensions_min: [u32; 3],
20 pub channel_dimensions_max: [u32; 3],
21}
22
23macro_rules! default_firing_threshold_impl {
24 () => {
25 None
26 };
27 ($value:expr) => {
28 Some($value)
29 };
30}
31
32macro_rules! default_mp_charge_accumulation_impl {
33 () => {
34 None
35 };
36 ($value:expr) => {
37 Some($value)
38 };
39}
40
41macro_rules! define_sensory_cortical_units_enum {
42 (
43 SensoryCorticalUnit {
44 $(
45 $(#[doc = $doc:expr])?
46 $variant_name:ident => {
47 friendly_name: $friendly_name:expr,
48 accepted_wrapped_io_data_type: $accepted_wrapped_io_data_type:expr,
49 cortical_id_unit_reference: $cortical_id_unit_reference:expr,
50 number_cortical_areas: $number_cortical_areas:expr,
51 $(default_firing_threshold: $default_firing_threshold:expr,)?
52 $(default_mp_charge_accumulation: $default_mp_charge_accumulation:expr,)?
53 cortical_type_parameters: {
54 $($param_name:ident: $param_type:ty),* $(,)?
55 },
56 $(allowed_frame_change_handling: [$($allowed_frame:ident),* $(,)?],)? cortical_area_properties: {
58 $($cortical_sub_unit_index:tt => ($io_cortical_area_configuration_flag_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])),* $(,)?
59 }
60 }
61 ),* $(,)?
62 }
63 ) => {
64 #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, serde::Serialize, serde::Deserialize)]
65 pub enum SensoryCorticalUnit {
66 $(
67 $(#[doc = $doc])?
68 $variant_name,
69 )*
70 }
71
72 impl SensoryCorticalUnit {
73 $(
74 paste::paste! {
75 #[doc = "Get cortical area types array for " $friendly_name " using individual parameters."]
76 pub const fn [<get_cortical_area_types_array_for_ $variant_name:snake _with_parameters >](
77 $($param_name: $param_type),*) -> [CorticalAreaType; $number_cortical_areas] {
78 [
79 $(CorticalAreaType::BrainInput($io_cortical_area_configuration_flag_expr)),*
80 ]
81 }
82
83 #[doc = "Get cortical IDs array for " $friendly_name " using individual parameters."]
84 pub const fn [<get_cortical_ids_array_for_ $variant_name:snake _with_parameters >](
85 $($param_name: $param_type,)* cortical_unit_index: CorticalUnitIndex) -> [CorticalID; $number_cortical_areas] {
86 let cortical_unit_identifier: [u8; 3] = $cortical_id_unit_reference;
87 [
88 $(
89 $io_cortical_area_configuration_flag_expr .as_io_cortical_id(true, cortical_unit_identifier, cortical_unit_index, CorticalSubUnitIndex::from($cortical_sub_unit_index))
90 ),*
91 ]
92 }
93 }
94 )*
95
96 pub const fn get_snake_case_name(&self) -> &'static str {
97 match self {
98 $(
99 SensoryCorticalUnit::$variant_name => paste::paste!{ stringify!([<$variant_name:snake>]) },
100 )*
101 }
102 }
103
104 pub fn from_snake_case_name(name: &str) -> Option<SensoryCorticalUnit> {
113 match name {
114 $(
115 paste::paste!{ stringify!([<$variant_name:snake>]) } => Some(SensoryCorticalUnit::$variant_name),
116 )*
117 _ => None,
118 }
119 }
120
121 pub const fn list_all() -> &'static [SensoryCorticalUnit] {
124 &[
125 $(
126 SensoryCorticalUnit::$variant_name,
127 )*
128 ]
129 }
130
131 pub const fn get_friendly_name(&self) -> &'static str {
133 match self {
134 $(
135 SensoryCorticalUnit::$variant_name => $friendly_name,
136 )*
137 }
138 }
139
140 pub const fn get_cortical_id_unit_reference(&self) -> [u8; 3] {
142 match self {
143 $(
144 SensoryCorticalUnit::$variant_name => $cortical_id_unit_reference,
145 )*
146 }
147 }
148
149 pub const fn get_number_cortical_areas(&self) -> usize {
151 match self {
152 $(
153 SensoryCorticalUnit::$variant_name => $number_cortical_areas,
154 )*
155 }
156 }
157
158 pub const fn get_default_firing_threshold(&self) -> Option<f64> {
161 match self {
162 $(
163 SensoryCorticalUnit::$variant_name => {
164 default_firing_threshold_impl!($($default_firing_threshold)?)
165 }
166 )*
167 }
168 }
169
170 pub const fn get_default_mp_charge_accumulation(&self) -> Option<bool> {
173 match self {
174 $(
175 SensoryCorticalUnit::$variant_name => {
176 default_mp_charge_accumulation_impl!($($default_mp_charge_accumulation)?)
177 }
178 )*
179 }
180 }
181
182 pub const fn get_accepted_wrapped_io_data_type(&self) -> &'static str { match self {
185 $(
186 SensoryCorticalUnit::$variant_name => stringify!($accepted_wrapped_io_data_type),
187 )*
188 }
189 }
190
191 pub fn get_unit_default_topology(&self) -> HashMap<CorticalSubUnitIndex, UnitTopology> {
193 match self {
194 $(
195 SensoryCorticalUnit::$variant_name => {
196 let mut topology = HashMap::new();
197 $(
198 topology.insert(
199 CorticalSubUnitIndex::from($cortical_sub_unit_index),
200 UnitTopology {
201 relative_position: [$rel_x, $rel_y, $rel_z],
202 channel_dimensions_default: [$dim_default_x, $dim_default_y, $dim_default_z],
203 channel_dimensions_min: [$dim_min_x, $dim_min_y, $dim_min_z],
204 channel_dimensions_max: [$dim_max_x, $dim_max_y, $dim_max_z],
205 }
206 );
207 )*
208 topology
209 }
210 )*
211 }
212 }
213
214
215 pub fn get_allowed_frame_change_handling(&self) -> Option<&'static [FrameChangeHandling]> { match self {
220 $(
221 SensoryCorticalUnit::$variant_name => {
222 $crate::get_allowed_frame_change_handling_impl!($($($allowed_frame),*)?)
223 }
224 )*
225 }
226 }
227
228 pub fn get_cortical_id_vector_from_index_and_serde_io_configuration_flags(&self, cortical_unit_index: CorticalUnitIndex, map: Map<String, Value>) -> Result<Vec<CorticalID>, crate::FeagiDataError> {
229 match self {
230 $(
231 SensoryCorticalUnit::$variant_name => {
232 paste::paste! {
233 let array = SensoryCorticalUnit::[<get_cortical_ids_array_for_ $variant_name:snake _with_parameters >](
234 $($param_type::try_from_serde_map(&map)?,)*
235 cortical_unit_index);
236 return Ok(array.to_vec());
237 }
238 }
239 )*
240 }
241 }
242
243
244
245 }
246
247 impl Display for SensoryCorticalUnit {
248 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
249 match self {
250 $(
251 SensoryCorticalUnit::$variant_name => write!(f, $friendly_name),
252 )*
253 }
254 }
255 }
256 };
257
258}
259sensor_cortical_units!(define_sensory_cortical_units_enum);
261
262impl SensoryCorticalUnit {
263 pub fn try_from_legacy_subtype(subtype: &str) -> Option<CorticalID> {
266 let subtype_bytes = subtype.as_bytes();
267 if subtype_bytes.len() != 3 {
268 return None;
269 }
270 let subtype_arr = [subtype_bytes[0], subtype_bytes[1], subtype_bytes[2]];
271 for unit in Self::list_all() {
272 if unit.get_cortical_id_unit_reference() == subtype_arr {
273 return Some(unit.get_default_cortical_id_for_group(CorticalUnitIndex::from(0u8)));
274 }
275 }
276 None
277 }
278
279 pub fn get_default_cortical_id_for_group(&self, group_index: CorticalUnitIndex) -> CorticalID {
281 use crate::genomic::cortical_area::io_cortical_area_configuration_flag::{
282 FrameChangeHandling, PercentageNeuronPositioning,
283 };
284 let fh = FrameChangeHandling::Absolute;
285 let pos = PercentageNeuronPositioning::Linear;
286 match self {
287 SensoryCorticalUnit::Infrared => {
288 Self::get_cortical_ids_array_for_infrared_with_parameters(fh, pos, group_index)[0]
289 }
290 SensoryCorticalUnit::Proximity => {
291 Self::get_cortical_ids_array_for_proximity_with_parameters(fh, pos, group_index)[0]
292 }
293 SensoryCorticalUnit::Shock => {
294 Self::get_cortical_ids_array_for_shock_with_parameters(fh, pos, group_index)[0]
295 }
296 SensoryCorticalUnit::Battery => {
297 Self::get_cortical_ids_array_for_battery_with_parameters(fh, pos, group_index)[0]
298 }
299 SensoryCorticalUnit::Servo => {
300 Self::get_cortical_ids_array_for_servo_with_parameters(fh, pos, group_index)[0]
301 }
302 SensoryCorticalUnit::AnalogGPIO => {
303 Self::get_cortical_ids_array_for_analog_g_p_i_o_with_parameters(
304 fh,
305 pos,
306 group_index,
307 )[0]
308 }
309 SensoryCorticalUnit::DigitalGPIO => {
310 Self::get_cortical_ids_array_for_digital_g_p_i_o_with_parameters(group_index)[0]
311 }
312 SensoryCorticalUnit::MiscData => {
313 Self::get_cortical_ids_array_for_misc_data_with_parameters(fh, group_index)[0]
314 }
315 SensoryCorticalUnit::TextEnglishInput => {
316 Self::get_cortical_ids_array_for_text_english_input_with_parameters(fh, group_index)
317 [0]
318 }
319 SensoryCorticalUnit::CountInput => {
320 Self::get_cortical_ids_array_for_count_input_with_parameters(fh, pos, group_index)
321 [0]
322 }
323 SensoryCorticalUnit::Vision => {
324 Self::get_cortical_ids_array_for_vision_with_parameters(fh, group_index)[0]
325 }
326 SensoryCorticalUnit::SegmentedVision => {
327 Self::get_cortical_ids_array_for_segmented_vision_with_parameters(fh, group_index)
328 [0]
329 }
330 SensoryCorticalUnit::Accelerometer => {
331 Self::get_cortical_ids_array_for_accelerometer_with_parameters(fh, pos, group_index)
332 [0]
333 }
334 SensoryCorticalUnit::Gyroscope => {
335 Self::get_cortical_ids_array_for_gyroscope_with_parameters(fh, pos, group_index)[0]
336 }
337 }
338 }
339}