Estrarre data da un grafico .fig

di il
12 risposte

Estrarre data da un grafico .fig

Buongiorno ragazzi! il mio problema è che devo estrarre i dati da un grafico classico nel piano cartesiano (x,y); ho provato a implementare un codice ma ho qualche problema.

h= openfig('prova.fig');
t= findobj(h,'type', 'line');

x= get(t,'XData');
y= get(t,'YData');

plot(x,y)


Voi avete qualche idea?

Grazie

12 Risposte

  • Re: Estrarre data da un grafico .fig

    Il codice che hai scritto è "quasi" giusto.
    L'unico errore consiste nel fatto che i dati del grafico sono memorizzati nella "property" "Children" dell'"axes" del grafico:

    Se disponi di una versione di Matlab >= R2014b puoi usare la "Dot Notation", per versioni precedenti, puoi usare la funzione "get" per estrarre i dati:
    
    
    % Create a sample Figure
    example_fig=figure
    t1=0:.1:2*pi;
    y1=cos(t1);
    t2=0:.1:4*pi;
    y2=sin(t2);
    plot(t1,y1,'r',t2,y2,'b')
    % Save the Figure
    savefig(example_fig,'prova.fig')
    % Close the figure
    close(example_fig)
    % Open the Figure
    openfig('prova.fig')
    
    % Dot Notation
    % Get the axes handle
    ax=gca;
    % Get the axes Children handle
    lines=ax.Children
    % Loop over the Children to extract the data
    for i=1:length(lines)
       data_line(i).X=lines(i).XData
       data_line(i).Y=lines(i).YData
       data_line(i).Z=lines(i).ZData
    end
    
    % Test the code
    
    % Open a new figure
    figure
    % Create an axes
    axes
    hold on
    % Loop over the extracted data to plot them
    for i=1:length(data_line)
       plot(data_line(i).X,data_line(i).Y)
    end
    
    % Same approach, using "get" instead of the Dot Notation
    close gcf
    
    openfig('prova.fig')
    
    % Using "get"
    ax=gca;
    lines=get(ax,'Children')
    for i=1:length(lines)
       data_line(i).X=get(lines(i),'XData')
       data_line(i).Y=get(lines(i),'YData')
       data_line(i).Z=get(lines(i),'ZData')
    end
    
    figure
    axes
    hold on
    for i=1:length(data_line)
       plot(data_line(i).X,data_line(i).Y)
    end
    
  • Re: Estrarre data da un grafico .fig

    Ciao., grazie mille per la risposta! ho matlab 2017 versione accademica, quindi ho provato a usare la dot notation, riesco ad estrarre i dati dal .fig ma poi quando li plotto non vedo i punti.
    ti allego i due grafici:

    1 come dovrebbe venire attachment=0]maxd.jpg[/attachment]

    2 come viene
    maxd.jpg
    maxd.jpg


    Allegati:
    22990_841a748642ba376a7d3b78938e0cab7c.jpg
    22990_841a748642ba376a7d3b78938e0cab7c.jpg
  • Re: Estrarre data da un grafico .fig

    Ho risolto! bastava mettere 'o'!
    grazie!!!
  • Re: Estrarre data da un grafico .fig

    Se in uno stesso script apro più grafici e quindi più .fig, come modifico il codice per poter estrarre ogni data da ogni grafico senza che si sovvrascrivano e poi riplottarli tutti insieme?
    openfig('maxd_ibrido.fig');
    openfig('maxd_irpinia.fig');
    
    % Using "get"
    ax_ibrido=gca;
    lines_ibrido=get(ax_ibrido,'Children')
    for i=1:length(lines_ibrido)
       data_line(i).X_ibrido=get(lines_ibrido(i),'XData')
       data_line(i).Y_ibrido=get(lines_ibrido(i),'YData')
     
    end
    
    ax_irpinia=gca;
    lines_irpinia=get(ax_irpinia,'Children')
    for j=1:length(lines_irpinia)
       data_line(j).X_irpinia=get(lines_irpinia(j),'XData')
       data_line(j).Y_irpinia=get(lines_irpinia(j),'YData')
     
    end
    
    figure 
    axes
    grid on
    hold on
    for i=1:length(data_line_ibrido)
        for j=1:length(lines_irpinia)
       plot(data_line(i).X_ibrido,data_line(i).Y_ibrido,'o')
       plot(data_line(j).X_irpinia,data_line(j).Y_irpinia,'p')
        end
    end
    title 'maxD-R'
  • Re: Estrarre data da un grafico .fig

    Con riferimento ai due grafici che hai inserito, come hai plottato i dati estratti quando hai ottenuto un grafico "vuoto"?
    Hai scritto che aggiungendo "o" hai risolto, ma la funzione "plot", dovrebbe creare una linea, se non viene specificato nessuno "stile".

    Venendo alla tua domanda.

    Nell'esempio che ti ho proposto nella risposta precedente, ho usato una "struct" ed ho memorizzato i dati estratti delle figure nei suoi campi, questo per avere la possibilità di avere in un'unica variabile i dati di tutte le curve anche se di dimensioni diverse da una curva all'altra, cosa che non avrei potuto fare se avessi usato una semplice matrice (nell'esempio puoi verificare che la seconda curva contiene il doppio dei punti della prima)

    Un approccio generale che consenta di estrarre dati da più "Figures" basato su un'estensione del metodo precedentemente proposto, potrebbe essere:
    [*] definire (in un cellarray) i nomi dei file ".fig" senza l'estensione
    [*] creare un ciclo "for" che apra le "Figure" e ne estragga i dati
    [*] salvare i dati estratti in una "struct" (come nell'esempio precedente), ma creando un campo per ogni "Figure"

    In pratica, potresti creare, sfruttando la funzionalità "dynamic filed names" delle "struct", un campo per ogni "Figure" assegnandogli il nome della "Figure", quindi, un "sottocampo" per ogni dato (uno per le "X", uno per le "Y", ...).

    Nel caso in cui una "Figure" contenga più di una curva, puoi salvare i dati in un "cellarray" in modo da gestire l'eventualità che le curve abbiano una quantità di dati diversa.

    Affinchè questo approccio funzioni, è essenziale che i nomi delle "Figure" non contengano quali spazi bianchi (o altri caratteri particolari come, ad esempio, "-"; in questo caso puoi sostituirli / eliminarli con la funzione "strrep").

    Nell'esempio che segue, vengono create due grafici, ciascuno con due curve, tutte le curve hanno un numero diverso di dati.

    I nomi delle due "Figure" sono: "prova_1.fig" e "prova_2.fig"

    In fase di lettura dei dati, viene creata la seguente "struct":
    
    data_line = 
    
        prova_1: [1x1 struct]
        prova_2: [1x1 struct]
    
    i cui due campi hanno il nome delle "Figure"

    Ogni campo, a sua volta, ha tre campi
    
    data_line.prova_1
        X: {2x1 cell}
        Y: {2x1 cell}
        Z: {2x1 cell}
    
    costituiti da "cellarray" nei quali sono memorizzati i dati delle (due) curve contenute nel grafico.

    Nota che, in fase di lettura, le curve presenti nel grafico vengono lette (e quindi memorizzate nei "cellarray") in ordine inverso rispetto a quello nel quale sono state create nel grafico.
    Nell'esempio di cui sopra
    
    data_line.prova_1.X{1}
    
    contiene i dati della seconda curva plottata nella prima "Figure".
    
    % Create two sample Figures
    f(1)=figure
    t1=0:.1:2*pi;
    t2=0:.1:4*pi;
    y1=cos(t1);
    y2=sin(t2);
    plot(t1,y1,'r',t2,y2,'b')
    % Save the Figure
    savefig(f(1),'prova_1.fig')
    f(2)=figure
    t3=0:.1:6*pi;
    t4=0:.1:8*pi;
    y3=cos(t3);
    y4=sin(t4);
    plot(t3,y3,'r',t4,y4,'b')
    % Save the Figure
    savefig(f(2),'prova_2.fig')
    % Close the example figures
    close(f(:))
    % Define the names of the files of the Figure (without specifying the file
    % extension
    fig_names{1}='prova_1'
    fig_names{2}='prova_2'
    % Loop over the Figures tobe read
    n_fig=length(fig_names)
    for i=1:n_fig
       % Open the i-th Figure
       openfig([fig_names{i} '.fig'])
       % Get the axes handle
       ax=gca;
       % Get the axes Children handle
       lines=ax.Children
       % Loop over the Children to extract the data
       for j=1:length(lines)
          % Create the field after the name of the "Figure"
          % Store the data in "cellarray"
          data_line.(fig_names{i}).X{j,:}=lines(j).XData
          data_line.(fig_names{i}).Y{j,:}=lines(j).YData
          data_line.(fig_names{i}).Z{j,:}=lines(j).ZData
       end
    end
    
  • Re: Estrarre data da un grafico .fig

    Probabilmente ho qualche problema con i messaggi privati, perchè rimangono perennemente "in uscita". Comunque sono arrivato al seguente punto:
    clear all
    close all
    clc
    
    % fig_names{1}='maxd_aquila'
    % fig_names{2}='maxd_elcentro'
    
    % Define the names of the files of the Figure
    % (without specifying the file
    % extension
    fig_names{1}='maxd_aquila'
    fig_names{2}='maxd_elcentro'
    % fig_names{3}='prova_3'
    % fig_names{4}='prova_4'
    
    % Loop over the Figures tobe read
    n_fig=length(fig_names)
    for i=1:n_fig
       % Open the i-th Figure
       openfig([fig_names{i} '.fig'])
       % Get the axes handle
       ax=gca;
       % Get the axes Children handle
       lines=ax.Children
       % Loop over the Children to extract the data
       for j=1:length(lines)
          % Create the field after the name of the "Figure"
          % Store the data in "cellarray"
          data_line.(fig_names{i}).X=lines(j).XData
          data_line.(fig_names{i}).Y=lines(j).YData
          data_line.(fig_names{i}).Z=lines(j).ZData
       end
    end
    
    figure
    axes
    hold on
    grid on
    p_handles=[];
    f_names=fieldnames(data_line)
    for i=1:length(f_names)
       p_handles(i)=plot(data_line.(f_names{i}).X,data_line.(f_names{i}).Y,'o')
    end
    legend(p_handles,f_names)
    Ho fatto girare il tuo codice con due grafici e funziona tutto tranne la parte finale dove plotta tutto insieme.
    Plotta solo due punti, una coppia (x,y) appartenente al primo grafico e l'altra appartente al secondo grafico. Entrambi per la prima riga dell'array. Probabilmente però il problema è già nel ciclo delle dataline dove sembra che trovi solo una coppia (x,y) quindi ovviamente poi nel plot ritrovo solo due punti.
    Ti allego i grafici per capirci




    Questo è l'inviluppo, come puoi vedere ha preso solo due valori:


    Grazie e scusa per il disturbo
  • Re: Estrarre data da un grafico .fig

    E' possibile che i grafici nelle "Figure" contengano più di una serie di dati?
    Se è così, questa volta è colpa mia, nel tentativo di semplificare il codice, non ho tenuto conto di questa possibilità.

    Ho aggiornato il codice in modo che plotti tutte le eventuali serie estratte dalle "Figure" di partenza.

    Se sei sicuro che tutte le serie di dati plottati in tutte le "Figure" abbiano sempre lo stesso numero di dati il codice si potrebbe semplificare ulteriormente anche se perderebbe di chiarezza.

    Estrazione dati dalle "Figure"
    
    % Define the names of the files of the Figure
    % (without specifying the file extension
    fig_names{1}='prova_1'
    fig_names{2}='prova_2'
    % Loop over the Figures tobe read
    n_fig=length(fig_names)
    for i=1:n_fig
       % Open the i-th Figure
       openfig([fig_names{i} '.fig'])
       % Get the axes handle
       ax=gca;
       % Get the axes Children handle
       lines=ax.Children
       % Loop over the Children to extract the data
       for j=1:length(lines)
          % Create the field after the name of the "Figure"
          % Store the data in "cellarray"
          data_line.(fig_names{i}).X(j,:)=lines(j).XData
          data_line.(fig_names{i}).Y(j,:)=lines(j).YData
          data_line.(fig_names{i}).Z(j,:)=lines(j).ZData
       end
    end
    
    Plottaggio dei dati estratti dalle "Figure"
    
    % Open a new Figure
    figure
    % Cheate an axes
    axes
    % Set "hold" to "on" to allow plotting multiple data set
    hold on
    % Initialize the array of the plots' handel
    p_handles=[];
    % Get the names of the struct fields
    f_names=fieldnames(data_line)
    % initialize the plot counter
    plot_cnt=0;
    % Loop over the Figures
    for i=1:length(f_names)
       % Loop over the data set of each Figure
       for j=1:size(data_line.(f_names{i}).X,1)
          % Increment the plot counter
          plot_cnt=plot_cnt+1
          % Create the string for the legend
          leg_str{plot_cnt}=[f_names{i} ' Data set # ' num2str(j)];
          % Plot the j-th data set of the i-th Figure
          p_handles(plot_cnt)=plot(data_line.(f_names{i}).X(j,:),data_line.(f_names{i}).Y(j,:),'linewidth',2)
       end
    end
    % Replace the "_" from the legend string with " " (a blank)
    leg_str=strrep(leg_str,'_',' ')
    % Add the legend to the chart
    legend(p_handles,leg_str)
    
  • Re: Estrarre data da un grafico .fig

    Perfetto!! ora funziona tutto , grazie mille!!!

    Un ultima cosa, è possibile fare in modo che nel plot finale i punti ottenuti da uno stesso grafico siano colorati di un colore e di un simbolo (ad esempio dei pallini) e di un altro grafico abbiano un altro colore e un altro simbolo?

    Grazie davvero
  • Re: Estrarre data da un grafico .fig

    Nella chiamata alla funzione "plot":
    [*] Per settare il tipo di simbolo (marker) devi settare la "property" "Marker" con il corrispondente carattere
    [*] Per settare il colore del bordo del simbolo (marker) devi settare la "property" "Markeredgecolor" con il corrispondente carattere
    [*] Per settare il colore di riempimento del simbolo (marker) devi settare la "property" "Markerfacecolor" con il corrispondente carattere
    [*] Per non plottare la line che congiunge i punti devi settare la "property" "Linestyle" come "none"

    Le liste dei simboli dei markers e dei caratteri che corrispondono ai colori le trovi in:

    https://it.mathworks.com/help/matlab/ref/plot.html#input_argument_namevalue_d119e766805
    https://it.mathworks.com/help/matlab/ref/plot.html#input_argument_namevalue_d119e766499
    https://it.mathworks.com/help/matlab/ref/plot.html#input_argument_namevalue_d119e766669
    https://it.mathworks.com/help/matlab/ref/plot.html#input_argument_namevalue_d119e767012
    https://it.mathworks.com/help/matlab/ref/plot.html#input_argument_namevalue_d119e767194

    Di seguito una versione aggiornata della sezione del codice che plotta i dati estratti.

    Il codice consente di plottare fino a cinque marker diversi, se devi plottare i dati estratti da più di cinque grafici (files ".fig") bisogna aggiungere i corrispondenti caratteri nella variabile "p_marker".

    Ho aggiunto un "controllo" nel codice: se i set di dati superano il numero di marker definiti nella variabile "p_marker" viene generato un messaggio di errore.
    
    % Open a new Figure
    figure
    % Cheate an axes
    axes
    % Set "hold" to "on" to allow plotting multiple data set
    hold on
    % Initialize the array of the plots' handel
    p_handles=[];
    % Get the names of the struct fields
    f_names=fieldnames(data_line)
    % initialize the plot counter
    plot_cnt=0;
    % Define the color set for the points to be plotted (each character defines
    % a color: r=red, b=blue, k=black, c=cyan, g=green, y=yellow)
    marker_color='rbkcgy'
    % Define the shape of the points' marker (each character defines a shape)
    p_marker='odsph'
    n_marker=length(p_marker)
    n_fig=length(f_names)
    if(length(p_marker) < length(f_names))
       disp(['ERROR: The number of marker types (' num2str(n_marker) ') in less than the number of data set (' num2str(n_fig) ')'])
       return
    end
    % Loop over the Figures
    for i=1:n_fig
       % Loop over the data set of each Figure
       for j=1:size(data_line.(f_names{i}).X,1)
          % Increment the plot counter
          plot_cnt=plot_cnt+1
          % Create the string for the legend
          leg_str{plot_cnt}=[f_names{i} ' Data set # ' num2str(j)];
          % Plot the j-th data set of the i-th Figure
          p_handles(plot_cnt)=plot(data_line.(f_names{i}).X(j,:), ...
                                   data_line.(f_names{i}).Y(j,:), ...
                                   'linestyle','none', ...
                                   'marker',p_marker(i), ...
                                   'markeredgecolor',marker_color(i), ...
                                   'markerfacecolor',marker_color(i))
       end
    end
    % Replace the "_" from the legend string with " " (a blank)
    leg_str=strrep(leg_str,'_',' ')
    % Add the legend to the chart
    legend(p_handles,leg_str)
    grid minor
    
  • Re: Estrarre data da un grafico .fig

    Perfetto! grazie ancora.

    però penso ci sia un problema ancora: plotta 4 punti invece di 5 (ho 5 grafici)
    Allegati:
    22990_81983e30e35883d19d612c07ce64d8c8.jpg
    22990_81983e30e35883d19d612c07ce64d8c8.jpg
  • Re: Estrarre data da un grafico .fig

    Mi sembra strano.
    Hai scritto i nomi dei 5 files da leggere nella variabile "fig_names"?
    Hai incrementato il valore tra parentesi in "fig_names"?

    Credo che tu abbia fatto delle modifiche al codice che ti ho proposto nellè risposte precedenti, pubblica il tuo codice così posso verificare.
  • Re: Estrarre data da un grafico .fig

    [Dovresti provare ad eseguire il codice in modalità "debug" in modo da verificare se (e quindi dove) possa esserci un baco.
    In alternativa, prova ad eseguire il codice che segue:
    
    close all
    clear all
    clc
    
    % Define the names of the files of the Figure
    % (without specifying the file extension
    fig_names{1}='maxd_aquila'
    fig_names{2}='maxd_elcentro'
    fig_names{3}='maxd_irpinia'
    fig_names{4}='maxd_friuli'
    fig_names{5}='maxd_ibrido'
    % Loop over the Figures tobe read
    n_fig=length(fig_names)
    for i=1:n_fig
       % Open the i-th Figure
       openfig([fig_names{i} '.fig'])
       % Get the axes handle
       ax=gca;
       % Get the axes Children handle
       lines=ax.Children
       % Loop over the Children to extract the data
       for j=1:length(lines)
          % Create the field after the name of the "Figure"
          % Store the data in "cellarray"
          data_line.(fig_names{i}).X(j,:)=lines(j).XData
          data_line.(fig_names{i}).Y(j,:)=lines(j).YData
          data_line.(fig_names{i}).Z(j,:)=lines(j).ZData
       end
    end
    
    % Open a new Figure
    %%%figure
    % Cheate an axes
    %%%axes
    % Set "hold" to "on" to allow plotting multiple data set
    %%%hold on
    %%%grid on
    % Initialize the array of the plots' handel
    p_handles=[];
    % Get the names of the struct fields
    f_names=fieldnames(data_line)
    % initialize the plot counter
    plot_cnt=0;
    % Loop over the Figures
    for i=1:length(f_names)
       % Loop over the data set of each Figure
       figure
       axes
       hold on
       for j=1:size(data_line.(f_names{i}).X,1)
          % Increment the plot counter
          plot_cnt=plot_cnt+1
          % Create the string for the legend
          leg_str{plot_cnt}=[f_names{i} ' Data set # ' num2str(j)];
          % Plot the j-th data set of the i-th Figure
          p_handles(plot_cnt)=plot(data_line.(f_names{i}).X(j,:),data_line.(f_names{i}).Y(j,:),'o')
       end
    end
    % Replace the "_" from the legend string with " " (a blank)
    % leg_str=strrep(leg_str,'_',' ')
    % Add the legend to the chart
    % legend(p_handles,leg_str)
    savefig('inviluppo_maxd-R.fig')
    
    
    Ho modificato la seconda parte (quella ce genera il grafico complessivo) in modo che, invece, crei una Figure per ogni set di dati letti dai grafici di partenza.

    Se i codice funziona dovresti ottenere gli stessi grafici di partenza.

    Quanti grafici ottieni?

    Se non ottieni tutti i grafici di partenza, verifica il contenuto della struct data_line:
    [*] nella CoomandWindow scrivi
    
    data_line
    
    dovresti ottenere i nomi dei cinque grafici di partenza (quelli contenuti in "fig_names"). Cosa ottieni?

    In sequenza, sempre dalla CommandWindow;
    
    data_line.xxx
    
    dove, di volta in volta, xxx è il nome dei campi che hai ottenuto prima (i nomi de grafici). Cosa ottieni?
Devi accedere o registrarti per scrivere nel forum
12 risposte