Recursive Function in Python

I recently wrote my first (from what I can recall anyway) recursive function
in Python. For many (most), this is probably no big deal, but I was pretty
stoked about how well it worked and wanted to share it in case anyone else ran
into a similar issue.

A little background…

I’m working with NCEP BUFR data which fortunately embeds the table into the file.

Aside: I like to write code that expects the data to describe itself. This is probably a relic of using NetCDF data, but is also based on my frustration of having to identify the pattern of a file and then write a bunch of special cases to handle non-standard formatting. So if the data file is self-describing, I’m in love. Even if it is BUFR data.

The tables have this general format which is described in detail here.

Bottom line is that there is a hierarchy of table descriptors. At the most basic level is the Table B descriptors. Next up the food chain is the Table D descriptors which are comprised of Table B descriptors and other Table D descriptors. eventually, each Table D descriptor boils down to a Table B descriptor. At the top is the Table A descriptor which is a general overview of what Table D (and hence Table B) descriptors you should expect.

So it looks something like:

Table A: [Table D1, Table D2, ... Table Dn] Table D1: [Table Dw, Table Dx, Table Ba, Table Dy, ... ,Table Dz] Table D2: [...] ... Table Dn: [...] Table Dp: [Table B1] Table Dq: [Table B2] Table Dr: [Table B3] ... Table B1: mnemonic, description, units, offset, range Table B2: mnemonic, description, units, offset, range ...

I’m sure anyone knowledgeable with BUFR will cringe at this and likely desire to flame the hell out of me. When I get more time, I’ll try to clean this up.

So, after cracking open the BUFR data file and read the header, how do I parse it such that I can create a dictionary (i.e., a hash array, or “lookup array”) where the key is a Table D descriptor and the values are all of the associated Table B descriptors?

This sounds perfectly suited for a recursive function built with the logic to keep drilling down until it reaches a Table B descriptor and once found, add it to the list.

Setup:

I copied and modified a BUFRLIB subroutine to extract the desired respective table data and put it in a string that would be easily parseable. The format was

MNEMONIC::,sub1,sub2,sub3

Once we have the data back into Python (whew!) I parse each table into it’s own dictionary with the following:

class test_py_bufrlib:

    ta_dict = {}
    tb_dict = {}
    td_dict = {}

    def makedict(self,arr):
        mydict = {}
        for x in arr:
            k,v = x.split('::,')
            mydict[k.strip()] = [x.strip() for x in v.split(',')]
        return mydict

    ...

    self.ta_dict = self.makedict(tbl_a)
    self.td_dict = self.makedict(tbl_d)
    self.tb_dict = self.makedict(tbl_b)

Our data structures are now


{ MNEMONIC_X:['sub1',sub2',...'subN'], MNEMONIC_Y:['sub1',sub2',...'subN'], ... }

Where ‘sub1’, etc. can be either a Table D or Table B descriptor. We then pass the MNEMONIC to the recursive function which then keeps going until it finds all the possible Table B descriptors associated with this particular MNEMONIC.

The function:


    def getbs(self, nemo, blist):
        if nemo in self.tb_dict:
            blist.append(nemo)
        elif nemo in self.td_dict:
            for x in self.td_dict[nemo]:
                self.getbs(x,blist)
        return blist

A few things to note:

  • We have stored the Table A, D, and B data as “global” variables (or in this case, class attributes) that are then accessed within the function.
  • Along with passing in the MNEMONIC, we also pass in a list to store the Table B’s
  • If the MNEMONIC is a key for the Table B dictionary, we store it in the list. Otherwise we check to see if it is a key for the Table D dictionary. (Note: the way that NCEP BUFR Tables work, and how I’ve prepared the data in FORTRAN is that the MNEMONICS should only come from Table D or B. Table A MNEMONICS are actually part of Table D. I didn’t make the rules. I’m just abusing them…)

The function call is like this:

        for a in sorted(self.ta_dict):
            print a + ':'
            for tln in self.ta_dict[a]:
                bs = self.getbs(tln,[])
                print '\t' + tln + ': ', bs

So our table which looked like this:

.------------------------------------------------------------------------------. | ------------ USER DEFINITIONS FOR TABLE-A TABLE-B TABLE D -------------- | |------------------------------------------------------------------------------| | MNEMONIC | NUMBER | DESCRIPTION | |----------|--------|----------------------------------------------------------| | | | | | NC002001 | A63218 | MSG TYPE 002-001 RAWINSONDE - FIXED LAND | | NC002002 | A63219 | MSG TYPE 002-002 RAWINSONDE - MOBIL LAND | | NC002003 | A63220 | MSG TYPE 002-003 RAWINSONDE - SHIP | | NC002004 | A63221 | MSG TYPE 002-004 DROPWINSONDE | | NC002005 | A63222 | MSG TYPE 002-005 PIBAL | | NC002006 | A62207 | MSG TYPE 002-006 OZONESONDE (LOW-RES) (FROM METO BUFR) | | NC002007 | A63223 | MSG TYPE 002-007 NOAA PROFILER NETWORK (NPN) WINDS | | NC002008 | A63224 | MSG TYPE 002-008 NeXRaD VAD WINDS FROM RADAR CODED MSG | | NC002009 | A61200 | MSG TYPE 002-009 PROFILER WINDS IN PILOT(PIBAL) FORMAT | | NC002010 | A61204 | MSG TYPE 002-010 NPN AND MAP PROFILER SPECTRAL MOMENTS | | NC002011 | A52201 | MSG TYPE 002-011 MULTI-AGENCY PROFILER (MAP) WINDS | | NC002012 | A52202 | MSG TYPE 002-012 NPN AND MAP RASS TEMPERATURES | | NC002013 | A52203 | MSG TYPE 002-013 JAPANESE MET AGENCY PROFILER WINDS | | NC002014 | A52205 | MSG TYPE 002-014 HONG KONG PROFILER WINDS | | NC002015 | A62208 | MSG TYPE 002-015 OZONESONDE (HIGH-RES) (FROM ASCII) | | NC002016 | A52206 | MSG TYPE 002-016 EUROPEAN PROFILER WINDS | | NC002017 | A63191 | MSG TYPE 002-017 NeXRaD VAD WINDS FROM LEVEL 2 DECODER | | | | | | WMOBLKST | 301001 | IDENTIFICATION - WMO BLOCK AND STATION NUMBER | | YYMMDD | 301011 | DATE -- YEAR, MONTH, DAY | | HHMM | 301012 | TIME -- HOUR, MINUTE | | LALOLV | 301024 | LOCATION -- LATITUDE, LONGITUDE, ELEVATION | | | | | | OZSNDFLT | 309030 | OZONESONDE FLIGHT DATA | | | | | | BID | 352001 | BULLETIN ID DATA | | RAWRPT | 352002 | RAW REPORT | | RCPTIM | 352003 | REPORT RECEIPT TIME DATA | | | | | | OZONELV1 | 361103 | OZONESONDE REPORT LEVEL DATA #1 | | OZONELV2 | 361104 | OZONESONDE REPORT LEVEL DATA #2 | | | | | | NXVADD2 | 361110 | VAD WIND LEVEL DATA (FROM LEVEL 2 DECODER) | | | | | | UASID | 361121 | RADIOSONDE/OZONESONDE STATION ID DATA | | UARID | 361122 | RADIOSONDE REPORT ID DATA | | UARLV | 361123 | RADIOSONDE REPORT LEVEL DATA | | UATMP | 361125 | RADIOSONDE TEMPERATURE DATA | | UAWND | 361126 | RADIOSONDE WIND DATA | | UAWSH | 361127 | RADIOSONDE WIND SHEAR DATA | | UACLD | 361128 | RADIOSONDE CLOUD DATA | | UASDG | 361129 | RADIOSONDE SOUNDING SYSTEM DATA | | UAADF | 361130 | RADIOSONDE 101AA "ADDITIONAL DATA" DATA | | UARDCS | 361131 | RADIOSONDE REPORT DIAGNOSTIC DATA | | UAGP07 | 361133 | RADIOSONDE CLASS 7 GEOPOTENTIAL DATA | | UAGP10 | 361134 | RADIOSONDE CLASS 10 GEOPOTENTIAL DATA | | | | | | PFLEV | 361162 | PROFILER REPORT LEVEL DATA | | PFLID | 361163 | PROFILER REPORT ID DATA | | | | | | NXVADD | 361170 | NEXRAD PART B WIND LEVEL DATA | | NXRID | 361172 | NEXRAD REPORT ID DATA | | | | | | RTID | 361173 | RASS TEMPERATURE ID DATA | | RTSEQ1 | 361174 | RASS TEMPERATURE SEQUENCE 1 | | | | | | MPSEQ1 | 362241 | MOMENT PROFILE ANTENNA SEQUENCE 1 | | MPSEQ2 | 362242 | MOMENT PROFILE ANTENNA SEQUENCE 2 | | | | | | JPID | 362243 | JAPAN/HONG KONG WIND PROFILER ID DATA | | JPSEQ1 | 362247 | JAPAN/HONG KONG WIND PROFILER SEQUENCE 1 | | | | | | EPSEQ1 | 362250 | EUROPEAN WIND PROFILER SEQUENCE 1 | | | | | | WMOB | 001001 | WMO BLOCK NUMBER | | WMOS | 001002 | WMO STATION NUMBER | | WMOR | 001003 | WMO REGION NUMBER | | BPID | 001005 | BUOY/PLATFORM IDENTIFIER | | SSTN | 001018 | SHORT STATION OR SITE NAME | | UAPART | 001192 | RADIOSONDE PART NAME | | RSML | 001197 | RADIOSONDE SHIP, DROP, OR MOBIL STATION ID | | RPID | 001198 | REPORT IDENTIFIER | | | | | | TOST | 002001 | TYPE OF STATION | | TIWM | 002002 | TYPE OF INSTRUMENTATION FOR WIND MEASUREMENT | | A4ME | 002003 | TYPE OF MEASURING EQUIPMENT USED | | RATP | 002011 | RADIOSONDE TYPE | | SIRC | 002013 | SOLAR AND INFRARED RADIATION CORRECTION | | TTSS | 002014 | TRACKING TECHNIQUE/STATUS OF SYSTEM USED | | ANTYP | 002101 | TYPE OF ANTENNA | | BEAMW | 002106 | 3-DB BEAMWIDTH | | MEFR | 002121 | MEAN FREQUENCY | | ANAZ | 002134 | ANTENNA BEAM AZIMUTH | | ANEL | 002135 | ANTENNA BEAM ELEVATION | | OISN | 002142 | OZONE INSTRUMENT SERIAL NUMBER/IDENTIFICATION | | OITP | 002143 | OZONE INSTRUMENT TYPE | | | | | | YEAR | 004001 | YEAR | | MNTH | 004002 | MONTH | | DAYS | 004003 | DAY | | HOUR | 004004 | HOUR | | MINU | 004005 | MINUTE | | TIMI | 004015 | TIME INCREMENT (SINCE LAUNCH TIME) IN MINUTES | | TPMI | 004025 | TIME PERIOD OR DISPLACEMENT | | TPSE | 004026 | TIME PERIOD OR DISPLACEMENT | | DAYW | 004193 | DAY OF THE WEEK | | RCYR | 004200 | YEAR - TIME OF RECEIPT | | RCMO | 004201 | MONTH - TIME OF RECEIPT | | RCDY | 004202 | DAY - TIME OF RECEIPT | | RCHR | 004203 | HOUR - TIME OF RECEIPT | | RCMI | 004204 | MINUTE - TIME OF RECEIPT | | UALNHR | 004210 | RADIOSONDE LAUNCH HOUR | | UALNMN | 004211 | RADIOSONDE LAUNCH MINUTE | | | | | | CLAT | 005002 | LATITUDE (COARSE ACCURACY) | | | | | | CLON | 006002 | LONGITUDE (COARSE ACCURACY) | | | | | | SELV | 007001 | HEIGHT OF STATION | | PRLC | 007004 | PRESSURE | | HEIT | 007007 | HEIGHT | | GP07 | 007008 | GEOPOTENTIAL | | XMPRLC | 007195 | EXTRAPOLATED MANDATORY LEVEL PRESSURE | | | | | | VSIG | 008001 | VERTICAL SOUNDING SIGNIFICANCE | | OVSS | 008006 | OZONE VERTICAL SOUNDING SIGNIFICANCE | | TSIG | 008021 | TIME SIGNIFICANCE | | ACAV | 008022 | TOTAL NUMBER W/ RESPECT TO ACCUM. OR AVERAGE | | RCTS | 008202 | RECEIPT TIME SIGNIFICANCE | | | | | | GP10 | 010008 | GEOPOTENTIAL | | PMSL | 010051 | PRESSURE AT MEAN SEA LEVEL | | XMGP10 | 010196 | EXTRAPOLATED MANDATORY LEVEL GEOPOTENTIAL | | | | | | WDIR | 011001 | WIND DIRECTION | | WSPD | 011002 | WIND SPEED | | UWND | 011003 | U-COMPONENT OF WIND | | VWND | 011004 | V-COMPONENT OF WIND | | WCMP | 011006 | W COMPONENT | | MWDL | 011044 | MEAN WIND DIRECTION FOR SURFACE-1500M LAYER | | MWSL | 011045 | MEAN WIND SPEED FOR SURFACE-1500M LAYER | | SDHS | 011050 | STANDARD DEVIATION HORIZONTAL WIND SPEED | | SDVS | 011051 | STANDARD DEVIATION VERTICAL WIND SPEED | | AWSB | 011061 | ABSOLUTE WIND SHEAR IN 1 KM LAYER BELOW | | AWSA | 011062 | ABSOLUTE WIND SHEAR IN 1 KM LAYER ABOVE | | WDIR1 | 011200 | SURFACE WIND DIRECTION | | WSPD1 | 011201 | SURFACE WIND SPEED | | RMSW | 011210 | ROOT MEAN SQUARE VECTOR WIND ERROR | | MWDH | 011221 | MEAN WIND DIRECTION FOR 1500M-3000M LAYER | | MWSH | 011222 | MEAN WIND SPEED FOR 1500M-3000M LAYER | | | | | | TMDB | 012101 | TEMPERATURE/DRY BULB TEMPERATURE | | TMDP | 012103 | DEW POINT TEMPERATURE | | TMVR | 012107 | VIRTUAL TEMPERATURE | | | | | | REHU | 013003 | RELATIVE HUMIDITY | | STBS5 | 013195 | MODIFIED SHOWALTER STABILITY INDEX | | | | | | MOPP | 015003 | MEASURED OZONE PARTIAL PRESSURE (SOUNDING) | | OSCF | 015004 | OZONE SOUNDING CORRECTION FACTOR | | OZOP | 015005 | OZONE P | | OZMR | 015192 | OZONE MIXING RATIO | | | | | | CLAM | 020011 | CLOUD AMOUNT | | CLTP | 020012 | CLOUD TYPE | | HBLCS | 020201 | HEIGHT ABOVE SURFACE OF BASE OF LOWEST CLOUD SEEN | | | | | | DMVR | 021014 | DOPPLER MEAN VELOCITY (RADIAL) | | DVSW | 021017 | DOPPLER VELOCITY SPECTRAL WIDTH | | STNR | 021030 | SIGNAL TO NOISE RATIO | | SPP0 | 021091 | RADAR SIGNAL DOPPLER SPECTRUM 0TH MOMENT | | | | | | SST1 | 022043 | SEA TEMPERATURE | | | | | | RAGL | 025001 | RANGE-GATE LENGTH | | MSPE | 025020 | MEAN SPEED ESTIMATION | | WICE | 025021 | WIND COMPUTATION ENHANCEMENT | | NPQC | 025034 | NOAA WIND PROFILER Q/C TEST RESULTS | | | | | | QMRK | 033002 | QUALITY INFORMATION | | QCEVR | 033024 | STATION ELEVATION QUALITY MARK (FOR MOBIL STATIONS) | | QMGP | 033192 | SDMEDIT QUALITY MARK FOR GEOPOTENTIAL | | QMAT | 033193 | SDMEDIT QUALITY MARK FOR TEMPERATURE | | QMDD | 033194 | SDMEDIT QUALITY MARK FOR MOISTURE | | QMWN | 033195 | SDMEDIT QUALITY MARK FOR WIND | | UARDC | 033202 | RADIOSONDE REPORT DIAGNOSTIC CODE | | QMPR | 033207 | SDMEDIT QUALITY MARK FOR PRESSURE | | CORN | 033215 | CORRECTED REPORT INDICATOR | | QMST | 033218 | SDMEDIT QUALITY MARK FOR SEA SURFACE TEMPERATURE | | QFV2 | 033229 | QUALITY FLAG FOR VAD WINDS GENERATED FROM LVL 2 DECODER | | | | | | BUHD | 035021 | BULLETIN BEING MONITORED (TTAAii) | | BULTIM | 035022 | BULLETIN BEING MONITORED (YYGGgg) | | BORG | 035023 | BULLETIN BEING MONITORED (CCCC) | | BBB | 035194 | BULLETIN BEING MONITORED (BBB) | | SEQNUM | 035195 | CHANNEL SEQUENCE NUMBER | | | | | | RRSTG | 058008 | RAW REPORT STRING | | | | | |------------------------------------------------------------------------------| | MNEMONIC | SEQUENCE | |----------|-------------------------------------------------------------------| | | | | NC002001 | YYMMDD HOUR {RCPTIM} {BID} UASID {UARID} | | NC002001 | {UARLV} {UARDCS} {RAWRPT} | | NC002001 | {UACLD} | | NC002001 | WMOB WMOS WMOR | | | | | NC002002 | YYMMDD HOUR {RCPTIM} {BID} UASID {UARID} | | NC002002 | {UARLV} {UARDCS} {RAWRPT} | | NC002002 | {UACLD} | | NC002002 | RSML QCEVR | | | | | NC002003 | YYMMDD HOUR {RCPTIM} {BID} UASID {UARID} | | NC002003 | {UARLV} {UARDCS} {RAWRPT} | | NC002003 | {UACLD} | | NC002003 | RSML WMOR | | | | | NC002004 | YYMMDD HOUR {RCPTIM} {BID} UASID {UARID} | | NC002004 | {UARLV} {UARDCS} {RAWRPT} | | NC002004 | | | NC002004 | RSML WMOR | | | | | NC002005 | YYMMDD HOUR {RCPTIM} {BID} UASID {UARID} | | NC002005 | {UARLV} {UARDCS} {RAWRPT} | | NC002005 | {UACLD} | | NC002005 | RSML QCEVR WMOB WMOS WMOR | | | | | NC002006 | WMOBLKST BPID LALOLV TSIG YYMMDD HHMM | | NC002006 | RATP OITP OISN OZSNDFLT | | | | | NC002007 | YYMMDD HHMM RCPTIM BID PFLID | | NC002007 | TSIG TPSE {PFLEV} | | | | | NC002008 | YYMMDD HHMM RCPTIM BID NXRID {NXVADD} {RAWRPT} | | | | | NC002009 | YYMMDD HOUR {RCPTIM} {BID} UASID {UARID} | | NC002009 | {UARLV} {UARDCS} {RAWRPT} | | NC002009 | {UACLD} | | NC002009 | RSML QCEVR WMOB WMOS WMOR | | | | | NC002010 | YYMMDD HHMM RCPTIM BID PFLID | | NC002010 | TSIG TPSE {MPSEQ1} | | | | | NC002011 | YYMMDD HHMM RCPTIM BID PFLID | | NC002011 | TSIG TPSE {PFLEV} | | | | | NC002012 | YYMMDD HHMM RCPTIM BID RTID | | NC002012 | TSIG TPSE {RTSEQ1} | | | | | NC002013 | YYMMDD HHMM RCPTIM BID JPID | | NC002013 | TSIG TPMI {JPSEQ1} | | | | | NC002014 | YYMMDD HHMM RCPTIM BID JPID | | NC002014 | TSIG TPMI {JPSEQ1} | | | | | NC002015 | TSIG YYMMDD HHMM UASID (OZONELV2) | | | | | NC002016 | YYMMDD HHMM RCPTIM BID CORN WMOBLKST LALOLV | | NC002016 | 201130 BEAMW 201000 | | NC002016 | 201133 202129 RAGL 202000 201000 | | NC002016 | 201149 202135 MEFR 202000 201000 | | NC002016 | TOST A4ME ANTYP MSPE WICE TSIG TPMI {EPSEQ1} | | | | | NC002017 | YYMMDD HHMM NXRID {NXVADD2} | | | | | BID | SEQNUM BUHD BORG BULTIM BBB | | | | | RAWRPT | RRSTG | | | | | RCPTIM | RCTS RCYR RCMO RCDY RCHR RCMI | | | | | UASID | RPID CLAT CLON SELV | | | | | UARID | RATP A4ME CORN UAPART TIWM | | | | | UARLV | VSIG QMPR PRLC QMGP | | UARLV | | | | | | UAGP07 | GP07 | | | | | UAGP10 | GP10 | | | | | UATMP | QMAT TMDB QMDD TMDP | | | | | UAWND | QMWN WDIR WSPD | | | | | UAWSH | AWSB AWSA | | | | | UACLD | CLTP CLAM HBLCS | | | | | UASDG | QMST SST1 SIRC TTSS UALNHR UALNMN | | | | | UAADF | MWDL MWSL MWDH MWSH STBS5 XMPRLC XMGP10 | | | | | UARDCS | UARDC | | | | | PFLID | WMOB WMOS RPID TOST SSTN A4ME | | PFLID | 201132 202130 MEFR 202000 201000 | | PFLID | CLAT CLON SELV CORN | | | | | PFLEV | HEIT NPQC | | PFLEV | QMWN WDIR WSPD SDHS | | PFLEV | WCMP SDVS | | | | | NXVADD | HEIT QMWN WDIR WSPD RMSW | | | | | NXVADD2 | HEIT QMWN UWND VWND QFV2 | | | | | NXRID | RPID CORN CLAT CLON SELV | | | | | MPSEQ1 | ANAZ ANEL {MPSEQ2} | | | | | MPSEQ2 | HEIT NPQC ACAV SPP0 STNR 202129 DMVR | | MPSEQ2 | 201132 DVSW 201000 202000 | | | | | RTID | WMOB WMOS RPID TOST SSTN A4ME | | RTID | CLAT CLON SELV CORN | | | | | RTSEQ1 | HEIT QMAT TMVR NPQC | | | | | JPID | WMOB WMOS RPID A4ME | | JPID | CLAT CLON SELV CORN | | | | | JPSEQ1 | HEIT QMRK QMWN WDIR WSPD WCMP STNR | | | | | EPSEQ1 | HEIT QMRK QMWN WDIR WSPD QMRK WCMP STNR | | | | | OZSNDFLT | OSCF OZOP {OZONELV1} | | | | | WMOBLKST | WMOB WMOS | | | | | YYMMDD | YEAR MNTH DAYS | | | | | HHMM | HOUR MINU | | | | | LALOLV | CLAT CLON SELV | | | | | OZONELV1 | TIMI OVSS PRLC MOPP | | | | | OZONELV2 | 201131 202130 TPMI 202000 202129 PRLC 202000 201000 | | OZONELV2 | HEIT TMDB 201132 202129 REHU 202000 201000 | | OZONELV2 | 201133 202130 MOPP 202000 201000 OZMR WDIR WSPD GP07 | | | | |------------------------------------------------------------------------------| | MNEMONIC | SCAL | REFERENCE | BIT | UNITS |-------------| |----------|------|-------------|-----|--------------------------|-------------| | | | | | |-------------| | WMOB | 0 | 0 | 7 | NUMERIC |-------------| | WMOS | 0 | 0 | 10 | NUMERIC |-------------| | WMOR | 0 | 0 | 3 | CODE TABLE |-------------| | BPID | 0 | 0 | 17 | NUMERIC |-------------| | SSTN | 0 | 0 | 40 | CCITT IA5 |-------------| | UAPART | 0 | 0 | 32 | CCITT IA5 |-------------| | BUHD | 0 | 0 | 48 | CCITT IA5 |-------------| | RSML | 0 | 0 | 64 | CCITT IA5 |-------------| | RPID | 0 | 0 | 64 | CCITT IA5 |-------------| | TOST | 0 | 0 | 2 | CODE TABLE |-------------| | A4ME | 0 | 0 | 4 | CODE TABLE |-------------| | RATP | 0 | 0 | 8 | CODE TABLE |-------------| | SIRC | 0 | 0 | 4 | CODE TABLE |-------------| | TTSS | 0 | 0 | 7 | CODE TABLE |-------------| | ANTYP | 0 | 0 | 4 | CODE TABLE |-------------| | BEAMW | 1 | 0 | 6 | DEGREES |-------------| | MEFR | -8 | 0 | 7 | HZ |-------------| | ANAZ | 2 | 0 | 16 | DEGREE |-------------| | ANEL | 2 | -9000 | 15 | DEGREE |-------------| | OISN | 0 | 0 | 32 | CCITT IA5 |-------------| | OITP | 0 | 0 | 7 | CODE TABLE |-------------| | SEQNUM | 0 | 0 | 32 | CCITT IA5 |-------------| | BORG | 0 | 0 | 32 | CCITT IA5 |-------------| | TIWM | 0 | 0 | 4 | FLAG TABLE |-------------| | YEAR | 0 | 0 | 12 | YEAR |-------------| | MNTH | 0 | 0 | 4 | MONTH |-------------| | DAYS | 0 | 0 | 6 | DAY |-------------| | HOUR | 0 | 0 | 5 | HOUR |-------------| | MINU | 0 | 0 | 6 | MINUTE |-------------| | TIMI | 0 | -2048 | 12 | MINUTES |-------------| | TPMI | 0 | -2048 | 12 | MINUTES |-------------| | TPSE | 0 | -4096 | 13 | SECONDS |-------------| | DAYW | 0 | 0 | 3 | CODE TABLE |-------------| | RCYR | 0 | 0 | 12 | YEAR |-------------| | RCMO | 0 | 0 | 4 | MONTH |-------------| | RCDY | 0 | 0 | 6 | DAY |-------------| | RCHR | 0 | 0 | 5 | HOUR |-------------| | RCMI | 0 | 0 | 6 | MINUTE |-------------| | UALNHR | 0 | 0 | 5 | HOUR |-------------| | UALNMN | 0 | 0 | 6 | MINUTE |-------------| | CLAT | 2 | -9000 | 15 | DEGREES |-------------| | CLON | 2 | -18000 | 16 | DEGREES |-------------| | SELV | 0 | -400 | 15 | METERS |-------------| | PRLC | -1 | 0 | 14 | PASCALS |-------------| | HEIT | 0 | -1000 | 17 | METERS |-------------| | GP07 | 0 | -10000 | 20 | (METERS/SECOND)**2 |-------------| | XMPRLC | -1 | 0 | 14 | PASCALS |-------------| | VSIG | 0 | 0 | 7 | FLAG TABLE |-------------| | OVSS | 0 | 0 | 9 | FLAG TABLE |-------------| | TSIG | 0 | 0 | 5 | CODE TABLE |-------------| | ACAV | 0 | 0 | 16 | NUMERIC |-------------| | RCTS | 0 | 0 | 6 | CODE TABLE |-------------| | GP10 | 0 | -10000 | 20 | (METERS/SECOND)**2 |-------------| | PMSL | -1 | 0 | 14 | PASCALS |-------------| | XMGP10 | 0 | -10000 | 20 | (METERS/SECOND)**2 |-------------| | WDIR | 0 | 0 | 9 | DEGREES TRUE |-------------| | WSPD | 1 | 0 | 12 | METERS/SECOND |-------------| | UWND | 1 | -4096 | 13 | METERS/SECOND |-------------| | VWND | 1 | -4096 | 13 | METERS/SECOND |-------------| | WCMP | 2 | -4096 | 13 | METERS/SECOND |-------------| | MWDL | 0 | 0 | 9 | DEGREES TRUE |-------------| | MWSL | 1 | 0 | 12 | METERS/SECOND |-------------| | SDHS | 1 | 0 | 12 | METERS/SECOND |-------------| | SDVS | 1 | 0 | 8 | METERS/SECOND |-------------| | AWSB | 1 | 0 | 12 | METERS/SECOND |-------------| | AWSA | 1 | 0 | 12 | METERS/SECOND |-------------| | WDIR1 | 0 | 0 | 9 | DEGREES TRUE |-------------| | WSPD1 | 1 | 0 | 12 | METERS/SECOND |-------------| | RMSW | 1 | 0 | 12 | METERS/SECOND |-------------| | MWDH | 0 | 0 | 9 | DEGREES TRUE |-------------| | MWSH | 1 | 0 | 12 | METERS/SECOND |-------------| | TMDB | 2 | 0 | 16 | DEGREES KELVIN |-------------| | TMDP | 2 | 0 | 16 | DEGREES KELVIN |-------------| | TMVR | 2 | 0 | 16 | DEGREES KELVIN |-------------| | REHU | 0 | 0 | 7 | % |-------------| | STBS5 | 0 | -40 | 8 | NUMERIC |-------------| | MOPP | 4 | 0 | 9 | PA |-------------| | OSCF | 3 | 0 | 11 | NUMERIC |-------------| | OZOP | 0 | 0 | 10 | DU |-------------| | OZMR | 4 | 0 | 17 | CM**3/M**3 |-------------| | CLAM | 0 | 0 | 4 | CODE TABLE |-------------| | CLTP | 0 | 0 | 6 | CODE TABLE |-------------| | HBLCS | 0 | 0 | 4 | CODE TABLE |-------------| | DMVR | 1 | -4096 | 13 | M/S |-------------| | DVSW | 1 | 0 | 8 | M/S |-------------| | SPP0 | 0 | -100 | 8 | DB |-------------| | STNR | 0 | -32 | 8 | DB |-------------| | SST1 | 2 | 0 | 15 | DEGREES KELVIN |-------------| | RAGL | -1 | 0 | 6 | METERS |-------------| | MSPE | 0 | 0 | 2 | CODE TABLE |-------------| | WICE | 0 | 0 | 8 | FLAG TABLE |-------------| | NPQC | 0 | 0 | 4 | FLAG TABLE |-------------| | QCEVR | 0 | 0 | 4 | CODE TABLE |-------------| | QMGP | 0 | 0 | 4 | CODE TABLE |-------------| | QMAT | 0 | 0 | 4 | CODE TABLE |-------------| | QMDD | 0 | 0 | 4 | CODE TABLE |-------------| | QMWN | 0 | 0 | 4 | CODE TABLE |-------------| | UARDC | 0 | 0 | 8 | CODE TABLE |-------------| | QMPR | 0 | 0 | 4 | CODE TABLE |-------------| | QMRK | 0 | 0 | 2 | CODE TABLE |-------------| | QMST | 0 | 0 | 4 | CODE TABLE |-------------| | QFV2 | 0 | 0 | 2 | CODE TABLE |-------------| | CORN | 0 | 0 | 3 | CODE TABLE |-------------| | BULTIM | 0 | 0 | 48 | CCITT IA5 |-------------| | BBB | 0 | 0 | 48 | CCITT IA5 |-------------| | RRSTG | 0 | 0 | 64 | CCITT IA5 |-------------| | | | | | |-------------| `------------------------------------------------------------------------------'

Is now parsed to look like this:

NC002001: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HOUR: ['HOUR'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] UASID: ['RPID', 'CLAT', 'CLON', 'SELV'] UARID: ['RATP', 'A4ME', 'CORN', 'UAPART', 'TIWM'] UARLV: ['VSIG', 'QMPR', 'PRLC', 'QMGP', 'GP07', 'GP10', 'QMAT', 'TMDB', 'QMDD', 'TMDP', 'QMWN', 'WDIR', 'WSPD', 'AWSB', 'AWSA'] UASDG: ['QMST', 'SST1', 'SIRC', 'TTSS', 'UALNHR', 'UALNMN'] UARDCS: ['UARDC'] RAWRPT: ['RRSTG'] UACLD: ['CLTP', 'CLAM', 'HBLCS'] UAADF: ['MWDL', 'MWSL', 'MWDH', 'MWSH', 'STBS5', 'XMPRLC', 'XMGP10'] WMOB: ['WMOB'] WMOS: ['WMOS'] WMOR: ['WMOR'] NC002002: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HOUR: ['HOUR'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] UASID: ['RPID', 'CLAT', 'CLON', 'SELV'] UARID: ['RATP', 'A4ME', 'CORN', 'UAPART', 'TIWM'] UARLV: ['VSIG', 'QMPR', 'PRLC', 'QMGP', 'GP07', 'GP10', 'QMAT', 'TMDB', 'QMDD', 'TMDP', 'QMWN', 'WDIR', 'WSPD', 'AWSB', 'AWSA'] UASDG: ['QMST', 'SST1', 'SIRC', 'TTSS', 'UALNHR', 'UALNMN'] UARDCS: ['UARDC'] RAWRPT: ['RRSTG'] UACLD: ['CLTP', 'CLAM', 'HBLCS'] RSML: ['RSML'] QCEVR: ['QCEVR'] NC002003: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HOUR: ['HOUR'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] UASID: ['RPID', 'CLAT', 'CLON', 'SELV'] UARID: ['RATP', 'A4ME', 'CORN', 'UAPART', 'TIWM'] UARLV: ['VSIG', 'QMPR', 'PRLC', 'QMGP', 'GP07', 'GP10', 'QMAT', 'TMDB', 'QMDD', 'TMDP', 'QMWN', 'WDIR', 'WSPD', 'AWSB', 'AWSA'] UASDG: ['QMST', 'SST1', 'SIRC', 'TTSS', 'UALNHR', 'UALNMN'] UARDCS: ['UARDC'] RAWRPT: ['RRSTG'] UACLD: ['CLTP', 'CLAM', 'HBLCS'] UAADF: ['MWDL', 'MWSL', 'MWDH', 'MWSH', 'STBS5', 'XMPRLC', 'XMGP10'] RSML: ['RSML'] WMOR: ['WMOR'] NC002004: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HOUR: ['HOUR'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] UASID: ['RPID', 'CLAT', 'CLON', 'SELV'] UARID: ['RATP', 'A4ME', 'CORN', 'UAPART', 'TIWM'] UARLV: ['VSIG', 'QMPR', 'PRLC', 'QMGP', 'GP07', 'GP10', 'QMAT', 'TMDB', 'QMDD', 'TMDP', 'QMWN', 'WDIR', 'WSPD', 'AWSB', 'AWSA'] UASDG: ['QMST', 'SST1', 'SIRC', 'TTSS', 'UALNHR', 'UALNMN'] UARDCS: ['UARDC'] RAWRPT: ['RRSTG'] UAADF: ['MWDL', 'MWSL', 'MWDH', 'MWSH', 'STBS5', 'XMPRLC', 'XMGP10'] RSML: ['RSML'] WMOR: ['WMOR'] NC002005: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HOUR: ['HOUR'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] UASID: ['RPID', 'CLAT', 'CLON', 'SELV'] UARID: ['RATP', 'A4ME', 'CORN', 'UAPART', 'TIWM'] UARLV: ['VSIG', 'QMPR', 'PRLC', 'QMGP', 'GP07', 'GP10', 'QMAT', 'TMDB', 'QMDD', 'TMDP', 'QMWN', 'WDIR', 'WSPD', 'AWSB', 'AWSA'] UASDG: ['QMST', 'SST1', 'SIRC', 'TTSS', 'UALNHR', 'UALNMN'] UARDCS: ['UARDC'] RAWRPT: ['RRSTG'] UACLD: ['CLTP', 'CLAM', 'HBLCS'] UAADF: ['MWDL', 'MWSL', 'MWDH', 'MWSH', 'STBS5', 'XMPRLC', 'XMGP10'] RSML: ['RSML'] QCEVR: ['QCEVR'] WMOB: ['WMOB'] WMOS: ['WMOS'] WMOR: ['WMOR'] NC002006: WMOBLKST: ['WMOB', 'WMOS'] BPID: ['BPID'] LALOLV: ['CLAT', 'CLON', 'SELV'] TSIG: ['TSIG'] YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RATP: ['RATP'] OITP: ['OITP'] OISN: ['OISN'] OZSNDFLT: ['OSCF', 'OZOP', 'TIMI', 'OVSS', 'PRLC', 'MOPP'] NC002007: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] PFLID: ['WMOB', 'WMOS', 'RPID', 'TOST', 'SSTN', 'A4ME', 'MEFR', 'CLAT', 'CLON', 'SELV', 'CORN'] TSIG: ['TSIG'] TPSE: ['TPSE'] PFLEV: ['HEIT', 'NPQC', 'QMWN', 'WDIR', 'WSPD', 'SDHS', 'WCMP', 'SDVS'] NC002008: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] NXRID: ['RPID', 'CORN', 'CLAT', 'CLON', 'SELV'] NXVADD: ['HEIT', 'QMWN', 'WDIR', 'WSPD', 'RMSW'] RAWRPT: ['RRSTG'] NC002009: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HOUR: ['HOUR'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] UASID: ['RPID', 'CLAT', 'CLON', 'SELV'] UARID: ['RATP', 'A4ME', 'CORN', 'UAPART', 'TIWM'] UARLV: ['VSIG', 'QMPR', 'PRLC', 'QMGP', 'GP07', 'GP10', 'QMAT', 'TMDB', 'QMDD', 'TMDP', 'QMWN', 'WDIR', 'WSPD', 'AWSB', 'AWSA'] UASDG: ['QMST', 'SST1', 'SIRC', 'TTSS', 'UALNHR', 'UALNMN'] UARDCS: ['UARDC'] RAWRPT: ['RRSTG'] UACLD: ['CLTP', 'CLAM', 'HBLCS'] UAADF: ['MWDL', 'MWSL', 'MWDH', 'MWSH', 'STBS5', 'XMPRLC', 'XMGP10'] RSML: ['RSML'] QCEVR: ['QCEVR'] WMOB: ['WMOB'] WMOS: ['WMOS'] WMOR: ['WMOR'] NC002010: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] PFLID: ['WMOB', 'WMOS', 'RPID', 'TOST', 'SSTN', 'A4ME', 'MEFR', 'CLAT', 'CLON', 'SELV', 'CORN'] TSIG: ['TSIG'] TPSE: ['TPSE'] MPSEQ1: ['ANAZ', 'ANEL', 'HEIT', 'NPQC', 'ACAV', 'SPP0', 'STNR', 'DMVR', 'DVSW'] NC002011: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] PFLID: ['WMOB', 'WMOS', 'RPID', 'TOST', 'SSTN', 'A4ME', 'MEFR', 'CLAT', 'CLON', 'SELV', 'CORN'] TSIG: ['TSIG'] TPSE: ['TPSE'] PFLEV: ['HEIT', 'NPQC', 'QMWN', 'WDIR', 'WSPD', 'SDHS', 'WCMP', 'SDVS'] NC002012: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] RTID: ['WMOB', 'WMOS', 'RPID', 'TOST', 'SSTN', 'A4ME', 'CLAT', 'CLON', 'SELV', 'CORN'] TSIG: ['TSIG'] TPSE: ['TPSE'] RTSEQ1: ['HEIT', 'QMAT', 'TMVR', 'NPQC'] NC002013: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] JPID: ['WMOB', 'WMOS', 'RPID', 'A4ME', 'CLAT', 'CLON', 'SELV', 'CORN'] TSIG: ['TSIG'] TPMI: ['TPMI'] JPSEQ1: ['HEIT', 'QMRK', 'QMWN', 'WDIR', 'WSPD', 'WCMP', 'STNR'] NC002014: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] JPID: ['WMOB', 'WMOS', 'RPID', 'A4ME', 'CLAT', 'CLON', 'SELV', 'CORN'] TSIG: ['TSIG'] TPMI: ['TPMI'] JPSEQ1: ['HEIT', 'QMRK', 'QMWN', 'WDIR', 'WSPD', 'WCMP', 'STNR'] NC002015: TSIG: ['TSIG'] YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] UASID: ['RPID', 'CLAT', 'CLON', 'SELV'] OZONELV2: ['TPMI', 'PRLC', 'HEIT', 'TMDB', 'REHU', 'MOPP', 'OZMR', 'WDIR', 'WSPD', 'GP07'] NC002016: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] RCPTIM: ['RCTS', 'RCYR', 'RCMO', 'RCDY', 'RCHR', 'RCMI'] BID: ['SEQNUM', 'BUHD', 'BORG', 'BULTIM', 'BBB'] CORN: ['CORN'] WMOBLKST: ['WMOB', 'WMOS'] LALOLV: ['CLAT', 'CLON', 'SELV'] 201130: [] BEAMW: ['BEAMW'] 201000: [] 201133: [] 202129: [] RAGL: ['RAGL'] 202000: [] 201000: [] 201149: [] 202135: [] MEFR: ['MEFR'] 202000: [] 201000: [] TOST: ['TOST'] A4ME: ['A4ME'] ANTYP: ['ANTYP'] MSPE: ['MSPE'] WICE: ['WICE'] TSIG: ['TSIG'] TPMI: ['TPMI'] EPSEQ1: ['HEIT', 'QMRK', 'QMWN', 'WDIR', 'WSPD', 'QMRK', 'WCMP', 'STNR'] NC002017: YYMMDD: ['YEAR', 'MNTH', 'DAYS'] HHMM: ['HOUR', 'MINU'] NXRID: ['RPID', 'CORN', 'CLAT', 'CLON', 'SELV'] NXVADD2: ['HEIT', 'QMWN', 'UWND', 'VWND', 'QFV2']

See that even if we encounter a Table B in the recursion, it is included. Also, note that we do run into instances where the “MNEMONIC” is unavailable because it is not really a MNEMONIC. For example, the numbers listed under NC002016 represent a type of replication.

Anyway. I know I have a lot of cleaning up of this post to do, but hopefully this is useful to someone.

Leave a Comment

Your email address will not be published. Required fields are marked *