2009-03-31 11 views
14

devo disegnare ternary/triangle plots rappresentano frazioni molari (x, y, z) di varie sostanze/miscele (x + y + z = 1). Ogni trama rappresenta sostanze di valore iso, ad es. sostanze che hanno lo stesso punto di fusione. I grafici devono essere disegnati sullo stesso triangolo con colori/simboli diversi e sarebbe bello se potessi anche collegare i punti.Library/strumento per disegnare ternari/piazzole triangolo

Ho visto matplotlib, R e gnuplot, ma non sembrano in grado di disegnare questo tipo di trama. Il pacchetto di terze parti ade4 per R sembra essere in grado di disegnarlo, ma non sono sicuro di poter disegnare più trame sullo stesso triangolo.

Ho bisogno di qualcosa che gira sotto Linux o Windows. Sono aperto a qualsiasi suggerimento, incluse le librerie per altre lingue, ad es. Perl, PHP, Ruby, C# e Java.

+0

Ci sono un paio di opzioni di ricerca di seguito elencati; prova 'library (sos); findFn ("{ternary plot}") ' –

+0

un pacchetto R appena creato fa quello che ti serve (e più) è basato su ggplot, il sito web è www.ggtern.com –

+0

@CristianCiupitu fatto –

risposta

7

R ha un pacchetto esterno chiamato VCD che dovrebbe fare quello che vuoi.

La documentazione è molto buona (122 pagine manuali distribuite con il pacchetto); c'è anche un libro con lo stesso nome, Visual Display of Quantitative Information, dall'autore del pacchetto (Prof. Michael Friendly).

Per creare diagramma ternario utilizzando VCD, basta chiamare ternaryplot() e passano in un m x 3 matrice, cioè una matrice con tre colonne.

La firma del metodo è molto semplice; è richiesto solo un singolo parametro (la matrice di dati m x 3); e tutti i parametri delle parole chiave si riferiscono all'estetica della trama, tranne che per la scala, che quando è impostata su 1 normalizza i dati in base alla colonna.

per tracciare punti dati sul diagramma ternario, le coordinate per un dato punto vengono calcolate come centro gravità di punti di massa in cui ciascun valore caratteristica comprendente la matrice di dati è un separato peso, quindi le coordinate di un punto V (a, b, c) sono

V(b, c/2, c * (3^.5)/2 

per generare lo schema qui sotto, gli appena creato dei dati falsi per rappresentare quattro diverse miscele chimiche, ciascuno costituito varie frazioni di tre sostanze (x, y, z). Ho ridimensionato l'input (quindi x + y + z = 1) ma la funzione lo farà per te se passi un valore per il suo parametro 'scale' (infatti, il valore predefinito è 1, che credo sia la tua domanda richiede). Ho usato colori diversi & simboli per rappresentare i quattro punti dati, ma puoi anche usare solo un singolo colore/simbolo ed etichettare ciascun punto (tramite l'argomento 'id').

http://www.freeimagehosting.net/uploads/35393eaba5.png

+0

Sembra decisamente interessante, peccato che abbia così tante dipendenze che non ho sulla mia macchina Fedora 12 :-(Comunque grazie per aver risposto e +1 da parte mia. –

+1

che è troppo male - penso che potresti esserti divertito usando quella libreria altrimenti. (Una coincidenza che quando stavo scrivendo la mia risposta sopra, ero seduto all'aeroporto di Bucarest mentre tornavo in Spagna da una scalata nelle splendide montagne di Fagaras.) Non penso di avere il rep per aggiungere un tag 'r' al tuo Q, quindi se sei d'accordo, magari aggiungi quel tag quando ne hai la possibilità. – doug

+0

Sono riuscito ad installarlo su Fedora 12 eseguendo R e digitando al prompt R 'install.packages (c ("vcd")). "Anche gli esempi dalla pagina di manuale' ternaryplot' hanno funzionato come un incantesimo. Grazie ancora! Per quanto riguarda il tag 'r', non ho notato il tuo commento, altrimenti l'avrei aggiunto PS: Sono felice che ti sia piaciuta la tua scalata –

0

Trova una libreria di disegno vettoriale e disegna da zero se non riesci a trovare un modo più semplice per farlo.

+0

Ho pensato anche a questo, ma sarebbe troppo lavoro (grugnito). Ci sono molti dettagli che devono essere compresi, ad es. le posizioni delle etichette degli assi o dei segni di graduazione. Btw, la soluzione di Phil sta fondamentalmente disegnando la trama da zero. –

3

Chloë Lewis sviluppato una classe generale triangolo-plot, destinato a sostenere la struttura del terreno triangolo con Python e Matplotlib. E 'disponibile qui http://nature.berkeley.edu/~chlewis/Sourcecode.html https://github.com/chlewissoil/TernaryPlotPy

editing Chloe aggiungere: spostato a un host più affidabile! Inoltre, è un repository pubblico, quindi se si desidera richiedere la libreria-izzazione, è possibile aggiungere un problema. Spero sia utile a qualcuno.

+0

Bei grafici e +1 Peccato che il codice non sia abbastanza generico da poter essere usato come libreria. –

+0

link invia 404 :( – oDDsKooL

+0

@chplewis: grazie per la modifica! –

13

Creato uno script molto semplice per la generazione di grafici ternari (o più). Nessuna griglia o tickline, ma quelle non sarebbero troppo difficili da aggiungere usando i vettori nella matrice "base".

enter image description here

from pylab import * 


def ternaryPlot(
      data, 

      # Scale data for ternary plot (i.e. a + b + c = 1) 
      scaling=True, 

      # Direction of first vertex. 
      start_angle=90, 

      # Orient labels perpendicular to vertices. 
      rotate_labels=True, 

      # Labels for vertices. 
      labels=('one','two','three'), 

      # Can accomodate more than 3 dimensions if desired. 
      sides=3, 

      # Offset for label from vertex (percent of distance from origin). 
      label_offset=0.10, 

      # Any matplotlib keyword args for plots. 
      edge_args={'color':'black','linewidth':2}, 

      # Any matplotlib keyword args for figures. 
      fig_args = {'figsize':(8,8),'facecolor':'white','edgecolor':'white'}, 
     ): 
    ''' 
    This will create a basic "ternary" plot (or quaternary, etc.) 
    ''' 
    basis = array(
        [ 
         [ 
          cos(2*_*pi/sides + start_angle*pi/180), 
          sin(2*_*pi/sides + start_angle*pi/180) 
         ] 
         for _ in range(sides) 
        ] 
       ) 

    # If data is Nxsides, newdata is Nx2. 
    if scaling: 
     # Scales data for you. 
     newdata = dot((data.T/data.sum(-1)).T,basis) 
    else: 
     # Assumes data already sums to 1. 
     newdata = dot(data,basis) 

    fig = figure(**fig_args) 
    ax = fig.add_subplot(111) 

    for i,l in enumerate(labels): 
     if i >= sides: 
      break 
     x = basis[i,0] 
     y = basis[i,1] 
     if rotate_labels: 
      angle = 180*arctan(y/x)/pi + 90 
      if angle > 90 and angle <= 270: 
       angle = mod(angle + 180,360) 
     else: 
      angle = 0 
     ax.text(
       x*(1 + label_offset), 
       y*(1 + label_offset), 
       l, 
       horizontalalignment='center', 
       verticalalignment='center', 
       rotation=angle 
      ) 

    # Clear normal matplotlib axes graphics. 
    ax.set_xticks(()) 
    ax.set_yticks(()) 
    ax.set_frame_on(False) 

    # Plot border 
    ax.plot(
     [basis[_,0] for _ in range(sides) + [0,]], 
     [basis[_,1] for _ in range(sides) + [0,]], 
     **edge_args 
    ) 

    return newdata,ax 


if __name__ == '__main__': 
    k = 0.5 
    s = 1000 

    data = vstack((
     array([k,0,0]) + rand(s,3), 
     array([0,k,0]) + rand(s,3), 
     array([0,0,k]) + rand(s,3) 
    )) 
    color = array([[1,0,0]]*s + [[0,1,0]]*s + [[0,0,1]]*s) 

    newdata,ax = ternaryPlot(data) 

    ax.scatter(
     newdata[:,0], 
     newdata[:,1], 
     s=2, 
     alpha=0.5, 
     color=color 
     ) 
    show() 
1

Ho appena scoperto uno strumento che utilizza Python/Matplotlib per generare diagramma ternario chiamati wxTernary. È disponibile tramite http://wxternary.sourceforge.net/ - Sono riuscito a generare correttamente una trama ternaria al primo tentativo.

+0

il progetto sembra non aver controllato nello script in SCM :( – oDDsKooL

0

Esiste un pacchetto R denominato soiltexture. È mirato alla trama del triangolo della trama del suolo, ma può essere personalizzato per alcuni aspetti.

6

Un pacchetto che ho scritto in R ha solo stato accettato per la CRAN, pagina web è www.ggtern.com:

Si basa off ggplot2, che ho usato come una piattaforma. La forza trainante per me era il desiderio di avere coerenza nel mio lavoro e, dal momento che utilizzo pesantemente ggplot2, lo sviluppo del pacchetto era una progressione logica.

Per quelli di voi che usano ggplot2, l'uso di ggtern dovrebbe essere un gioco da ragazzi, e, ecco un paio di dimostrazioni di ciò che può essere raggiunto.

Feldspar

Prodotto con il seguente codice:

# Load data 
data(Feldspar) 

# Sort it by decreasing pressure 
# (so small grobs sit on top of large grobs 
Feldspar <- Feldspar[with(Feldspar, order(-P.Gpa)), ] 

# Build and Render the Plot 
ggtern(data = Feldspar, aes(x = An, y = Ab, z = Or)) + 
#the layer 
geom_point(aes(fill = T.C, 
       size = P.Gpa, 
       shape = Feldspar)) + 
#scales 
scale_shape_manual(values = c(21, 24)) + 
scale_size_continuous(range = c(2.5, 7.5)) + 
scale_fill_gradient(low = "green", high = "red") + 

#theme tweaks 
theme_tern_bw() + 
theme(legend.position  = c(0, 1), 
     legend.justification = c(0, 1), 
     legend.box.just  = "left") + 

#tweak guides 
guides(shape= guide_legend(order =1, 
          override.aes=list(size=5)), 
     size = guide_legend(order =2), 
     fill = guide_colourbar(order=3)) + 

#labels and title 
labs(size = "Pressure/GPa", 
    fill = "Temperature/C") + 
ggtitle("Feldspar - Elkins and Grove 1990") 

grafici di contorno sono stati anche patch per l'ambiente ternario, e, l'inserimento di una nuova geometria per rappresentare intervalli di confidenza via il Mahalanobis Distanza.

Contour

Prodotto con il seguente codice:

ggtern(data=Feldspar,aes(An,Ab,Or)) + 
    geom_confidence(aes(group=Feldspar, 
         fill=..level.., 
         alpha=1-..level..), 
         n=2000, 
        breaks=c(0.01,0.02,0.03,0.04, 
          seq(0.05,0.95,by=0.1), 
          0.99,0.995,0.9995), 
        color=NA,linetype=1) + 
    geom_density2d(aes(color=..level..)) + 
    geom_point(fill="white",aes(shape=Feldspar),size=5) + 
    theme_tern_bw() + 
    theme_tern_nogrid() + 
    theme(ternary.options=element_ternary(padding=0.2), 
         legend.position=c(0,1), 
         legend.justification=c(0,1), 
         legend.box.just="left") + 
    labs(color="Density",fill="Confidence", 
    title="Feldspar - Elkins and Grove 1990 + Confidence Levels + Density") + 
    scale_color_gradient(low="gray",high="magenta") + 
    scale_fill_gradient2(low="red",mid="orange",high="green", 
         midpoint=0.8) + 
    scale_shape_manual(values=c(21,24)) + 
    guides(shape= guide_legend(order =1, 
          override.aes=list(size=5)), 
     size = guide_legend(order =2), 
     fill = guide_colourbar(order=3), 
     color= guide_colourbar(order=4), 
     alpha= "none")