venerdì 12 dicembre 2025

Frattalita' in misure di spessore (2)

Aggiornamento bibliografico (che mi ero completamente saltato all'Universita')

Sediment Accumulation Rates and the Completeness of Stratigraphic Sections
 Peter M. Sadler
The Journal of Geology, Vol. 89, No. 5 (Sep., 1981), pp. 569-584

Estimation of completeness of stratigraphical sections using
empirical data and theoretical models 
 
Peter M.Sadler & David J. Strauss 
Journal of the Geological Society, London, Vol. 147, 1990,pp. 471-485
 
The nature of stratigraphical record (3 ed) 
D. Ager (1993) 
Wiley and Sons 
capitolo 3 More gaps than records pag.43 
 
Fractals models in Earth Sciences
Korvin Gabor (1992)
Elsevier Science Ltd
cap.2 Fractals in Flatland : a romance in <2 dimensions 
 ----------------------------------------------------------------------------- 

 

Seconda puntata dell'esperimento iniziato qui

 Su suggerimento di uno degli autori ho provato ad utilizzare i dati di questo articolo in cui sono presenti dettagliate stratigrafie del Scaglia Toscana

The Scaglia Toscana Formation of the Monti del Chianti:
new lithostratigraphic and biostratigraphic data
Enrico Pandeli (*, **), Milvio Fazzuoli (*), Fabio Sandrelli (***), Roberto Mazzei (***),
Simonetta Monechi (*), Marisa Nocchi (****), Ivan Martini (***) & Gigliola Valleri (*) Ital. J. Geosci., Vol. 137, No. 1 (2018), pp. 38-61, 12 figs., 1 tab., 1 plate, 2 extrapl. (doi: 10.3301/IJG.2017.16)
© Società Geologica Italiana, Roma 2018

 


 
Sono state considerati considerati gli affioramenti Sugame (48 dati Middle Eocene-Lower Oligocene) , Castello di Brolio (251 dati Upper Cretaceous-Lower Oligocene) , Cintoia West (150 dati Upper Cretaceous-Middle Upper Eocene ) , Montegrossi (208 dati) e Lucolena North (Upper Cretaceous--Lower Oligocene 63 dati). Come si vede non tutte le serie ricoprono esattamente lo stesso periodo temporale e le stess formazioni. Si evidenzia che alcune serie non presentano una serie deposizionale continua







In generale tutti i grafici mostrano una curva spezzata con valori di D>1 sulle scale di maggiori dimensioni e valori nettamente inferiori a 1 per le scale di dettaglio. Alle scale maggiori emerge quindi una tendenza alla frattalita' ed autosomiglianza che si perde alle piccola scala

Il motivo di questo andamento e' perche' i cicli tettonici e climatici influenzano solo le scali maggiori (ma potrebbe essere anche un problema di sotto campionamento degli strati meno potenti)

Questo e' il codice gentilmente fornito da Gemini 

 

import numpy as np
import matplotlib.pyplot as plt
import os

def box_counting_dimension_1d(data, max_box_size=None, plot=True):
    """
    Calcola la dimensione frattale di una serie di dati 1D utilizzando il metodo del box-counting.

    Args:
        data (np.array): La serie di dati 1D (spessore di strato) come array NumPy.
        max_box_size (int, optional): La dimensione massima delle scatole da testare.
        plot (bool): Se True, visualizza il log-log plot.

    Returns:
        float: La dimensione frattale calcolata (pendenza del log-log plot).
    """
    # 1. Preparazione dei dati (la logica rimane la stessa)
    data = np.asarray(data)
   
    # Rimuovi eventuali valori non finiti (NaN, Inf) che potrebbero derivare dal caricamento
    data = data[np.isfinite(data)]

    if len(data) < 2:
        print("Errore: Il set di dati è troppo piccolo o vuoto dopo la pulizia.")
        return np.nan

    min_val = np.min(data)
    max_val = np.max(data)
   
    if max_val == min_val:
        return 1.0

    L = len(data)
   
    if max_box_size is None:
        max_box_size = L // 4
   
    # Raccogli le dimensioni delle scatole (epsilon) da testare
    r_values = 2**np.arange(1, int(np.log2(max_box_size)) + 1)
   
    # Scalatura dell'asse Y per mappare i punti in uno spazio 2D approssimativamente quadrato
    y_scaled = (data - min_val) / (max_val - min_val) * (L - 1)
    points = np.column_stack((np.arange(L), y_scaled))

    log_r = []
    log_N = []
   
    # 3. Box-Counting
    for r in r_values:
        # Calcola le coordinate delle scatole
        box_coords = np.floor(points / r).astype(int)
       
        # Conta le scatole uniche
        N_r = len(np.unique(box_coords, axis=0))
       
        if N_r > 0:
            log_r.append(np.log(1/r))
            log_N.append(np.log(N_r))
           
    log_r = np.array(log_r)
    log_N = np.array(log_N)
   
    if len(log_r) < 2:
        print("Errore: Non abbastanza punti per calcolare la pendenza. Prova con una serie di dati più lunga.")
        return np.nan
       
# Nuova sezione: Selezione dei primi 4 punti
    num_punti_fit = 3

    if len(log_r) < num_punti_fit:
        print(f"Attenzione: Trovati solo {len(log_r)} punti. Eseguo la regressione su tutti i punti disponibili.")
        log_r_fit = log_r
        log_N_fit = log_N
    else:
        # Seleziona i primi 'num_punti_fit' punti (corrispondenti alle scale più piccole/fini)
        #log_r_fit = log_r[-num_punti_fit:]
        #log_N_fit = log_N[-num_punti_fit:]
        log_r_fit = log_r[:num_punti_fit]
        log_N_fit = log_N[:num_punti_fit]
   
    # Esegue la regressione lineare solo sui punti selezionati
    coeffs, residuals, rank, singular_values, rcond = np.polyfit(log_r_fit, log_N_fit, 1, full=True)
    fractal_dimension = coeffs[0]
    # ----------------------------------------------------
   
    # 5. Plot (Opzionale)
    if plot:
        plt.figure(figsize=(10, 6))
        # Plot di TUTTI i punti
        plt.plot(log_r, log_N, 'bo', label='Punti Dati Totali')
       
        # Plot della linea di regressione utilizzando solo l'intervallo di punti selezionato
        p = np.poly1d(coeffs)
       
        # Plot della linea SOLO sul range dei punti usati per il fit (opzionale, per chiarezza)
        plt.plot(log_r_fit, p(log_r_fit), 'r-',
                 label=f'Fit (Primi {len(log_r_fit)} punti): D = {fractal_dimension:.4f}')

        # Evidenzia i punti usati per il fit
        plt.plot(log_r_fit, log_N_fit, 'ro', markerfacecolor='none', markersize=10,
                 label=f'Punti usati per la regressione')

        plt.title('Sugame')
        plt.xlabel(r'$\log(1/\epsilon)$')
        plt.ylabel(r'$\log(N(\epsilon))$')
        plt.legend()
        plt.grid(True, which="both", linestyle="--")
        plt.show()

    return fractal_dimension

# --- Esempio di Utilizzo AGGIORNATO ---

NOME_FILE_CSV = "sugame.csv"

print("--- Calcolo della Dimensione Frattale ---")

if not os.path.exists(NOME_FILE_CSV):
    print(f"ERRORE: File '{NOME_FILE_CSV}' non trovato.")
    print("Assicurati che il file esista nella stessa directory dello script.")
else:
    try:
        # Carica i dati dal file CSV
        # usecols=0 specifica di usare solo la prima colonna
        # dtype=int assicura che i dati vengano letti come interi
        spessore_strato_dati = np.genfromtxt(
            NOME_FILE_CSV,
            delimiter=',',
            dtype=int,
            skip_header=0,
            filling_values=np.nan # Sostituisce i valori mancanti con NaN (che puliremo dopo)
        )
       
        if spessore_strato_dati.ndim > 1:
            # Se per qualche motivo numpy legge più colonne, forziamo solo la prima
            spessore_strato_dati = spessore_strato_dati[:, 0]
       
        print(f"Dati caricati con successo da '{NOME_FILE_CSV}'.")
        print(f"Numero di punti dati: {len(spessore_strato_dati)}")

        # Calcola e stampa il risultato
        D = box_counting_dimension_1d(spessore_strato_dati, plot=True)

        print(f"\nRisultato:")
        print(f"Dimensione Frattale (D) calcolata: {D:.4f}")

    except Exception as e:
        print(f"Si è verificato un errore durante il caricamento o l'analisi dei dati: {e}")

 Ben sapendo che non e' propriamente corretto ho provato a vedere cosa succedeva sommando tutti i dati di tutte le serie

 



 

 

Hacking Lisciani Step Imparotutto

 

Per smontare il gioco si deve togliere la plastica antiscivolo al di sotto del gioco. Le viti sono nascoste li' ed usando le dita non si riescono ad individuare i fori 

Una volta rimossa la parte superiore devono rimuovere i cavi del pulsante superiore, il cavo dello speaker ed il lettore delle carte. I cavi hanno una connessione fast e si smontando semplicemente

 

si accede quindi alla scheda madre. Al centro si osserva un microcontrollore FCM32F030C8T6, si sono due shift register 74HC959 ed i controller per i motori passo passo ULN2003C 

Nella scheda madre e' inserita una SD Card rimuovibile (fermata solo da nastro adesivo trasparente) da 512 Mb formattata Fat32 ed occupata per circa 130 Mb. Immagino che questo sistema permetta di configurare facilmente il dispositivo per diversi mercati con differenti linguaggi

Il contenuto e' costuito in folder (nel mio caso numerati da 005 a 126 piu' una BACK)

In ogni folder ci sono i file wav del gioco. Per esempio nel folder 005 ci sono file wav numerati da 31.wav a 35.wav per la carta Leone. I file wav sono codificato mono 16 bit signed integer PCM, 352 kps, sample 22.05 KHz con campo commento iTunPGAP 0

Inoltre sono presenti uno o piu' file .txt (step.txt stepn.txt e ans.txt, ) con il seguente contenuto


!0#0,0,0,0#635,1782;630,1785;624,1788;619,1791;614,1795;609,1798;604,1801;598,1805;593,1808;588,1812;582,1815;577,1819;571,1823;566,1826;560,1830;555,1834;549,1838;543,1842;538,1846;532,1850;526,1855;526,1855;528,1859;529,1863;531,1868;533,1872;534,1877;536,1881;537,1885;539,1890;540,1895;542,1899;543,1904;544,1908;546,1913;547,1917;548,1922;549,1927;551,1931;552,1936;553,1941;554,1946;555,1950;555,1950;561,1946;567,1942;574,1938;580,1934;586,1930;592,1926;598,1923;604,1919;610,1915;616,1912;622,1908;628,1905;633,1901;639,1898;645,1895;650,1892;656,1889;662,1886;667,1883;673,1880;673,1880;671,1875;670,1870;668,1865;667,1860;665,1856;663,1851;662,1846;660,1842;658,1837;657,1832;655,1828;653,1823;651,1818;649,1814;647,1809;645,1804;643,1800;641,1795;639,1791;637,1786;635,1782;
!1#0,0,0,0#663,1850;668,1848;673,1845;678,1843;683,1841;688,1839;692,1837;697,1835;702,1832;707,1830;707,1830;712,1827;718,1825;723,1822;728,1819;733,1816;737,1813;742,1811;747,1808;752,1805;756,1802;761,1799;765,1796;769,1793;773,1789;778,1786;782,1783;786,1780;790,1776;793,1773;797,1770;801,1766;804,1763;808,1759;811,1755;814,1752;817,1748;820,1744;823,1740;826,1736;829,1732;832,1728;834,1724;837,1720;839,1716;841,1712;843,1708;845,1703;847,1699;849,1695;851,1690;852,1686;853,1681;855,1676;856,1672;857,1667;858,1662;859,1657;859,1652;860,1647;860,1642;860,1637;860,1632;860,1626;860,1621;860,1616;859,1610;859,1605;858,1599;857,1594;856,1588;855,1582;853,1577;852,1571;850,1565;848,1559;846,1553;844,1547;842,1541;839,1535;836,1529;833,1523;831,1517;827,1510;824,1504;821,1498;817,1491;813,1485;809,1479;805,1472;801,1466;796,1460;792,1453;787,1447;782,1441;777,1434;772,1428;767,1422;761,1416;756,1409;756,1409;750,1403;745,1397;739,1391;733,1385;727,1380;721,1374;715,1368;709,1363;703,1358;697,1353;690,1348;684,1343;678,1338;672,1334;666,1329;659,1325;653,1321;647,1317;641,1313;634,1309;628,1305;622,1302;616,1299;610,1296;604,1293;598,1290;592,1287;586,1285;580,1283;574,1280;568,1278;562,1276;556,1275;550,1273;545,1272;539,1271;533,1270;528,1269;522,1268;517,1267;511,1267;506,1266;501,1266;496,1266;490,1266;485,1266;480,1267;475,1267;470,1268;465,1268;461,1269;456,1270;451,1272;447,1273;442,1274;437,1276;433,1277;428,1279;424,1281;420,1283;416,1285;411,1287;407,1290;403,1292;399,1295;395,1297;391,1300;387,1303;383,1306;380,1309;376,1312;372,1316;369,1319;365,1323;361,1326;358,1330;354,1334;351,1337;348,1341;344,1345;341,1350;338,1354;335,1358;332,1363;328,1367;325,1372;322,1376;319,1381;316,1386;316,1386;314,1390;311,1395;309,1400;306,1404;304,1409;301,1413;299,1418;297,1423;295,1427;292,1432;
!1#0,0,0,0#325,1519;328,1514;331,1509;334,1504;336,1499;337,1493;339,1488;339,1483;339,1477;339,1472;337,1467;336,1462;334,1457;331,1453;328,1449;325,1445;321,1442;317,1439;312,1437;307,1435;302,1433;297,1433;292,1432;287,1432;281,1433;276,1434;270,1436;265,1438;260,1441;254,1444;250,1448;245,1452;241,1456;236,1461;233,1466;229,1471;226,1477;223,1482;221,1488;219,1494;218,1499;217,1505;217,1510;217,1516;217,1521;218,1526;220,1530;222,1534;224,1538;227,1542;230,1545;234,1547;238,1550;243,1551;247,1552;253,1553;258,1553;263,1553;269,1553;275,1551;280,1550;286,1548;292,1545;297,1542;303,1539;308,1535;313,1532;317,1527;322,1523;325,1519;
 

 sono presenti anche dei file di lunghezza nulla. Il nome del file e' descrittivo del contenuto della cartella. turtle.txt di lunghezza zero indica che i file .wav e step.txt sono relativi alla carta della tartaruga 

in pratica queste le istruzioni per muovere il pennino. Si tratta di coppie di valori interi separati da virgola e le varie coppie sono divise da punti e virgola

Se si plottano le coppie di valori della carta Leone si ha questo risultato

questo invece il tracciato per la barca

Questo e' il programma per visualizzare il file step.txt come un disegno


import matplotlib.pyplot as plt
import os

def parse_scribbles(data_string):
    """
    Parsa la stringa di dati nel formato '!<tipo>#0,0,0,0#x1,y1;x2,y2;...'
    e restituisce una lista di dizionari, ognuno contenente il tipo e le coordinate.
    """
    scribbles = []
    # Rimuovi spazi e dividi i blocchi principali per '!'
    blocks = data_string.strip().split('!')
   
    for block in blocks:
        if not block.strip():
            continue
           
        # Tenta di dividere il blocco in [tipo], [info non usate], [coordinate]
        parts = block.split('#')
        if len(parts) < 3:
            continue
       
        try:
            # Il tipo è il primo carattere del blocco (e.g., '0' o '1')
            scribble_type = int(parts[0].strip())
            coords_string = parts[2]
        except ValueError:
            # Salta se il tipo non è un numero valido
            continue

        # Dividi la stringa delle coordinate per ';' per ottenere i singoli punti
        points_str = coords_string.split(';')
       
        x_coords = []
        y_coords = []
        for point_str in points_str:
            if not point_str.strip():
                continue
            try:
                # Dividi x e y per ','
                x, y = map(int, point_str.split(','))
                x_coords.append(x)
                y_coords.append(y)
            except ValueError:
                # Salta se un punto non è nel formato 'x,y' valido
                continue

        if x_coords and y_coords:
            scribbles.append({'type': scribble_type, 'x': x_coords, 'y': y_coords})
           
    return scribbles

def plot_scribbles(scribbles):
    """
    Genera il plot dei dati delle linee.
    """
    plt.figure(figsize=(10, 8))

    # Definisci colori e etichette per i diversi tipi di tratto
    colors = {0: 'blue', 1: 'red', 2: 'green', 3: 'purple'} # Puoi espandere i tipi
    labels = {0: 'Tipo 0 (Penna)', 1: 'Tipo 1 (Marcatore)', 2: 'Tipo 2', 3: 'Tipo 3'}

    plotted_types = set()
    for scribble in scribbles:
        scribble_type = scribble['type']
       
        # Scegli colore e etichetta, assicurandoti che l'etichetta appaia solo una volta
        color = colors.get(scribble_type, 'gray')
        label_to_use = labels.get(scribble_type, f'Tipo {scribble_type}') if scribble_type not in plotted_types else None
       
        # Plotta la linea
        plt.plot(scribble['x'], scribble['y'],
                 color=color,
                 marker=None, # Non mostrare i singoli punti per non appesantire il plot
                 linestyle='-',
                 linewidth=2,
                 label=label_to_use)
       
        plotted_types.add(scribble_type)

    # Inverti l'asse Y perché le coordinate delle immagini spesso hanno Y=0 in alto
    plt.gca().invert_yaxis()
   
    # Imposta un rapporto di aspetto uguale per evitare distorsioni (disegno non stirato)
    plt.gca().set_aspect('equal', adjustable='box')

    # Aggiungi titoli e legenda
    plt.title('Visualizzazione Disegno da File TXT')
    plt.xlabel('Coordinata X')
    plt.ylabel('Coordinata Y')
   
    if plotted_types:
        plt.legend(loc='best')
       
    plt.grid(True, linestyle='--', alpha=0.6)
    plt.show()

# --- Esecuzione Principale ---
file_name = 'step.txt'

# 2. Leggi il file di input
try:
    with open(file_name, 'r') as f:
        file_content = f.read()
except FileNotFoundError:
    print(f"Errore: File '{file_name}' non trovato.")
    exit()

# 3. Parsa e Plotta
if file_content.strip():
    parsed_scribbles = parse_scribbles(file_content)
    if parsed_scribbles:
        plot_scribbles(parsed_scribbles)
    else:
        print("Nessun dato di disegno valido trovato nel file.")
else:
    print("Il file è vuoto.")


 


 


questo e' il pulsante superiore


 questa e' la scheda del lettore delle carte. Si tratta di un lettore ottico con 7 coppie di emettitore/ricevitore .. in linea di principio sono 7 bit quindi in linea di principio sarebbero possibili 128 carte distinte.. il sistema pero' e' simmetrico e non so come vengono gestite le carte messe al contrario


 se i mettono le carte controluce si osserva alcune zone opache per la lettura della carte ..le carte non sono simmetriche quindi dovrebbe essere confermato il numero di 128 distinte carte possibili

Facendo un po' di prove ho trovato la regola. Se la carta fa passare luce vale come Bit=1, altrimenti settato Bit=0

La posizione e' la seguente. in pratica i bit si leggono in senso orario partendo da quello piu' significativo in alto a destra

Bit0   Bit6 

Bit1   Bit5

Bit2   Bit4

        Bit3 

Per esempio la carta la lettera P ha la seguente disposizione

1 0
1 1
0 0
 1

ricostruendo la sequenza si ottiene 101011 che equivale al numero decimale 43. Se sulla scheda SD si va al folder 43 troveremo gli audio appunto della lettera P

Altro esempio con la carta Arancia

0 0
1 0
1 1
 0
la sequenza diventa 10110 ovvero decimale 22  

 

 

i motori stepper sono dei TH24BYJ

l'integrato per la ricarica della batteria e' un ETA9742

connessione per il modulo di ricarica USB-C. La porta USB funziona quindi solo come alimentazione. Sulla scheda madre si sono pero' dei reofori vicino alla scritta HHQUICK_V2.3 che portano direttamente al microntrollore e potrebbe essere la porta di programmazione

ed a questo punto perche' non farlo parlare toscano


 

 

 

 

 

 

 

 

 

martedì 9 dicembre 2025

Esponente di Hurst su torbidita' di acquiferi apuani

In questo post vengono analizzati i valori di torbidita' della sorgente del Frigido (periodo 13/02/2020 01/12/2025 dati orari ) e Carbonera (26/07/2006 21/06/2013 dati ogni 3 minuti ) legate all'acquiferi carsico delle Alpi Apuane

 

Torbidita' del tempo Frigido

 

Il parametro Esponente di Hurst e' stato introdotto Hurst, H. E. (1951). Long-term storage capacity of reservoirs. Transactions of the American Society of Civil Engineers, 116(1), 770-808. 

E' una misura dell'inerzia del sistema idrogeologico (ovvero capacita' di stoccaggio) e della complessita' della rete carsica. Per i valore di 0.82 e 0.85 trovati si ha che il sistema non e' casuale (H=0.5), non e' deterministicamente semplice ed il comportamento e' correlato su differenti scale di tempo ed e' un sistema che ha "memoria" del proprio passato

Non e' possibile prevedere in maniera completamente deterministica il valore esatto del parametro indagato  

Frigido

Con modelli deterministici si avra' un discreto successo su scale di tempo brevi ma non sulla previsione a lunga scadenza. Il passaggio da regime deterministico a frattale e' indicato come tempo di crossover e si individua dai punti di flesso sull'andamento dei punti. Per Carbonera (grafico sottostante) il punto di cross over e'  tra 1000 e 10000 unita' che tradotto nel passo di campionamento si arriva ad intervallo da le 5 e le 50 ore

Carbonera

Valori di H vicini ad 1 indicano persistenza nei valori (sia che siano massimi che minimi) e questo puo' incidere anche sul valore massimo e non solo sulle code della distribuzione

La memoria non si esaurisce mai ma ha una legge di decadimento come una potenze (in questo caso 2*0.84 -2 = -0.32 

 

con questa legge e l'esponente calcolate la correlazione ha un peso superiore al  10% fino a 1000 intervalli temporali (rho = 0.10^(1/-0.32)

Il fatto che il calcolo di H risulti sostanzialmente identico su serie con diverso passo di campionamento e' un indice della frattalita' del fenomeno osservato (e' indipendente dalla scala del tempo di osservazione)
 
il valore di Hurst prossimo ad 1 indica che e' probabile che la torbidita' aumenti nel prossimo lag (passo di campionamento) e' fortemente dipendente da cio' che accade nel lag precedente . Cio' sarebbe in contrasto con il concetto di massimo relativo della curva di scarica ma la statistica deve essere considerata valida al mantenersi delle condizioni al contorno e delle relative forzanti. Con un valore di 0.82 la coda di esaurimento sara' lunga

 

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

# --- 1. FUNZIONE DEFINIZIONE per l'ANALISI R/S MANUALE ---

def compute_rs_data(series):
    """
    Calcola la statistica Rango Riscalato (R/S) per una serie temporale.
    Restituisce gli intervalli temporali (n) e i valori medi di R/S.
    """
    N = len(series)
    # Definisce gli intervalli temporali (n) in progressione geometrica fino a N/4
    n_values = np.unique(np.logspace(1, np.log10(N // 4), num=50, dtype=int))
    n_values = n_values[n_values >= 1]
   
    rs_values = []
   
    for n in n_values:
        if n == 0: continue
       
        num_blocks = N // n
        rs_per_block = []
       
        for i in range(num_blocks):
            block = series[i * n : (i + 1) * n]
           
            mean = np.mean(block)
            std_dev = np.std(block)
           
            if std_dev == 0:
                continue

            X = np.cumsum(block - mean)
            R = np.max(X) - np.min(X)
           
            rs_per_block.append(R / std_dev)
       
        if rs_per_block:
            rs_values.append(np.mean(rs_per_block))
        else:
            break

    return n_values[:len(rs_values)], np.array(rs_values)


# --- 2. CARICAMENTO E PREPARAZIONE DEI DATI ADATTATI ---

FILE_NAME = "frigido.csv"
COLUMN_NAME = "Torbidita NTU"
FILTER_N_THRESHOLD = 100

try:
    # ATTENZIONE: Caricamento con separatore PUNTO E VIRGOLA (;) e decimale VIRGOLA (,)
    df = pd.read_csv(FILE_NAME, sep=';', decimal=',')
   
    # Seleziona la colonna 'Torbidita NTU'
    discharge_series = df[COLUMN_NAME]
   
    # Conversione in numerico e gestione dei NaN (valori mancanti o non validi)
    discharge_series = pd.to_numeric(discharge_series, errors='coerce').dropna()
   
    # Converti in array NumPy
    discharge_data = discharge_series.values
   
except FileNotFoundError:
    print(f"Errore: Il file '{FILE_NAME}' non è stato trovato. Assicurati che sia nella directory corretta.")
    exit()
except KeyError:
    print(f"Errore: La colonna '{COLUMN_NAME}' non è stata trovata nel file. Controlla il nome esatto.")
    print(f"Colonne disponibili: {df.columns.tolist()}")
    exit()

if len(discharge_data) < 100:
     print("Errore: Non ci sono abbastanza punti dati validi per eseguire l'analisi R/S.")
     exit()

# --- 3. CALCOLO R/S ---

rs_n, rs_rs = compute_rs_data(discharge_data)

# Calcolo di H (Esponente di Hurst) per l'INTERVALLO COMPLETO
log_n_full = np.log10(rs_n)
log_rs_full = np.log10(rs_rs)
coefficients_full = np.polyfit(log_n_full, log_rs_full, 1)
H_full = coefficients_full[0]
c_full = 10**coefficients_full[1]


# --- 4. PLOT: ANALISI R/S INTERVALLO COMPLETO ---

plt.figure(figsize=(8, 5))
plt.plot(rs_n, c_full * rs_n**H_full, color="deepskyblue", label=f'Pendenza Frattale (H={H_full:.2f})')
plt.scatter(rs_n, rs_rs, color="navy", alpha=0.5, label='Dati R/S empirici')
plt.xscale('log')
plt.yscale('log')
plt.xlabel('Intervallo Temporale (n)')
plt.ylabel('Rango Riscalato R/S')
plt.title(f'Scaling Frattale della Torbidità (Full Range)')
plt.legend()
plt.savefig('Frigido_Full_R_S_Plot.png')


# --- 5. PLOT: INTERVALLO FILTRATO (n > 100) ---

filter_mask = rs_n > FILTER_N_THRESHOLD
X_filtered = rs_n[filter_mask]
Y_filtered = rs_rs[filter_mask]

# Calcolo di H per il solo intervallo filtrato
if len(X_filtered) > 1:
    log_n_filtered = np.log10(X_filtered)
    log_rs_filtered = np.log10(Y_filtered)
   
    coefficients_filtered = np.polyfit(log_n_filtered, log_rs_filtered, 1)
    H_filtered = coefficients_filtered[0]
    c_filtered = 10**coefficients_filtered[1]
   
    plt.figure(figsize=(8, 5))
    plt.scatter(X_filtered, Y_filtered, color="darkgreen", alpha=0.7, label=f'Dati R/S empirici (n > {FILTER_N_THRESHOLD})')
    plt.plot(X_filtered, c_filtered * X_filtered**H_filtered, color="red", linestyle='--',
             label=f'Pendenza Frattale Filtrata (H={H_filtered:.2f})')

    plt.xscale('log')
    plt.yscale('log')
    plt.xlabel('Intervallo Temporale (n)')
    plt.ylabel('Rango Riscalato R/S')
    plt.title(f'Scaling Frattale della Torbidità (Intervallo Temporale > {FILTER_N_THRESHOLD})')
    plt.legend()
    plt.savefig('Frigido_Filtered_R_S_Plot_gt_100.png')
   
    print("\n--- Risultati del Calcolo ---")
    print(f"Hurst Esponent (Torbidità - Intervallo Completo): {H_full:.4f}")
    print(f"Hurst Esponent (Torbidità - Filtrato n>{FILTER_N_THRESHOLD}): {H_filtered:.4f}")
else:
    print(f"Nota: Non ci sono abbastanza punti dati rimasti dopo il filtraggio (n > {FILTER_N_THRESHOLD}) per generare il grafico filtrato.")

 

 

Frattalita' in misure di spessore (2)

Aggiornamento bibliografico (che mi ero completamente saltato all'Universita') Sediment Accumulation Rates and the Completeness of S...