# Path: pywr/dataframe_tools.py
# def align_and_resample_dataframe(df, target_index, resample_func="mean"):
#     """Align and resample a DataFrame to the provided index.
# 
#     This function attempts to align an input dataframe to a target index. The
#      index of the incoming dataframe must be time based and will be cast to a
#     `PeriodIndex` (using `to_period()`). Up or down sampling is selected based
#      on the relative frequencies of the two indexes. The exact method depends
#      also on the type of frequencies (offsets) involved (e.g. `Tick` or
#      `DataOffset`). Up-sampling uses forward filling. Whereas down-sampling
#      uses the provided `resample_func`.
# 
#     Parameters
#     ==========
# 
#     df : `pandas.DataFrame`
#         The input data that needs to be aligned and/or resampled.
#     target_index : `pandas.PeriodIndex`
#         The target index that the input should be aligned and resampled to match.
#     resample_func : str, func
#         Function to be used when down-sampling from high frequency data to lower
#         frequency.
# 
#     """
#     # Must resample and align the DataFrame to the model.
#     start = target_index[0]
#     end = target_index[-1]
# 
#     if not isinstance(df.index, pandas.PeriodIndex):
#         # Converting to period is sometimes unreliable. E.g. with freq='7D'
#         # If the target frequency is passed explicitly this can help, but
#         # not all Timestamp frequencies convert to Period frequencies. Therefore,
#         # this can not be the default.
#         try:
#             df = df.to_period()
#         except AttributeError:
#             df = df.to_period(df.index.freq.freqstr)
# 
#     if not isinstance(target_index, pandas.PeriodIndex):
#         raise ValueError("Period index expected.")
# 
#     model_freq = target_index.freq
#     df_freq = df.index.freq
# 
#     # Determine how to do the resampling based on the frequency type
#     # and whether to do up or down sampling.
#     if isinstance(model_freq, Tick):
#         # Model is tick based e.g. daily or hourly
#         if isinstance(df_freq, Tick):
#             # Dataframe is also tick based
#             if model_freq >= df_freq:
#                 # Down sampling (i.e. from high freq to lower model freq)
#                 df = _down_sample_tick_to_tick(df, target_index, resample_func)
#             else:
#                 df = _up_sample_tick_to_tick(df, target_index)
#         else:
#             # Dataframe must be offset based
#             # Generally this is going to be up sampling to a higher model freq
#             df = _resample_date_offset_to_tick(df, target_index, resample_func)
# 
#     elif isinstance(model_freq, DateOffset):
#         # Model is based on date offsets.
#         if isinstance(df_freq, Tick):
#             # Dataframe is tick based
#             # Generally this is going to be down sampling to a lower model freq
#             df = _down_sample_tick_to_date_offset(df, target_index, resample_func)
#         else:
#             # Dataframe must be offset based
#             # Down sampling (i.e. from high freq to lower model freq)
#             try:
#                 df = _resample_date_offset_to_date_offset(
#                     df, target_index, resample_func
#                 )
#             except IncompatibleFrequency:
#                 raise ResamplingError(df, target_index)
# 
#     df = df[start:end]
# 
#     if not df.index.equals(target_index):
#         raise ResamplingError(df, target_index)
# 
#     if df.isnull().values.any():
#         raise ValueError("Missing values detected after resampling dataframe.")
# 
#     return df
# 
# class ResamplingError(Exception):
#     def __init__(self, original_dataframe, target_index):
#         self.original_dataframe = original_dataframe
#         self.target_index = target_index
#         message = (
#             f'Failed to convert input dataframe with index "{original_dataframe.index}" to model index '
#             f'"{target_index}".'
#         )
#         super().__init__(message)


from pywr.dataframe_tools import align_and_resample_dataframe, ResamplingError
import numpy as np
import pandas as pd
import pytest
        input_resampled = align_and_resample_dataframe(
            input_df, model_index, resample_func=resample_func
        )

        pd.testing.assert_index_equal(input_resampled.index, model_index)
        pd.testing.assert_frame_equal(
            input_resampled, input_resampled.resample("7D").agg(resample_func)
        )

    @pytest.mark.parametrize("resample_func", ["mean", "max"])
    def test_misaligned_daily_to_7daily(self, resample_func):
        """Test daily to 7-day model time-step."""
        input_df = make_df("D", start="2014-12-20")
        model_index = make_model_index("7D")

        input_resampled = align_and_resample_dataframe(
            input_df, model_index, resample_func=resample_func
        )

        pd.testing.assert_index_equal(input_resampled.index, model_index)
        pd.testing.assert_frame_equal(
            input_resampled, input_resampled.resample("7D").agg(resample_func)
        )

    @pytest.mark.parametrize("resample_func", ["mean", "max"])
    def test_weekly_to_monthly(self, resample_func):
        """Test weekly to monthly model time-step."""
        input_df = make_df("W")
        model_index = make_model_index("M")


# Path: pywr/dataframe_tools.py
# def align_and_resample_dataframe(df, target_index, resample_func="mean"):
#     """Align and resample a DataFrame to the provided index.
# 
#     This function attempts to align an input dataframe to a target index. The
#      index of the incoming dataframe must be time based and will be cast to a
#     `PeriodIndex` (using `to_period()`). Up or down sampling is selected based
#      on the relative frequencies of the two indexes. The exact method depends
#      also on the type of frequencies (offsets) involved (e.g. `Tick` or
#      `DataOffset`). Up-sampling uses forward filling. Whereas down-sampling
#      uses the provided `resample_func`.
# 
#     Parameters
#     ==========
# 
#     df : `pandas.DataFrame`
#         The input data that needs to be aligned and/or resampled.
#     target_index : `pandas.PeriodIndex`
#         The target index that the input should be aligned and resampled to match.
#     resample_func : str, func
#         Function to be used when down-sampling from high frequency data to lower
#         frequency.
# 
#     """
#     # Must resample and align the DataFrame to the model.
#     start = target_index[0]
#     end = target_index[-1]
# 
#     if not isinstance(df.index, pandas.PeriodIndex):
#         # Converting to period is sometimes unreliable. E.g. with freq='7D'
#         # If the target frequency is passed explicitly this can help, but
#         # not all Timestamp frequencies convert to Period frequencies. Therefore,
#         # this can not be the default.
#         try:
#             df = df.to_period()
#         except AttributeError:
#             df = df.to_period(df.index.freq.freqstr)
# 
#     if not isinstance(target_index, pandas.PeriodIndex):
#         raise ValueError("Period index expected.")
# 
#     model_freq = target_index.freq
#     df_freq = df.index.freq
# 
#     # Determine how to do the resampling based on the frequency type
#     # and whether to do up or down sampling.
#     if isinstance(model_freq, Tick):
#         # Model is tick based e.g. daily or hourly
#         if isinstance(df_freq, Tick):
#             # Dataframe is also tick based
#             if model_freq >= df_freq:
#                 # Down sampling (i.e. from high freq to lower model freq)
#                 df = _down_sample_tick_to_tick(df, target_index, resample_func)
#             else:
#                 df = _up_sample_tick_to_tick(df, target_index)
#         else:
#             # Dataframe must be offset based
#             # Generally this is going to be up sampling to a higher model freq
#             df = _resample_date_offset_to_tick(df, target_index, resample_func)
# 
#     elif isinstance(model_freq, DateOffset):
#         # Model is based on date offsets.
#         if isinstance(df_freq, Tick):
#             # Dataframe is tick based
#             # Generally this is going to be down sampling to a lower model freq
#             df = _down_sample_tick_to_date_offset(df, target_index, resample_func)
#         else:
#             # Dataframe must be offset based
#             # Down sampling (i.e. from high freq to lower model freq)
#             try:
#                 df = _resample_date_offset_to_date_offset(
#                     df, target_index, resample_func
#                 )
#             except IncompatibleFrequency:
#                 raise ResamplingError(df, target_index)
# 
#     df = df[start:end]
# 
#     if not df.index.equals(target_index):
#         raise ResamplingError(df, target_index)
# 
#     if df.isnull().values.any():
#         raise ValueError("Missing values detected after resampling dataframe.")
# 
#     return df
# 
# class ResamplingError(Exception):
#     def __init__(self, original_dataframe, target_index):
#         self.original_dataframe = original_dataframe
#         self.target_index = target_index
#         message = (
#             f'Failed to convert input dataframe with index "{original_dataframe.index}" to model index '
#             f'"{target_index}".'
#         )
#         super().__init__(message)


# Path: tests/test_df_resampling.py
from pywr.dataframe_tools import align_and_resample_dataframe, ResamplingError
import numpy as np
import pandas as pd
import pytest

        input_resampled = align_and_resample_dataframe(
            input_df, model_index, resample_func=resample_func
        )

        pd.testing.assert_index_equal(input_resampled.index, model_index)
        pd.testing.assert_frame_equal(
            input_resampled, input_resampled.resample("7D").agg(resample_func)
        )

    @pytest.mark.parametrize("resample_func", ["mean", "max"])
    def test_misaligned_daily_to_7daily(self, resample_func):
        """Test daily to 7-day model time-step."""
        input_df = make_df("D", start="2014-12-20")
        model_index = make_model_index("7D")

        input_resampled = align_and_resample_dataframe(
            input_df, model_index, resample_func=resample_func
        )

        pd.testing.assert_index_equal(input_resampled.index, model_index)
        pd.testing.assert_frame_equal(
            input_resampled, input_resampled.resample("7D").agg(resample_func)
        )

    @pytest.mark.parametrize("resample_func", ["mean", "max"])
    def test_weekly_to_monthly(self, resample_func):
        """Test weekly to monthly model time-step."""
        input_df = make_df("W")
        model_index = make_model_index("M")


        with pytest.raises(ResamplingError):