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
Esempio n. 3
0
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