Skip to content
Snippets Groups Projects
Commit 0b146ae7 authored by Udo Eisenbarth's avatar Udo Eisenbarth :speech_balloon:
Browse files

Implement analyze_energy function for NodeBeamSplitter

parent 94d3be46
No related branches found
No related tags found
No related merge requests found
......@@ -29,6 +29,7 @@ fn main() {
write!(output, "{}", scenery.to_dot()).unwrap();
println!("{:?}", scenery.node_ref(i_s).unwrap());
println!("{:?}", scenery.node_ref(i_d1).unwrap());
println!("{:?}", scenery.node_ref(i_d2).unwrap());
let mut analyzer=AnalyzerEnergy::new(&scenery);
print!("Analyze...");
......@@ -37,4 +38,5 @@ fn main() {
Err(e) => println!("Error: {}",e)
}
println!("{:?}", scenery.node_ref(i_d1).unwrap());
println!("{:?}", scenery.node_ref(i_d2).unwrap());
}
......@@ -30,8 +30,8 @@ impl Light {
pub fn data(&self) -> Option<&LightData> {
self.data.as_ref()
}
pub fn set_data(&mut self, data: LightData) {
self.data = Some(data);
pub fn set_data(&mut self, data: Option<LightData>) {
self.data = data;
}
}
......
use crate::{
optic_node::{Dottable, Optical},
optic_ports::OpticPorts,
analyzer::AnalyzerType,
error::OpossumError,
optic_node::{Dottable, LightResult, Optical},
optic_ports::OpticPorts, lightdata::{LightData, LightDataEnergy},
};
type Result<T> = std::result::Result<T, OpossumError>;
#[derive(Debug)]
/// An ideal beamsplitter node with a given splitting ratio.
pub struct NodeBeamSplitter {
......@@ -24,6 +28,33 @@ impl NodeBeamSplitter {
pub fn set_ratio(&mut self, ratio: f32) {
self.ratio = ratio;
}
pub fn analyze_energy(&mut self, incoming_data: LightResult) -> Result<LightResult> {
let in1=incoming_data.clone().into_iter().find(|data| data.0=="input1");
let in2=incoming_data.into_iter().find(|data| data.0=="input2");
let mut in1_energy=0.0;
let mut in2_energy=0.0;
if let Some(in1)=in1 {
if let Some(in1)=in1.1 {
match in1 {
LightData::Energy(e) => in1_energy=e.energy,
_ => return Err(OpossumError::Analysis("expected energy value".into()))
}
}
}
if let Some(in2)=in2 {
if let Some(in2)=in2.1 {
match in2 {
LightData::Energy(e) => in2_energy=e.energy,
_ => return Err(OpossumError::Analysis("expected energy value".into()))
}
}
}
let out1_energy=LightDataEnergy{energy: in1_energy*self.ratio+in2_energy*(1.0-self.ratio)};
let out2_energy =LightDataEnergy{energy: in1_energy*(1.0-self.ratio) + in2_energy*self.ratio};
Ok(vec![("out1_trans1_refl2".into(),Some(LightData::Energy(out1_energy))),("out2_trans2_refl1".into(),Some(LightData::Energy(out2_energy)))])
}
}
impl Default for NodeBeamSplitter {
......@@ -44,6 +75,16 @@ impl Optical for NodeBeamSplitter {
ports.add_output("out2_trans2_refl1").unwrap();
ports
}
fn analyze(
&mut self,
incoming_data: LightResult,
analyzer_type: &AnalyzerType,
) -> Result<LightResult> {
match analyzer_type {
AnalyzerType::Energy => self.analyze_energy(incoming_data),
}
}
}
impl Dottable for NodeBeamSplitter {
......
use crate::{optic_node::{Optical, Dottable, LightResult}, optic_ports::OpticPorts};
use crate::{optic_node::{Optical, Dottable, LightResult}, optic_ports::OpticPorts, error::OpossumError};
use crate::lightdata::LightData;
type Result<T> = std::result::Result<T, OpossumError>;
#[derive(Debug, Default)]
/// This node rerpresents an universal detector. Any [`LightData`] coming in will be stored internally for later display / export. So far it only has one input (in1).
pub struct NodeDetector {
......@@ -16,12 +18,12 @@ impl Optical for NodeDetector {
ports.add_input("in1").unwrap();
ports
}
fn analyze(&mut self, incoming_data: LightResult, _analyzer_type: &crate::analyzer::AnalyzerType) -> LightResult {
fn analyze(&mut self, incoming_data: LightResult, _analyzer_type: &crate::analyzer::AnalyzerType) -> Result<LightResult> {
let data=incoming_data.into_iter().filter(|data| data.0=="in1").last();
if let Some(data)=data {
self.light_data=Some(data.1);
self.light_data=data.1;
}
LightResult::default()
Ok(LightResult::default())
}
}
......
use crate::{
lightdata::LightData,
optic_node::{Dottable, Optical, LightResult},
optic_ports::OpticPorts,
optic_ports::OpticPorts, error::OpossumError,
};
type Result<T> = std::result::Result<T, OpossumError>;
/// This node represents a source of light. Hence it has only one output port (out1) and no input ports. Source nodes usually are the first nodes of an optic scenery.
#[derive(Debug, Default)]
pub struct NodeSource {
......@@ -38,10 +40,13 @@ impl Optical for NodeSource {
ports
}
fn analyze(&mut self, _incoming_edges: LightResult, _analyzer_type: &crate::analyzer::AnalyzerType) -> LightResult {
fn analyze(&mut self, _incoming_edges: LightResult, _analyzer_type: &crate::analyzer::AnalyzerType) -> Result<LightResult> {
let data=self.light_data.clone();
let result:LightResult =vec![("out1".into(), data.unwrap())];
result
if data.is_some() {
Ok(vec![("out1".into(), data)])
} else {
Err(OpossumError::Analysis(format!("no input data available")))
}
}
}
......
......@@ -2,8 +2,10 @@ use std::fmt::Debug;
use crate::analyzer::AnalyzerType;
use crate::lightdata::LightData;
use crate::optic_ports::OpticPorts;
use crate::error::OpossumError;
pub type LightResult=Vec<(String,LightData)>;
pub type LightResult=Vec<(String,Option<LightData>)>;
type Result<T> = std::result::Result<T, OpossumError>;
/// An [`OpticNode`] is the basic struct representing an optical component.
pub struct OpticNode {
......@@ -65,7 +67,7 @@ impl OpticNode {
pub fn ports(&self) -> &OpticPorts {
&self.ports
}
pub fn analyze(&mut self, incoming_data: LightResult, analyzer_type: &AnalyzerType) -> LightResult {
pub fn analyze(&mut self, incoming_data: LightResult, analyzer_type: &AnalyzerType) -> Result<LightResult> {
self.node.analyze(incoming_data, analyzer_type)
}
}
......@@ -87,9 +89,9 @@ pub trait Optical {
OpticPorts::default()
}
fn analyze(&mut self, _incoming_data: LightResult, _analyzer_type: &AnalyzerType) -> LightResult {
fn analyze(&mut self, _incoming_data: LightResult, _analyzer_type: &AnalyzerType) -> Result<LightResult> {
print!("{}: No analyze function defined.", self.node_type());
LightResult::default()
Ok(LightResult::default())
}
}
......
......@@ -5,7 +5,7 @@ use crate::analyzer::AnalyzerType;
use crate::error::OpossumError;
use crate::light::Light;
use crate::lightdata::LightData;
use crate::optic_node::{LightResult, OpticComponent, OpticNode};
use crate::optic_node::{OpticComponent, OpticNode};
use petgraph::algo::toposort;
use petgraph::algo::*;
use petgraph::prelude::{DiGraph, EdgeIndex, NodeIndex};
......@@ -172,8 +172,7 @@ impl OpticScenery {
for idx in sorted {
let node = self.g.node_weight(idx).unwrap();
let incoming_edges = self.incoming_edges(idx);
let checked_edges=OpticScenery::check_incoming_edges_for_node(node, &incoming_edges)?;
let outgoing_edges = node.borrow_mut().analyze(checked_edges, analyzer_type);
let outgoing_edges = node.borrow_mut().analyze(incoming_edges, analyzer_type)?;
for outgoing_edge in outgoing_edges {
self.set_outgoing_edge_data(idx, outgoing_edge.0, outgoing_edge.1)
}
......@@ -185,32 +184,6 @@ impl OpticScenery {
))
}
}
fn check_incoming_edges_for_node(
node: &Rc<RefCell<OpticNode>>,
incoming_edges: &Vec<(String, Option<LightData>)>,
) -> Result<LightResult> {
let ports = node.borrow().ports().inputs();
let edge_ports = incoming_edges
.into_iter()
.map(|edge| edge.0.clone())
.collect::<Vec<String>>();
let all_ports_connected = ports
.into_iter()
.all(|input_port_name| edge_ports.contains(&input_port_name));
if !all_ports_connected {
return Err(OpossumError::OpticScenery(format!("not all ports coneected to node <{}>",node.borrow().name())));
}
else {
for edge in incoming_edges.iter()
{
if edge.1.is_none() {
return Err(OpossumError::OpticScenery(format!("input port <{}> of node <{}> has no light data set",edge.0, node.borrow().name())));
}
}
let unwrapped_edged= incoming_edges.into_iter().map(|edge| (edge.0.clone(),edge.1.as_ref().unwrap().clone())).collect::<LightResult>();
Ok(unwrapped_edged)
}
}
/// Sets the description of this [`OpticScenery`].
pub fn set_description(&mut self, description: String) {
self.description = description;
......@@ -219,34 +192,6 @@ impl OpticScenery {
pub fn description(&self) -> &str {
self.description.as_ref()
}
/// Returns the nodes topological of this [`OpticScenery`].
///
/// # Panics
///
/// Panics if .
///
/// # Errors
///
/// This function will return an error if .
// pub fn nodes_topological(&self) -> Result<Vec<(Rc<OpticNode>, Vec<Light>)>> {
// let sorted = toposort(&self.g, None);
// if let Ok(sorted) = sorted {
// let nodes_edges = sorted
// .into_iter()
// .map(|idx| {
// (
// self.g.node_weight(idx).unwrap().to_owned(),
// self.incoming_edges(idx),
// )
// })
// .collect();
// Ok(nodes_edges)
// } else {
// Err(OpossumError::OpticScenery(
// "Analyis: topological sort failed".into(),
// ))
// }
// }
/// Returns the nodes unordered of this [`OpticScenery`].
pub fn nodes_unordered(&self) -> Vec<NodeIndex> {
self.g.node_indices().collect::<Vec<NodeIndex>>()
......@@ -263,7 +208,7 @@ impl OpticScenery {
})
.collect::<Vec<(String, Option<LightData>)>>()
}
pub fn set_outgoing_edge_data(&mut self, idx: NodeIndex, port: String, data: LightData) {
pub fn set_outgoing_edge_data(&mut self, idx: NodeIndex, port: String, data: Option<LightData>) {
let edges = self.g.edges_directed(idx, petgraph::Direction::Outgoing);
let edge_ref = edges
.into_iter()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment