<commit_before>#!/usr/bin/env python

# wham.py
# The Weighted Histogram Analysis Method (WHAM) for combining histograms
# from several files.
import pandas as pd
import numpy as np

import logging
logger = logging.getLogger(__name__)

class WHAM(object):
    """
    Weighted Histogram Analysis Method

    Note
    ----
    Several parts of the docstrings mention F&S, which is intended to refer
    the reader to reference [1], in particular pages 184-187 in the 2nd
    edition (section called "Self-Consistent Histogram Method").

    Reference
    ---------
    [1] <NAME> and <NAME>. Understanding Molecular Simulation:
        From Algorithms to Applications. 2nd Edition. 2002.
    """

    def __init__(self, tol=1e-10, max_iter=1000000, cutoff=0.05):
        """
        Initialize (empty) WHAM calculation object.

        Parameters
        ----------
        tol : float
            tolerance for convergence
        max_iter : int
            maximum number of iterations
        cutoff : float
            windowing cutoff
        """
        self.tol = tol
        self.max_iter = max_iter
        self.cutoff = cutoff

        self.hists = { }
        self.nhists = 0
        self.keys = []

        self.sample_every = max_iter + 1
        self._float_format = "10.8"

    @property
    def float_format(self):
        return lambda x : "{:" + self._float_format + "f}".format(x)

    @float_format.setter
    def float_format(self, value):
        self._float_format = value

    def load_files(self,fnames):  # pragma: no cover
        """Load a file or files into the internal structures.

        Requires either pandas or something else with pandas-like read_table
        and concat functions.
        """
        frames = []
        try:
            for fname in fnames:
                frames.append(pd.read_table(fname, index_col=0, sep=" ",
                                            usecols=[0,1], header=None))
        except TypeError:
            frames.append(pd.read_table(fnames, index_col=0, sep=" ",
                                        usecols=[0,1], header=None))
            fnames = [fnames]
        df = pd.concat(frames, axis=1)
        df.columns=fnames
        # self.load_from_dataframe(df)
        return df


    def prep_reverse_cumulative(self, df, cutoff=None, tol=None):
        """
        Created cleaned dataframe for further analysis.

        This version assumes that the input is the result of a reversed
        cumulative histogram. That means that it cleans leading input where
        the initial 

        Returns
        -------
        cleaned_df
        """
        if cutoff is None:
            cutoff = self.cutoff
        if tol is None:
            tol = self.tol

        # clear things that don't pass the cutoff
        hist_max = df.max(axis=0)
        raw_cutoff = cutoff*hist_max
        cleaned_df = df.apply(
            lambda s : [x if x > raw_cutoff[s.name] else 0.0 for x in s]
        )

        # clear duplicates of leading values
        test_f = lambda val1, val2, val_max : (
            abs(val1 - val2) > tol or abs(val1 - val_max) > tol
        )
        cleaned_df = cleaned_df.apply(
            lambda s : [
                s.iloc[i] if test_f(s.iloc[i], s.iloc[i+1], s.max()) else 0.0
                for i in range(len(s)-1)
            ] + [s.iloc[-1]]
        )<commit_msg>docstring improvments<commit_after>#!/usr/bin/env python

# wham.py
# The Weighted Histogram Analysis Method (WHAM) for combining histograms
# from several files.
import pandas as pd
import numpy as np

import logging
logger = logging.getLogger(__name__)

class WHAM(object):
    """
    Weighted Histogram Analysis Method

    Note
    ----
    Several parts of the docstrings mention F&S, which is intended to refer
    the reader to reference [1]_, in particular pages 184-187 in the 2nd
    edition (section called "Self-Consistent Histogram Method").

    Reference
    ---------
    .. [1] <NAME> and <NAME>. Understanding Molecular Simulation:
       From Algorithms to Applications. 2nd Edition. 2002.
    """

    def __init__(self, tol=1e-10, max_iter=1000000, cutoff=0.05):
        """
        Initialize (empty) WHAM calculation object.

        Parameters
        ----------
        tol : float
            tolerance for convergence
        max_iter : int
            maximum number of iterations
        cutoff : float
            windowing cutoff

        Attributes
        ----------
        sample_every : int
            frequency (in iterations) to report debug information

        """
        self.tol = tol
        self.max_iter = max_iter
        self.cutoff = cutoff

        self.sample_every = max_iter + 1
        self._float_format = "10.8"

    @property
    def float_format(self):
        """Float output format. Example: 10.8 (default)"""
        return lambda x : "{:" + self._float_format + "f}".format(x)

    @float_format.setter
    def float_format(self, value):
        self._float_format = value

    def load_files(self,fnames):  # pragma: no cover
        """Load a file or files into the internal structures.

        Requires either pandas or something else with pandas-like read_table
        and concat functions.

        Parameters
        ----------
        fnames : string or list of string
            file(s) to read in; each gives a column of the dataframe, with
            common indexes (keys)

        Returns
        -------
        pd.DataFrame
            dataframe with each input histogram in a column
        """
        # TODO: add some validation of formatting
        frames = []
        try:
            for fname in fnames:
                frames.append(pd.read_table(fname, index_col=0, sep=" ",
                                            usecols=[0,1], header=None))
        except TypeError:
            frames.append(pd.read_table(fnames, index_col=0, sep=" ",
                                        usecols=[0,1], header=None))
            fnames = [fnames]
        df = pd.concat(frames, axis=1)
        df.columns=fnames
        return df


    def prep_reverse_cumulative(self, df, cutoff=None, tol=None):
        """
        Created cleaned dataframe for further analysis.

        This version assumes that the input is the result of a reversed
        cumulative histogram. That means that it cleans leading input where
        the initial 
        

        Returns
        -------
        cleaned_df
        """
        if cutoff is None:
            cutoff = self.cutoff
        if tol is None:
            tol = self.tol

        # clear things that don't pass the cutoff
        hist_max = df.max(axis=0)
        raw_cutoff = cutoff*hist_max
        cleaned_df = df.apply(
            lambda s : [x if x > raw_cutoff[s.name] else 0.0 for x in s]
        )

        # clear duplicates of leading values
        test_f = lambda val1, val2, val_max : (
            abs(val1 - val2) > tol or abs(val1 - val_max) > tol
        )
        cleaned_df = cleaned_df.apply(
            lambda s : [
                s.iloc[i] if test_f(s.iloc[i], s.iloc[i+1], s.max()) else 0.0
                for i in range(len(s)-1)
            ] + [s.iloc[-1]]
        )
{'fraction_non_alphanumeric': 0.09500693481276005, 'fraction_numerical': 0.014701803051317614, 'mean_word_length': 1.7273071104387292, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3847537', 'n_tokens_mistral': 2130, 'n_tokens_neox': 1995, 'n_words': 638}