def delta_s(X_c, X, style, level, kind, title, ranshow, title_font, figsize,
            directory, fig_format, color, indicator, detail, indeces, ex_save,
            Units):
    '''
    
    Parameters
    ----------
    As described in the main class
    
    Returns
    -------
    Nothing specific. But it shows the plot, save the plots and save the plotted
    data in form of excel file
    
    '''

    # As some processes are needed to be done on the inputs, to keep the main variable unchanged, we will make a copy of them
    X_c = X_c.copy()  # After shock
    X = X.copy()  # Baseline

    # Checking the styles,units,levels and the indicator
    style = style_check(style)
    tit, level = level_check(level)
    kind = kind_check(kind)

    # To check if the given indicator exists in the database aggregated level
    indicator = indic_check(indicator,
                            list(indeces['S_ind'].get_level_values(1)))

    # Implementing the plot style
    plt.style.use(style)

    if detail:
        # For the detailed case, more levels should be taken to show detailed information
        X_c = X_c.loc[(slice(None), indicator),
                      level].groupby(axis=1,
                                     level=[0,
                                            2]).sum().groupby(axis=0,
                                                              level=0).sum()
        X = X.loc[(slice(None), indicator),
                  level].groupby(axis=1,
                                 level=[0, 2]).sum().groupby(axis=0,
                                                             level=0).sum()
    else:
        # Otherwise, only the main level will be taken
        X_c = X_c.loc[indicator, level]
        X = X.loc[indicator, level]

    # defining the d_x matrix
    if kind == 'Absolute':
        # Here the unit won't be printed because there is not a single unit anymore
        d_x, unit = (X_c - X), Units.loc[indicator].iloc[0].values.tolist()[0]

    else:
        d_x, unit = (X_c - X) / X * 100, '%'

    # if detail is True, we need to reindex it
    if detail:
        # Take only the first level of index
        d_x.index = d_x.index.get_level_values(0)
        d_x.columns = d_x.columns.get_level_values(1)

    # Due to competutional errors, even in the case that one thing is not changed,
    # we may have very small differences
    # This makes the graphs ugly!! To solve the issue we print an error for the
    # user to make them understand.
    if abs(d_x.sum().sum()) <= 0.000001:
        print(
            'The following matrix seems to be unchanged in the implemented shock, Maybe the changes are very small or they are related to computational errors.'
        )

    # Specifing the range of showing results
    d_x = drop_fun(data=d_x, ranshow=ranshow)

    # Transposing the dataframe
    d_x = d_x.T

    # Removing the name of the indeces for better representation
    d_x.index.name = None
    d_x.columns.name = None

    # Title Definition
    # If is not given by user, choose the default title
    if title == 'default':
        title = '{} Change{}'.format(indicator, tit)
        # Otherwise, use the one which is given by user.
    else:
        title = title

    # If detail is True, we need legens
    if detail:
        try:
            d_x.plot(kind='bar', stacked=True,
                     colormap=color)  # With a color map
        except:
            d_x.plot(kind='bar', stacked=True,
                     color=color)  # With a color list
        plt.legend(loc='center left',
                   bbox_to_anchor=(1, 0.5),
                   fancybox=True,
                   shadow=True)

    # Otherwise, we don't need to have legends, becuase ther is only one
    else:
        try:
            d_x.plot(kind='bar', stacked=False, legend=False, colormap=color)
        except:
            d_x.plot(kind='bar', stacked=False, legend=False, color=color)

    plt.title(title)
    plt.ylabel(unit)

    # Saving and showing the plot
    # check if the same file already exists or not
    i = 1
    dir = '{}\{}_{}.{}'.format(directory, title, i, fig_format)
    while file_exist(dir):
        i += 1
        dir = '{}\{}_{}.{}'.format(directory, title, i, fig_format)
    plt.savefig(dir, bbox_inches='tight', dpi=150)
    plt.show()

    # Saving the final dataframe into an excel file in the same directory
    i = 1
    dir = '{}\{}_{}.xlsx'.format(directory, i, title)
    while file_exist(dir):
        i += 1
        dir = '{}\{}_{}.xlsx'.format(directory, i, title)
    if ex_save:
        with pd.ExcelWriter(dir) as writer:
            d_x.to_excel(writer)
def delta_p(X_c, X, style, level, title, title_font, figsize, directory,
            fig_format, color, ex_save):
    '''
    
    Parameters
    ----------
    As described in the main class
    
    Returns
    -------
    Nothing specific. But it shows the plot, save the plots and save the plotted
    data in form of excel file
    
    '''

    # As some processes are needed to be done on the inputs, to keep the main variable unchanged, we will make a copy of them
    X_c = X_c.copy()  # After shock
    X = X.copy()  # Baseline

    # Checking the styles,title and the unit
    style = style_check(style)
    tit, level = level_check(level)

    # Implementing the plot style
    plt.style.use(style)

    # Taking the level only from the columns
    X_c = X_c[level]
    X = X[level]

    # Title Definition
    # The title not given by the user
    if title == 'default':
        title = 'Price ratio{}'.format(tit)
        # Title given by the user
    else:
        title = title

    # Making the d_x matrix: Here is X_c/X cause is the price ratio
    d_x = X_c / X

    # Reindexing the index and columns:
    # If both level exist
    if len(level) == 2:
        d_x.index, d_x.columns = X.index.get_level_values(0), [
            d_x.columns.get_level_values(0),
            d_x.columns.get_level_values(1)
        ]
        # If only one level exits: This makes the plot more beautiful!!
    else:
        d_x.index, d_x.columns = X.index.get_level_values(
            0), d_x.columns.get_level_values(1)

    # Removing the name of the indeces for better representation
    d_x.index.name = None
    d_x.columns.name = None

    # Using a heatmap plot
    fig = plt.figure(figsize=figsize)
    ax = sns.heatmap(d_x.T, annot=False, cmap=color)

    plt.ylabel('Price Ratio')
    plt.title(title)

    # Save and show the plot
    i = 1
    dir = '{}\{}_{}.{}'.format(directory, title, i, fig_format)
    while file_exist(dir):
        i += 1
        dir = '{}\{}_{}.{}'.format(directory, title, i, fig_format)
    plt.savefig(dir, bbox_inches='tight', dpi=150)
    plt.show()

    # save the final dataframe in form of an excel file in the same directory
    i = 1
    dir = '{}\{}_{}.xlsx'.format(directory, i, title)
    while file_exist(dir):
        i += 1
        dir = '{}\{}_{}.xlsx'.format(directory, i, title)
    if ex_save:
        with pd.ExcelWriter(dir) as writer:
            d_x.to_excel(writer)
def delta_xv(X_c, X, style, unit, m_unit, level, kind, title, ranshow,
             title_font, figsize, directory, fig_format, color, info, drop,
             ex_save):
    '''
    
    Parameters
    ----------
    As described in the main class
    
    Returns
    -------
    Nothing specific. But it shows the plot, save the plots and save the plotted
    data in form of excel file
    
    '''

    # As some processes are needed to be done on the inputs, to keep the main variable unchanged, we will make a copy of them
    X_c = X_c.copy()  # After shock
    X = X.copy()  # Baseline

    # default unit
    if unit == 'default':
        unit = m_unit

    # Checking the units and styles
    unit = unit_check(unit)
    style = style_check(style)
    conversion = unit_converter(m_unit, unit)
    tit, level = level_check(level)
    kind = kind_check(kind)

    # Implementing the plot style
    plt.style.use(style)

    # Reshaping X matrix for better representation and Taking the level
    if info == 'X':

        # If the plot is X, it should be reshaped
        X_c = x_reshape(X_c)
        X = x_reshape(X)

        # With the new reshaped X, the levels should be taken from both
        # index and columns side
        X_c = X_c.loc[level, level]
        X = X.loc[level, level]

    elif info == 'VA':
        # In case of VA, the level should be taken from the columns not the index
        X_c = X_c[level]
        X = X[level]

    # defining the d_x matrix
    # For absolute case, d_x is the differnece between the shock and baseline
    # results multiplied with the conversion ratio. Unit as given by user

    # For percentage case, d_x is the relative change of production with respect
    # to the baseline. Unit is %
    if kind == 'Absolute': d_x = (X_c - X) * conversion
    else: d_x, unit = (X_c - X) / X * 100, '%'

    # Check the title
    if info == 'X':
        # If the title is not given by the user, the default one will be used
        if title == 'default':
            title = 'Production Change{}'.format(tit)
            # Otherwise, the one given by the user will be used
        else:
            title = title

    elif info == 'VA':
        # If the title is not given by the user, the default one will be used
        if title == 'default':
            title = 'Value Added Change{}'.format(tit)
            # Otherwise, the one given by the user will be used
        else:
            title = title

    # Reindexing to avoid showing multiple indeces: only the second level
    if info == 'X': d_x.index = X.index.get_level_values(1)
    elif info == 'VA':
        # If both levels are taken, the first two levels of columns will be taken
        if len(level) == 2:
            d_x.index, d_x.columns = X.index.get_level_values(0), [
                d_x.columns.get_level_values(0),
                d_x.columns.get_level_values(1)
            ]
            # Otherwise, just the second level will be taken. This make the plots more beautiful
        else:
            d_x.index, d_x.columns = X.index.get_level_values(
                0), d_x.columns.get_level_values(1)

    # Droping some of the categories based on the user input
    if drop:
        d_x = d_x.drop(drop)

    # defining the range of the valuse to be shown
    if info == 'X': d_x = drop_fun(data=d_x.T, ranshow=ranshow)
    elif info == 'VA': d_x = drop_fun(data=d_x, ranshow=ranshow)

    # Transposing the dataframe
    d_x = d_x.T

    # Removing the name of the indeces for better representation
    d_x.index.name = None
    d_x.columns.name = None

    # Plotting
    if info == 'X':
        # If both levels are given, we need to have legend cuase two categries exist
        if len(level) == 2:
            # Depending on the input of the color, the code will be different
            try:
                d_x.plot(kind='bar',
                         figsize=figsize,
                         stacked=True,
                         colormap=color)  # colormap if a color map is given
            except:
                d_x.plot(kind='bar',
                         figsize=figsize,
                         stacked=True,
                         color=color)  # color if a color list is given
            plt.legend(loc='center left',
                       bbox_to_anchor=(1, 0.5),
                       fancybox=True,
                       shadow=True)
        # If only one level exists, we dont need the legend anly more
        else:
            try:
                d_x.plot(kind='bar',
                         figsize=figsize,
                         legend=None,
                         stacked=True,
                         colormap=color)
            except:
                d_x.plot(kind='bar',
                         figsize=figsize,
                         legend=None,
                         stacked=True,
                         color=color)

    if info == 'VA':
        try:
            d_x.plot(kind='bar', figsize=figsize, stacked=True, colormap=color)
        except:
            d_x.plot(kind='bar', figsize=figsize, stacked=True, color=color)
        plt.legend(loc='center left',
                   bbox_to_anchor=(1, 0.5),
                   fancybox=True,
                   shadow=True)

    # Due to competutional errors, even in the case that one thing is not changed,
    # we may have very small differences
    # This makes the graphs ugly!! To solve the issue we print an error for the
    # user to make them understand.
    if abs(d_x.sum().sum()) <= 0.000001:
        print(
            'The following matrix seems to be unchanged in the implemented shock, Maybe the changes are very small or they are related to computational errors.'
        )

    # check if the same file already exists or not
    i = 1
    dir = '{}\{}_{}.{}'.format(directory, title, i, fig_format)
    while file_exist(dir):
        i += 1
        dir = '{}\{}_{}.{}'.format(directory, title, i, fig_format)

    plt.title(title, fontsize=title_font)
    plt.ylabel(unit)
    plt.savefig(dir, bbox_inches='tight', dpi=150)
    plt.show()

    # Save the dataframe into a excel file in the same directory
    # Check if the excel file with the same name already exists
    i = 1
    dir = '{}\{}_{}.xlsx'.format(directory, i, title)
    while file_exist(dir):
        i += 1
        dir = '{}\{}_{}.xlsx'.format(directory, i, title)
    if ex_save:
        with pd.ExcelWriter(dir) as writer:
            d_x.to_excel(writer)