feagi_structures/genomic/
motor_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::genomic::sensory_cortical_unit::UnitTopology;
10use crate::motor_cortical_units;
11use paste;
12use serde_json::{Map, Value};
13use std::collections::HashMap;
14use std::fmt::{Display, Formatter};
15
16#[macro_export]
18macro_rules! get_allowed_frame_change_handling_impl { () => {
20 None
21 };
22 ($($allowed:ident),+) => {
23 Some(&[$(FrameChangeHandling::$allowed),+] as &'static [FrameChangeHandling])
24 };
25}
26
27macro_rules! define_motor_cortical_units_enum {
28 (
29 MotorCorticalUnit {
30 $(
31 $(#[doc = $doc:expr])?
32 $variant_name:ident => {
33 friendly_name: $friendly_name:expr,
34 accepted_wrapped_io_data_type: $accepted_wrapped_io_data_type:expr,
35 cortical_id_unit_reference: $cortical_id_unit_reference:expr,
36 number_cortical_areas: $number_cortical_areas:expr,
37 cortical_type_parameters: {
38 $($param_name:ident: $param_type:ty),* $(,)?
39 },
40 $(allowed_frame_change_handling: [$($allowed_frame:ident),* $(,)?],)? cortical_area_properties: {
42 $($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])),* $(,)?
43 }
44 }
45 ),* $(,)?
46 }
47 ) => {
48 #[derive(Debug, Hash, PartialEq, Eq, Clone, Copy, serde::Deserialize, serde::Serialize)]
49 pub enum MotorCorticalUnit {
50 $(
51 $(#[doc = $doc])?
52 $variant_name,
53 )*
54 }
55
56 impl MotorCorticalUnit {
57 $(
58 paste::paste! {
59 #[doc = "Get cortical area types array for " $friendly_name "."]
60 pub const fn [<get_cortical_area_types_array_for_ $variant_name:snake _with_parameters >](
61 $($param_name: $param_type),*) -> [CorticalAreaType; $number_cortical_areas] {
62 [
63 $(CorticalAreaType::BrainOutput($io_cortical_area_configuration_flag_expr)),*
64 ]
65 }
66
67 #[doc = "Get cortical IDs array for " $friendly_name "."]
68 pub const fn [<get_cortical_ids_array_for_ $variant_name:snake _with_parameters >](
69 $($param_name: $param_type,)* cortical_unit_index: CorticalUnitIndex) -> [CorticalID; $number_cortical_areas] {
70 let cortical_unit_identifier: [u8; 3] = $cortical_id_unit_reference;
71 [
72 $(
73 $io_cortical_area_configuration_flag_expr .as_io_cortical_id(false, cortical_unit_identifier, cortical_unit_index, CorticalSubUnitIndex::from($cortical_sub_unit_index))
74 ),*
75 ]
76 }
77 }
78 )*
79
80 pub const fn get_snake_case_name(&self) -> &'static str {
81 match self {
82 $(
83 MotorCorticalUnit::$variant_name => paste::paste!{ stringify!([<$variant_name:snake>]) },
84 )*
85 }
86 }
87
88 pub const fn get_accepted_wrapped_io_data_type(&self) -> &'static str {
91 match self {
92 $(
93 MotorCorticalUnit::$variant_name => stringify!($variant_name:snake),
94 )*
95 }
96 }
97
98 pub fn from_snake_case_name(name: &str) -> Option<MotorCorticalUnit> {
107 match name {
108 $(
109 paste::paste!{ stringify!([<$variant_name:snake>]) } => Some(MotorCorticalUnit::$variant_name),
110 )*
111 _ => None,
112 }
113 }
114
115 pub const fn list_all() -> &'static [MotorCorticalUnit] {
120 &[
121 $(
122 MotorCorticalUnit::$variant_name,
123 )*
124 ]
125 }
126
127 pub const fn get_friendly_name(&self) -> &'static str {
129 match self {
130 $(
131 MotorCorticalUnit::$variant_name => $friendly_name,
132 )*
133 }
134 }
135
136 pub const fn get_cortical_id_unit_reference(&self) -> [u8; 3] {
138 match self {
139 $(
140 MotorCorticalUnit::$variant_name => $cortical_id_unit_reference,
141 )*
142 }
143 }
144
145 pub const fn get_number_cortical_areas(&self) -> usize {
147 match self {
148 $(
149 MotorCorticalUnit::$variant_name => $number_cortical_areas,
150 )*
151 }
152 }
153
154 pub fn get_unit_default_topology(&self) -> HashMap<CorticalSubUnitIndex, UnitTopology> {
156 match self {
157 $(
158 MotorCorticalUnit::$variant_name => {
159 let mut topology = HashMap::new();
160 $(
161 topology.insert(
162 CorticalSubUnitIndex::from($cortical_sub_unit_index),
163 UnitTopology {
164 relative_position: [$rel_x, $rel_y, $rel_z],
165 channel_dimensions_default: [$dim_default_x, $dim_default_y, $dim_default_z],
166 channel_dimensions_min: [$dim_min_x, $dim_min_y, $dim_min_z],
167 channel_dimensions_max: [$dim_max_x, $dim_max_y, $dim_max_z],
168 }
169 );
170 )*
171 topology
172 }
173 )*
174 }
175 }
176
177 pub fn get_allowed_frame_change_handling(&self) -> Option<&'static [FrameChangeHandling]> {
181 match self {
182 $(
183 MotorCorticalUnit::$variant_name => {
184 $crate::get_allowed_frame_change_handling_impl!($($($allowed_frame),*)?)
185 }
186 )*
187 }
188 }
189
190 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> {
191 match self {
192 $(
193 MotorCorticalUnit::$variant_name => {
194 paste::paste! {
195 let array = MotorCorticalUnit::[<get_cortical_ids_array_for_ $variant_name:snake _with_parameters >](
196 $($param_type::try_from_serde_map(&map)?,)*
197 cortical_unit_index);
198 return Ok(array.to_vec());
199 }
200 }
201 )*
202 }
203 }
204
205 }
206
207 impl Display for MotorCorticalUnit {
208 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
209 match self {
210 $(
211 MotorCorticalUnit::$variant_name => write!(f, $friendly_name),
212 )*
213 }
214 }
215 }
216 };
217
218}
219motor_cortical_units!(define_motor_cortical_units_enum);