I am trying to create a parsing function that will generate the Date and Time of METAR reports which contain 6 hourly weather information. Based on the research I have done, I have found a parsing function that will do what I am trying to accomplish:
While I am sure that this is the parsing function that I need, I am somewhat unsure where I can implement this function into my METAR parsing code. I have tried this function in multiple sections of the METAR parsing code (separate copies to ensure the original stays intact), but I am unsure where I can place it within the code that would allow for the proper parsing of the Dates and times for the reports I need.
For clarity, the METAR parsing code is the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
import pandas as pd import numpy as np import seaborn as sns import DateTime Training_METAR = pd.read_csv( "KBOS Boston Training Metar Data.csv" ) Test_METAR = pd.read_csv( "KBOS Test METAR Data.csv" ) np.random.seed( 0 ) # print(Training_METAR['valid'].head()) Training_METAR[ "Dates_Needed" ] = pd.to_datetime(Training_METAR[ "valid" ], format = "%m/%d/%Y %H:%M" ) print (Training_METAR[ "Dates_Needed" ].head()) |
For clarity, the METAR parsing code is the following:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
import os import pathlib # get your own relative path import pandas as pd from lazyme.string import color_print import csv # included in python 3.8.2 install import numpy as np import tkinter as tk from tkinter import filedialog import seaborn as sns import datetime count = 1 # this is an example string from the decoder doc with added fields # exampleData = "METAR KABC 121755Z AUTO 21016G24KT 180V240 1SM R11/P6000FT -RA " \ # "BR BKN015 OVC025 06/04 A2990 RMK AO2 PK WND 20032/25 WSHFT 1715 " \ # "VIS 3/4V1 1/2 VIS 3/4 RWY11 RAB07 CIG 013V017 CIG 017 RWY11 " \ # "PRESFR SLP125 P0003 60009 70015 T00640036 10066 21012 400461006 " \ # "58033 TSNO $" class MetarDataObj( object ): """ A Metar Object contains only the data that is decoded from a single metar string. """ """ The contents of the example data and their field labels METAR - TYPE OF REPORT KABC - STATION IDENTIFIER 121755Z - DATE/TIME AUTO - REPORT MODIFIER 21016G24KT 180V240 - WIND DIRECTION AND SPEED 1SM - VISIBILITY R11/P6000FT - RUNWAY VISUAL RANGE -RA BR - WEATHER PHENOMENA BKN015 OVC025 - SKY CONDITION 06/04 - TEMPERATURE/DEW POINT A2990 - ALTIMETER RMK - REMARK - TORNADIC ACTIVITY AO2 - TYPE OF AUTOMATED STATION PK WND 20032/25 - PEAK WIND WSHFT 1715 - WIND SHIFT - TOWER OR SURFACE VISIBILITY VIS 3/4V1 1/2 - VARIABLE PREVAILING VISIBILITY VIS 3/4 RWY11 - VISIBILITY AT SECOND LOCATION - LIGHTNING RAB07 - BEGINNING AND ENDING OF PRECIPITATION AND THUNDERSTORM CIG 013V017 - VIRGA CIG 017 RWY11 - VARIABLE CEILING HEIGHT PRESFR - PRESSURE RISING OR FALLING RAPIDLY SLP125 - SEA-LEVEL PRESSURE P0003 - HOURLY PRECIPITATION AMOUNT 60009 - 3- AND 6-HOUR PRECIPITATION AMOUNT ** want this - 24-HOUR PRECIPITATION AMOUNT ** want this T00640036 - HOURLY TEMPERATURE AND DEW POINT 10066 - 6-HOUR MAXIMUM TEMPERATURE ** want this 21012 - 6-HOUR MINIMUM TEMPERATURE ** want this - 24-HOUR MAXIMUM AND MINIMUM TEMPERATURE ** want this 58033 - PRESSURE TENDENCY TSNO - SENSOR STATUS INDICATORS $ - MAINTENANCE CHECK INDICATOR """ # class constructor def __init__( self , metarString): # class local variables, initialized to nothing self .precip6 = None self .temp6max = None self .temp6min = None self .time = None # call function to parse data, pass string from constructor # handle empty construction if metarString ! = None : self .parseCSVdata(metarString) # process metar data def parseCSVdata( self , aString): """ Here we will parse the metar string passed into the default constructor. """ # the field named 'SEA-LEVEL PRESSURE' is the stake in the ground. # stripping off everything before this field, packing into a list tinyMetar = aString[aString.find( "SLP" ): - 1 ].split() # remove the stake # color_print('\tSpreadsheet row' + str(count) + '\n', color="red") # an empty list looks like [] # handling the case where a row does not have a stake in the ground if len (tinyMetar) ! = 0 : # Loop over contents looking for data, skipping over the stake for metarField in tinyMetar: # look for 6 hour precip if metarField[ 0 ] = = "6" and len (metarField) = = 5 : # get the 6 hour if metarField[ 1 :] = = "////" : self .precip6 = None else : self .precip6 = float (metarField[ 3 :]) * . 01 elif metarField[ 0 ] = = "T" and len (metarField) = = 9 : continue # look for 6 hour max elif metarField[ 0 ] = = "1" and len (metarField) = = 5 : # custom exception handling # try to catch improper field if metarField[ 1 :] = = "////" : self .temp6max = None else : try : float (metarField) # try to do this but don't die if # fails t6minSign = None # get the sign of max if metarField[ 1 ] = = "0" : # positive temp t6minSign = "" else : # negative temp t6minSign = "-" # get 6 hr max self .temp6max = float ( t6minSign + metarField[ 2 ] + "." + metarField[ 3 :]) except ValueError: # if it fails come down here and do this continue # look for 6 hour min elif metarField[ 0 ] = = "2" and len (metarField) = = 5 : t6minSign = None # get the sign of min if metarField[ 1 :] = = "////" : self .temp6min = None else : if metarField[ 1 ] = = "0" : # positive temp t6minSign = "" else : # negative temp t6minSign = "-" # get 6 hr min self .temp6min = float (t6minSign + metarField[ 2 ] + "." + metarField[ 3 :]) # color_print("\trow skipped", color="yellow") |