#!/usr/bin/env python
# coding: utf-8

# In[107]:


import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cross_decomposition import PLSRegression
from sklearn.decomposition import PCA
from sklearn.preprocessing import LabelEncoder
from sklearn.model_selection import cross_val_predict
from sklearn.metrics import r2_score
import plotly.graph_objects as go
from matplotlib.patches import Ellipse
import plotly.express as px
import plotly.graph_objects as go
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.gridspec import GridSpec


# === 1. CARREGAR DADOS ===
df = pd.read_csv('D:/OPLS_two variavel _MILO_FIM.csv')
df.columns = df.columns.str.strip()
df = df[df['ID'].str.strip() != 'Oct']
df = df.fillna(0)

# === 2. PREPARAR X e y (SEM LOG) ===
X = df.drop(columns=['ID', 'Activity'])
y = df['Activity'].str.strip()
label_encoder = LabelEncoder()
y_encoded = label_encoder.fit_transform(y)

# === 3. ESCALONAMENTO PARETO ===
std = X.std()
std[std == 0] = 1e-12
X_scaled = (X - X.mean()) / np.sqrt(std)
X_scaled = X_scaled.fillna(0)
X_scaled = X_scaled.loc[:, X_scaled.var() > 0]

# === 4. OPLS (via PLS) ===
pls = PLSRegression(n_components=3)
pls.fit(X_scaled, y_encoded)
T_pred = pls.x_scores_
P_pred = pls.x_loadings_
X_ortho = X_scaled - T_pred[:, [0]] @ P_pred[:, [0]].T
T_ortho = PCA(n_components=2).fit_transform(X_ortho)

explained_var_opls1 = np.var(T_pred[:, 0]) / np.sum(np.var(X_scaled, axis=0)) * 100
explained_var_orth1 = np.var(T_ortho[:, 0]) / np.sum(np.var(X_scaled, axis=0)) * 100

# === 5. SCORES ===
scores_df = pd.DataFrame(np.hstack([T_pred[:, [0]], T_ortho]), columns=['OPLS1', 'Orth1', 'Orth2'])
scores_df['Mes'] = df['ID'].values
scores_df['Classe'] = y.values
scores_df_clean = scores_df.dropna(subset=['Classe'])

# === 6. LOADINGS ===
loadings_df = pd.DataFrame(P_pred[:, [0]], columns=['OPLS1'])
loadings_df['Composto'] = X_scaled.columns
loadings_df['Abs_Loading'] = loadings_df['OPLS1'].abs()
pca_loading = PCA(n_components=2).fit_transform(X_scaled.T)
loadings_df['PC2'] = pca_loading[:, 0]
loadings_df['PC3'] = pca_loading[:, 1]

# === 7. GRÁFICO SCORES 2D ===
plt.figure(figsize=(9, 6))
for classe in scores_df_clean['Classe'].unique():
    subset = scores_df_clean[scores_df_clean['Classe'] == classe]
    plt.scatter(subset['OPLS1'], subset['Orth1'], label=classe)
    for _, row in subset.iterrows():
        plt.text(row['OPLS1'] + 0.05, row['Orth1'], row['Mes'], fontsize=8)
plt.title('OPLS-DA - Scores 2D')
plt.xlabel('OPLS1 (Preditivo)')
plt.ylabel('Orth1 (Ortogonal)')
plt.legend()
plt.grid(True)
plt.tight_layout()
plt.show()

# === 7.1 ELIPSES DE CONFIANÇA ===
def plot_ellipse(x, y, ax, color, alpha=0.2):
    if len(x) < 2:
        return
    cov = np.cov(x, y)
    if np.isnan(cov).any() or np.linalg.matrix_rank(cov) < 2:
        return
    lambda_, v = np.linalg.eig(cov)
    lambda_ = np.sqrt(lambda_)
    ell = Ellipse(xy=(np.mean(x), np.mean(y)),
                  width=lambda_[0]*4, height=lambda_[1]*4,
                  angle=np.rad2deg(np.arccos(v[0, 0])),
                  edgecolor=color,
                  facecolor=color,
                  alpha=alpha)
    ax.add_patch(ell)

fig, ax = plt.subplots(figsize=(9, 6))
cores = plt.cm.Set2(np.linspace(0, 1, scores_df_clean['Classe'].nunique()))
for i, classe in enumerate(scores_df_clean['Classe'].unique()):
    subset = scores_df_clean[scores_df_clean['Classe'] == classe]
    ax.scatter(subset['OPLS1'], subset['Orth1'], label=classe, color=cores[i], edgecolor='k')
    plot_ellipse(subset['OPLS1'], subset['Orth1'], ax, color=cores[i])
    for _, row in subset.iterrows():
        ax.text(row['OPLS1'] + 0.05, row['Orth1'], row['Mes'], fontsize=8)
ax.set_title('Scores Plot with Confidence Ellipses')
ax.set_xlabel(f'T score [1] ({explained_var_opls1:.1f}%)')
ax.set_ylabel(f'Orthogonal T score [1] ({explained_var_orth1:.1f}%)')
ax.grid(True)
ax.legend()
plt.tight_layout()
plt.show()

# === 9. LOADINGS 3D INTERATIVO COM LEGENDA NO PLOT ===
import matplotlib.colors as mcolors
import matplotlib as mpl

# Gerar cores baseadas no valor absoluto do loading
norm = mcolors.Normalize(vmin=loadings_df['Abs_Loading'].min(), vmax=loadings_df['Abs_Loading'].max())
cmap = mpl.colormaps['turbo']
loadings_df['Color'] = loadings_df['Abs_Loading'].apply(lambda x: mcolors.to_hex(cmap(norm(x))))

# Criar figura Plotly 3D
fig_3d = go.Figure()

# Adicionar um trace para cada composto para criar legenda
for _, row in loadings_df.iterrows():
    fig_3d.add_trace(go.Scatter3d(
        x=[row['OPLS1']],
        y=[row['PC2']],
        z=[row['PC3']],
        mode='markers',
        marker=dict(
            size=7,
            color=row['Color'],
            opacity=0.9,
            line=dict(color='black', width=0.5)
        ),
        name=row['Composto'],  # Vai aparecer na legenda
        hovertemplate="<b>%{text}</b><br>OPLS1: %{x:.2f}<br>PC2: %{y:.2f}<br>PC3: %{z:.2f}<extra></extra>",
        text=row['Composto']
    ))

# Layout
fig_3d.update_layout(
    title=dict(text='Loadings 3D - OPLS1 x PC2 x PC3', font=dict(size=18, family="Arial", color='black')),
    scene=dict(
        xaxis_title='OPLS1',
        yaxis_title='PC2',
        zaxis_title='PC3',
        xaxis=dict(title_font=dict(size=12)),
        yaxis=dict(title_font=dict(size=12)),
        zaxis=dict(title_font=dict(size=12))
    ),
    margin=dict(l=0, r=0, b=0, t=40),
    showlegend=True,  # ✅ Agora a legenda aparece
    legend=dict(
        x=1.02,  # 👈 Lado direito externo
        y=1,     # 👈 Topo
        bgcolor="white",
        bordercolor="black",
        borderwidth=1,
        font=dict(size=8)
    )
)

fig_3d.show()

# Layout com fundo similar ao 3D
fig_2d.update_layout(
    title=dict(text='Loadings 2D - OPLS1 vs PC2', font=dict(size=18, family="Arial", color='black')),
    xaxis_title='OPLS1',
    yaxis_title='PC2',

    plot_bgcolor="whitesmoke",    # 🔥 Fundo da área de plotagem como no 3D
    paper_bgcolor="white",       # 🔥 Fundo externo (fora da plotagem)

    # 🔥 Configurações dos eixos e grades
    xaxis=dict(
        title_font=dict(size=14),
        showgrid=True,
        gridcolor='white',        # 🔲 Cor da grade (quadradinhos)
        zeroline=False,
        zerolinecolor='gray',
        linecolor='black',
        linewidth=0,
        mirror=True
    ),
    yaxis=dict(
        title_font=dict(size=14),
        showgrid=True,
        gridcolor='white',
        zeroline=False,
        zerolinecolor='gray',
        linecolor='black',
        linewidth=1,
        mirror=True
    ),

    width=800,
    height=600,
    showlegend=True,
    legend=dict(
        x=1.02,
        y=1,
        bgcolor="white",
        bordercolor="black",
        borderwidth=1,
        font=dict(size=8)
    )
)

fig_2d.show()


# === 10. R² e Q² ===
r2 = pls.score(X_scaled, y_encoded)
y_cv_pred = cross_val_predict(pls, X_scaled, y_encoded, cv=len(X_scaled))
q2 = r2_score(y_encoded, y_cv_pred)
print(f"\n📈 R² (ajuste): {r2:.3f}")
print(f"🔍 Q² (validação cruzada): {q2:.3f}")

# === 11. VIP SCORES ===
t = pls.x_scores_
w = pls.x_weights_
q = pls.y_loadings_
p, h = w.shape
s = np.diag(t.T @ t @ q.T @ q)
vip = np.sqrt(p * np.sum((w**2) * s, axis=1) / np.sum(s))
vip_scores = pd.DataFrame({'Composto': X_scaled.columns, 'VIP': vip})

from scipy.stats import pearsonr
# === 12. Correlações com aOPLS - Usando dados escalonados (para tabela) ===
mask_swf = df['Activity'].str.strip() == 'SWF'
aopls_swf = T_pred[mask_swf.values, 0]
X_scaled_swf = X_scaled.iloc[mask_swf.values, :]

from scipy.stats import ttest_ind

def calcular_correlacoes_com_pvalor(X_filtrado, aopls_filtrado):
    resultado = []
    for composto in X_filtrado.columns:
        x = X_filtrado[composto]
        if np.std(x) > 0 and np.std(aopls_filtrado) > 0:
            corr = np.corrcoef(x, aopls_filtrado)[0, 1]
            # Cálculo do p-valor da correlação (teste t de correlação)
            n = len(x)
            t_stat = corr * np.sqrt((n - 2) / (1 - corr**2))
            from scipy.stats import t
            p_value = 2 * (1 - t.cdf(abs(t_stat), df=n-2))
        else:
            corr = np.nan
            p_value = np.nan
        resultado.append({'Composto': composto, 'Correl_OPLS1': corr, 'p_value': p_value})
    return pd.DataFrame(resultado)

#correl_df_fws = calcular_correlacoes_com_pvalor(X_scaled_fws, aopls_fws).sort_values(by='Correl_OPLS1', ascending=False)

# === 13. Tabela completa com VIP, correlação, p-valor e q-valor ===

# Calcular correlações e p-valores
correl_df_swf = calcular_correlacoes_com_pvalor(X_scaled_swf, aopls_swf).sort_values(by='p_value')

# Adicionar coluna de ID (número sequencial)
correl_df_swf = correl_df_swf.reset_index(drop=True)
correl_df_swf['ID'] = correl_df_swf.index + 1

# Merge com VIP
tabela_swf = correl_df_swf.merge(vip_scores, on='Composto')
tabela_swf = tabela_swf.reset_index(drop=True)


# Calcular q-value (Benjamini-Hochberg manual)
N = len(tabela_swf)  # Número total de compostos
tabela_swf['q_value'] = (tabela_swf['p_value'] * N) / tabela_swf['ID']
tabela_swf['q_value'] = tabela_swf['q_value'].clip(upper=1)  # Limitar q_value no máximo 1

# Organizar colunas
tabela_swf = tabela_swf[['ID', 'Composto', 'Correl_OPLS1', 'VIP', 'p_value', 'q_value']]

# Exibir tabela completa
print(" Correlation Values, VIP, p-value, and q-value :")
print(tabela_swf.to_string(index=False))

# Salvar Excel (opcional)
tabela_swf.to_excel('Tabela_Completa_OPLS.xlsx', index=False)


#13.1 Tabela filtrada com p < 0.05 e VIP > 1 (incluindo q_value) ===
tabela_significativa = tabela_swf[
    (tabela_swf['p_value'] < 0.05) & 
    (tabela_swf['VIP'] > 1)
].sort_values(by='Correl_OPLS1', ascending=False)

# 🔥 Resetar o índice, se quiser também remover internamente
tabela_significativa = tabela_significativa.reset_index(drop=True)

print("\n🚀 Compounds with p_value < 0.05, VIP > 1 e seus q-values:")
print(tabela_significativa[['ID','Composto', 'Correl_OPLS1', 'VIP', 'p_value', 'q_value']].to_string(index=False))


# === 14. GRÁFICO DE VIP SCORES ===
vip_scores_sorted = vip_scores.sort_values(by='VIP', ascending=False)
cores_vip = ['#31a354' if v > 1 else '#d9f0a3' for v in vip_scores_sorted['VIP']]

plt.figure(figsize=(12, 6))
plt.bar(vip_scores_sorted['Composto'], vip_scores_sorted['VIP'], color=cores_vip)
plt.axhline(y=1, color='red', linestyle='--', label='VIP limit = 1')
plt.xticks(rotation=90)
plt.title('VIP Scores of Compounds')
plt.ylabel('VIP Score')
plt.xlabel('Compound')
plt.tight_layout()
plt.legend()
plt.show()





# In[88]:


# === 15. HEATMAP - Compostos correlacionados com meses 'Normal' ===
import seaborn as sns
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# >>> NÃO sobrescreve seu df original <<<
df_hm = df.copy()

# Filtrar apenas meses válidos no padrão 'Jan-21' OU apenas 'Jan'
validos = df_hm['ID'].astype(str).str.strip().str.fullmatch(r'[A-Za-z]{3}(-\d{2})?')
df_hm = df_hm[validos].reset_index(drop=True)

# Selecionar as mesmas linhas em X
X_heatmap = X.iloc[validos.values].copy()

# >>> deixar nomes dos compostos em minúsculas (para bater com filtros) <<<
X_heatmap.columns = X_heatmap.columns.astype(str).str.strip().str.lower()

# >>> Criar rótulo só do mês (sem ano) <<<
dt1 = pd.to_datetime(df_hm['ID'].astype(str).str.strip(), format='%b-%y', errors='coerce')
dt2 = pd.to_datetime(df_hm['ID'].astype(str).str.strip(), format='%b', errors='coerce')
dt = dt1.fillna(dt2)

df_hm['ID_mes'] = dt.dt.strftime('%b')  # "Apr", "May", ...
X_heatmap.index = df_hm['ID_mes'].values

# =========================
# >>> AQUI: lista de compostos que você quer manter no heatmap <<<
# =========================
compostos_alvo = [
    "alpha.-pinene",
    "camphene",
    "(+)-sabinene",
    "(-)-beta-pinene",
    "limonene",
    "eucalyptol",
    "camphor",
    "4-terpineol",
    "alpha-copaene",
    "caryophyllene",
    "beta-gurjunene",
    "aromadendrene",
    "alpha-caryophyllene",
    "alpha-amorphene",
    "bicyclogermacrene",
    "cadina-1.4-diene",   # <<< SEM <trans-> (igual na sua tabela)
    "spathulenol",
]
compostos_alvo = [c.strip().lower() for c in compostos_alvo]

# Usar todos os compostos com correlação calculada (em minúsculas)
todos_normal = correl_df_normal['Composto'].astype(str).str.strip().str.lower().values

# >>> CORREÇÃO MÍNIMA: remover "<trans->" de todos_normal para bater com sua tabela <<<
todos_normal = [c.replace(" <trans->", "") for c in todos_normal]

# >>> manter só compostos que existem em X_heatmap (evita KeyError) <<<
todos_normal = [c for c in todos_normal if c in X_heatmap.columns]

# Seleção original por correlação
heatmap_data = X_heatmap.loc[:, todos_normal]

# >>> manter apenas os compostos da lista alvo <<<
heatmap_data = heatmap_data.loc[:, heatmap_data.columns.isin(compostos_alvo)]

# Cores por tipo de mês
classe_color = df_hm.set_index('ID_mes').loc[heatmap_data.index, 'Activity'].astype(str).str.strip()
palette = {'Normal': 'darkgreen', 'Fraco': 'darkred'}
col_colors = classe_color.map(palette).values

# Plot do heatmap
plt.figure(figsize=(14, 10))
ax = sns.heatmap(
    heatmap_data.T,
    cmap="YlGn_r",
    annot=False,
    cbar_kws={'label': 'Value without Scaling'},
    xticklabels=heatmap_data.index  # já está sem ano
)

# Colorir os rótulos dos meses
for tick_label, color in zip(ax.get_xticklabels(), col_colors):
    if pd.notna(color):
        tick_label.set_color(color)

plt.xlabel("Months")
plt.ylabel("Compounds")
plt.tight_layout()
plt.show()

# === LIMPAR NOMES DE COLUNAS ===
df_hm.columns = df_hm.columns.str.strip()

# === Selecionar apenas colunas numéricas ===
df_numerico = df_hm.select_dtypes(include=np.number).copy()
df_numerico['ID'] = df_hm['ID']  # mantém ID original

# === Agrupar por meses ===
df_grouped = df_numerico.groupby('ID').agg(['mean', 'std'])

# === Ordenar os meses corretamente (agora sem ano) ===
meses_ordenados = dt.dropna().sort_values().dt.strftime('%b').unique()


# In[106]:


# === 14. GRÁFICO DE VIP SCORES ===
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# ======= CORREÇÃO (somente para esse problema): padronizador de nomes =======
def norm_composto(x):
    return str(x).strip().lower().replace(" <trans->", "")

# VIP plot: só garante que o eixo X use o nome "real" normalizado (sem quebrar)
vip_scores_sorted = vip_scores.sort_values(by='VIP', ascending=False).copy()
vip_scores_sorted['Composto'] = vip_scores_sorted['Composto'].astype(str).map(norm_composto)

cores_vip = ['#31a354' if v > 1 else '#d9f0a3' for v in vip_scores_sorted['VIP']]

plt.figure(figsize=(12, 6))
plt.bar(vip_scores_sorted['Composto'], vip_scores_sorted['VIP'], color=cores_vip)
plt.axhline(y=1, color='red', linestyle='--', label='VIP limit = 1')
plt.xticks(rotation=90)
plt.title('VIP Scores of Compounds')
plt.ylabel('VIP Score')
plt.xlabel('Compound')
plt.tight_layout()
plt.legend()
plt.show()


# === 15. HEATMAP - Compostos correlacionados com meses 'Normal' ===
# ✅ Crie uma cópia apenas para o heatmap, sem alterar o df principal
df_heatmap = df[df['ID'].astype(str).str.len() == 3].copy()
X_heatmap = X.loc[df_heatmap.index].copy()
X_heatmap.index = df_heatmap['ID'].astype(str).values  # Meses como índice

# ======= CORREÇÃO (somente para esse problema): padronizar colunas e lista correl_df_swf para bater =======
X_heatmap.columns = X_heatmap.columns.astype(str).map(norm_composto)

todos_swf = correl_df_swf['Composto'].astype(str).map(norm_composto).values
heatmap_data = X_heatmap.loc[:, X_heatmap.columns.intersection(todos_swf)].copy()

# Checar se há dados suficientes
if heatmap_data.empty:
    print("⚠️ Heatmap vazio — nenhum dado disponível para os compostos filtrados.")
else:
    # ✅ Meses sem ano (se já for "Jan", fica "Jan")
    meses_sem_ano = [str(m).split('-')[0] for m in heatmap_data.index]

    # ✅ Colocar os nomes dos compostos em minúsculas no eixo Y (sem mudar o dataframe)
    ylabels_minusculo = [str(c).lower() for c in heatmap_data.columns]

    # Cores por tipo de mês
    classe_color = df_heatmap.set_index('ID').loc[heatmap_data.index, 'Activity'].astype(str).str.strip()
    palette = {'SWF': 'darkgreen', 'Fraco': 'darkred'}
    col_colors = classe_color.map(palette).values

    # Plot do heatmap
    plt.figure(figsize=(14, 10))
    ax = sns.heatmap(
        heatmap_data.T,
        cmap="YlGn_r",
        annot=False,
        cbar_kws={'label': 'Value without Scaling'},
        xticklabels=meses_sem_ano,       # ✅ meses sem ano
        yticklabels=ylabels_minusculo    # ✅ compostos em minúsculas
    )

    # Colorir os rótulos dos meses
    for tick_label, color in zip(ax.get_xticklabels(), col_colors):
        if pd.notna(color):
            tick_label.set_color(color)

   
    plt.xlabel("Months")
    plt.ylabel("Compounds")
    plt.tight_layout()
    plt.show()


# In[99]:


# ================================
# GRÁFICO DOS COMPOSTOS COM p < 0.05
# ================================

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# ======= CORREÇÃO (somente para esse problema): normalizar alpha e vírgula->ponto =======
def norm_composto(x):
    s = str(x).strip().lower()
    s = s.replace(" <trans->", "")
    # normaliza "alpha" quando vier com símbolo grego ou encoding quebrado
    s = s.replace("α", "alpha")
    s = s.replace("î±", "alpha")
    # normaliza separador decimal/composição (ex.: 1,4 -> 1.4)
    s = s.replace(",", ".")
    return s

compostos_significativos = [
    'camphor',
    'bicyclogermacrene',
    'cadina-1,4-diene',
    'beta-gurjunene',
]

# ======= normalizar lista para bater com df_grouped =======
compostos_significativos = [norm_composto(c) for c in compostos_significativos]

cores = plt.cm.YlGn(np.linspace(0.4, 0.9, len(compostos_significativos)))

plt.figure(figsize=(12, 6))

bar_width = 0.15
x = np.arange(len(meses_ordenados))

# ✅ Meses sem ano (ex.: "Jan-21" -> "Jan")
meses_sem_ano = [str(m).split('-')[0] for m in meses_ordenados]

# ======= padronizar as colunas do df_grouped para lookup =======
df_grouped_cols_norm = pd.MultiIndex.from_tuples(
    [(norm_composto(c), stat) for (c, stat) in df_grouped.columns],
    names=df_grouped.columns.names
)
df_grouped_norm = df_grouped.copy()
df_grouped_norm.columns = df_grouped_cols_norm

for i, composto in enumerate(compostos_significativos):
    medias = df_grouped_norm[(composto, 'mean')].reindex(meses_ordenados).fillna(0)
    desvios = df_grouped_norm[(composto, 'std')].reindex(meses_ordenados).fillna(0)

    plt.bar(
        x + i * bar_width,
        medias,
        yerr=desvios,
        width=bar_width,
        label=str(composto).lower(),   # ✅ legenda em minúsculas
        color=cores[i],
        alpha=0.9,
        capsize=4
    )

plt.ylabel('Avarage Peak area', fontsize=12)
plt.xlabel('Months', fontsize=12)

# ✅ Aplicar meses sem ano no eixo X
plt.xticks(
    x + bar_width * (len(compostos_significativos) / 2),
    meses_sem_ano,
    rotation=45
)

plt.legend()
plt.tight_layout()
plt.show()


# In[102]:


# ================================
# GRÁFICO DOS COMPOSTOS COM p < 0.05
# ================================

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# ======= CORREÇÃO (somente para esse problema): normalizar alpha e vírgula->ponto =======
def norm_composto(x):
    s = str(x).strip().lower()
    s = s.replace(" <trans->", "")
    # normaliza "alpha" quando vier com símbolo grego ou encoding quebrado
    s = s.replace("α", "alpha")
    s = s.replace("î±", "alpha")
    # normaliza separador decimal/composição (ex.: 1,4 -> 1.4)
    s = s.replace(",", ".")
    return s

compostos_significativos = [
    'bicyclogermacrene',
    'cadina-1,4-diene',
    'beta-gurjunene',
]

# ======= normalizar lista para bater com df_grouped =======
compostos_significativos = [norm_composto(c) for c in compostos_significativos]

cores = plt.cm.YlGn(np.linspace(0.4, 0.9, len(compostos_significativos)))

plt.figure(figsize=(12, 6))

bar_width = 0.15

# ✅ Meses sem ano (ex.: "Jan-21" -> "Jan")
meses_sem_ano = [str(m).split('-')[0] for m in meses_ordenados]

# ======= SÓ ESTA ALTERAÇÃO: reordenar meses para começar em Mar e terminar em Feb =======
ordem_mar_fev = ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
meses_ordenados = [m for m in ordem_mar_fev if m in meses_sem_ano]

# atualizar eixo x conforme a nova ordem
x = np.arange(len(meses_ordenados))

# ======= padronizar as colunas do df_grouped para lookup =======
df_grouped_cols_norm = pd.MultiIndex.from_tuples(
    [(norm_composto(c), stat) for (c, stat) in df_grouped.columns],
    names=df_grouped.columns.names
)
df_grouped_norm = df_grouped.copy()
df_grouped_norm.columns = df_grouped_cols_norm

for i, composto in enumerate(compostos_significativos):
    # reindex agora usa a ordem Mar->Feb
    medias = df_grouped_norm[(composto, 'mean')].reindex(meses_ordenados).fillna(0)
    desvios = df_grouped_norm[(composto, 'std')].reindex(meses_ordenados).fillna(0)

    plt.bar(
        x + i * bar_width,
        medias,
        yerr=desvios,
        width=bar_width,
        label=str(composto).lower(),   # ✅ legenda em minúsculas
        color=cores[i],
        alpha=0.9,
        capsize=4
    )

plt.ylabel('Avarage Peak Area', fontsize=12)
plt.xlabel('Months', fontsize=12)

# ✅ Aplicar meses no eixo X (Mar → Feb)
plt.xticks(
    x + bar_width * (len(compostos_significativos) / 2),
    meses_ordenados,
    rotation=45
)

plt.legend()
plt.tight_layout()
plt.show()


# In[101]:


# ================================
# GRÁFICO DOS COMPOSTOS COM p < 0.05
# ================================

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# ======= CORREÇÃO (somente para esse problema): normalizar alpha (α/Î±/î±) =======
def norm_composto(x):
    s = str(x).strip().lower()
    s = s.replace(" <trans->", "")
    # normaliza "alpha" quando vier com símbolo grego ou com encoding quebrado
    s = s.replace("α", "alpha")
    s = s.replace("î±", "alpha")
    s = s.replace("Î±".lower(), "alpha")  # cobre "Î±" -> "î±" após lower()
    return s

compostos_significativos = [
    'spathulenol',
    '4-terpineol',
    'alpha-Cadinol',
    'beta-myrcene',
    'globulol',
    'selina-3.11-dien-6-Î±-ol',
    'alpha-cadinol',
]

# ======= normalizar lista para bater com df_grouped =======
compostos_significativos = [norm_composto(c) for c in compostos_significativos]

cores = plt.cm.YlGn(np.linspace(0.4, 0.9, len(compostos_significativos)))

plt.figure(figsize=(12, 6))

bar_width = 0.15

# ✅ Meses sem ano (ex.: "Jan-21" -> "Jan")
meses_sem_ano = [str(m).split('-')[0] for m in meses_ordenados]

# ======= SÓ ESTA ALTERAÇÃO: reordenar meses para começar em Mar e terminar em Feb =======
ordem_mar_fev = ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
meses_ordenados = [m for m in ordem_mar_fev if m in meses_sem_ano]

# atualizar eixo x conforme a nova ordem
x = np.arange(len(meses_ordenados))

# ======= padronizar as colunas do df_grouped para lookup =======
df_grouped_cols_norm = pd.MultiIndex.from_tuples(
    [(norm_composto(c), stat) for (c, stat) in df_grouped.columns],
    names=df_grouped.columns.names
)
df_grouped_norm = df_grouped.copy()
df_grouped_norm.columns = df_grouped_cols_norm

for i, composto in enumerate(compostos_significativos):
    medias = df_grouped_norm[(composto, 'mean')].reindex(meses_ordenados).fillna(0)
    desvios = df_grouped_norm[(composto, 'std')].reindex(meses_ordenados).fillna(0)

    plt.bar(
        x + i * bar_width,
        medias,
        yerr=desvios,
        width=bar_width,
        label=str(composto).lower(),   # ✅ legenda em minúsculas
        color=cores[i],
        alpha=0.9,
        capsize=4
    )

plt.ylabel('Avarage Peak Area ', fontsize=12)
plt.xlabel('Months', fontsize=12)

# ✅ Aplicar meses (Mar → Feb) no eixo X
plt.xticks(
    x + bar_width * (len(compostos_significativos) / 2),
    meses_ordenados,
    rotation=45
)

plt.legend()
plt.tight_layout()
plt.show()


# In[104]:


# ================================
# GRÁFICO DOS COMPOSTOS COM p < 0.05
# ================================

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# ======= CORREÇÃO (somente para esse problema): normalizar alpha e vírgula->ponto =======
def norm_composto(x):
    s = str(x).strip().lower()
    s = s.replace(" <trans->", "")
    # normaliza "alpha" quando vier com símbolo grego ou encoding quebrado
    s = s.replace("α", "alpha")
    s = s.replace("î±", "alpha")
    # normaliza separador decimal/composição (ex.: 1,4 -> 1.4)
    s = s.replace(",", ".")
    return s

compostos_significativos = [
    'camphor',
    'safrole',
]

# ======= normalizar lista para bater com df_grouped =======
compostos_significativos = [norm_composto(c) for c in compostos_significativos]

cores = plt.cm.YlGn(np.linspace(0.4, 0.9, len(compostos_significativos)))

plt.figure(figsize=(12, 6))

bar_width = 0.15

# ✅ Meses sem ano (ex.: "Jan-21" -> "Jan")
meses_sem_ano = [str(m).split('-')[0] for m in meses_ordenados]

# ======= SÓ ESTA ALTERAÇÃO: reordenar meses para começar em Mar e terminar em Feb =======
ordem_mar_fev = ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
meses_ordenados = [m for m in ordem_mar_fev if m in meses_sem_ano]

# atualizar eixo x conforme a nova ordem
x = np.arange(len(meses_ordenados))

# ======= padronizar as colunas do df_grouped para lookup =======
df_grouped_cols_norm = pd.MultiIndex.from_tuples(
    [(norm_composto(c), stat) for (c, stat) in df_grouped.columns],
    names=df_grouped.columns.names
)
df_grouped_norm = df_grouped.copy()
df_grouped_norm.columns = df_grouped_cols_norm

for i, composto in enumerate(compostos_significativos):
    # reindex agora usa a ordem Mar->Feb
    medias = df_grouped_norm[(composto, 'mean')].reindex(meses_ordenados).fillna(0)
    desvios = df_grouped_norm[(composto, 'std')].reindex(meses_ordenados).fillna(0)

    plt.bar(
        x + i * bar_width,
        medias,
        yerr=desvios,
        width=bar_width,
        label=str(composto).lower(),   # ✅ legenda em minúsculas
        color=cores[i],
        alpha=0.9,
        capsize=4
    )

plt.ylabel('Avarage Peak Area', fontsize=12)
plt.xlabel('Months', fontsize=12)

# ✅ Aplicar meses no eixo X (Mar → Feb)
plt.xticks(
    x + bar_width * (len(compostos_significativos) / 2),
    meses_ordenados,
    rotation=45
)

# ✅ legenda no canto superior direito, fora das barras
plt.legend(loc='upper left', bbox_to_anchor=(1.02, 1), borderaxespad=0)

plt.tight_layout()
plt.show()


# In[105]:


# ================================
# GRÁFICO DOS COMPOSTOS COM p < 0.05
# ================================

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd

# ======= CORREÇÃO (somente para esse problema): normalizar alpha (α/Î±/î±) =======
def norm_composto(x):
    s = str(x).strip().lower()
    s = s.replace(" <trans->", "")
    # normaliza "alpha" quando vier com símbolo grego ou com encoding quebrado
    s = s.replace("α", "alpha")
    s = s.replace("î±", "alpha")
    s = s.replace("Î±".lower(), "alpha")  # cobre "Î±" -> "î±" após lower()
    return s

compostos_significativos = [
    'spathulenol',
    '4-terpineol',
    'alpha-Cadinol',
    'beta-myrcene',
    'globulol',
    'selina-3.11-dien-6-Î±-ol',
    'alpha-cadinol',
]

# ======= normalizar lista para bater com df_grouped =======
compostos_significativos = [norm_composto(c) for c in compostos_significativos]

# ✅ SÓ ESTA ALTERAÇÃO: cores com mais contraste entre os dois primeiros (mantendo paleta verde)
posicoes = np.linspace(0.40, 0.90, len(compostos_significativos))
if len(posicoes) >= 2:
    posicoes[0] = 0.88  # mais escuro
    posicoes[1] = 0.50  # mais claro (bem diferente do 1º)
cores = plt.cm.YlGn(posicoes)

plt.figure(figsize=(12, 6))

bar_width = 0.15

# ✅ Meses sem ano (ex.: "Jan-21" -> "Jan")
meses_sem_ano = [str(m).split('-')[0] for m in meses_ordenados]

# ======= SÓ ESTA ALTERAÇÃO: reordenar meses para começar em Mar e terminar em Feb =======
ordem_mar_fev = ['Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec','Jan','Feb']
meses_ordenados = [m for m in ordem_mar_fev if m in meses_sem_ano]

# atualizar eixo x conforme a nova ordem
x = np.arange(len(meses_ordenados))

# ======= padronizar as colunas do df_grouped para lookup =======
df_grouped_cols_norm = pd.MultiIndex.from_tuples(
    [(norm_composto(c), stat) for (c, stat) in df_grouped.columns],
    names=df_grouped.columns.names
)
df_grouped_norm = df_grouped.copy()
df_grouped_norm.columns = df_grouped_cols_norm

for i, composto in enumerate(compostos_significativos):
    medias = df_grouped_norm[(composto, 'mean')].reindex(meses_ordenados).fillna(0)
    desvios = df_grouped_norm[(composto, 'std')].reindex(meses_ordenados).fillna(0)

    plt.bar(
        x + i * bar_width,
        medias,
        yerr=desvios,
        width=bar_width,
        label=str(composto).lower(),   # ✅ legenda em minúsculas
        color=cores[i],
        alpha=0.9,
        capsize=4
    )

plt.ylabel('Avarage Peak Area ', fontsize=12)
plt.xlabel('Months', fontsize=12)

# ✅ Aplicar meses (Mar → Feb) no eixo X
plt.xticks(
    x + bar_width * (len(compostos_significativos) / 2),
    meses_ordenados,
    rotation=45
)

plt.legend()
plt.tight_layout()
plt.show()


# In[ ]:




