# Augur: A Step Towards Realistic Drift Detection in Production MLSystems - Code
# Copyright 2022 Carnegie Mellon University.
# 
# NO WARRANTY. THIS CARNEGIE MELLON UNIVERSITY AND SOFTWARE ENGINEERING INSTITUTE MATERIAL IS FURNISHED ON AN "AS-IS" BASIS. CARNEGIE MELLON UNIVERSITY MAKES NO WARRANTIES OF ANY KIND, EITHER EXPRESSED OR IMPLIED, AS TO ANY MATTER INCLUDING, BUT NOT LIMITED TO, WARRANTY OF FITNESS FOR PURPOSE OR MERCHANTABILITY, EXCLUSIVITY, OR RESULTS OBTAINED FROM USE OF THE MATERIAL. CARNEGIE MELLON UNIVERSITY DOES NOT MAKE ANY WARRANTY OF ANY KIND WITH RESPECT TO FREEDOM FROM PATENT, TRADEMARK, OR COPYRIGHT INFRINGEMENT.
# 
# Released under a MIT (SEI)-style license, please see license.txt or contact permission@sei.cmu.edu for full terms.
# 
# [DISTRIBUTION STATEMENT A] This material has been approved for public release and unlimited distribution.  Please see Copyright notice for non-US Government use and distribution.
# 
# Carnegie Mellon® is registered in the U.S. Patent and Trademark Office by Carnegie Mellon University.
# 
# This Software includes and/or makes use of the following Third-Party Software subject to its own license:
# 1. Tensorflow (https://github.com/tensorflow/tensorflow/blob/master/LICENSE) Copyright 2014 The Regents of the University of California.
# 2. Pandas (https://github.com/pandas-dev/pandas/blob/main/LICENSE) Copyright 2021 AQR Capital Management, LLC, Lambda Foundry, Inc. and PyData Development Team, and open source contributors.
# 3. scikit-learn (https://github.com/scikit-learn/scikit-learn/blob/main/COPYING) Copyright 2021 The scikit-learn developers.
# 4. numpy (https://github.com/numpy/numpy/blob/main/LICENSE.txt) Copyright 2021 NumPy Developers.
# 5. scipy (https://github.com/scipy/scipy/blob/main/LICENSE.txt) Copyright 2021 SciPy Developers.
# 6. statsmodels (https://github.com/statsmodels/statsmodels/blob/main/LICENSE.txt) Copyright 2018 Jonathan E. Taylor, Scipy developers, statsmodels Developers.
# 7. matplotlib (https://github.com/matplotlib/matplotlib/blob/main/LICENSE/LICENSE) Copyright 2016 Matplotlib development team.
# 
# DM22-0044

import shutil

from drift import drift_generator
from utils import arguments
from utils.config import Config
from utils import logging
from datasets import dataset

LOG_FILE_NAME = "drifter.log"
DEFAULT_CONFIG_FILENAME = "./drifter_config.json"
DRIFT_EXP_CONFIG_FOLDER = "../experiments/drifter"


def load_dataset(dataset_filename, dataset_class_name):
    """Load dataset to drift."""
    dataset_class = dataset.load_dataset_class(dataset_class_name)
    base_dataset = dataset_class()
    base_dataset.load_from_file(dataset_filename)
    return base_dataset


def main():
    logging.setup_logging(LOG_FILE_NAME)

    # Allow selecting configs for experiments, and load it.
    args = arguments.get_parsed_arguments()
    config_file = Config.get_config_file(args, DRIFT_EXP_CONFIG_FOLDER, DEFAULT_CONFIG_FILENAME)
    config = Config()
    config.load(config_file)

    # Load scenario data.
    drift_module, params = drift_generator.load_drift_config(config.get("drift_scenario"))

    if args.test:
        drift_generator.test_drift(config, drift_module, params, config.get("bins"))
    else:
        # Sort dataset into bins.
        base_dataset = load_dataset(config.get("dataset"), config.get("dataset_class"))
        bin_value = config.get("bin_value") if config.contains("bin_value") else "results"
        bin_shuffle = config.get("bin_shuffle") if config.contains("bin_shuffle") else True
        bins = drift_generator.load_bins(base_dataset, config.get("bins"), bin_value, bin_shuffle)

        # Apply drift.
        drifted_dataset = drift_generator.apply_drift(bins, drift_module, params)
        drift_generator.add_timestamps(drifted_dataset, config.get("timestamps"))

        # Save it to regular file, and timestamped file.
        drifted_dataset.save_to_file(config.get("output"))
        print("Copying output file to timestamped backup.")
        shutil.copyfile(config.get("output"), drift_generator.get_drift_stamped_name(config.get("output")))


if __name__ == '__main__':
    main()

[((38, 20, 38, 66), 'datasets.dataset.load_dataset_class', 'dataset.load_dataset_class', ({(38, 47, 38, 65): 'dataset_class_name'}, {}), '(dataset_class_name)', False, 'from datasets import dataset\n'), ((45, 4, 45, 40), 'utils.logging.setup_logging', 'logging.setup_logging', ({(45, 26, 45, 39): 'LOG_FILE_NAME'}, {}), '(LOG_FILE_NAME)', False, 'from utils import logging\n'), ((48, 11, 48, 43), 'utils.arguments.get_parsed_arguments', 'arguments.get_parsed_arguments', ({}, {}), '()', False, 'from utils import arguments\n'), ((49, 18, 49, 96), 'utils.config.Config.get_config_file', 'Config.get_config_file', ({(49, 41, 49, 45): 'args', (49, 47, 49, 70): 'DRIFT_EXP_CONFIG_FOLDER', (49, 72, 49, 95): 'DEFAULT_CONFIG_FILENAME'}, {}), '(args, DRIFT_EXP_CONFIG_FOLDER, DEFAULT_CONFIG_FILENAME)', False, 'from utils.config import Config\n'), ((50, 13, 50, 21), 'utils.config.Config', 'Config', ({}, {}), '()', False, 'from utils.config import Config\n'), ((66, 26, 66, 81), 'drift.drift_generator.apply_drift', 'drift_generator.apply_drift', ({(66, 54, 66, 58): 'bins', (66, 60, 66, 72): 'drift_module', (66, 74, 66, 80): 'params'}, {}), '(bins, drift_module, params)', False, 'from drift import drift_generator\n')]