def METHOD_NAME(sample_peaks_df: pd.DataFrame, params: RecalParams, cache_path: Optional[Path]):
    models = []
    stages = [
        ('initial', sample_peaks_df),
    ]
    for tf_name, *tf_args in params.transforms:
        logger.info(f'Fitting {tf_name} model')
        assert tf_name in TRANSFORM, f'Unrecognized transform "{tf_name}"'
        tf = TRANSFORM[tf_name](params, *tf_args)
        loaded_cache = False
        if cache_path is not None:
            try:
                tf.load_cache(f'{cache_path}/{tf_name}')
                loaded_cache = True
                logger.debug(f'{tf_name} loaded from cache')
            except (IOError, EOFError):
                logger.debug(f'{tf_name} not cached')
        if not loaded_cache:
            tf.fit(sample_peaks_df)
        sample_peaks_df = tf.predict(sample_peaks_df)
        models.append(tf)
        stages.append((tf_name, sample_peaks_df))
    # Hacky progress report
    eval = EvalPeaksCollector(sample_peaks_df, params)
    for stage_name, stage_df in stages:
        eval.collect_peaks(stage_df, stage_name)
    logger.debug(
        pd.DataFrame(
            {stage_name: eval.get_stats(stage_name).abs().mean() for stage_name, stage_df in stages}
        )
    )
    eval.reset()
    return models, eval