<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def modeled_savings( baseline_model, reporting_model, result_index, temperature_data, with_disaggregated=False, confidence_level=0.90, predict_kwargs=None, ):
 """ Compute modeled savings, i.e., savings in which baseline and reporting usage values are based on models. This is appropriate for annualizing or weather normalizing models. Parameters baseline_model : :any:`eemeter.CalTRACKUsagePerDayCandidateModel` Model to use for predicting pre-intervention usage. reporting_model : :any:`eemeter.CalTRACKUsagePerDayCandidateModel` Model to use for predicting post-intervention usage. result_index : :any:`pandas.DatetimeIndex` The dates for which usage should be modeled. temperature_data : :any:`pandas.Series` Hourly-frequency timeseries of temperature data during the modeled period. with_disaggregated : :any:`bool`, optional If True, calculate modeled disaggregated usage estimates and savings. confidence_level : :any:`float`, optional The two-tailed confidence level used to calculate the t-statistic used in calculation of the error bands. Ignored if not computing error bands. predict_kwargs : :any:`dict`, optional Extra kwargs to pass to the baseline_model.predict and reporting_model.predict methods. Returns ------- results : :any:`pandas.DataFrame` DataFrame with modeled savings, indexed with the result_index. Will include the following columns: - ``modeled_baseline_usage`` - ``modeled_reporting_usage`` - ``modeled_savings`` If `with_disaggregated` is set to True, the following columns will also be in the results DataFrame: - ``modeled_baseline_base_load`` - ``modeled_baseline_cooling_load`` - ``modeled_baseline_heating_load`` - ``modeled_reporting_base_load`` - ``modeled_reporting_cooling_load`` - ``modeled_reporting_heating_load`` - ``modeled_base_load_savings`` - ``modeled_cooling_load_savings`` - ``modeled_heating_load_savings`` error_bands : :any:`dict`, optional If baseline_model and reporting_model are instances of CalTRACKUsagePerDayModelResults, will also return a dictionary of FSU and error bands for the aggregated energy savings over the normal year period. """

    prediction_index = result_index

    if predict_kwargs is None:
        predict_kwargs = {}

    model_type = None  # generic
    if isinstance(baseline_model, CalTRACKUsagePerDayModelResults):
        model_type = "usage_per_day"

    if model_type == "usage_per_day" and with_disaggregated:
        predict_kwargs["with_disaggregated"] = True

    def _predicted_usage(model):
        model_prediction = model.predict(
            prediction_index, temperature_data, **predict_kwargs
        )
        predicted_usage = model_prediction.result
        return predicted_usage

    predicted_baseline_usage = _predicted_usage(baseline_model)
    predicted_reporting_usage = _predicted_usage(reporting_model)
    modeled_baseline_usage = predicted_baseline_usage["predicted_usage"].to_frame(
        "modeled_baseline_usage"
    )
    modeled_reporting_usage = predicted_reporting_usage["predicted_usage"].to_frame(
        "modeled_reporting_usage"
    )

    def modeled_savings_func(row):
        return row.modeled_baseline_usage - row.modeled_reporting_usage

    results = modeled_baseline_usage.join(modeled_reporting_usage).assign(
        modeled_savings=modeled_savings_func
    )

    if model_type == "usage_per_day" and with_disaggregated:
        modeled_baseline_usage_disaggregated = predicted_baseline_usage[
            ["base_load", "heating_load", "cooling_load"]
        ].rename(
            columns={
                "base_load": "modeled_baseline_base_load",
                "heating_load": "modeled_baseline_heating_load",
                "cooling_load": "modeled_baseline_cooling_load",
            }
        )

        modeled_reporting_usage_disaggregated = predicted_reporting_usage[
            ["base_load", "heating_load", "cooling_load"]
        ].rename(
            columns={
                "base_load": "modeled_reporting_base_load",
                "heating_load": "modeled_reporting_heating_load",
                "cooling_load": "modeled_reporting_cooling_load",
            }
        )

        def modeled_base_load_savings_func(row):
            return row.modeled_baseline_base_load - row.modeled_reporting_base_load

        def modeled_heating_load_savings_func(row):
            return (
                row.modeled_baseline_heating_load - row.modeled_reporting_heating_load
            )

        def modeled_cooling_load_savings_func(row):
            return (
                row.modeled_baseline_cooling_load - row.modeled_reporting_cooling_load
            )

        results = (
            results.join(modeled_baseline_usage_disaggregated)
            .join(modeled_reporting_usage_disaggregated)
            .assign(
                modeled_base_load_savings=modeled_base_load_savings_func,
                modeled_heating_load_savings=modeled_heating_load_savings_func,
                modeled_cooling_load_savings=modeled_cooling_load_savings_func,
            )
        )

    results = results.dropna().reindex(results.index)  # carry NaNs

    error_bands = None
    if model_type == "usage_per_day":  # has totals_metrics
        error_bands = _compute_error_bands_modeled_savings(
            baseline_model.totals_metrics,
            reporting_model.totals_metrics,
            results,
            baseline_model.interval,
            reporting_model.interval,
            confidence_level,
        )
    return results, error_bands