Python: find højdekurver fra matplotlib.pyplot.contour()

Jeg forsøger at finde ud af (men ikke tegne!) højdekurver for nogle data: der er

from pprint import pprint 
import matplotlib.pyplot 
z = [[0.350087, 0.0590954, 0.002165], [0.144522, 0.885409, 0.378515], 
     [0.027956, 0.777996, 0.602663], [0.138367, 0.182499, 0.460879], 
     [0.357434, 0.297271, 0.587715]] 
cn = matplotlib.pyplot.contour(z) 

Jeg ved cn indeholder højdekurver, jeg ønsker, men jeg kan ikke synes at få
til dem. Jeg har prøvet flere ting:

print dir(cn) 
pprint(cn.collections[0]) 
print dir(cn.collections[0]) 
pprint(cn.collections[0].figure) 
print dir(cn.collections[0].figure) 

til ingen nytte. Jeg ved cn er en ContourSet, og cn.collections er et array
af LineCollections. Jeg mener, at en LineCollection er en bred vifte af liniestykker, men jeg
kan ikke finde ud af at udvinde disse segmenter.

Mit ultimative mål er at skabe en KML-fil, der plotter data med en verden, der
kort, og konturerne til, at data så godt.

Men da nogle af mine data punkter er tæt på hinanden, og andre
er langt væk, jeg har brug for det faktiske polygoner (linestrings), der gør op
konturerne, og ikke bare en rasteriseret billede af konturer.

Jeg er noget overrasket over qhull ikke gøre noget som dette.

At bruge Mathematica ‘ s ListContourPlot og derefter eksportere som SVG virker, men jeg
vil bruge noget open source.

Jeg kan ikke bruge den velkendte CONREC algoritme, fordi mine data ikke er på en
mesh (der er ikke altid flere y-værdier for en given x-værdi, og
vice versa).

Den løsning har ikke til python, men er nødt til at være open source
og kørbar på Linux.

OriginalForfatteren barrycarter | 2013-08-18

2 svar

  1. 22

    Du kan få den vertices tilbage ved looping over samlinger og stier, og ved hjælp af den iter_segments() metode til matplotlib.stien.Sti.

    Her er en funktion, der returnerer vertices som et sæt af indlejrede lister af højdekurver, kontur sektioner og arrays af x,y vertices:

    import numpy as np
    
    def get_contour_verts(cn):
        contours = []
        # for each contour line
        for cc in cn.collections:
            paths = []
            # for each separate section of the contour line
            for pp in cc.get_paths():
                xy = []
                # for each segment of that section
                for vv in pp.iter_segments():
                    xy.append(vv[0])
                paths.append(np.vstack(xy))
            contours.append(paths)
    
        return contours

    Edit:

    Det er også muligt at beregne konturer uden at plotte noget at bruge udokumenterede matplotlib._cntr C modul:

    from matplotlib import pyplot as plt
    from matplotlib import _cntr as cntr
    
    z = np.array([[0.350087, 0.0590954, 0.002165],
                  [0.144522,  0.885409, 0.378515],
                  [0.027956,  0.777996, 0.602663],
                  [0.138367,  0.182499, 0.460879], 
                  [0.357434,  0.297271, 0.587715]])
    
    x, y = np.mgrid[:z.shape[0], :z.shape[1]]
    c = cntr.Cntr(x, y, z)
    
    # trace a contour at z == 0.5
    res = c.trace(0.5)
    
    # result is a list of arrays of vertices and path codes
    # (see docs for matplotlib.path.Path)
    nseg = len(res) // 2
    segments, codes = res[:nseg], res[nseg:]
    
    fig, ax = plt.subplots(1, 1)
    img = ax.imshow(z.T, origin='lower')
    plt.colorbar(img)
    ax.hold(True)
    p = plt.Polygon(segments[0], fill=False, color='w')
    ax.add_artist(p)
    plt.show()

    Python: find højdekurver fra matplotlib.pyplot.contour()

    Dette gjorde det trick, tak! (den første, der er, har ikke testet den anden, men jeg er sikker på det ville virke alt for). Nysgerrig: er den 2. løsning kræver et xy-mesh, eller ville det fungere med vilkårlige x og y-værdier?
    Ville du nødt til at give det en maske, selvom du kan altid bruge noget som scipy.interpolate.griddata at få denne
    Forventer du cntr.Cntr() til at være hurtigere end matplotlib.pyplot.contour() ?
    Det ville være min naive antagelse, da _cntr ville ikke involvere nogen plotte overhead. Hvis ydelsen er en bekymring, så skal du nok tid begge metoder.
    Bare ved at kigge på kildekoden til contour og matplotlib.contour.QuadContourSet. Du kan få en lang vej ved hjælp ?? IPython magi til at undersøge source kode af en funktion eller et objekt. Husk på, at udokumenterede komponenter, der er tilbøjeligt til at ændre sig uden varsel i fremtidige versioner af matplotlib.

    OriginalForfatteren ali_m

  2. 2

    Det ser ud til, at kontur-data er i .allsegs attribut af QuadContourSet objekt, der returneres af plt.contour() funktion.

    Den .allseg attribut er en liste over alle de niveauer, (som kan være angivet, når du ringer plt.contour(X,Y,Z,V). For hvert niveau du få en liste over numpy nx2 arrays.

    plt.figure()
    plt.contour(X, Y, Z, [0], colors='r')
    
    plt.figure()
    for ii, seg in enumerate(C.allsegs[0]):
        plt.plot(seg[:,0], seg[:,1], '.-', label=ii)
    plt.legend(fontsize=9, loc='best')

    I ovenstående eksempel, er kun en plan er givet, så len(C.allsegs) =1. Du får:

    contour plot
    Python: find højdekurver fra matplotlib.pyplot.contour()

    den udpakkede kurver
    Python: find højdekurver fra matplotlib.pyplot.contour()

    OriginalForfatteren Dneis

Skriv et svar

Din e-mailadresse vil ikke blive publiceret. Krævede felter er markeret med *