def approximate_spd( panel_properties: Dict[str, Any], des_distance: float, des_intensity: float, des_spectrum: Dict[str, float], ) -> Tuple[Dict, Dict, float]: """Approximates spectral power distribution.""" # Get desired spd vector (i.e. `b` in Ax=b) desired_spd_dict = calculate_spd_dict(des_intensity, des_spectrum) desired_spd_vector = accessors.vectorize_dict(desired_spd_dict) # Get channel spd matrix (i.e. `A` in Ax=b) raw_channel_spd_ndict = build_channel_spd_ndict(panel_properties, des_distance) channel_spd_ndict = translate_spd_ndict(raw_channel_spd_ndict, desired_spd_dict) channel_spd_matrix = accessors.matrixify_nested_dict(channel_spd_ndict) # Get channel setpoints (i.e `x` in Ax=b) channel_setpoint_vector = solve_setpoints(channel_spd_matrix, desired_spd_vector) channel_setpoint_list = [] for setpoint in channel_setpoint_vector: channel_setpoint_list.append(setpoint * 100) channel_types = panel_properties.get("channel_types", {}) channel_setpoint_dict = accessors.dictify_list(channel_setpoint_list, channel_types) # Get output spd, spectrum, and intensity output_spd_list = calculate_output_spd(channel_spd_matrix, channel_setpoint_vector) output_spectrum_list, output_intensity = deconstruct_spd(output_spd_list) output_spectrum_dict = accessors.dictify_list(output_spectrum_list, desired_spd_dict) # Map channel setpoints from channel types to channel instances mapped_channel_setpoint_dict = {} channels = panel_properties.get("channels", {}) for channel_name, channel_entry in channels.items(): key = channel_entry.get("type") setpoint = channel_setpoint_dict.get(key, 0) mapped_channel_setpoint_dict[channel_name] = round(setpoint, 2) # Successfully approximated spectral power distribution return mapped_channel_setpoint_dict, output_spectrum_dict, output_intensity
def calculate_resultant_spd( panel_properties: Dict[str, Any], reference_spd_dict: Dict[str, float], channel_setpoint_dict: Dict[str, float], distance: float, ) -> Tuple[Dict[str, float], float]: """Calculates spd from provided channel outputs at distance. Returns spd with the same spectral bands as the reference spd.""" # Parse channel properties channels = panel_properties.get("channels", {}) # Get channel spd matrix raw_channel_spd_ndict = build_channel_spd_ndict(panel_properties, distance) channel_spd_ndict = translate_spd_ndict(raw_channel_spd_ndict, reference_spd_dict) channel_spd_matrix = accessors.matrixify_nested_dict(channel_spd_ndict) # Factorize setpoint types. The type setpoint is the average of all instance setpoints factorized_channel_setpoint_dict: Dict[str, float] = {} count: Dict[str, int] = {} for channel_name, setpoint in channel_setpoint_dict.items(): channel_dict = channels.get(channel_name, {}) channel_type = channel_dict.get("type", "Error") if channel_type in factorized_channel_setpoint_dict: prev_setpoint = factorized_channel_setpoint_dict[channel_type] weighted_prev_setpoint = prev_setpoint * count[channel_type] count[channel_type] += 1 new_setpoint = (weighted_prev_setpoint + setpoint) / count[channel_type] factorized_channel_setpoint_dict[channel_type] = new_setpoint else: factorized_channel_setpoint_dict[channel_type] = setpoint count[channel_type] = 1 # Get channel setpoint vector channel_setpoint_list = accessors.listify_dict( factorized_channel_setpoint_dict) channel_setpoint_vector = [] for setpoint_percent in channel_setpoint_list: setpoint_decimal = setpoint_percent / 100.0 channel_setpoint_vector.append(setpoint_decimal) # Get output spd, spectrum, and intensity output_spd_list = calculate_output_spd(channel_spd_matrix, channel_setpoint_vector) output_spectrum_list, output_intensity = deconstruct_spd(output_spd_list) output_spectrum_dict = accessors.dictify_list(output_spectrum_list, reference_spd_dict) return output_spectrum_dict, output_intensity
def test_dictify_list() -> None: list_ = [1, 2, 3] reference_dict = {"a": 4, "b": 5, "c": 6} expected = {"a": 1, "b": 2, "c": 3} dict_ = accessors.dictify_list(list_, reference_dict) assert dict_ == expected