mod region_id;
pub use region_id::RegionID;
use crate::genomic::cortical_area::CorticalID;
use crate::FeagiDataError;
use serde::{Deserialize, Serialize};
use std::collections::{HashMap, HashSet};
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[derive(Default)]
pub enum RegionType {
#[default]
Undefined,
}
impl std::fmt::Display for RegionType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "undefined")
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct BrainRegion {
pub region_id: RegionID,
pub name: String,
pub region_type: RegionType,
#[serde(default)]
pub cortical_areas: HashSet<CorticalID>,
#[serde(default)]
pub properties: HashMap<String, serde_json::Value>,
}
impl BrainRegion {
pub fn new(
region_id: RegionID,
name: String,
region_type: RegionType,
) -> Result<Self, FeagiDataError> {
if name.trim().is_empty() {
return Err(FeagiDataError::BadParameters(
"name cannot be empty".to_string(),
));
}
Ok(Self {
region_id,
name,
region_type,
cortical_areas: HashSet::new(),
properties: HashMap::new(),
})
}
pub fn with_areas(mut self, areas: impl IntoIterator<Item = CorticalID>) -> Self {
self.cortical_areas.extend(areas);
self
}
pub fn with_properties(mut self, properties: HashMap<String, serde_json::Value>) -> Self {
self.properties = properties;
self
}
pub fn add_area(&mut self, area_id: CorticalID) -> bool {
self.cortical_areas.insert(area_id)
}
pub fn remove_area(&mut self, area_id: &CorticalID) -> bool {
self.cortical_areas.remove(area_id)
}
pub fn contains_area(&self, area_id: &CorticalID) -> bool {
self.cortical_areas.contains(area_id)
}
pub fn get_all_areas(&self) -> Vec<&CorticalID> {
self.cortical_areas.iter().collect()
}
pub fn area_count(&self) -> usize {
self.cortical_areas.len()
}
pub fn clear_areas(&mut self) {
self.cortical_areas.clear();
}
pub fn get_property(&self, key: &str) -> Option<&serde_json::Value> {
self.properties.get(key)
}
pub fn add_property(&mut self, key: String, value: serde_json::Value) {
self.properties.insert(key, value);
}
pub fn to_dict(&self) -> serde_json::Value {
let area_ids: Vec<String> = self
.cortical_areas
.iter()
.map(|id| id.as_base_64())
.collect();
let mut dict = serde_json::json!({
"id": self.region_id.to_string(),
"name": self.name,
"region_type": self.region_type.to_string(),
"cortical_areas": area_ids,
});
for (key, value) in &self.properties {
dict[key] = value.clone();
}
dict
}
}