Erstellen Sie mit Python selbst die bekannte 3-Tage-Darstellung des Röntgenflusses von NOAA / GOES

Erstellen Sie mit Python selbst die bekannte 3-Tage-Darstellung des Röntgenflusses von NOAA / GOES

** Hinweis: Es enthält ziemlich spezielle Inhalte, wie z. B. die verwendeten Daten. Ich werde die Erklärung der Physik und der Begriffe der entsprechenden Literatur überlassen. Für diejenigen, die von der Suche usw. zu sehen kamen, wird die Erklärung einiger Module aus [4. Erläuterung jedes Codeteils](Nr. 4 - Erläuterung jedes Codeteils) gegeben. Bitte beziehen Sie sich darauf. ** ** ** Menschen in der gleichen Branche sind sich der Neuerfindung von Rädern bewusst. Wenn es jedoch eine innovativere Methode gibt, lassen Sie es uns bitte wissen. Die Abkehr von IDL zu Python ist jedoch eine der Hauptannahmen.

1. Hintergrund

1.1. Was und warum machst du dir die Mühe, es selbst zu machen?

Ich werde die folgende Figur selbst machen, die ich irgendwo hätte sehen sollen, wenn ich mit der Sonne geforscht hätte. ** Die Zahl, die Sie gemacht haben, ist in [5. Eigentlich zeichnen](# 5 - Eigentlich zeichnen), also schauen Sie sie sich bitte alleine an. ** ** ** goes_xrays_20170906.png

Kürzlich ~~ (Ich habe es in letzter Zeit nicht gesehen, daher weiß ich nicht wann) ~~, Seite GOES Xray Flux ist interaktiv Es wurde zu einem Diagramm geändert. Das ist aber kein Problem ――Es stimmt, dass der Wert leicht zu erkennen ist, aber ehrlich gesagt gibt es keine Möglichkeit, Echtzeitinformationen über die Zeit und Minute des Flusses zu benötigen. ――Da das Röntgenzeitprofil dieses Formats seit langem verwendet wird, sind viele Menschen erleichtert, das Bild dieses Formats zu sehen.

1.2 Voraussetzungen

In diesem Artikel, in diesem Artikel 2Fqiita-image-store.s3.amazonaws.com% 2F0% 2F222849% 2F1e675340-79ff-4aa1-1891-b79d3c369eb3.png? Ixlib = rb-1.2.2 Ich benutze oft das Wort "Achsen", das in erscheint. Wenn Sie den folgenden Inhalt und Code verstehen möchten, empfehlen wir Ihnen, die "Abbildung" und "Achsen" mit einem schnellen Verständnis zu lesen.

Darüber hinaus werden, wie im Vorwort beschrieben, Fachbegriffe nicht erläutert. Bitte beachten Sie. Ich werde die Module etc. so weit wie möglich ohne Fachbegriffe erklären.

2. Erstellen eines Programms

2.1. Modulimport

Dieses Mal habe ich verschiedene Module importiert, die ich zum ersten Mal verwende, um mich an das Erscheinungsbild zu halten.

import numpy as np
import datetime,calendar,requests
import pandas as pd
from io import StringIO

import matplotlib
%matplotlib inline ##Zum Zeichnen auf Jupyter Notebook

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import matplotlib.transforms as transforms
from matplotlib.dates import DateFormatter
from matplotlib.dates import date2num
from matplotlib.offsetbox import AnchoredOffsetbox, TextArea, HPacker, VPacker

2.2 Datenort

Grundsätzlich sind alle Daten bis GOES 15 öffentlich zugänglich. Beispielsweise liegen im September 2017 die durchschnittlichen 1-Minuten-Röntgendaten von GOES-15 im CSV-Format [hier] vor (https://satdat.ngdc.noaa.gov/sem/goes/data/avg/2017/09/goes15) Es befindet sich unter /csv/g15_xrs_1m_20170901_20170930.csv). Dieses Mal werden wir fortfahren, damit wir Diagramme erstellen können, ohne Dateien lokal herunterladen zu müssen.

An dieser Stelle wird davon ausgegangen, dass Sie die GOES-Primär- und GOES-Sekundärzahlen kennen, wenn Sie das Diagramm erstellen möchten. Ich bin mir sicher, dass der IDL-Befehl primäre Informationen enthielt, daher werde ich ihn nach Möglichkeit eines Tages hinzufügen.

Um ein 3-Tage-Diagramm zu erstellen, beziehen Sie sich zunächst auf die Originaldaten. Die durchschnittlichen 1-Minuten-Röntgendaten von GOES werden jeden Monat im CSV-Format veröffentlicht. Seien Sie also vorsichtig, wenn Sie monatlich auf die Daten verweisen.

def read_csv_skiprows(url):
    resp = requests.get(url)
    data_text = resp.text
    
    is_skip, skip_row = False,1
    for line in data_text.split('\n'):##Teilen Sie jede Zeile'data:'suchen nach
        if 'data:' in line:
            is_skip = True
            break
        skip_row += 1

    if not is_skip:
        skip_row = 0
    return pd.read_csv(StringIO(data_text),skiprows=skip_row)

def get_goes_csv(goesnum,date,trange=3):
    ##Erstes Date auf dem Grundstück:tstart
    if type(date)==list:
        ts = datetime.date(date[0],date[1],date[2])
    elif (type(date)==datetime.date)or(type(date)==datetime.datetime):
        ts = date
    ##Letztes Datum auf dem Grundstück:tend
    te = ts+datetime.timedelta(days=trange)
    url = []
    if ts.month!=te.month: ##Wenn die Grafik Monate umfasst
        for i,t in enumerate([ts,te]): ##Holen Sie sich den Index mit Aufzählung
            ##Holen Sie sich den letzten Tag eines jeden Monats
            last_day = calendar.monthrange(t.year,t.month)[1]
            url.append('https://satdat.ngdc.noaa.gov/sem/goes/data/avg/{:04}/{:02}/goes{:02}/csv/g{:02}_xrs_1m_{:04}{:02}{:02}_{:02}{:02}{:02}.csv'.format(t.year,t.month,goesnum,goesnum,t.year,t.month,1,t.year,t.month,last_day))
            if i==0:
                d = read_csv_skiprows(url[i])
            else: ##Diesmal wird davon ausgegangen, dass der Monat nicht mehr als einmal überschritten wird.
                df = pd.concat([d,read_csv_skiprows(url[i])])
            
    else:
        last_day = calendar.monthrange(ts.year,ts.month)[1]
        url.append('https://satdat.ngdc.noaa.gov/sem/goes/data/avg/{:04}/{:02}/goes{:02}/csv/g{:02}_xrs_1m_{:04}{:02}{:02}_{:02}{:02}{:02}.csv'\
                    .format(ts.year,ts.month,goesnum,goesnum,ts.year,ts.month,1,ts.year,ts.month,last_day))
        df = read_csv_skiprows(url[0])
    
    ##Da die Datumsspalte vom Typ str ist, ändern Sie sie in einen Typ, der die Zeit verarbeiten kann
    df.time_tag = pd.to_datetime(df.time_tag)
    ##Gibt Daten zwischen ts und te zurück
    df_obj = df[(df.time_tag>=ts)&(df.time_tag<=te)]
    return df_obj

Obwohl es im CSV-Format sein soll, kann es etwas nervig sein, also hier Wie Sie sehen können, beginnen die gewünschten Daten von unten, und der erste Teil beschreibt die Erläuterung der Daten. "Read_csv" von "Pandas" kann zur Zielzeile springen, indem das Argument "Skiprows" oder "Header" angegeben wird, wenn eine solche Beschreibung vorliegt. Was jedoch problematisch ist, ist die Datei (oder Beobachtung) Die Anzahl der Zeilen, um die Daten zu erreichen, hängt von der Zeit ab.
Da es jedoch eine Beschreibung von "Daten" gibt, suchen Sie unmittelbar vor den Daten die Anzahl der Zeilen, die mit diesem als Ziel übersprungen werden sollen. Diese Methode wurde zuvor unter teratail unterrichtet.

Mit der obigen Verarbeitung können GOES-Röntgendaten erfasst werden. Wenn Sie vorerst Ihr eigenes GOES-Röntgendiagramm erstellen möchten, fügen Sie GOES-Daten zu [Sunpy] hinzu (https://docs.sunpy.org/en/v0.8.5/generated/gallery/goes_hek_m25.html) [^ 1] Da es einen Befehl zum Abrufen gibt, können Sie diesen auch verwenden. [^ 1]: Dieser Teil wagt es, auf die alte Version des Dokuments zu verweisen. Aus irgendeinem Grund wird die Abbildung im Dokument der neuesten Version nicht angezeigt und ist intuitiv zu verstehen. Weil es schwierig ist.

Der Nachteil ist jedoch, dass Sie jeweils nur Daten von einem Satelliten abrufen können (obwohl dies eine Übertreibung sein kann, da dies in den meisten Fällen kein Problem darstellt). In der Fackel vom 6. September 2017 sind beispielsweise die Daten von Fackel, die um 8:57 Uhr aufgetreten sind gerecht Es ist in GOES-15 gefallen, und es ist notwendig, es mit den Daten von GOES-13 zu ergänzen. In diesem Fall ist es möglicherweise besser, zur NOAA zu gehen.

3. Code abgeschlossen

Aus dem Fazit konnte ich mit folgendem Code ausgeben. Es ist sehr lang. Teilweise erklärt in [4. Erläuterung jedes Codeteils](# 4 - Erläuterung jedes Codeteils). Wenn Sie vorerst ein Diagramm wünschen, fahren Sie mit [5. Eigentlich zeichnen] fort (# 5 - Eigentlich zeichnen).

plt.rcParams['font.family'] = 'Simplex'
plt.rcParams['font.size'] = 10
plt.rcParams['figure.dpi'] = 100

plt.rcParams['axes.linewidth'] = 1

plt.rcParams['lines.antialiased'] = False
plt.rcParams['text.antialiased'] = False
plot_antialiased = False

##Alles in Pixeleinheiten
wdict = dict(
    grid  = 1, ##Gitterlinienbreite
    spine = 1, ##Rahmenlinienbreite
    tick  = 1, ##Linienbreite skalieren
    line  = 0.01, ##Diagrammlinienbreite
)
##Pixel in Punkt konvertieren
def px2pt(px):
    dpi = plt.rcParams['figure.dpi']
    return px*72/dpi

def plot_goes(t, trange ,goes ,savename, wdict, width=6.4, ylim=(10**-9,10**-2)):
    '''
    t      :Startdatum des Plots(type=datetime.date or list)
             (e.g. datetime.date(2017,9,4) or [2017,9,4]) 
    trange :Täglicher Plotzeitraum(type=int) (e.g. trange=3 > 3 days plot)
    goes   :GOES Satellitennummernlistenformat zu erwerben(e.g. [15,13])
             index =0 ist primär(1-8A>red, 0.5-4A>blue)
             index =1 ist zweitrangig(1-8A>yellow, 0.5-4A>purple)
    width  :Standardmäßig Plotbreite=6.4
             if it is 'extend', extend the width with trange
    ylim   :Standardeinstellung für den Bereich der y-Achse=(10**-9,10**-2)
Wahrscheinlich nicht notwendig, um sich zu ändern, aber entworfen, um in Ordnung zu sein, um sich zu ändern
    '''
    if type(t)==list:
        t = datetime.date(t[0],t[1],t[2])
    elif (type(t)==datetime.date)or(type(t)==datetime.datetime):
        pass
    else:
        print('t should be a list or a datetime object.')
    
    fs_def = plt.rcParams['font.size']
    dpi    = plt.rcParams['figure.dpi']
    y0_fig = plt.rcParams['figure.subplot.bottom']
    y1_fig = plt.rcParams['figure.subplot.top']
    
    ##Breiteneinstellung
    if width=='extend':
        width = (dpi*6.4 + (dpi*6.4 - fs_def*10)/3*(trange-3))/dpi
    elif type(width)==float:
        width = width
    else:
        print('width is \'extend\' or float')

    ##Der linke und rechte Rand haben die Schriftgröße* 10 (Verhältnis zur Figur)
    margin = fs_def/(100*width)*10

    ##Breite pro Tag(Verhältnis zur Figur)
    w_day  = (1-2*margin)/trange
    ax = []

    ##Rahmen(axes)Schaffung
    fig = plt.figure(figsize=(width,4.8))
    for i in range(trange):
        t_s = t + datetime.timedelta(days=i)
        t_e = t_s + datetime.timedelta(days=1)

        if i==0: ##Erster Tag
            ax.append(fig.add_axes([margin+i*w_day,y0_fig,w_day,(y1_fig-y0_fig)],\
                                   yscale='log', xlim=[t_s,t_e], ylim=ylim, zorder=-i))
            new_xticks = date2num([t_s,t_e])

        else: ##Nach dem zweiten Tag
            ax.append(fig.add_axes([margin+i*w_day,y0_fig,w_day,(y1_fig-y0_fig)],\
                                   yscale='log', xlim=[t_s,t_e], ylim=ylim, yticklabels=[], zorder=-i))
            new_xticks = date2num([t_e])

        ax[i].xaxis.set_major_locator(ticker.FixedLocator(new_xticks))
        ax[i].xaxis.set_major_formatter(DateFormatter('%b %d'))
        ax[i].xaxis.set_minor_locator(matplotlib.dates.HourLocator(interval=3))
        ax[i].yaxis.grid(lw=px2pt(wdict['grid']),color='black')

        ax[i].tick_params(axis='x', which='major', bottom=True, top=True, direction='in', length=6, width=px2pt(wdict['tick']), pad=fs_def)
        ax[i].tick_params(axis='x', which='minor', bottom=True, top=True, direction='in', length=3, width=px2pt(wdict['tick']))

        for j in ax[i].spines.keys(): ##Anpassen der Linienbreite des Rahmens
            ax[i].spines[j].set_linewidth(px2pt(wdict['spine']))
        ##Skalierung anpassen
        if i==0: ##Erster Tag
            ax[i].tick_params(axis='y', which='both', right=True, left=True, direction='in', length=6, width=px2pt(wdict['tick']))
            ax[i].spines['right'].set_visible(False)
        elif i==trange-1: ##Letzter Tag
            ax[i].tick_params(axis='y', which='both', right=True, left=False, direction='in', length=6, width=px2pt(wdict['tick']))
            ax[i].spines['left'].set_visible(False)            
        else: ##Andere
            ax[i].tick_params(axis='y', which='both', right=True, left=False, direction='in', length=6, width=px2pt(wdict['tick']))
            ax[i].spines['left'].set_visible(False)
            ax[i].spines['right'].set_visible(False)


    ## Flare class text
    f_pos = ax[-1].get_position()

    trans = transforms.blended_transform_factory(fig.transFigure,transforms.IdentityTransform())
    X10_y_display   = ax[-1].transData.transform((date2num(t_e),10**-3))[1]
    X_y_display     = ax[-1].transData.transform((date2num(t_e),10**-4))[1]
    w = X10_y_display - X_y_display

    ##Relative Schriftgröße zur gesamten Figur
    ##Wird verwendet, um Ränder beim Platzieren von Klassentext zuzulassen, damit dieser nicht am äußeren Rahmen haftet
    cls_text_size = plt.rcParams['font.size']/(plt.rcParams['figure.figsize'][0])/72

    for i,cls in enumerate(['X', 'M', 'C', 'B', 'A']):
        pos = [f_pos.x1,X10_y_display - w/2 - i*w]
        if (pos[1]>=ax[-1].transData.transform((date2num(t_e),ax[-1].get_ylim()[0]))[1])&\
           (pos[1]<=ax[-1].transData.transform((date2num(t_e),ax[-1].get_ylim()[1]))[1]):
            ax[-1].text(pos[0]+cls_text_size/5,pos[1],cls,horizontalalignment='left',verticalalignment='center',transform=trans)

    ## GOES number and wavelength
    ybox_b = TextArea('GOES{} 0.5-4.0 A'.format(goes[0]), textprops=dict(color='#001DFF', size='large' ,rotation=90,ha='left',va='bottom')) #Blau
    ybox_r = TextArea('GOES{} 1.0-8.0 A'.format(goes[0]), textprops=dict(color='#FF0000', size='large' ,rotation=90,ha='left',va='bottom')) #rot
    ybox_primary = VPacker(children=[ybox_r, ybox_b],align='bottom', pad=0, sep=2*fs_def)
    if len(goes)==2:
        ybox_p = TextArea('GOES{} 0.5-4.0 A'.format(goes[1]), textprops=dict(color='#5400A8', size='large' ,rotation=90,ha='left',va='bottom')) #lila
        ybox_y = TextArea('GOES{} 1.0-8.0 A'.format(goes[1]), textprops=dict(color='#FFA500', size='large' ,rotation=90,ha='left',va='bottom')) #Gelb
        ybox_secondary = VPacker(children=[ybox_y, ybox_p],align='bottom', pad=0, sep=2*fs_def)
        ybox = HPacker(children=[ybox_primary,ybox_secondary],align='bottom', pad=0, sep=fs_def)
        anchored_ybox = AnchoredOffsetbox(loc=5, child=ybox, pad=0., frameon=False, bbox_to_anchor=(1-margin*0.25, 0.5), 
                                          bbox_transform=fig.transFigure, borderpad=0.)
    else:
        ybox = ybox_primary
        anchored_ybox = AnchoredOffsetbox(loc=5, child=ybox, pad=0., frameon=False, bbox_to_anchor=(1-margin*0.5, 0.5), 
                                          bbox_transform=fig.transFigure, borderpad=0.)
    ax[-1].add_artist(anchored_ybox)

    ##Erstellung von Achsenbeschriftungen(dummy axes)
    ax_dummy = fig.add_axes([margin,y0_fig,1-margin*2,y1_fig-y0_fig],frameon=False)
    ax_dummy.tick_params(labelcolor='none', top='off', bottom='off', left='off', right='off')
    ax_dummy.set_xlabel('Universal Time',size='large')
    ax_dummy.set_ylabel('Watts m$^{-2}$',size='large')
    ax_dummy.set_title('GOES Xray Flux (1-minute data)',size='x-large')

    ax_dummy.text(1, 1-cls_text_size/5, 'Begin: {} {} {} 0000 UTC'.format(t.year,t.strftime('%b'),t.day),
            horizontalalignment='right',
            verticalalignment='top',
            transform=fig.transFigure)
    ## X-ray data plot
    color = iter(['#FF0000','#001DFF','#FFA500','#5400A8']) ## red, blue, yellow, purple 
    zo = iter([4,3,2,1])
    for g in goes:
        wavelength = iter(['1.0-8.0 A','0.5-4.0 A'])
        data = get_goes_csv(g,t,trange)
        xray_long  = np.ma.masked_where((data.B_AVG<=ylim[0])|(data.B_AVG>=ylim[1]),data.B_AVG)
        xray_short = np.ma.masked_where((data.A_AVG<=ylim[0])|(data.A_AVG>=ylim[1]),data.A_AVG)
        ax[0].plot(data.time_tag,xray_long, lw=px2pt(wdict['line']),c=next(color),label='GOES{} 1.0-8.0 A'.format(g),aa=plot_antialiased,clip_on=False,zorder=next(zo))
        ax[0].plot(data.time_tag,xray_short,lw=px2pt(wdict['line']),c=next(color),label='GOES{} 0.5-4.0 A'.format(g),aa=plot_antialiased,clip_on=False,zorder=next(zo))
        
    ## save graph
    fig.savefig(savename)

4. Erläuterung jedes Teils des Codes

Ich werde jeden Teil vorstellen. Wenn Sie es vorerst verwenden möchten, überspringen Sie es bitte.

4.1. Schriftart

Laut hier ist die in IDL verwendete Schriftart Simplex Roman. Dieses Mal war ich besonders auf das Erscheinungsbild bedacht, also habe ich es von Free Font Site heruntergeladen und verwendet. Es wurde unter Mac OS nicht standardmäßig installiert. Wenn Sie sich also daran halten möchten, laden Sie es bitte herunter. Wenn du es nicht brauchst

plt.rcParams['font.family'] = 'Arial'

Ich denke, dass es ein einfach zu lesendes Diagramm sein wird, wenn Sie es als solches festlegen.

4.2 Aliase

plt.rcParams['lines.antialiased'] = False
plt.rcParams['text.antialiased'] = False
plot_antialiased = False

Wenn matplotlib im Bitmap-Format wie png oder jpg ausgegeben wird, wird das Anti-Aliasing automatisch ergänzt und ausgeführt, sodass keine Zacken auftreten. Wenn Sie ein Diagramm normal zeichnen, müssen Sie sich darüber keine Sorgen machen, aber diesmal war ich besonders darauf bedacht. Wenn Sie alle oben genannten Parameter auf True setzen, wird ein Anti-Aliasing durchgeführt, und ich denke, das ist sicherer. Darüber hinaus scheint es keine Möglichkeit zu geben, das Anti-Aliasing von Ticks aufzuheben.

4.3. Konvertierung von Pixel und Punkt

def px2pt(px):
    dpi = plt.rcParams['figure.dpi']
    return px*72/dpi

Dies ist auch eine verschwenderische Verpflichtung. Im Originalbild wurde die Breite jeder Linie als 1 Pixel angegeben, deshalb habe ich sie dafür erstellt. Denn die Einheit bei der Angabe der Breite usw. mit matplotlib ist alles Punkt. 1 Punkt ist 1/72 von 1 Zoll, und die Beziehung zwischen Zoll und Pixel ändert sich abhängig von der dpi, so dass dies korrigiert wird.

4.4. Breiteneinstellung

if width=='extend':
    width = (dpi*6.4 + (dpi*6.4 - fs_def*10)/3*(trange-3))/dpi
elif type(width)==float:
    width = width
else:
    print('width is \'extend\' or float')

Das Originalbild hatte eine Höhe von 480 Pixel und eine Breite von 640 Pixel. Die Grundlagen lauten also: (dpi ist 100). Wenn Sie jedoch ein Diagramm erstellen möchten, das länger als 3 Tage dauert, können Sie "width ==" verlängern "angeben, um die horizontale Größe zu erhöhen, während die Breite pro Tag dieselbe bleibt wie für das 3-Tage-Diagramm. Hat. Wenn Sie normalerweise die Breite mit dem Typ "float" angeben, wird diese Größe festgelegt, der Betrieb kann jedoch nicht garantiert werden. Wenn Sie sorgfältig darüber nachdenken und ein Diagramm erstellen, das kürzer als 3 Tage ist, wird ein Fehler ausgegeben, sodass ich ihn später beschreiben werde ([6. Einfach zeichnen](# 6 - Einfach zeichnen).

4.5 Randeinstellungen

##Der linke und rechte Rand haben die Schriftgröße* 10 (Verhältnis zur Figur)
margin = fs_def/(100*width)*10

##Breite pro Tag(Verhältnis zur Figur)
w_day  = (1-2*margin)/trange

Stellen Sie den linken und rechten Rand ein. Wie Sie im Kommentar sehen können, habe ich die Schriftgröße auf das Zehnfache eingestellt.

4.6 Rahmeneinstellung

##Rahmen(axes)Schaffung
fig = plt.figure(figsize=(width,4.8))
for i in range(trange):
    t_s = t + datetime.timedelta(days=i)
    t_e = t_s + datetime.timedelta(days=1)

    if i==0: ##Erster Tag
        ax.append(fig.add_axes([margin+i*w_day,y0_fig,w_day,(y1_fig-y0_fig)],\
                               yscale='log', xlim=[t_s,t_e], ylim=ylim, zorder=-i))
        new_xticks = date2num([t_s,t_e])

    else: ##Nach dem zweiten Tag
        ax.append(fig.add_axes([margin+i*w_day,y0_fig,w_day,(y1_fig-y0_fig)],\
                               yscale='log', xlim=[t_s,t_e], ylim=ylim, yticklabels=[], zorder=-i))
        new_xticks = date2num([t_e])

    ax[i].xaxis.set_major_locator(ticker.FixedLocator(new_xticks))
    ax[i].xaxis.set_major_formatter(DateFormatter('%b %d'))
    ax[i].xaxis.set_minor_locator(matplotlib.dates.HourLocator(interval=3))
    ax[i].yaxis.grid(lw=px2pt(grid_width),color='black')

    ax[i].tick_params(axis='x', which='major', bottom=True, top=True, direction='in', length=6, width=px2pt(tick_width), pad=fs_def)
    ax[i].tick_params(axis='x', which='minor', bottom=True, top=True, direction='in', length=3, width=px2pt(tick_width))

    for j in ax[i].spines.keys(): ##Anpassen der Linienbreite des Rahmens
        ax[i].spines[j].set_linewidth(px2pt(spine_width))
    ##Skalierung anpassen
    if i==0: ##Erster Tag
        ax[i].tick_params(axis='y', which='both', right=True, left=True, direction='in', length=6, width=px2pt(tick_width))
        ax[i].spines['right'].set_visible(False)
    elif i==trange-1: ##Letzter Tag
        ax[i].tick_params(axis='y', which='both', right=True, left=False, direction='in', length=6, width=px2pt(tick_width))
        ax[i].spines['left'].set_visible(False)            
    else: ##Andere
        ax[i].tick_params(axis='y', which='both', right=True, left=False, direction='in', length=6, width=px2pt(tick_width))
        ax[i].spines['left'].set_visible(False)
        ax[i].spines['right'].set_visible(False)

Wahrscheinlich der Teil, der die meiste Zeit gebraucht hat, um sich auf die feinsten Teile zu konzentrieren. Schließlich scheint Matplotlib nicht über den Speicher im Originaldiagramm zu verfügen, sondern über die Mittel zum Zeichnen. inside_ticks.png

Ich dachte daran, gewaltsam einen horizontalen Balken zu schreiben, der den Bereich mit "ax.hline ()" usw. trennte, aber ich wollte nicht viel rohe Gewalt anwenden. Als ich Sync fragte, ob IDL verarbeitet werden kann, scheint IDL eine Funktion zum Hinzufügen einer Achse an einer beliebigen Stelle zu haben. ~~ Gib es Matplotlib. ~~ Ich konnte nicht anders, also beschloss ich, mich mit dem Aufteilen von "Achsen" zu befassen. Insbesondere durch Angabe der Koordinaten mit "add_axes" wird der Bereich wie in der folgenden Abbildung gezeigt unterteilt, und durch Ändern der Anzeige des Rahmens (in matplotlib scheint er als "Wirbelsäule" bezeichnet zu werden) kann der Rahmen sicher erstellt werden. Hat vervollständigt. multiple_axes.png

4.6 Flare-Klassentext

## Flare class text
##Holen Sie sich die Koordinaten der Achsen ganz links
f_pos = ax[-1].get_position()

trans = transforms.blended_transform_factory(fig.transFigure,transforms.IdentityTransform())
X10_y_display   = ax[-1].transData.transform((date2num(t_e),10**-3))[1]
X_y_display     = ax[-1].transData.transform((date2num(t_e),10**-4))[1]
w = X10_y_display - X_y_display

##Relative Schriftgröße zur gesamten Figur
##Wird verwendet, um Ränder beim Platzieren von Klassentext zuzulassen, damit dieser nicht am äußeren Rahmen haftet
cls_text_size = plt.rcParams['font.size']/(plt.rcParams['figure.figsize'][0])/72

for i,cls in enumerate(['X', 'M', 'C', 'B', 'A']):
    pos = [f_pos.x1,X10_y_display - w/2 - i*w]
    if (pos[1]>=ax[-1].transData.transform((date2num(t_e),ax[-1].get_ylim()[0]))[1])&\
       (pos[1]<=ax[-1].transData.transform((date2num(t_e),ax[-1].get_ylim()[1]))[1]):
        ax[-1].text(pos[0]+cls_text_size/5,pos[1],cls,horizontalalignment='left',verticalalignment='center',transform=trans)

Dies ist der am wenigsten lesbare Teil dieses Codes. Es tut mir Leid.
Die Flare-Klasse wird durch den Wert auf der vertikalen Achse bestimmt, daher müssen Sie die Zeichen in "axis.text" auf den richtigen Wert setzen. Es gibt verschiedene Möglichkeiten, die Koordinaten beim Platzieren von "axis.text" festzulegen.

  1. Koordinaten, die den Pixeln der gesamten Figur entsprechen
  2. Relative Koordinaten mit (0,0) unten links und (1,1) oben rechts
  3. In den Achsen (Rahmen) in der Abbildung ist die untere linke (0,0) und die obere rechte (1,1).
  4. Koordinaten, die den Werten entsprechen, die die Figur hat

In dieser Abbildung ist die horizontale Achse jedoch die Zeit, also habe ich (4) aufgegeben (Ist es möglich, date2num zu verwenden?). Aus diesem Grund habe ich es so gestaltet, dass Zeichen an der richtigen Position außerhalb des Rahmens platziert werden können, während "blended_transform_factory" verwendet wird, das eine Mischung aus (1) bis (3) verarbeiten kann. Speziell,

trans = transforms.blended_transform_factory(fig.transFigure,transforms.IdentityTransform())

Auf diese Weise bezieht sich die x-Koordinate auf (2; figure.transFigure) und die y-Koordinate auf (4;transforms.IdentityTransform ()), so dass text platziert werden kann. Hier scheint es ein Durcheinander von Verbesserungen zu geben ...

4.7. Eine Legende erstellen

## GOES number and wavelength

##Stellen Sie dies ein, indem Sie den Text jeder Farbe um 90 Grad drehen
ybox_b = TextArea('GOES{} 0.5-4.0 A'.format(goes[0]), textprops=dict(color='#001DFF', size='large' ,rotation=90,ha='left',va='bottom')) #Blau
ybox_r = TextArea('GOES{} 1.0-8.0 A'.format(goes[0]), textprops=dict(color='#FF0000', size='large' ,rotation=90,ha='left',va='bottom')) #rot

##Vertikal mit VPacker verbinden
ybox_primary = VPacker(children=[ybox_r, ybox_b],align='bottom', pad=0, sep=2*fs_def)

##Wenn Sie sowohl primäre als auch sekundäre zeichnen möchten
##Erstellen Sie auf die gleiche Weise eine sekundäre Verbindung und stellen Sie eine horizontale Verbindung mit HPacker her
if len(goes)==2:
    ybox_p = TextArea('GOES{} 0.5-4.0 A'.format(goes[1]), textprops=dict(color='#5400A8', size='large' ,rotation=90,ha='left',va='bottom')) #lila
    ybox_y = TextArea('GOES{} 1.0-8.0 A'.format(goes[1]), textprops=dict(color='#FFA500', size='large' ,rotation=90,ha='left',va='bottom')) #Gelb
    ybox_secondary = VPacker(children=[ybox_y, ybox_p],align='bottom', pad=0, sep=2*fs_def)
    ybox = HPacker(children=[ybox_primary,ybox_secondary],align='bottom', pad=0, sep=fs_def)
    ##Installation in Anchored Offsetbox Der Installationsort wird für jede Ortsnummer festgelegt.
    ## loc=5 ist'center right'Mit anderen Worten, die rechte Mitte der Figur
    anchored_ybox = AnchoredOffsetbox(loc=5, child=ybox, pad=0., frameon=False, bbox_to_anchor=(1-margin*0.25, 0.5), bbox_transform=fig.transFigure, borderpad=0.)
else: ##Wenn nur primär, nur primär
    ybox = ybox_primary
    anchored_ybox = AnchoredOffsetbox(loc=5, child=ybox, pad=0., frameon=False, bbox_to_anchor=(1-margin*0.5, 0.5), bbox_transform=fig.transFigure, borderpad=0.)
ax[-1].add_artist(anchored_ybox)

Dies ist auch weniger lesbar.

Im Originalbild wird die Legende außerhalb des Rahmens um 90 Grad nach rechts gedreht. Mit matplotlib können Sie die Legende aus dem Rahmen entfernen, aber es scheint nichts zu tun, um sie zu drehen. Außerdem können Sie die Farbe in "axis.text" anscheinend nicht ändern, sodass Sie die verschiedenfarbigen "Texte" separat platzieren müssen. Dies ist nur mit der Koordinatenspezifikation sehr schwierig. Daher habe ich mit "VPacker" und "HPacker" von "matplotlib.offsetbox", die an relativen Positionen platziert werden können, die Legende reproduziert, die sich außerhalb der Figur drehte. Es ist eine ziemlich Brute-Force-Technik.

Generieren Sie zuerst jeden "Text" mit "TextArea" und verbinden Sie sie mit "VPacker" und "HPacker". Die auf diese Weise vervollständigte Pseudo-Legende wurde am rechten Ende der Figur mit "Anchored Offsetbox" installiert.

4.8. Achsenbeschriftungen erstellen

##Erstellung von Achsenbeschriftungen(dummy axes)
ax_dummy = fig.add_axes([margin,y0_fig,1-margin*2,y1_fig-y0_fig],frameon=False)
ax_dummy.tick_params(labelcolor='none', top='off', bottom='off', left='off', right='off')
ax_dummy.set_xlabel('Universal Time',size='large')
ax_dummy.set_ylabel('Watts m$^{-2}$',size='large')
ax_dummy.set_title('GOES Xray Flux (1-minute data)',size='x-large')

ax_dummy.text(1, 1-cls_text_size/5, 'Begin: {} {} {} 0000 UTC'.format(t.year,t.strftime('%b'),t.day),
        horizontalalignment='right',
        verticalalignment='top',
        transform=fig.transFigure)

Ich habe die Methode der separaten Anzeige von "Achsen" verwendet, um den Maßstab innerhalb der Figur anzuzeigen ~~ (grobe Technik) ~~, aber dank dessen konnte die Position der Etiketteneinstellung auf der horizontalen Achse nicht bestimmt werden. .. Deshalb habe ich eine große Dummy-Achse erstellt, die nichts anzeigt, und die Achsenbeschriftung dafür festgelegt. dummy_axes.png

Außerdem habe ich die detaillierte Reproduktion der Zeichen aufgegeben, die oben, unten, links und rechts im Originalbild angezeigt werden (da die Zeichen unten nicht erforderlich sind). Wenn jedoch oben rechts keine Startzeit für die Daten vorhanden ist, sind die Informationen zum Jahr der Daten nicht bekannt. Daher habe ich beschlossen, diesen Teil in Eile anzuzeigen.

4.9. Darstellung der Röntgendaten

## X-ray data plot
color = iter(['#FF0000','#001DFF','#FFA500','#5400A8']) ## red, blue, yellow, purple 
zo = iter([4,3,2,1])
for g in goes:
    wavelength = iter(['1.0-8.0 A','0.5-4.0 A'])
    data = get_goes_csv(g,t,trange)
    xray_long  = np.ma.masked_where((data.B_AVG<=ylim[0])|(data.B_AVG>=ylim[1]),data.B_AVG)
    xray_short = np.ma.masked_where((data.A_AVG<=ylim[0])|(data.A_AVG>=ylim[1]),data.A_AVG)
    ax[0].plot(data.time_tag,xray_long, lw=px2pt(line_width),c=next(color),label='GOES{} 1.0-8.0 A'.format(g),aa=plot_antialiased,clip_on=False,zorder=next(zo))
    ax[0].plot(data.time_tag,xray_short,lw=px2pt(line_width),c=next(color),label='GOES{} 0.5-4.0 A'.format(g),aa=plot_antialiased,clip_on=False,zorder=next(zo))

Endlich kam ich zur Darstellung der Röntgendaten.

Von den Spalten in der GOES 1-Minuten-Durchschnittsdaten-CSV-Datei benötigen Sie "time_tag", "A_AVG" und "B_AVG", um den Röntgenfluss zu zeichnen. "time_tag" speichert die Zeit pro Minute so wie sie ist, und "A_AVG" und "B_AVG" speichern die durchschnittlichen Röntgendaten, die 0,05 bis 0,4 nm bzw. 0,1 bis 0,8 nm entsprechen. Es ist gewesen. Diese werden basierend auf der "DataFrame" -Syntax von "Pandas" extrahiert.

zorder ist die Zeichenreihenfolge. Je größer dieser Wert ist, desto mehr wird er im Vordergrund angezeigt. Im Originalbild wurde der Wert von GOES primary im Vordergrund angezeigt, daher habe ich die Zahl so eingestellt.

Eine andere Sache, die ich mache, ist die Angabe von "clip_on = False" beim Plotten. Da wir dieses Mal "Achsen" für das Datum vorbereitet haben, ist es notwendig, "axes.plot" für diese Nummer aufzurufen. Wenn Sie jedoch "clip_on = False" angeben, wird es außerhalb der vorbereiteten "Achsen" gezeichnet. Daher werden die Daten für alle Tage am ersten Tag in "Achsen" aufgezeichnet. Durch Ausführen dieses clip_on = False kann das Diagramm außerdem am Rand platziert werden.

Außerdem wird der Wert mit "np.ma.masked_where" maskiert. Die diesmal verwendeten Daten speichern "-99999", wenn die Daten verloren gehen, und wenn dies so wie es ist auf der Protokollskala aufgezeichnet wird, wird ein Diagramm wie ein Potential vom Typ "Well" erstellt.

Wenn Sie im standardmäßig festgelegten Bereich von "ylim = (10 ** -9, 10 ** -2)" zeichnen, gibt es im Grunde kein Problem. Wenn Sie dies jedoch ändern, ist "clip_on = False" Aufgrund des Effekts der Einstellung besteht die Möglichkeit, dass die Darstellung in vertikaler Richtung erfolgt. aus diesem Grund,

xray_long  = np.ma.masked_where((data.B_AVG<=ylim[0])|(data.B_AVG>=ylim[1]),data.B_AVG)

Auf diese Weise werden alle Daten, die aus dem eingestellten Bereich der y-Achse kommen, einschließlich "-99999", maskiert. Dadurch bleibt das maskierte Diagramm leer, ohne eine Verbindung herzustellen.

Normalerweise macht das Speichern von "np.nan" auch das Diagramm leer, daher gibt es meines Erachtens nicht viele Beispiele für die Verwendung von "numpy.ma", aber beim Zeichnen eines völlig anderen Diagramms "np". Manchmal war es bequemer, eine Maske aufzusetzen, als nan zu lagern. Daher verwende ich hier numpy.ma zum Zwecke der Einführung.

5. Zeichnen Sie tatsächlich

** Hinweis: Simplex-Schriftarten sind möglicherweise nicht standardmäßig auf jedem PC verfügbar. ** ** ** Ich werde mit der obigen Funktion zeichnen. Grundsätzlich werden zuerst die erforderlichen Parameter deklariert,

plt.rcParams['font.family'] = 'Simplex'
plt.rcParams['font.size'] = 10
plt.rcParams['figure.dpi'] = 100

plt.rcParams['axes.linewidth'] = 1

plt.rcParams['lines.antialiased'] = False
plt.rcParams['text.antialiased'] = False
plot_antialiased = False

##Alles in Pixeleinheiten
wdict = dict(
    grid  = 1, ##Gitterlinienbreite
    spine = 1, ##Rahmenlinienbreite
    tick  = 1, ##Linienbreite skalieren
    line  = 0.01, ##Diagrammlinienbreite
)

plot_goes([2017,9,4], 3 ,[15,13] ,'goes.png', wdict, width=6.4, ylim=(10**-9,10**-2))

Sie können es so zeichnen. goes.png Im Vergleich nebeneinander sieht es so aus. compare.png

Ist es nicht ganz reproduzierbar? ?? Da die heruntergeladene Simplex-Schriftart ziemlich dünn ist, denke ich, dass ein Teil der Zeichen aufgrund von Entfremdung nicht angezeigt wird und dass fast alles außer den Zeicheninformationen oben, unten, links und rechts reproduziert werden konnte. ~~ Es scheint, dass die Größe des Rahmens manuell angepasst werden muss. ~~ Damit ist das Kopieren abgeschlossen.

Sie sollten problemlos zeichnen können, auch wenn Sie jede Eingabe ein wenig ändern.

plot_goes([2017,9,4], 5 ,[15] ,'goes_extend.png', wdict, width='extend', ylim=(10**-9,10**-2))

goes_extend.png

6. Einfaches Zeichnen

Mit [5. Tatsächlich zeichnen](# 5 - Eigentlich zeichnen) ist die Reproduktion der ursprünglichen Familie fast abgeschlossen. Lassen Sie uns von nun an ein etwas praktischeres (einfaches) Diagramm erstellen.

Die beiden obersten Elemente, bei denen der obige Code "goes_plot ()" kompliziert ist, sind:

Ich denke. Ich denke nicht, dass Sie bei Postern und Präsentationsfolien so besonders sein müssen, deshalb werde ich versuchen, sie zu entfernen und den Code zu vereinfachen. Darüber hinaus ruft die obige Funktion "goes_plot ()" bei jeder Ausführung Daten vom Server ab, was zeitaufwändig und überlastbar sein kann. Daher werden wir die heruntergeladenen Daten wiederverwenden und einige Änderungen vornehmen, damit die Details der Abbildung angepasst werden können. (Natürlich ist es am besten, die Datendatei lokal herunterzuladen und zu laden.)

6.1. Code

plt.rcParams['font.family'] = 'Arial'
plt.rcParams['font.size'] = 11
plt.rcParams['figure.dpi'] = 100

plt.rcParams['axes.linewidth'] = 1

plt.rcParams['lines.antialiased'] = True
plt.rcParams['text.antialiased'] = True
plot_antialiased = True

##Alles in Pixeleinheiten
wdict = dict(
    grid  = 1, ##Gitterlinienbreite
    spine = 1, ##Rahmenlinienbreite
    tick  = 1, ##Linienbreite skalieren
    line  = 2, ##Diagrammlinienbreite
)
##Pixel in Punkt konvertieren
def px2pt(px):
    dpi = plt.rcParams['figure.dpi']
    return px*72/dpi

def plot_goes_simple(t, trange ,goes ,savename, wdict, width=6.4, ylim=(10**-9,10**-2)):
    '''
    t      :Startdatum des Plots(type=datetime.date or list)
             (e.g. datetime.date(2017,9,4) or [2017,9,4]) 
    trange :Täglicher Plotzeitraum(type=int) (e.g. trange=3 > 3 days plot)
    goes   :GOES Satellitennummernlistenformat zu erwerben(e.g. [15,13])
             index =0 ist primär(1-8A>red, 0.5-4A>blue)
             index =1 ist zweitrangig(1-8A>yellow, 0.5-4A>purple)
    width  :Standardmäßig Plotbreite=6.4
             if it is 'extend', extend the width with trange
    ylim   :Standardeinstellung für den Bereich der y-Achse=(10**-9,10**-2)
Wahrscheinlich nicht notwendig, um sich zu ändern, aber entworfen, um in Ordnung zu sein, um sich zu ändern
    '''
    if type(t)==list:
        t = datetime.date(t[0],t[1],t[2])
    elif (type(t)==datetime.date)or(type(t)==datetime.datetime):
        pass
    else:
        print('t should be a list or a datetime object.')
    
    fs_def = plt.rcParams['font.size']
    dpi    = plt.rcParams['figure.dpi']
    y0_fig = plt.rcParams['figure.subplot.bottom']
    y1_fig = plt.rcParams['figure.subplot.top']
    
    ##Breiteneinstellung
    if width=='extend':
        width = (dpi*6.4 + (dpi*6.4 - fs_def*10)/3*(trange-3))/dpi
    elif type(width)==float:
        width = width
    else:
        print('width is \'extend\' or float')

    ##Der linke und rechte Rand haben die Schriftgröße* 10 (Verhältnis zur Figur)
    margin = fs_def/(100*width)*10

    ##Breite pro Tag(Verhältnis zur Figur)
    w_day  = (1-2*margin)/trange
    ax = []
    
    ##Rahmen(axes)Schaffung
    t_s = t
    t_e = t_s + datetime.timedelta(days=trange)
    
    fig = plt.figure(figsize=(width,4.8))
    ##Wenn Sie eine normale Legende in den Rahmen einfügen, fügen Sie diese zwangsweise hinzu_Ohne Angabe mit Achsen
    ##Standard Abb.add_Ich denke, Nebenhandlung ist in Ordnung
    #ax = fig.add_axes([margin,y0_fig,1-2*margin,y1_fig-y0_fig],yscale='log', xlim=[t_s,t_e], ylim=ylim)
    ax = fig.add_subplot(111,yscale='log', xlim=[t_s,t_e], ylim=ylim)
    new_xticks = date2num([t_s+datetime.timedelta(days=i) for i in range(trange+1)])

    ax.xaxis.set_major_locator(ticker.FixedLocator(new_xticks))
    ax.xaxis.set_major_formatter(DateFormatter('%b %d'))
    ax.xaxis.set_minor_locator(matplotlib.dates.HourLocator(interval=3))
    ax.yaxis.grid(lw=px2pt(wdict['grid']),color='black')

    ax.tick_params(axis='x', which='major', bottom=True, top=True, direction='in', length=6, width=px2pt(wdict['tick']), pad=fs_def)
    ax.tick_params(axis='x', which='minor', bottom=True, top=True, direction='in', length=3, width=px2pt(wdict['tick']))
    ax.tick_params(axis='y', which='both', right=True, left=True, direction='in', length=6, width=px2pt(wdict['tick']))
    
    for j in ax.spines.keys(): ##Anpassen der Linienbreite des Rahmens
        ax.spines[j].set_linewidth(px2pt(wdict['spine']))

    ## Flare class text
    f_pos = ax.get_position()

    trans = transforms.blended_transform_factory(fig.transFigure,transforms.IdentityTransform())
    X10_y_display   = ax.transData.transform((date2num(t_e),10**-3))[1]
    X_y_display     = ax.transData.transform((date2num(t_e),10**-4))[1]
    w = X10_y_display - X_y_display

    ##Relative Schriftgröße zur gesamten Figur
    ##Wird verwendet, um Ränder beim Platzieren von Klassentext zuzulassen, damit dieser nicht am äußeren Rahmen haftet
    cls_text_size = plt.rcParams['font.size']/(plt.rcParams['figure.figsize'][0])/72
    
    for i,cls in enumerate(['X', 'M', 'C', 'B', 'A']):
        pos = [f_pos.x1,X10_y_display - w/2 - i*w]
        if (pos[1]>=ax.transData.transform((date2num(t_e),ax.get_ylim()[0]))[1])&\
           (pos[1]<=ax.transData.transform((date2num(t_e),ax.get_ylim()[1]))[1]):
            ax.text(pos[0]+cls_text_size/2,pos[1],cls,horizontalalignment='center',verticalalignment='center',transform=trans)

    ##Wenn Sie hier einen Kommentar abgeben, können Sie die Legende außerhalb des Rahmens platzieren
    '''
    ## GOES number and wavelength
    ybox_b = TextArea('GOES{} 0.5-4.0 A'.format(goes[0]), textprops=dict(color='#001DFF', size='large' ,rotation=90,ha='left',va='bottom')) #Blau
    ybox_r = TextArea('GOES{} 1.0-8.0 A'.format(goes[0]), textprops=dict(color='#FF0000', size='large' ,rotation=90,ha='left',va='bottom')) #rot
    ybox_primary = VPacker(children=[ybox_r, ybox_b],align='bottom', pad=0, sep=2*fs_def)
    if len(goes)==2:
        ybox_p = TextArea('GOES{} 0.5-4.0 A'.format(goes[1]), textprops=dict(color='#5400A8', size='large' ,rotation=90,ha='left',va='bottom')) #lila
        ybox_y = TextArea('GOES{} 1.0-8.0 A'.format(goes[1]), textprops=dict(color='#FFA500', size='large' ,rotation=90,ha='left',va='bottom')) #Gelb
        ybox_secondary = VPacker(children=[ybox_y, ybox_p],align='bottom', pad=0, sep=2*fs_def)
        ybox = HPacker(children=[ybox_primary,ybox_secondary],align='bottom', pad=0, sep=fs_def)
        anchored_ybox = AnchoredOffsetbox(loc=5, child=ybox, pad=0., frameon=False, bbox_to_anchor=(1-margin*0.25, 0.5), 
                                          bbox_transform=fig.transFigure, borderpad=0.)
    else:
        ybox = ybox_primary
        anchored_ybox = AnchoredOffsetbox(loc=5, child=ybox, pad=0., frameon=False, bbox_to_anchor=(1-margin*0.5, 0.5), 
                                          bbox_transform=fig.transFigure, borderpad=0.)
    ax.add_artist(anchored_ybox)
    '''
    
    ##Erstellung von Achsenbeschriftungen
    ax.set_xlabel('Universal Time',size='large')
    ax.set_ylabel('Watts m$^{-2}$',size='large')
    ax.set_title('GOES Xray Flux (1-minute data)',size='x-large')

    ax.text(1, 1-cls_text_size/5, 'Begin: {} {} {} 0000 UTC'.format(t.year,t.strftime('%b'),t.day),
            horizontalalignment='right',
            verticalalignment='top',
            transform=fig.transFigure)

    ## X-ray data plot
    color = iter(['#FF0000','#001DFF','#FFA500','#5400A8']) ## red, blue, yellow, purple 
    zo = iter([4,3,2,1])

    for i,g in enumerate(goes):
        data = data_temp[i]
        xray_long  = np.ma.masked_where((data.B_AVG<=ylim[0])|(data.B_AVG>=ylim[1]),data.B_AVG)
        xray_short = np.ma.masked_where((data.A_AVG<=ylim[0])|(data.A_AVG>=ylim[1]),data.A_AVG)
        ax.plot(data.time_tag,xray_long, lw=px2pt(wdict['line']),c=next(color),label='GOES{} 1.0-8.0 A'.format(g),aa=plot_antialiased,clip_on=False,zorder=next(zo))
        ax.plot(data.time_tag,xray_short,lw=px2pt(wdict['line']),c=next(color),label='GOES{} 0.5-4.0 A'.format(g),aa=plot_antialiased,clip_on=False,zorder=next(zo))
        
    ## simple legend
    leg = ax.legend(handlelength=0, handletextpad=0, ncol=2)
    for line, text in zip(leg.get_lines(), leg.get_texts()):
        text.set_color(line.get_color())
    
    ## save graph
    fig.savefig(savename)

Die Notation um die Variable "ax" hat sich geringfügig geändert, da nicht mehr mehrere "Achsen" platziert werden müssen. Bitte beachten Sie beim Arrangieren den Unterschied zu plot_goes ().

## simple legend
leg = ax.legend(handlelength=0, handletextpad=0, ncol=2)
for line, text in zip(leg.get_lines(), leg.get_texts()):
    text.set_color(line.get_color())

Also habe ich den Legendenmarker unsichtbar gemacht und die Farbe des Legenden-Textes in die Farbe geändert, die jedem Plot entspricht.

6.2 Zeichnen

Ich habe einige ausprobiert, aber die folgenden Parameter scheinen genau richtig zu sein.

plt.rcParams['font.family'] = 'Arial'
plt.rcParams['font.size'] = 11
plt.rcParams['figure.dpi'] = 100

plt.rcParams['axes.linewidth'] = 1

plt.rcParams['lines.antialiased'] = True
plt.rcParams['text.antialiased'] = True
plot_antialiased = True

##Alles in Pixeleinheiten
wdict = dict(
    grid  = 1, ##Gitterlinienbreite
    spine = 1, ##Rahmenlinienbreite
    tick  = 1, ##Linienbreite skalieren
    line  = 2, ##Diagrammlinienbreite
)

Speichern Sie die Röntgendaten in data_temp und zeichnen Sie sie wie folgt auf.

t = [2017,9,4]
trange = 3
goes = [15,13]

data_temp = []
for g in goes:
    data_temp.append(get_goes_csv(g,t,trange))

plot_goes_simple(t, trange, goes, 'goes_simple.png', wdict, width=6.4, ylim=(10**-9,10**-2))

goes_simple.png

Wenn es so aussieht, ist es meiner Meinung nach relativ leicht zu sehen, selbst wenn Sie es auf ein Poster setzen.

7. Schlussfolgerung

Wenn ich etwas Besonderes wollte, konnte ich nicht aufhören. Ich habe viel über "Äxte" gelernt. Wenn Sie eine Chance haben, verwenden Sie sie bitte für Papiere, Präsentationsfolien, Poster usw. Wenn es hilft, auch wenn ich Sie irgendwo treffe, wenn Sie sagen "es war nützlich", bin ich sehr froh, dass Sie das Gefühl haben "ich habe es getan".

Wenn Sie Fragen oder Verbesserungen haben, können Sie sich gerne an uns wenden. GOES-16 hat Echtzeitdaten im JSON-Format veröffentlicht, aber Sie haben nur die Daten für die letzte Woche. Werden frühere Daten bald veröffentlicht? Ich werde in Schwierigkeiten sein, wenn ich es nicht tue. ~~ Sobald das Format festgelegt ist, möchte ich es so gestalten, dass es unterstützt werden kann.

Verweise

Matplotlib im Allgemeinen matplotlib.figure.Figure — Matplotlib 3.1.2 documentation Grundkenntnisse über Matplotlib, die ich früh kennenlernen wollte, oder die Geschichte eines Künstlers, der das Erscheinungsbild anpassen kann - Qiita Eine Zusammenfassung von matplotlib-Qiita matplotlib reverse pull memo (einfaches Diagramm) --Qiita matplotlib reverse pull memo (Rahmenausgabe) --Qiita

um Zecke, Wirbelsäule Legen Sie die Achsenskala des Diagramms der Zeitreihendaten mit matplotlib.dates | Analysis Train fest Matplotlib-Skala und Skalenetikett, Skalenlinie Erstellen Sie ein Diagramm mit mit matplotlib --Qiita entfernten Rändern

Textplatzierung und Koordinatenspezifikation (Transformation) Text properties and layout — Matplotlib 3.1.2 documentation Transformations Tutorial — Matplotlib 3.1.2 documentation

Festlegen von Achsenbeschriftungen für mehrere Unterzeichnungen (Festlegen von Dummy-Achsen) python - pyplot axes labels for subplots - Stack Overflow

Anpassung der Legendenmarkierung und der Legentextfarbe python - How do you just show the text label in plot legend? (e.g. remove a label's line in the legend) - Stack Overflow Option to set the text color in legend to be same as the line · Issue #10720 · matplotlib/matplotlib · GitHub

Erstellen einer um 90 Grad gedrehten Legende (matplotlib.offsetbox) python - Matplotlib: y-axis label with multiple colors - Stack Overflow matplotlib.offsetbox — Matplotlib 3.1.2 documentation

numpy.ma The numpy.ma module — NumPy v1.17 Manual

Recommended Posts

Erstellen Sie mit Python selbst die bekannte 3-Tage-Darstellung des Röntgenflusses von NOAA / GOES
[Python] Anmelden Ihres eigenen Moduls
Erstellen Sie Ihre eigenen Linux-Befehle in Python
[LLDB] Erstellen Sie Ihren eigenen Befehl mit Python
Verwenden Sie einfach Ihre eigenen Funktionen in Python
Holen Sie sich Ihre eigene IP-Adresse in Python
Erstellen Sie schnell Ihr eigenes Modul mit setuptools (Python)
Machen Sie mit Python eine Joyplot-ähnliche Handlung von R.
Importieren Sie Ihre eigenen Module mit der Python-Entwicklung von Grasshopper
Erstellen Sie Ihre eigenen Big Data in Python zur Validierung
Erstellen Sie Ihr eigenes Random Dot Stereogram (RDS) in Python.
Versuchen Sie, Ihr eigenes Intro-Quiz mit Python zu verbessern
Verwenden Sie CASA Toolkit in Ihrer eigenen Python-Umgebung
[Road to Intermediate Python] Definieren Sie in Ihrer eigenen Klasse
Versuchen Sie, Ihre eigenen Objekte mit Prioritätswarteschlangen in Python zu sortieren
Mach nicht test.py in Python!
Erstellen Sie ein Lesezeichen in Python
Stellen Sie Opencv in Python zur Verfügung
Segfo Python in 2 Zeilen
Zeichnen Sie geografische Informationen in Python
Röntgenbeugungssimulation mit Python
Erstellen Sie Ihre eigene Diagrammstrukturklasse und deren Zeichnung mit Python