#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Thu Mar  7 19:29:46 2024

@author: silviamassaro
"""

import numpy as np
import random
import matplotlib.pyplot as plt
import math
from scipy import integrate


# ========================== Definiton of (d0, d1) in km ======================  

d0_km= 10
d1_km= 288

# ========================== Definiton of (T0, T1) in cm ======================

T= [100,10] 

# =========================Beta distributions for eccentricity ================
    
# Beta parameters to calculate (and sample) the equatorial eccentricity:
    
# alpha_equatorial= 2.3911
# beta_equatorial = 1.0184

# beta_params = {
#     "equatorial": (alpha_equatorial, beta_equatorial),
# }

# Beta parameters to calculate (and sample) the mid-latitude eccentricity:
    
alpha_midlatitude = 4.3004
beta_midlatitude = 1.0285

beta_params = {
    "midlatitude": (alpha_midlatitude, beta_midlatitude),
}


#Dictionary to memorize the sampled values of eccentricity based on equatorial 
#and mid-latitude volcanic belts:

eps = {}

num_samples = 1000

for choice in beta_params.keys():
    alpha, beta = beta_params[choice]
    sampled_values = [random.betavariate(alpha, beta) for _ in range(num_samples)]
    eps[choice] = sampled_values
    print(f"Sampled eccentricity values {choice}: {eps[choice]}")


#%%CALCULATIONS:


#Define the range of sqrt(A)=x (for x0 and x1)

r = math.sqrt(3.14)

total_uniform=np.zeros(3000)




# DEFINE THE FUNCTION TO CREATE UNIFORM DISTRIBUTION:

def uniform_probability_function(x, mag_left, mag_right):
    if x >= mag_left and x <= mag_right:
        return 1 / (mag_right - mag_left)
    else:
        return 0
    
    
def calculate_percentile(min_value, max_value, percentile):
    if 0 <= percentile <= 1:
        return min_value + percentile * (max_value - min_value)
    else:
        raise ValueError("Il percentile deve essere compreso tra 0 e 1")
        

    
# DEFINE LISTS USEFUL FOR HISTOGRAMS GRAPHS: 

#In these lists you can find the final results of Magnitude (min and max) that 
#will be shown in the histogram:
    
    
dati_simu = []
mag_values = set()

dati_mag_left=[]
dati_mag_right=[]
mag_medi=[]

dati_vol_left=[]
dati_vol_right=[]

dati_mass_left=[]
dati_mass_right=[]


min_x = float('inf')  
max_x = float('-inf') 


 
#LOOP TO CHECK THE NECESSARY CONDITION TO CARRY ON THE CALCULATION: 

count=0

# Calculation of k and y:
for eps_value in eps.values(): 
    for val in eps_value:
        valore_float = float(val)  
        eps2 = valore_float ** 2
        k = 1 - eps2
        y = pow(k, 0.25)   
        
##WARNING: 
        war = d0_km * 2 / k
        if d1_km > war:
            left0 = 0.5 * r * d0_km * y
            right0 = d0_km * r * y / k
            left1 = 0.5 * r * d1_km * y
            right1 = r * d1_km * y / k
            #print('***** Calculations for x0, x1 *****')
            #print(left0, ' < x0 < ', right0)
            #print(left1, ' < x1 < ', right1)
            count=count+1
  
            
#STEPS TO OBTAIN THE MAGNITUDE:
          
#Calculate Lamba_thick range (in km) 
#Definition of the parameters used for l_left (minimum value):
            a1= (pow(d1_km,2)/4)
            a0 = (pow(d0_km,2)/pow(k,2))
            a = a1-a0
            b = math.log(T[0]/T[1])
            arg1=a/b
#Definition of the parameters used for l_right (maximum value):
            c1 = pow(d1_km,2)/pow(k,2)  
            c0 = pow(d0_km,2)/4
            c= c1-c0
            arg2=c/b
#lambda_left < lambda < lambda_right
            l_left_I= r*y*np.sqrt(arg1)
            l_right_I= r*y*np.sqrt(arg2)
            #print (l_left_I, ' < lambda  < ', l_right_I)
           
#Calculate Volume (in m^3)
#volume_min(left) < volume < volume_max(right)
            vol_left= (3*1e06)*pow(l_left_I,1.53)
            vol_right= (3*1e06)*pow(l_right_I,1.53)
            dati_vol_left.append(vol_left)
            dati_vol_right.append(vol_right)
            print ('***** Calculations for Volumes *****')
            print (vol_left/1e9, ' < Volume (km^3) < ', vol_right/1e9)
        
#Calculate Mass (in kg)
            rho= 1000  #bulk density of the deposit in (kg/m^3)
            mass_left = rho*vol_left
            mass_right = rho*vol_right
            dati_mass_left.append(mass_left)
            dati_mass_right.append(mass_right)
            #print (mass_left, ' < Mass (kg) < ', mass_right)
            
#Calculation of the  Magnitude (from Mason et al., 2004):
    
#Magnitude_min(left) < Magnitude < Magnitude(right):
    
            mag_left= math.log10(mass_left)-7.0
            mag_right= math.log10(mass_right)-7.0
            dati_mag_left.append(mag_left)
            dati_mag_right.append(mag_right)
            print ('***** Calculations for Magnitude *****')
            print ('mag_min:', mag_left, 'mag_max:', mag_right)
            
            min_x = min(min_x, mag_left)
            max_x = max(max_x, mag_right)
                      
#For each sampled eccentricity, a mixing data function is created for each (mag_left, mag_right) data:
            integral_result, _ = integrate.quad(uniform_probability_function, mag_left, mag_right, args=(mag_left, mag_right))
            #print("Area under the curve:", integral_result)

# Creation of x values:          
            x_values = np.linspace(min_x,max_x, 3000)
                                  

#For each x, the probability values are calculated:
            probability_values = [uniform_probability_function(x, mag_left, mag_right) for x in x_values]
            
            total_uniform+=probability_values
            

# =============================================================================
#******************************* PLOTS ***************************************
# =============================================================================


#NORMALIZED UNIFORM DISTRIBUTION considering the normalized probability for 
#each couple of data (mag_min, mag_max):
    
            plt.plot(x_values, probability_values)           
            plt.fill_between(x_values, probability_values, alpha=0.5)


# ONLY FOR THE HISTOGRAM: Put Magnitude_min and Magnitude_max in different lists 
# so as to create histograms: 
        
            dati_mag_medi=(mag_left+mag_right)/2
            mag_medi.append(dati_mag_medi)

            dati_mag_left.append(mag_left)
            mag_values.add(mag_left)

            dati_mag_right.append(mag_right)
            mag_values.add(mag_right)
             

plt.ylabel('Density of Probability')
plt.title('Mixing distribution')
plt.grid(True)
plt.savefig('mixing.png', dpi=300, bbox_inches='tight')
plt.show()
print('Number of iterations:',count) 



# GRAPH OF THE NORMALIZED UNIFORM DISTRIBUTION (SUM):
somma_area_finale=np.trapz(total_uniform) 
total_uniform_norm=total_uniform/somma_area_finale 
area_total_uniform_norm=np.trapz(total_uniform_norm)   
#print("Total area under the normalized curve:", area_total_uniform_norm) 

# CALCULATION OF THE CUMULATIVE PROBABILITY:
cumulative_prob = np.cumsum(total_uniform_norm)

# DRAW THE PERCENTILES ON THE GRAPH: (i.e., 1sigma, 2sigma)
percentiles = [5, 16, 50, 84, 95]  # Puoi aggiungere altri valori desiderati
percentile_values = [np.interp(p / 100, cumulative_prob, x_values) for p in percentiles]


plt.plot(x_values, total_uniform_norm)
plt.fill_between(x_values, total_uniform_norm, alpha=0.5)

# VERTICAL LINES FOR PERCENTILES:

for percentile_value, color, percentile in zip(percentile_values, ['purple', 'green', 'red','orange', 'blue'], percentiles):
     plt.axvline(x=percentile_value, color=color, linestyle='--', label=f'Percentile {percentile}°')
    
for p, value in zip(percentiles, percentile_values):
    print(f"Percentile {p}°: {value}")

#LEGEND:
min_x = np.min(x_values)
max_x = np.max(x_values)
min_y = np.min(total_uniform_norm)
max_y = np.max(total_uniform_norm)

plt.text(max_x - (max_x - min_x) * 1, max_y - (max_y - min_y) * 0.9, f'count: {count}', fontsize=12, ha='left', va='bottom', color='black')
        
plt.ylabel('Normalized Probability')
plt.xlabel('Magnitudo')
plt.title('Normalized Uniform Distribution - FL, Etna')
plt.legend(loc='best')

plt.grid(False)
plt.savefig('Test_FL_uniform.png', dpi=300)

plt.show()


          
# HISTOGRAMI:      
               

counts_right, bins_right = np.histogram(dati_mag_right, bins=8, range=(3, 7))
total_data_right = len(dati_mag_right)
normalized_frequency_right = counts_right / total_data_right


counts_left, bins_left = np.histogram(dati_mag_left, bins=8, range=(3, 7))

total_data_left = len(dati_mag_left)
normalized_frequency_left = counts_left / total_data_left


#CREATION OF THE HISTOGRAM OF THE SIMULATED DATA HAVING THE NORMALIZED FREQUENCY:
    
fig, ax = plt.subplots()

right_bars = ax.bar(bins_right[:-1], normalized_frequency_right, width=(bins_right[1]-bins_right[0]),
        color='orange', alpha=0.5, edgecolor='black', label='Modeled mag_right')

left_bars = ax.bar(bins_left[:-1], normalized_frequency_left, width=(bins_left[1]-bins_left[0]),
        color='blue', alpha=0.5, edgecolor='black', label='Modeled mag_left')


# AXES:
    
ax.set_ylim(0, 1.1)

# x-ticks:
ax.set_xticks(np.concatenate([bins_right, bins_left]))
xtick_labels = np.concatenate([bins_right, bins_left])
ax.set_xticklabels(xtick_labels, rotation=45)

# WIDTH OF x-ticks:
for bar in right_bars:
    bar.set_x(bar.get_x() - (bins_right[1] - bins_right[0]) / 2)
for bar in left_bars:
    bar.set_x(bar.get_x() - (bins_left[1] - bins_left[0]) / 2)


ax.set_xlabel('Magnitude')
ax.set_ylabel('Normalized Frequency')
ax.set_title('Test case: FL, Etna')
ax.legend()

# LEGEND:
legend = ax.legend(fontsize='small')

plt.savefig('Test_FL_histo.png', dpi=300, bbox_inches='tight')
plt.show()

