Source code for pyEPR.toolbox.pythonic

# -*- coding: utf-8 -*-
"""
Created on Sat Feb 04 09:32:46 2017

@author: Zlatko K. Minev, pyEPR ream
"""
from __future__ import division, print_function, absolute_import   # Python 2.7 and 3 compatibility
import platform         # Which OS we run
import numpy as np
import pandas as pd
import warnings
import matplotlib.pyplot as plt

# Constants
from collections import OrderedDict
from ..calcs.constants import Planck, elementary_charge, epsilon_0, pi, π, ħ, ϕ0, e_el
from .. import Dict

# ==============================================================================
# Utility functions
# ==============================================================================

[docs]def combinekw(kw1, kw2): ''' Copy kw1, update with kw2, return result ''' kw = kw1.copy() kw.update(kw2) return kw
def isint(value): try: int(value) return True except ValueError: return False def isfloat(value): try: float(value) return True except ValueError: return False def floor_10(x): ''' round to nearest lower power of 10 c''' return 10.**(np.floor(np.log10(x)))
[docs]def fact(n): ''' Factorial ''' if n <= 1: return 1 return n * fact(n-1)
[docs]def nck(n, k): ''' choose ''' return fact(n)/(fact(k)*fact(n-k))
def get_above_diagonal(M): ''' extract the values that are above the diagonal. Assumes square matrix ''' return M[np.triu_indices(M.shape[0], k=1)]
[docs]def df_find_index(s: pd.Series, find, degree=2, ax=False): """ Given a Pandas Series such as of freq with index Lj, find the Lj that would give the right frequency """ max_ = max(s.index.values) min_ = min(s.index.values) if find <= max_ and find >= min_: # interpolate z = pd.Series(list(s.index.values)+[np.NaN], index=list(s) + [find]) z = z.sort_index() z = z.interpolate() return z[find], z else: print('extrapolating') z = pd.Series(list(s.index.values), index=list(s)) p = df_extrapolate(z, degree=degree, ax=False) value = p(find) return value, p
def df_interpolate_value(s: pd.Series, find, ax=False, method='index'): """ Given a Pandas Series such as of freq with index Lj, find the freq that would correspond to Lj given a value not in the index """ z = pd.Series(list(s) + [np.NaN], index=list(s.index.values)+[find]) z = z.sort_index() z = z.interpolate(method=method) return z[find], z def df_extrapolate(s, degree=2, ax=False, rng_scale=2.): """ For a pandas series Returns np.poly1d """ z = np.polyfit(s.index.values, s.values, degree) p = np.poly1d(z) if ax: if ax is True: ax = plt.gca() max_ = max(s.index.values) min_ = min(s.index.values) rng = max_ - min_ xp = np.linspace(min_-rng_scale*rng, max_+rng_scale*rng, 100) ys = p(xp) ax.plot(xp, ys) s.plot(marker='o', ax=ax) return p def df_regress_value(s: pd.Series, index, degree=2, ax=False, method='index', rng_scale=2.): """ for pandas series. calls either df_interpolate_value or df_extrapolate """ max_ = max(s.index.values) min_ = min(s.index.values) if index > max_ or index < min_: # print('extrapolate') p = df_extrapolate(s, degree=degree, ax=ax, rng_scale=rng_scale) value = p(index) else: value = df_interpolate_value(s, index, method=method)[0] return value def series_of_1D_dict_to_multi_df(Uj_ind: pd.Series): df = pd.DataFrame(dict([(k, v) for k, v in Uj_ind.items()])).transpose() df.index.set_names(Uj_ind.index.names, inplace=True) return df
[docs]def sort_df_col(df): ''' sort by numerical int order ''' return df.sort_index(axis=1) # Buggy code, doesn't handles ints as inputs or floats as inputs col_names = df.columns if np.all(col_names.map(isint)): return df[col_names.astype(int).sort_values().astype(str)] elif np.all(col_names.map(isfloat)): # raises error in some cases return df[col_names.astype(float).sort_values().astype(str)] else: return df
[docs]def sort_Series_idx(sr): ''' sort by numerical int order ''' idx_names = sr.index if np.all(idx_names.map(isint)): return sr[idx_names.astype(int).sort_values().astype(str)] if np.all(idx_names.map(isfloat)): return sr[idx_names.astype(float).sort_values().astype(str)] else: return sr
def get_instance_vars(obj, Forbidden=[]): VARS = {} for v in dir(obj): if not (v.startswith('__') or v.startswith('_')): if not callable(getattr(obj, v)): # Added for using addict.Dict which is not callable. if not isinstance(getattr(obj, v), Dict): if not (v in Forbidden): VARS[v] = getattr(obj, v) return VARS def deprecated(func): """This is a decorator which can be used to mark functions as deprecated. It will result in a warning being emitted when the function is used. See StackExchange""" def newFunc(*args, **kwargs): warnings.simplefilter('always', DeprecationWarning) # turn off filter warnings.warn("Call to deprecated function {}.".format( func.__name__), category=DeprecationWarning, stacklevel=2) warnings.simplefilter('default', DeprecationWarning) # reset filter return func(*args, **kwargs) newFunc.__name__ = func.__name__ newFunc.__doc__ = func.__doc__ newFunc.__dict__.update(func.__dict__) return newFunc def info_str_platform(): return ''' System platform information: system : %s node : %s release : %s machine : %s processor: %s summary : %s version : %s Python platform information: version : %s (implem: %s) compiler : %s ''' % ( platform.system(), platform.node(), platform.release(), platform.machine(), platform.processor(), platform.platform(), platform.version(), platform.python_version(), platform.python_implementation(), platform.python_compiler()) # ============================================================================== # Matrix # ==============================================================================
[docs]def divide_diagonal_by_2(CHI0, div_fact=2.): CHI = CHI0.copy() CHI[np.diag_indices_from(CHI)] /= div_fact return CHI
def print_color(text, style=0, fg=24, bg=43, newline=True): '''For newer, see pc (or Print_colors) style 0..8; fg 30..38; bg 40..48 ''' format = ';'.join([str(style), str(fg), str(bg)]) s = '\x1b[%sm %s \x1b[0m' % (format, text) if newline: print(s) else: print(s, end='') class Print_colors: '''Colors class:reset all colors with colors.reset; two sub classes fg for foreground and bg for background; use as colors.subclass.colorname. i.e. colors.fg.red or colors.bg.green also, the generic bold, disable, underline, reverse, strike through, and invisible work with the main class i.e. colors.bold https://www.geeksforgeeks.org/print-colors-python-terminal/ Example use: ..codeblock python print(colors.bg.green, "adgd", colors.fg.red, "dsgdsg") print(colors.bg.lightgrey, "dsgsd", colors.fg.red, "sdgsd") ''' reset = '\033[0m' bold = '\033[01m' disable = '\033[02m' underline = '\033[04m' reverse = '\033[07m' strikethrough = '\033[09m' invisible = '\033[08m' class fg: black = '\033[30m' red = '\033[31m' green = '\033[32m' orange = '\033[33m' blue = '\033[34m' purple = '\033[35m' cyan = '\033[36m' lightgrey = '\033[37m' darkgrey = '\033[90m' lightred = '\033[91m' lightgreen = '\033[92m' yellow = '\033[93m' lightblue = '\033[94m' pink = '\033[95m' lightcyan = '\033[96m' class bg: black = '\033[40m' red = '\033[41m' green = '\033[42m' orange = '\033[43m' blue = '\033[44m' purple = '\033[45m' cyan = '\033[46m' lightgrey = '\033[47m' pc = Print_colors # ============================================================================== # %% Dataframe # ==============================================================================
[docs]def DataFrame_col_diff(PS, indx=0): ''' check weather the columns of a dataframe are equal, returns a T/F series of the row index that specifies which rows are different USE: PS[DataFrame_col_diff(PS)] ''' R = [] for i in range(PS.shape[1]-1): R += [PS.iloc[:, i] == PS.iloc[:, i+1]] if len(R) == 1: return np.logical_not(R[0]) else: return np.logical_not(np.logical_and.reduce(R)) # pylint: disable=no-member
def DataFrame_display_side_by_side(*args, do_display=True): ''' from pyEPR.toolbox.pythonic import display_dfs https://stackoverflow.com/questions/38783027/jupyter-notebook-display-two-pandas-tables-side-by-side ''' from IPython.display import display_html html_str = '' for df in args: html_str += df.to_html() text = html_str.replace('table', 'table style="display:inline"') if do_display: display_html(text, raw=True) return text display_dfs = DataFrame_display_side_by_side
[docs]def xarray_unravel_levels(arr, names, my_convert=lambda x: x): ''' Takes in nested dict of dict of dataframes names : names of lists; you dont have to include the last two dataframe columns & rows, but you can to override them requires xarray ''' import xarray # pylint: disable=import-error if type(arr) == pd.DataFrame: return xarray.DataArray(arr, dims=None if len(names) == 0 else names) elif type(arr) in [OrderedDict, dict]: return xarray.concat([xarray_unravel_levels(item, names[1:]) for k, item in arr.items()], pd.Index(arr.keys(), name=names[0])) elif type(arr) == xarray.DataArray: return arr else: return my_convert(arr)
[docs]def robust_percentile(calc_data, ROBUST_PERCENTILE=2.): ''' analysis helper function ''' vmin = np.percentile(calc_data, ROBUST_PERCENTILE) vmax = np.percentile(calc_data, 100 - ROBUST_PERCENTILE) return vmin, vmax
__all__ = ['fact', 'nck', 'combinekw', 'divide_diagonal_by_2', 'df_find_index', 'sort_df_col', 'sort_Series_idx', 'print_matrix', 'print_NoNewLine', 'DataFrame_col_diff', 'xarray_unravel_levels', 'robust_percentile']