├── .github └── workflows │ └── ci.yml ├── .gitignore ├── Dockerfile ├── LICENSE ├── MANIFEST.in ├── README.rst ├── docs ├── Makefile ├── Notes.md ├── api.rst ├── conf.py ├── index.rst ├── internals.rst └── make.bat ├── pybufrkit ├── __init__.py ├── __main__.py ├── bitops.py ├── bufr.py ├── coder.py ├── commands.py ├── constants.py ├── dataprocessor.py ├── dataquery.py ├── decoder.py ├── definitions │ ├── section0.json │ ├── section1-1.json │ ├── section1-2.json │ ├── section1-3.json │ ├── section1-4.json │ ├── section2.json │ ├── section3.json │ ├── section4.json │ └── section5.json ├── descriptors.py ├── encoder.py ├── errors.py ├── mdquery.py ├── query.py ├── renderer.py ├── script.py ├── tables.py ├── tables │ └── 0 │ │ ├── 0_0 │ │ ├── 6 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 7 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 8 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 9 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 10 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 11 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 12 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 13 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 14 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 15 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 16 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 17 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 18 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 19 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 20 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 21 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 22 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 23 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 24 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 25 │ │ │ ├── MetaA.json │ │ │ ├── MetaB.json │ │ │ ├── MetaC.json │ │ │ ├── MetaD.json │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 26 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 27 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 28 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 29 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 30 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 31 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 32 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 33 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 34 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 35 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 36 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 37 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 38 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 39 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 40 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 41 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ ├── 42 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ └── 43 │ │ │ ├── TableB.json │ │ │ ├── TableD.json │ │ │ └── code_and_flag.json │ │ └── 98_0 │ │ ├── 1 │ │ ├── TableB.json │ │ ├── TableD.json │ │ └── code_and_flag.json │ │ ├── 2 │ │ ├── TableB.json │ │ ├── TableD.json │ │ └── code_and_flag.json │ │ ├── 3 │ │ ├── TableB.json │ │ ├── TableD.json │ │ └── code_and_flag.json │ │ └── 101 │ │ ├── TableB.json │ │ ├── TableD.json │ │ └── code_and_flag.json ├── tablespreparer.py ├── templatecompiler.py ├── templatedata.py └── utils.py ├── setup.cfg ├── setup.py └── tests ├── benchmark_data ├── ISMD01_OKPR.bufr ├── ISND02_LLBD.bufr ├── IUSD40_OKLI.bufr ├── aaen_55.bufr ├── aben_55.bufr ├── ahws_139.bufr ├── airc_142.bufr ├── airc_144.bufr ├── airs_57.bufr ├── alws_139.bufr ├── amda_144.bufr ├── amsa_55.bufr ├── amsb_55.bufr ├── amse_55.bufr ├── amsu_55.bufr ├── amv2_87.bufr ├── amv3_87.bufr ├── asbh_139.bufr ├── asbl_139.bufr ├── asca_139.bufr ├── asch_139.bufr ├── ascs_139.bufr ├── aseh_139.bufr ├── asel_139.bufr ├── ashs_139.bufr ├── asr3_190.bufr ├── atap_55.bufr ├── ateu_155.bufr ├── atms_201.bufr ├── atov_55.bufr ├── avhm_87.bufr ├── avhn_87.bufr ├── avhr_58.bufr ├── b002_95.bufr ├── b002_96.bufr ├── b003_56.bufr ├── b004_145.bufr ├── b005_87.bufr ├── b005_89.bufr ├── b006_96.bufr ├── b007_31.bufr ├── bssh_170.bufr ├── bssh_176.bufr ├── bssh_178.bufr ├── bssh_180.bufr ├── btem_109.bufr ├── btem_111.bufr ├── buoy_27.bufr ├── cmwi_87.bufr ├── cmwn_87.bufr ├── cnow_28.bufr ├── cori_156.bufr ├── crex_7.bufr ├── crit_202.bufr ├── csrh_189.bufr ├── emsg_189.bufr ├── emsg_87.bufr ├── euwv_87.bufr ├── fy3a_154.bufr ├── fy3b_154.bufr ├── g2nd_208.bufr ├── g2to_206.bufr ├── go15_87.bufr ├── goee_87.bufr ├── goes_87.bufr ├── goga_89.bufr ├── grst_26.bufr ├── gsd1_208.bufr ├── gsd2_208.bufr ├── gsd3_208.bufr ├── gst4_26.bufr ├── hirb_55.bufr ├── hirs_55.bufr ├── ias1_240.bufr ├── iasi_241.bufr ├── ifco_208.bufr ├── ikco_217.bufr ├── itrg_208.bufr ├── itwt_233.bufr ├── j2eo_216.bufr ├── j2nb_216.bufr ├── jaso_214.bufr ├── jason2.bufr ├── kond_209.bufr ├── maer_207.bufr ├── masr_190.bufr ├── meta_140.bufr ├── mhen_55.bufr ├── mhsa_55.bufr ├── mhsb_55.bufr ├── mhse_55.bufr ├── mloz_206.bufr ├── modi_87.bufr ├── modw_87.bufr ├── monw_87.bufr ├── mpco_217.bufr ├── nomi_206.bufr ├── nos1_208.bufr ├── nos2_208.bufr ├── nos3_208.bufr ├── nos4_208.bufr ├── nos5_208.bufr ├── nos6_208.bufr ├── nos7_208.bufr ├── nos8_208.bufr ├── ocea_131.bufr ├── ocea_132.bufr ├── ocea_133.bufr ├── ocea_21.bufr ├── pgps_110.bufr ├── pilo_91.bufr ├── rada_250.bufr ├── rado_250.bufr ├── s4kn_165.bufr ├── sato_84.bufr ├── sb19_206.bufr ├── sbu8_206.bufr ├── sentinel1.bufr ├── ship_11.bufr ├── ship_12.bufr ├── ship_13.bufr ├── ship_14.bufr ├── ship_19.bufr ├── ship_9.bufr ├── smin_49.bufr ├── smis_49.bufr ├── smiu_49.bufr ├── smos_203.bufr ├── sn4k_165.bufr ├── soil_7.bufr ├── ssbt_127.bufr ├── stuk_7.bufr ├── syno_1.bufr ├── syno_2.bufr ├── syno_3.bufr ├── syno_4.bufr ├── temp_101.bufr ├── temp_102.bufr ├── temp_106.bufr ├── tmr7_129.bufr ├── tros_31.bufr └── wavb_134.bufr ├── data ├── 207003.bufr ├── 207003.datadump.cmp ├── 207003.json ├── 207003.values.cmp ├── ISMD01_OKPR.bufr ├── ISMD01_OKPR.json ├── ISMD01_OKPR.values.cmp ├── IUSK73_AMMC_040000.bufr ├── IUSK73_AMMC_182300.bufr ├── IUSK73_AMMC_182300.json ├── IUSK73_AMMC_182300.values.cmp ├── JUBE99_EGRR.bufr ├── amv2_87.bufr ├── amv2_87.json ├── amv2_87.values.cmp ├── asr3_190.bufr ├── asr3_190.json ├── asr3_190.values.cmp ├── b002_95.bufr ├── b002_95.json ├── b002_95.values.cmp ├── b005_89.bufr ├── b005_89.json ├── b005_89.values.cmp ├── contrived.bufr ├── g2nd_208.bufr ├── g2nd_208.json ├── g2nd_208.values.cmp ├── jaso_214.bufr ├── jaso_214.json ├── jaso_214.values.cmp ├── mpco_217.bufr ├── mpco_217.json ├── mpco_217.values.cmp ├── multi_invalid_messages.bufr ├── ncep.352.bufr ├── prepbufr.bufr ├── profiler_european.bufr ├── profiler_european.json ├── profiler_european.values.cmp ├── rado_250.bufr ├── rado_250.datadump.cmp ├── rado_250.json ├── rado_250.values.cmp ├── uegabe.bufr ├── uegabe.json └── uegabe.values.cmp ├── test_Benchmark.py ├── test_Decoder.py ├── test_Encoder.py ├── test_Encoder_arguments.py ├── test_NodePathParser.py ├── test_Tables.py ├── test_TemplateCompiler.py ├── test_TemplateData.py ├── test_bufr.py ├── test_commands.py ├── test_dataquery.py ├── test_generate_message.py ├── test_mdquery.py ├── test_mismatched_bitmap.py ├── test_nodepath.py ├── test_optional_parameter.py ├── test_optional_parameter_v2_even.py ├── test_optional_parameter_v2_odd.py ├── test_prepbufr.py ├── test_script.py ├── test_tablespreparer.py ├── test_utils.py └── test_value_255_for_031001.py /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python 2 | name: ci 3 | on: 4 | push: 5 | branches: 6 | - master 7 | pull_request: 8 | branches: 9 | - master 10 | jobs: 11 | ci: 12 | runs-on: ubuntu-latest 13 | strategy: 14 | fail-fast: false 15 | max-parallel: 6 16 | matrix: 17 | python-version: ["3.8", "3.9", "3.10", "3.11", "pypy-3.9"] 18 | steps: 19 | - uses: actions/checkout@v3 20 | - uses: actions/setup-python@v4 21 | with: 22 | python-version: ${{ matrix.python-version }} 23 | - run: pip install --upgrade pip 24 | - if: ${{ matrix.python-version }} == "3.11" 25 | run: pip install ruff && ruff check --output-format=github --ignore=E501 --target-version=py37 . 26 | - run: pip install pytest . 27 | - run: pytest 28 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | 5 | # C extensions 6 | *.so 7 | 8 | # Distribution / packaging 9 | .Python 10 | env/ 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | #lib/ 17 | lib64/ 18 | parts/ 19 | sdist/ 20 | var/ 21 | *.egg-info/ 22 | .installed.cfg 23 | *.egg 24 | 25 | # PyInstaller 26 | # Usually these files are written by a python script from a template 27 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 28 | *.manifest 29 | *.spec 30 | 31 | # Installer logs 32 | pip-log.txt 33 | pip-delete-this-directory.txt 34 | 35 | # Unit test / coverage reports 36 | htmlcov/ 37 | .tox/ 38 | .coverage 39 | .cache 40 | nosetests.xml 41 | coverage.xml 42 | 43 | # Translations 44 | *.mo 45 | *.pot 46 | 47 | # Django stuff: 48 | *.log 49 | 50 | # Sphinx documentation 51 | docs/_build/ 52 | 53 | # PyBuilder 54 | target/ 55 | 56 | # IDE 57 | .idea 58 | 59 | # Vim 60 | *.swp 61 | 62 | # Misc 63 | tmp* 64 | debug 65 | benchmark*.prof 66 | *.bak 67 | .eggs 68 | .pytest_cache/ 69 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM pypy:2 2 | 3 | RUN pip install six bitstring 4 | COPY pybufrkit /opt/app/pybufrkit 5 | ENV PYTHONPATH=/opt/app 6 | 7 | ENTRYPOINT ["pypy", "-m", "pybufrkit"] 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Yang Wang 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include MANIFEST.in 2 | include README.md 3 | include LICENSE 4 | 5 | recursive-include docs * 6 | 7 | recursive-include pybufrkit/definitions *.json 8 | recursive-include pybufrkit/tables * 9 | recursive-include tests * -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Python Toolkit for WMO BUFR Messages 2 | ==================================== 3 | 4 | .. image:: https://github.com/ywangd/pybufrkit/actions/workflows/ci.yml/badge.svg 5 | :target: https://github.com/ywangd/pybufrkit 6 | 7 | `PyBufrKit `_ is a **pure** Python package 8 | to work with WMO BUFR (FM-94) messages. It can be used as both a 9 | command line tool or library to decode and encode BUFR messages. Here is a brief 10 | list of some of the features: 11 | 12 | * Pure Python 13 | * Handles both compressed and un-compressed messages 14 | * Handles all practical operator descriptors, including data quality info, 15 | stats, bitmaps, etc. 16 | * Option to construct hierarchial structure of a message, e.g. associate 17 | first order stats data to their owners. 18 | * Convenient subsetting support for BUFR messages 19 | * Comprehensive query support for BUFR messages 20 | * Script support enables flexible extensions, e.g. filtering through large number of files. 21 | * Tested with the same set of BUFR files used by 22 | `ecCodes `_ 23 | and `BUFRDC `_. 24 | 25 | More documentation at http://pybufrkit.readthedocs.io/ 26 | 27 | An `online BUFR decoder `_ powered by PyBufrKit, 28 | `Serverless `_ and `AWS Lambda `_. 29 | 30 | Installation 31 | ------------ 32 | PyBufrKit is compatible with Python 2.7, 3.5+, and `PyPy `_. 33 | To install from PyPi:: 34 | 35 | pip install pybufrkit 36 | 37 | Or from `conda-forge `_:: 38 | 39 | conda install -c conda-forge pybufrkit 40 | 41 | Or from source:: 42 | 43 | python setup.py install 44 | 45 | Command Line Usage 46 | ------------------ 47 | 48 | The command line usage of the toolkit takes the following form:: 49 | 50 | pybufrkit [OPTIONS] command ... 51 | 52 | where the ``command`` is one of following actions that can be performed by the tool: 53 | 54 | * ``decode`` - Decode a BUFR file to outputs of various format, e.g. JSON 55 | * ``encode`` - Encode a BUFR file from a JSON input 56 | * ``info`` - Decode only the metadata sections (i.e. section 0, 1, 2, 3) of given BUFR files 57 | * ``split`` - Split given BUFR files into one message per file 58 | * ``subset`` - Subset the given BUFR file and save as new file 59 | * ``query`` - Query metadata or data of given BUFR files 60 | * ``script`` - Embed BUFR query expressions into normal Python script 61 | * ``lookup`` - Look up information about the given list of comma separated BUFR descriptors 62 | * ``compile`` - Compile the given comma separated BUFR descriptors 63 | 64 | Here are a few examples using the tool from command line. For more details, please refer 65 | to the help option, e.g. ``pybufrkit decode -h``. Also checkout the 66 | `documentation `_. 67 | 68 | .. code-block:: Bash 69 | 70 | # Decode a BUFR file and output in the default flat text format 71 | pybufrkit decode BUFR_FILE 72 | 73 | # Decode a file that is a concatenation of multiple BUFR messages, 74 | # skipping any erroneous messages and continue on next one 75 | pybufrkit decode -m --continue-on-error FILE 76 | 77 | # Filter through a multi-message file and only decode messages 78 | # that have data_category equals to 2. See below for details 79 | # about usable filter expressions. 80 | pybufrkit decode -m --filter '${%data_category} == 2' FILE 81 | 82 | # Decode a BUFR file and display it in a hierarchical structure 83 | # corresponding to the BUFR Descriptors. In addition, the attribute 84 | # descriptors are associated to their (bitmap) corresponding descriptors. 85 | pybufrkit decode -a BUFR_FILE 86 | 87 | # Decode a BUFR file and output in the flat JSON format 88 | pybufrkit decode -j BUFR_FILE 89 | 90 | # Encode from a flat JSON file to BUFR 91 | pybufrkit encode -j JSON_FILE BUFR_FILE 92 | 93 | # Decode a BUFR file, pipe it to the encoder to encode it back to BUFR 94 | pybufrkit decode BUFR_FILE | pybufrkit encode - 95 | 96 | # Decode only the metadata sections of a BUFR file 97 | pybufrkit info BUFR_FILE 98 | 99 | # Split a BUFR file into one message per file 100 | pybufrkit split BUFR_FILE 101 | 102 | # Subset from a given BUFR file 103 | pybufrkit subset 0,3,6,9 BUFR_FILE 104 | 105 | # Query values from the metadata sections (section 0, 1, 2, 3): 106 | pybufrkit query %n_subsets BUFR_FILE 107 | 108 | # Query all values for descriptor 001002 of the data section 109 | pybufrkit query 001002 BUFR_FILE 110 | 111 | # Query for those root level 001002 of the BUFR Template 112 | pybufrkit query /001002 BUFR_FILE 113 | 114 | # Query for 001002 that is a direct child of 301001 115 | pybufrkit query /301001/001002 BUFR_FILE 116 | 117 | # Query for all 001002 of the first subset 118 | pybufrkit query '@[0] > 001002' BUFR_FILE 119 | 120 | # Query for associated field of 021062 121 | pybufrkit query 021062.A21062 BUFR_FILE 122 | 123 | # Filtering through a number of BUFR files with Script support 124 | # (find files that have multiple subsets): 125 | pybufrkit script 'if ${%n_subsets} > 1: print(PBK_FILENAME)' DIRECTORY/*.bufr 126 | 127 | # Lookup information for a Element Descriptor (along with its code table) 128 | pybufrkit lookup -l 020003 129 | 130 | # Compile a BUFR Template composed as a comma separated list of descriptors 131 | pybufrkit compile 309052,205060 132 | 133 | 134 | Library Usage 135 | ------------- 136 | 137 | The following code shows an example of basic library usage 138 | 139 | .. code-block:: Python 140 | 141 | # Decode a BUFR file 142 | from pybufrkit.decoder import Decoder 143 | decoder = Decoder() 144 | with open(SOME_BUFR_FILE, 'rb') as ins: 145 | bufr_message = decoder.process(ins.read()) 146 | 147 | # Convert the BUFR message to JSON 148 | from pybufrkit.renderer import FlatJsonRenderer 149 | json_data = FlatJsonRenderer().render(bufr_message) 150 | 151 | # Encode the JSON back to BUFR file 152 | from pybufrkit.encoder import Encoder 153 | encoder = Encoder() 154 | bufr_message_new = encoder.process(json_data) 155 | with open(BUFR_OUTPUT_FILE, 'wb') as outs: 156 | outs.write(bufr_message_new.serialized_bytes) 157 | 158 | # Decode for multiple messages from a single file 159 | from pybufrkit.decoder import generate_bufr_message 160 | with open(SOME_FILE, 'rb') as ins: 161 | for bufr_message in generate_bufr_message(decoder, ins.read()): 162 | pass # do something with the decoded message object 163 | 164 | # Query the metadata 165 | from pybufrkit.mdquery import MetadataExprParser, MetadataQuerent 166 | n_subsets = MetadataQuerent(MetadataExprParser()).query(bufr_message, '%n_subsets') 167 | 168 | # Query the data 169 | from pybufrkit.dataquery import NodePathParser, DataQuerent 170 | query_result = DataQuerent(NodePathParser()).query(bufr_message, '001002') 171 | 172 | # Script 173 | from pybufrkit.script import ScriptRunner 174 | # NOTE: must use the function version of print (Python 3), NOT the statement version 175 | code = """print('Multiple' if ${%n_subsets} > 1 else 'Single')""" 176 | runner = ScriptRunner(code) 177 | runner.run(bufr_message) 178 | 179 | **For more help, please check the documentation site at** http://pybufrkit.readthedocs.io/ 180 | -------------------------------------------------------------------------------- /docs/Notes.md: -------------------------------------------------------------------------------- 1 | ## Operators 2 | 3 | ### 204 YYY 4 | * 031021 can be used multiple times inside one 204YYY session to change the 5 | meaning of the attached bits. 6 | * Every new 204YYY session must be immediately followed by a 031021 field. 7 | 8 | * How to define compound associated field (not just simply repeating 204YYY)? 9 | 10 | ### Data present bit-map 11 | It can be defined immediately after an operator that requires it, e.g. 224000. 12 | Otherwise, its definition requires an opening 236000. If it is to be re-used, 13 | it then must be defined using 236000. 14 | 15 | * Bit 0 means data **present**, while 1 means data **NOT** present. 16 | * Multiple Bit-map definition is possible and stored like a stack? A cancel 17 | operator (237255) only cancels the most recent definition. But 235000 can 18 | cancel all definitions at once. 19 | 20 | 21 | * `mpco_217.bufr` is malformed 22 | There is an erroneous replication descriptor `114000` which should be `116000` 23 | to include 2 more items. This file has been corrected so that the decoding can pass. 24 | -------------------------------------------------------------------------------- /docs/api.rst: -------------------------------------------------------------------------------- 1 | .. _api: 2 | 3 | 4 | API reference 5 | ============= 6 | 7 | .. automodule:: pybufrkit 8 | 9 | .. automodule:: pybufrkit.bufr 10 | :members: 11 | 12 | .. automodule:: pybufrkit.descriptors 13 | :members: 14 | 15 | .. automodule:: pybufrkit.tables 16 | :members: 17 | 18 | .. automodule:: pybufrkit.coder 19 | :members: 20 | 21 | .. automodule:: pybufrkit.decoder 22 | :members: 23 | 24 | .. automodule:: pybufrkit.encoder 25 | :members: 26 | 27 | .. automodule:: pybufrkit.templatecompiler 28 | :members: 29 | 30 | .. automodule:: pybufrkit.templatedata 31 | :members: 32 | 33 | .. automodule:: pybufrkit.dataquery 34 | :members: 35 | 36 | .. automodule:: pybufrkit.mdquery 37 | :members: 38 | 39 | .. automodule:: pybufrkit.query 40 | :members: 41 | 42 | .. automodule:: pybufrkit.script 43 | :members: 44 | 45 | .. automodule:: pybufrkit.renderer 46 | :members: 47 | 48 | .. automodule:: pybufrkit.bitops 49 | :members: 50 | 51 | .. automodule:: pybufrkit.commands 52 | :members: 53 | 54 | .. automodule:: pybufrkit.utils 55 | :members: 56 | 57 | .. automodule:: pybufrkit.constants 58 | :members: 59 | 60 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | .. include:: ../README.rst 2 | 3 | .. include:: internals.rst 4 | 5 | Show me the code 6 | ---------------- 7 | Check the code to see details. 8 | 9 | .. toctree:: 10 | :maxdepth: 2 11 | 12 | api 13 | 14 | Indices and tables 15 | ================== 16 | 17 | * :ref:`genindex` 18 | * :ref:`modindex` 19 | * :ref:`search` 20 | -------------------------------------------------------------------------------- /pybufrkit/__main__.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import sys 5 | 6 | if __name__ == '__main__': 7 | from pybufrkit import main 8 | 9 | sys.exit(main()) 10 | -------------------------------------------------------------------------------- /pybufrkit/constants.py: -------------------------------------------------------------------------------- 1 | """ 2 | pybufrkit.constants 3 | ~~~~~~~~~~~~~~~~~~~ 4 | 5 | Various constants used in the module. 6 | 7 | """ 8 | from __future__ import absolute_import 9 | from __future__ import print_function 10 | 11 | import sys 12 | import os 13 | 14 | # Set the base directory accordingly for PyInstaller 15 | # noinspection PyUnresolvedReferences,PyProtectedMember 16 | BASE_DIR = sys._MEIPASS if getattr(sys, 'frozen', False) else os.path.dirname(__file__) 17 | 18 | # Default directory to read the definition JSON files 19 | DEFAULT_DEFINITIONS_DIR = os.path.join(BASE_DIR, 'definitions') 20 | 21 | # Default directory to load the BUFR tables 22 | DEFAULT_TABLES_DIR = os.path.join(BASE_DIR, 'tables') 23 | 24 | NBITS_PER_BYTE = 8 25 | 26 | MESSAGE_START_SIGNATURE = b'BUFR' 27 | MESSAGE_STOP_SIGNATURE = b'7777' 28 | 29 | PARAMETER_TYPE_UNEXPANDED_DESCRIPTORS = 'unexpanded_descriptors' 30 | PARAMETER_TYPE_TEMPLATE_DATA = 'template_data' 31 | 32 | BITPOS_START = 'bitpos_start' 33 | 34 | # A list of numbers that corresponds to missing values for a number of bits up to 64 35 | NUMERIC_MISSING_VALUES = [2 ** i - 1 for i in range(65)] 36 | 37 | 38 | # Number of bits for represent number of bits used for difference 39 | NBITS_FOR_NBITS_DIFF = 6 40 | 41 | UNITS_STRING = 'CCITT IA5' 42 | UNITS_FLAG_TABLE = 'FLAG TABLE' 43 | UNITS_CODE_TABLE = 'CODE TABLE' 44 | UNITS_COMMON_CODE_TABLE_C1 = 'Common CODE TABLE C-1' 45 | 46 | INDENT_CHARS = ' ' 47 | -------------------------------------------------------------------------------- /pybufrkit/dataprocessor.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import six 5 | import itertools 6 | from pybufrkit.descriptors import flat_member_ids 7 | from pybufrkit.templatedata import FixedReplicationNode, DelayedReplicationNode 8 | 9 | __all__ = ['BufrTableDefinitionProcessor'] 10 | 11 | 12 | class BufrTableDefinitionProcessor(object): 13 | 14 | def process(self, bufr_message): 15 | assert bufr_message.n_subsets.value == 1, 'Expect only one subset for defining BUFR tables, got {}'.format( 16 | bufr_message.n_subsets.value) 17 | bufr_message.wire() 18 | template_data = bufr_message.template_data.value 19 | assert len(template_data.decoded_nodes) == 3, 'Expect 3 sections in template data for defining BUFR tables' 20 | next_value = self._process_table_a_entries( 21 | template_data.decoded_nodes[0], template_data.decoded_values) 22 | b_entries = self._process_table_b_entries( 23 | next_value, template_data.decoded_nodes[1], template_data.decoded_values) 24 | d_entries = self._process_table_d_entries( 25 | next_value, template_data.decoded_nodes[2], template_data.decoded_values) 26 | return [[], b_entries, d_entries] 27 | 28 | def _process_table_a_entries(self, decoded_node, decoded_values): 29 | n_repeats, is_delayed_replication = self._get_n_repeats(decoded_node, decoded_values) 30 | assert flat_member_ids(decoded_node.descriptor) == [1, 2, 3] 31 | vc = itertools.count(n_repeats * 3 + 1 if is_delayed_replication else 0) 32 | 33 | def get_decoded_values(): 34 | value = decoded_values[next(vc)] 35 | if isinstance(value, six.binary_type): 36 | value = value.decode() 37 | return value 38 | 39 | return get_decoded_values 40 | 41 | def _process_table_b_entries(self, next_value, decoded_node, decoded_values): 42 | n_repeats, is_delayed_replication = self._get_n_repeats(decoded_node, decoded_values) 43 | if is_delayed_replication: 44 | next_value() 45 | 46 | assert flat_member_ids(decoded_node.descriptor) == [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 47 | return dict([self._process_table_b_one_entry(next_value) for ir in range(n_repeats)]) 48 | 49 | def _process_table_b_one_entry(self, next_value): 50 | return ( 51 | next_value() + next_value() + next_value(), 52 | [ 53 | next_value().rstrip() + next_value().rstrip(), 54 | next_value().strip(), 55 | (1 if next_value().strip() == '+' else -1) * int(next_value().strip()), 56 | (1 if next_value().strip() == '+' else -1) * int(next_value().strip()), 57 | int(next_value().strip()), 58 | '', 0, 0 59 | ] 60 | ) 61 | 62 | def _process_table_d_entries(self, next_value, decoded_node, decoded_values): 63 | n_repeats, is_delayed_replication = self._get_n_repeats(decoded_node, decoded_values) 64 | if is_delayed_replication: 65 | next_value() 66 | 67 | assert flat_member_ids(decoded_node.descriptor) == [10, 11, 12, 205064, 101000, 31001, 30] 68 | 69 | return dict([self._process_table_d_one_entry(next_value) for _ in range(n_repeats)]) 70 | 71 | def _process_table_d_one_entry(self, next_value): 72 | return ( 73 | next_value() + next_value() + next_value(), 74 | [ 75 | next_value().rstrip(), 76 | [next_value() for i in range(next_value())] 77 | ] 78 | ) 79 | 80 | def _get_n_repeats(self, decoded_node, decoded_values): 81 | assert isinstance(decoded_node, (FixedReplicationNode, DelayedReplicationNode)) 82 | if isinstance(decoded_node, FixedReplicationNode): 83 | return decoded_node.descriptor.n_repeats, False 84 | else: 85 | return decoded_values[decoded_node.factor.index], True 86 | -------------------------------------------------------------------------------- /pybufrkit/definitions/section0.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 0, 3 | "description": "Indicator section", 4 | "default": true, 5 | "optional": false, 6 | "parameters": [ 7 | { 8 | "name": "start_signature", 9 | "nbits": 32, 10 | "type": "bytes", 11 | "expected": "BUFR", 12 | "as_property": false 13 | }, 14 | { 15 | "name": "length", 16 | "nbits": 24, 17 | "type": "uint", 18 | "as_property": true 19 | }, 20 | { 21 | "name": "edition", 22 | "nbits": 8, 23 | "type": "uint", 24 | "as_property": true 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /pybufrkit/definitions/section1-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 1, 3 | "description": "Identification section", 4 | "optional": false, 5 | "parameters": [ 6 | { 7 | "name": "originating_centre", 8 | "nbits": 16, 9 | "type": "uint", 10 | "as_property": false 11 | }, 12 | { 13 | "name": "update_sequence_number", 14 | "nbits": 8, 15 | "type": "uint" 16 | }, 17 | { 18 | "name": "is_section2_presents", 19 | "nbits": 1, 20 | "type": "bool", 21 | "as_property": false 22 | }, 23 | { 24 | "name": "flag_bits", 25 | "nbits": 7, 26 | "type": "bin" 27 | }, 28 | { 29 | "name": "data_category", 30 | "nbits": 8, 31 | "type": "uint", 32 | "as_property": true 33 | }, 34 | { 35 | "name": "data_local_subcategory", 36 | "nbits": 8, 37 | "type": "uint" 38 | }, 39 | { 40 | "name": "master_table_version", 41 | "nbits": 8, 42 | "type": "uint", 43 | "as_property": true 44 | }, 45 | { 46 | "name": "local_table_version", 47 | "nbits": 8, 48 | "type": "uint", 49 | "as_property": true 50 | }, 51 | { 52 | "name": "year", 53 | "nbits": 8, 54 | "type": "uint", 55 | "as_property": true 56 | }, 57 | { 58 | "name": "month", 59 | "nbits": 8, 60 | "type": "uint", 61 | "as_property": true 62 | }, 63 | { 64 | "name": "day", 65 | "nbits": 8, 66 | "type": "uint", 67 | "as_property": true 68 | }, 69 | { 70 | "name": "hour", 71 | "nbits": 8, 72 | "type": "uint", 73 | "as_property": true 74 | }, 75 | { 76 | "name": "minute", 77 | "nbits": 8, 78 | "type": "uint", 79 | "as_property": true 80 | }, 81 | { 82 | "name": "second", 83 | "nbits": 8, 84 | "type": "uint", 85 | "as_property": true 86 | } 87 | ] 88 | } -------------------------------------------------------------------------------- /pybufrkit/definitions/section1-2.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 1, 3 | "description": "Identification section", 4 | "optional": false, 5 | "parameters": [ 6 | { 7 | "name": "section_length", 8 | "nbits": 24, 9 | "type": "uint" 10 | }, 11 | { 12 | "name": "master_table_number", 13 | "nbits": 8, 14 | "type": "uint", 15 | "as_property": true 16 | }, 17 | { 18 | "name": "originating_centre", 19 | "nbits": 16, 20 | "type": "uint", 21 | "as_property": true 22 | }, 23 | { 24 | "name": "update_sequence_number", 25 | "nbits": 8, 26 | "type": "uint" 27 | }, 28 | { 29 | "name": "is_section2_presents", 30 | "nbits": 1, 31 | "type": "bool", 32 | "as_property": true 33 | }, 34 | { 35 | "name": "flag_bits", 36 | "nbits": 7, 37 | "type": "bin" 38 | }, 39 | { 40 | "name": "data_category", 41 | "nbits": 8, 42 | "type": "uint", 43 | "as_property": true 44 | }, 45 | { 46 | "name": "data_local_subcategory", 47 | "nbits": 8, 48 | "type": "uint" 49 | }, 50 | { 51 | "name": "master_table_version", 52 | "nbits": 8, 53 | "type": "uint", 54 | "as_property": true 55 | }, 56 | { 57 | "name": "local_table_version", 58 | "nbits": 8, 59 | "type": "uint", 60 | "as_property": true 61 | }, 62 | { 63 | "name": "year", 64 | "nbits": 8, 65 | "type": "uint", 66 | "as_property": true 67 | }, 68 | { 69 | "name": "month", 70 | "nbits": 8, 71 | "type": "uint", 72 | "as_property": true 73 | }, 74 | { 75 | "name": "day", 76 | "nbits": 8, 77 | "type": "uint", 78 | "as_property": true 79 | }, 80 | { 81 | "name": "hour", 82 | "nbits": 8, 83 | "type": "uint", 84 | "as_property": true 85 | }, 86 | { 87 | "name": "minute", 88 | "nbits": 8, 89 | "type": "uint", 90 | "as_property": true 91 | }, 92 | { 93 | "name": "local_bytes", 94 | "nbits": 0, 95 | "type": "bytes", 96 | "as_property": true, 97 | "optional": true 98 | } 99 | ] 100 | } -------------------------------------------------------------------------------- /pybufrkit/definitions/section1-3.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 1, 3 | "description": "Identification section", 4 | "optional": false, 5 | "parameters": [ 6 | { 7 | "name": "section_length", 8 | "nbits": 24, 9 | "type": "uint" 10 | }, 11 | { 12 | "name": "master_table_number", 13 | "nbits": 8, 14 | "type": "uint", 15 | "as_property": true 16 | }, 17 | { 18 | "name": "originating_subcentre", 19 | "nbits": 8, 20 | "type": "uint", 21 | "as_property": true 22 | }, 23 | { 24 | "name": "originating_centre", 25 | "nbits": 8, 26 | "type": "uint", 27 | "as_property": true 28 | }, 29 | { 30 | "name": "update_sequence_number", 31 | "nbits": 8, 32 | "type": "uint" 33 | }, 34 | { 35 | "name": "is_section2_presents", 36 | "nbits": 1, 37 | "type": "bool", 38 | "as_property": true 39 | }, 40 | { 41 | "name": "flag_bits", 42 | "nbits": 7, 43 | "type": "bin" 44 | }, 45 | { 46 | "name": "data_category", 47 | "nbits": 8, 48 | "type": "uint", 49 | "as_property": true 50 | }, 51 | { 52 | "name": "data_local_subcategory", 53 | "nbits": 8, 54 | "type": "uint" 55 | }, 56 | { 57 | "name": "master_table_version", 58 | "nbits": 8, 59 | "type": "uint", 60 | "as_property": true 61 | }, 62 | { 63 | "name": "local_table_version", 64 | "nbits": 8, 65 | "type": "uint", 66 | "as_property": true 67 | }, 68 | { 69 | "name": "year", 70 | "nbits": 8, 71 | "type": "uint", 72 | "as_property": true 73 | }, 74 | { 75 | "name": "month", 76 | "nbits": 8, 77 | "type": "uint", 78 | "as_property": true 79 | }, 80 | { 81 | "name": "day", 82 | "nbits": 8, 83 | "type": "uint", 84 | "as_property": true 85 | }, 86 | { 87 | "name": "hour", 88 | "nbits": 8, 89 | "type": "uint", 90 | "as_property": true 91 | }, 92 | { 93 | "name": "minute", 94 | "nbits": 8, 95 | "type": "uint", 96 | "as_property": true 97 | }, 98 | { 99 | "name": "second", 100 | "nbits": 8, 101 | "type": "uint", 102 | "as_property": true 103 | } 104 | ] 105 | } -------------------------------------------------------------------------------- /pybufrkit/definitions/section1-4.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 1, 3 | "description": "Identification section", 4 | "default": true, 5 | "optional": false, 6 | "parameters": [ 7 | { 8 | "name": "section_length", 9 | "nbits": 24, 10 | "type": "uint" 11 | }, 12 | { 13 | "name": "master_table_number", 14 | "nbits": 8, 15 | "type": "uint", 16 | "as_property": true 17 | }, 18 | { 19 | "name": "originating_centre", 20 | "nbits": 16, 21 | "type": "uint", 22 | "as_property": true 23 | }, 24 | { 25 | "name": "originating_subcentre", 26 | "nbits": 16, 27 | "type": "uint", 28 | "as_property": true 29 | }, 30 | { 31 | "name": "update_sequence_number", 32 | "nbits": 8, 33 | "type": "uint" 34 | }, 35 | { 36 | "name": "is_section2_presents", 37 | "nbits": 1, 38 | "type": "bool", 39 | "as_property": true 40 | }, 41 | { 42 | "name": "flag_bits", 43 | "nbits": 7, 44 | "type": "bin" 45 | }, 46 | { 47 | "name": "data_category", 48 | "nbits": 8, 49 | "type": "uint", 50 | "as_property": true 51 | }, 52 | { 53 | "name": "data_i18n_subcategory", 54 | "nbits": 8, 55 | "type": "uint" 56 | }, 57 | { 58 | "name": "data_local_subcategory", 59 | "nbits": 8, 60 | "type": "uint" 61 | }, 62 | { 63 | "name": "master_table_version", 64 | "nbits": 8, 65 | "type": "uint", 66 | "as_property": true 67 | }, 68 | { 69 | "name": "local_table_version", 70 | "nbits": 8, 71 | "type": "uint", 72 | "as_property": true 73 | }, 74 | { 75 | "name": "year", 76 | "nbits": 16, 77 | "type": "uint", 78 | "as_property": true 79 | }, 80 | { 81 | "name": "month", 82 | "nbits": 8, 83 | "type": "uint", 84 | "as_property": true 85 | }, 86 | { 87 | "name": "day", 88 | "nbits": 8, 89 | "type": "uint", 90 | "as_property": true 91 | }, 92 | { 93 | "name": "hour", 94 | "nbits": 8, 95 | "type": "uint", 96 | "as_property": true 97 | }, 98 | { 99 | "name": "minute", 100 | "nbits": 8, 101 | "type": "uint", 102 | "as_property": true 103 | }, 104 | { 105 | "name": "second", 106 | "nbits": 8, 107 | "type": "uint", 108 | "as_property": true 109 | }, 110 | { 111 | "name": "local_bytes", 112 | "nbits": 0, 113 | "type": "bytes", 114 | "as_property": true, 115 | "optional": true 116 | } 117 | ] 118 | } -------------------------------------------------------------------------------- /pybufrkit/definitions/section2.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 2, 3 | "description": "Optional section", 4 | "default": true, 5 | "optional": true, 6 | "parameters": [ 7 | { 8 | "name": "section_length", 9 | "nbits": 24, 10 | "type": "uint" 11 | }, 12 | { 13 | "name": "reserved_bits", 14 | "nbits": 8, 15 | "type": "bin" 16 | }, 17 | { 18 | "name": "local_bits", 19 | "nbits": 0, 20 | "type": "bin" 21 | } 22 | ] 23 | } -------------------------------------------------------------------------------- /pybufrkit/definitions/section3.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 3, 3 | "description": "Data description section", 4 | "default": true, 5 | "optional": false, 6 | "parameters": [ 7 | { 8 | "name": "section_length", 9 | "nbits": 24, 10 | "type": "uint" 11 | }, 12 | { 13 | "name": "reserved_bits", 14 | "nbits": 8, 15 | "type": "bin" 16 | }, 17 | { 18 | "name": "n_subsets", 19 | "nbits": 16, 20 | "type": "uint", 21 | "as_property": true 22 | }, 23 | { 24 | "name": "is_observation", 25 | "nbits": 1, 26 | "type": "bool", 27 | "as_property": true 28 | }, 29 | { 30 | "name": "is_compressed", 31 | "nbits": 1, 32 | "type": "bool", 33 | "as_property": true 34 | }, 35 | { 36 | "name": "flag_bits", 37 | "nbits": 6, 38 | "type": "bin" 39 | }, 40 | { 41 | "name": "unexpanded_descriptors", 42 | "nbits": 0, 43 | "type": "unexpanded_descriptors", 44 | "as_property": true 45 | } 46 | ] 47 | } -------------------------------------------------------------------------------- /pybufrkit/definitions/section4.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 4, 3 | "description": "Data section", 4 | "default": true, 5 | "optional": false, 6 | "parameters": [ 7 | { 8 | "name": "section_length", 9 | "nbits": 24, 10 | "type": "uint" 11 | }, 12 | { 13 | "name": "reserved_bits", 14 | "nbits": 8, 15 | "type": "bin" 16 | }, 17 | { 18 | "name": "template_data", 19 | "nbits": 0, 20 | "type": "template_data", 21 | "as_property": true 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /pybufrkit/definitions/section5.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": 5, 3 | "description": "End section", 4 | "default": true, 5 | "optional": false, 6 | "end_of_message": true, 7 | "parameters": [ 8 | { 9 | "name": "stop_signature", 10 | "nbits": 32, 11 | "type": "bytes", 12 | "expected": "7777" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /pybufrkit/errors.py: -------------------------------------------------------------------------------- 1 | """ 2 | pybufrkit.errors 3 | ~~~~~~~~~~~~~~~~ 4 | """ 5 | 6 | 7 | class PyBufrKitError(Exception): 8 | """ 9 | This is the root exception object of the package. 10 | """ 11 | 12 | def __init__(self, message=''): 13 | self.message = message 14 | 15 | def __str__(self): 16 | return 'Error: {}'.format(self.message) 17 | 18 | 19 | class UnknownDescriptor(PyBufrKitError): 20 | """ 21 | An unknown, i.e. not found in BUFR tables, BUFR descriptor. 22 | """ 23 | 24 | 25 | class BitReadError(PyBufrKitError): 26 | """ 27 | Bit reading error 28 | """ 29 | 30 | 31 | class PathExprParsingError(PyBufrKitError): 32 | """ 33 | Error on parsing a Path expression 34 | """ 35 | 36 | 37 | class MetadataExprParsingError(PyBufrKitError): 38 | """ 39 | Error on parsing a metadata variable expression 40 | """ 41 | 42 | 43 | class QueryError(PyBufrKitError): 44 | """ 45 | General error on query processing 46 | """ 47 | -------------------------------------------------------------------------------- /pybufrkit/mdquery.py: -------------------------------------------------------------------------------- 1 | """ 2 | pybufrkit.mdquery 3 | ~~~~~~~~~~~~~~~~~ 4 | """ 5 | from __future__ import absolute_import 6 | from __future__ import print_function 7 | 8 | import logging 9 | 10 | from pybufrkit.errors import MetadataExprParsingError 11 | 12 | __all__ = ['MetadataExprParser', 'MetadataQuerent', 'METADATA_QUERY_INDICATOR_CHAR'] 13 | 14 | log = logging.getLogger(__file__) 15 | 16 | METADATA_QUERY_INDICATOR_CHAR = '%' 17 | 18 | 19 | class MetadataExprParser(object): 20 | def parse(self, metadata_expr): 21 | """ 22 | 23 | :param str metadata_expr: The metadata expression string to parse 24 | :return: A 2-element tuple of section index and metadata name 25 | :rtype: (int, str) 26 | """ 27 | metadata_expr = metadata_expr.strip() 28 | if metadata_expr[0] != METADATA_QUERY_INDICATOR_CHAR: 29 | raise MetadataExprParsingError('Metadata expression must start with "%"') 30 | 31 | if '.' in metadata_expr: 32 | section_index, metadata_name = metadata_expr[1:].split('.') 33 | try: 34 | section_index = int(section_index) 35 | except ValueError: 36 | raise MetadataExprParsingError('Invalid section index: {}'.format(section_index)) 37 | 38 | else: 39 | section_index = None 40 | metadata_name = metadata_expr[1:] 41 | 42 | return section_index, metadata_name 43 | 44 | 45 | class MetadataQuerent(object): 46 | """ 47 | :param MetadataExprParser metadata_expr_parser: Parser for metadata expression 48 | """ 49 | 50 | def __init__(self, metadata_expr_parser): 51 | 52 | self.metadata_expr_parser = metadata_expr_parser 53 | 54 | def query(self, bufr_message, metadata_expr): 55 | section_index, metadata_name = self.metadata_expr_parser.parse(metadata_expr) 56 | sections = [s for s in bufr_message.sections 57 | if s.get_metadata('index') == section_index or section_index is None] 58 | for section in sections: 59 | for parameter in section: 60 | if parameter.name == metadata_name: 61 | return parameter.value 62 | 63 | return None 64 | -------------------------------------------------------------------------------- /pybufrkit/query.py: -------------------------------------------------------------------------------- 1 | """ 2 | pybufrkit.query 3 | ~~~~~~~~~~~~~~~ 4 | """ 5 | from __future__ import absolute_import 6 | from __future__ import print_function 7 | 8 | 9 | from pybufrkit.dataquery import NodePathParser, DataQuerent 10 | from pybufrkit.mdquery import MetadataExprParser, MetadataQuerent, METADATA_QUERY_INDICATOR_CHAR 11 | 12 | 13 | class BufrMessageQuerent(object): 14 | """ 15 | This is a convenient class for querents of metadata and data sections. 16 | It provides an uniform interface for querying the BufrMessage object. 17 | """ 18 | 19 | def __init__(self): 20 | self.metadata_querent = MetadataQuerent(MetadataExprParser()) 21 | self.data_querent = DataQuerent(NodePathParser()) 22 | 23 | def query(self, bufr_message, query_expr): 24 | query_expr = query_expr.lstrip() 25 | if query_expr[0] == METADATA_QUERY_INDICATOR_CHAR: 26 | return self.metadata_querent.query(bufr_message, query_expr) 27 | else: 28 | return self.data_querent.query(bufr_message, query_expr) 29 | -------------------------------------------------------------------------------- /pybufrkit/script.py: -------------------------------------------------------------------------------- 1 | """ 2 | pybufrkit.script 3 | ~~~~~~~~~~~~~~~~ 4 | """ 5 | from __future__ import absolute_import 6 | from __future__ import print_function 7 | 8 | import functools 9 | import ast 10 | 11 | from pybufrkit.dataquery import QueryResult 12 | from pybufrkit.query import BufrMessageQuerent 13 | 14 | __all__ = ['process_embedded_query_expr', 'ScriptRunner'] 15 | 16 | STATE_IDLE = '' 17 | STATE_EMBEDDED_QUERY = '${' 18 | STATE_SINGLE_QUOTE = "'" 19 | STATE_DOUBLE_QUOTE = '"' 20 | STATE_COMMENT = '#' 21 | 22 | 23 | def process_embedded_query_expr(input_string): 24 | """ 25 | This function scans through the given script and identify any path/metadata 26 | expressions. For each expression found, an unique python variable name will 27 | be generated. The expression is then substituted by the variable name. 28 | 29 | :param str input_string: The input script 30 | :return: A 2-element tuple of the substituted string and a dict of substitutions 31 | :rtype: (str, dict) 32 | """ 33 | keep = [] 34 | state = '' 35 | idx_char = idx_var = 0 36 | substitutions = {} # keyed by query expression 37 | 38 | query_expr = [] 39 | while idx_char < len(input_string): 40 | c = input_string[idx_char] 41 | 42 | if state == STATE_EMBEDDED_QUERY: 43 | if c == '}': 44 | state = STATE_IDLE 45 | s = ''.join(query_expr).strip() 46 | query_expr = [] 47 | if s not in substitutions: 48 | varname = 'PBK_{}'.format(idx_var) 49 | idx_var += 1 50 | substitutions[s] = varname 51 | else: 52 | varname = substitutions[s] 53 | keep.append(varname) 54 | else: 55 | query_expr.append(c) 56 | 57 | elif (c == "'" or c == '"') and state != STATE_EMBEDDED_QUERY: 58 | if state == c: # quoting pair found, pop it 59 | state = STATE_IDLE 60 | elif state == '': # new quote begins 61 | state = c 62 | keep.append(c) 63 | 64 | elif c == '$' and state == STATE_IDLE: # an unquoted $ 65 | if idx_char + 1 < len(input_string) and input_string[idx_char + 1] == '{': 66 | state = STATE_EMBEDDED_QUERY 67 | # Once it enters the embedded query state, any pond, 68 | # double/single quotes will be ignored 69 | idx_char += 1 70 | else: 71 | keep.append(c) 72 | 73 | elif c == '#' and state == STATE_IDLE: 74 | state = STATE_COMMENT 75 | keep.append(c) 76 | 77 | elif c == '\n' and state == STATE_COMMENT: 78 | state = STATE_IDLE 79 | keep.append(c) 80 | 81 | else: 82 | keep.append(c) 83 | 84 | idx_char += 1 85 | 86 | return ''.join(keep), substitutions 87 | 88 | 89 | # The following constants represent the nesting levels for values from BUFR data 90 | # section. The nesting levels are decided by the level of parenthesis, which is 91 | # represented by the numbers. A number Zero means no parenthesis at all, i.e. 92 | # scalar. A number One means one level of parenthesis, i.e. a simple list with 93 | # no nesting. 94 | DATA_VALUES_NEST_LEVEL_0 = 0 # flatten to scalar by return only the first element 95 | DATA_VALUES_NEST_LEVEL_1 = 1 # flatten to a list with no nesting, this is the default 96 | DATA_VALUES_NEST_LEVEL_2 = 2 # flatten to a list nested with subsets 97 | DATA_VALUES_NEST_LEVEL_4 = 4 # no flatten at all, fully nested by subsets, replications 98 | 99 | 100 | class ScriptRunner(object): 101 | """ 102 | This class is responsible for running the given script against BufrMessage 103 | object. 104 | 105 | .. attribute:: code_string 106 | The processed/substituted source code. 107 | 108 | .. attribute:: code_object 109 | The compiled code object from the code string. 110 | 111 | .. attribute:: pragma 112 | Extra processing directives 113 | 114 | .. attribute:: metadata_only 115 | Whether the script requires only metadata part of the BUFR message to work. 116 | 117 | .. attribute:: querent 118 | The BufrMessageQuerent object for performing the values query. 119 | """ 120 | 121 | def __init__(self, input_string, 122 | data_values_nest_level=None, 123 | mode='exec'): 124 | self.code_string, self.substitutions = process_embedded_query_expr(input_string) 125 | 126 | self.pragma = { 127 | 'data_values_nest_level': DATA_VALUES_NEST_LEVEL_1, 128 | } 129 | # Read pragma from inside the script 130 | self.process_pragma() 131 | 132 | # Pragma passed from function call has higher priority 133 | if data_values_nest_level is not None: 134 | self.pragma['data_values_nest_level'] = data_values_nest_level 135 | 136 | self.mode = mode 137 | self.code_object = compile(self.code_string, '', mode) 138 | 139 | self.metadata_only = True 140 | for query_str in self.substitutions.keys(): 141 | if not query_str.startswith('%'): 142 | self.metadata_only = False 143 | break 144 | 145 | self.querent = BufrMessageQuerent() 146 | 147 | def run(self, bufr_message): 148 | variables = self.prepare_variables(bufr_message) 149 | if self.mode == 'exec': 150 | exec (self.code_object, variables) 151 | return variables 152 | else: 153 | return eval(self.code_object, variables) 154 | 155 | def prepare_variables(self, bufr_message): 156 | variables = { 157 | varname: self.get_query_result(bufr_message, query_string) 158 | for query_string, varname in self.substitutions.items() 159 | } 160 | variables.update( 161 | { 162 | 'PBK_BUFR_MESSAGE': bufr_message, 163 | 'PBK_FILENAME': bufr_message.filename, 164 | } 165 | ) 166 | return variables 167 | 168 | def get_query_result(self, bufr_message, query_expr): 169 | qr = self.querent.query(bufr_message, query_expr) 170 | if isinstance(qr, QueryResult): 171 | return self.flatten_data_values(qr) 172 | return qr 173 | 174 | def flatten_data_values(self, qr): 175 | data_values_nest_level = self.pragma['data_values_nest_level'] 176 | 177 | if data_values_nest_level == DATA_VALUES_NEST_LEVEL_0: 178 | values = qr.all_values(flat=True) 179 | values = functools.reduce(lambda x, y: x + y, values, []) 180 | return values[0] if len(values) > 0 else None 181 | 182 | elif data_values_nest_level == DATA_VALUES_NEST_LEVEL_1: 183 | values = qr.all_values(flat=True) 184 | return functools.reduce(lambda x, y: x + y, values, []) 185 | 186 | elif data_values_nest_level == DATA_VALUES_NEST_LEVEL_2: 187 | return qr.all_values(flat=True) 188 | 189 | else: # No flatten, fully nested 190 | return qr.all_values() 191 | 192 | def process_pragma(self): 193 | for line in self.code_string.splitlines(): 194 | if not line.startswith('#$'): 195 | return 196 | 197 | for assignment in line[3:].split(','): 198 | k, v = assignment.split('=') 199 | k = k.strip() 200 | if k in self.pragma: 201 | self.pragma[k] = ast.literal_eval(v.strip()) 202 | -------------------------------------------------------------------------------- /pybufrkit/tables/0/0_0/25/MetaA.json: -------------------------------------------------------------------------------- 1 | { 2 | "Description": "BUFR Table A - Data category", 3 | "header": ["Code figure", "Meaning"], 4 | "entries": [ 5 | ["0", "Surface data - land"], 6 | ["1", "Surface data - sea"], 7 | ["2", "Vertical soundings (other than satellite)"], 8 | ["3", "Vertical soundings (satellite)"], 9 | ["4", "Single level upper - air data (other than satellite)"], 10 | ["5", "Single level upper - air data (satellite)"], 11 | ["6", "Radar data"], 12 | ["7", "Synoptic features"], 13 | ["8", "Physical/chemical constituents"], 14 | ["9", "Dispersal and transport"], 15 | ["10", "Radiological data"], 16 | ["11", "BUFR tables, complete replacement or update"], 17 | ["12", "Surface data (satellite)"], 18 | ["13", "Forecasts"], 19 | ["14", "Warnings"], 20 | ["15 - 19", "Reserved"], 21 | ["20", "Status information"], 22 | ["21", "Radiances (satellite measured)"], 23 | ["22", "Radar (satellite) but not altimeter and scatterometer"], 24 | ["23", "Lidar (satellite)"], 25 | ["24", "Scatterometry (satellite)"], 26 | ["25", "Altimetry (satellite)"], 27 | ["26", "Spectrometry (satellite)"], 28 | ["27", "Gravity measurement (satellite)"], 29 | ["28", "Precision orbit (satellite)"], 30 | ["29", "Space environment (satellite)"], 31 | ["30", "Calibration datasets (satellite)"], 32 | ["31", "Oceanographic data"], 33 | ["32 - 100", "Reserved"], 34 | ["101", "Image data (satellite)"], 35 | ["102 - 239", "Reserved"], 36 | ["240 - 254", "For experimental use"], 37 | ["255", "Other category"] 38 | ] 39 | } 40 | -------------------------------------------------------------------------------- /pybufrkit/tables/0/0_0/25/MetaB.json: -------------------------------------------------------------------------------- 1 | {"description": "BUFR/CREX Table B - Classification of elements", 2 | "headers": ["F", "X", "Class", "Comments"], 3 | "entries": [ 4 | ["0", "00", "BUFR/CREX table entries", ""], 5 | ["0", "01", "Identification", "Identifies origin and type of data"], 6 | ["0", "02", "Instrumentation", "Defines instrument types used"], 7 | ["0", "03", "Instrumentation", "Defines instrument types used"], 8 | ["0", "04", "Location (time)", "Defines time and time derivatives"], 9 | ["0", "05", "Location (horizontal - 1)", "Defines geographical position, including horizontal derivatives, in association with Class 06 (first dimension of horizontal space)"], 10 | ["0", "06", "Location (horizontal - 2)", "Defines geographical position, including horizontal derivatives, in association with Class 05 (second dimension of horizontal space)"], 11 | ["0", "07", "Location (vertical)", "Defines height, altitude, pressure level, including vertical derivatives of position"], 12 | ["0", "08", "Significance qualifiers", "Defines special character of data"], 13 | ["0", "09", "Reserved", ""], 14 | ["0", "10", "Non - coordinate location (vertical)", "Height, altitude, pressure and derivatives observed or measured, not defined as a vertical location"], 15 | ["0", "11", "Wind and turbulence", "Wind speed, direction, etc."], 16 | ["0", "12", "Temperature", ""], 17 | ["0", "13", "Hydrographic and hydrological elements", "Humidity, rainfall, snowfall, etc."], 18 | ["0", "14", "Radiation and radiance", ""], 19 | ["0", "15", "Physical/chemical constituents", ""], 20 | ["0", "19", "Synoptic features", ""], 21 | ["0", "20", "Observed phenomena", "Defines present/past weather, special phenomena, etc."], 22 | ["0", "21", "Radar data", ""], 23 | ["0", "22", "Oceanographic elements", ""], 24 | ["0", "23", "Dispersal and transport", ""], 25 | ["0", "24", "Radiological elements", ""], 26 | ["0", "25", "Processing information", ""], 27 | ["0", "26", "Non-coordinate location (time)", "Defines time and time derivatives that are not coordinates"], 28 | ["0", "27", "Non-coordinate location (horizontal - 1)", "Defines geographical positions, in conjunction with Class 28, that are not coordinates"], 29 | ["0", "28", "Non-coordinate location (horizontal - 2)", "Defines geographical positions, in conjunction with Class 27, that are not coordinates"], 30 | ["0", "29", "Map data", ""], 31 | ["0", "30", "Image", ""], 32 | ["0", "31", "Data description operator qualifiers", "Elements used in conjunction with data description operators"], 33 | ["0", "33", "Quality information", ""], 34 | ["0", "35", "Data monitoring information", ""], 35 | ["0", "40", "Satellite data", ""] 36 | ] 37 | } -------------------------------------------------------------------------------- /pybufrkit/tables/0/0_0/25/MetaC.json: -------------------------------------------------------------------------------- 1 | {"description": "BUFR Table C - Data description operators", 2 | "headers": ["F", "X", "Operand", "Name", "Definition"], 3 | "entries": [ 4 | ["2", "01", "YYY", "Change data width", "Add (YYY-128) bits to the data width given for each data element in Table B, other than CCITT IA5 (character) data, code or flag tables."], 5 | ["2", "02", "YYY", "Change scale", "Add YYY-128 to the scale for each data element in Table B, other than CCITT IA5 (character) data, code or flag tables."], 6 | ["2", "03", "YYY", "Change reference values", "Subsequent element descriptors define new reference values for corresponding Table B entries. Each new reference value is represented by YYY bits in the Data section. Definition of new reference values is concluded by coding this operator with YYY = 255. Negative reference values shall be represented by a positive integer with the left-most bit (bit 1) set to 1."], 7 | ["2", "04", "YYY", "Add associated field", "Precede each data element with YYY bits of information. This operation associates a data field (e.g. quality control information) of YYY bits with each data element."], 8 | ["2", "05", "YYY", "Signify character", "YYY characters (CCITT International Alphabet No. 5) are inserted as a data field of YYY x 8 bits in length."], 9 | ["2", "06", "YYY", "Signify data width for the immediately following local descriptor", "YYY bits of data are described by the immediately following descriptor."], 10 | ["2", "07", "YYY", "Increase scale, reference value and data width", "For Table B elements, which are not CCITT IA5 (character data), code tables, or flag tables: 1. Add YYY to the existing scale factor 2. Multiply the existing reference value by 10YYY 3. Calculate ((10 x YYY) + 2) / 3, disregard any fractional remainder and add the result to the existing bit width."], 11 | ["2", "08", "YYY", "Change width of CCITT IA5 field", "YYY characters from CCITT International Alphabet No. 5 (representing YYY x 8 bits in length) replace the specified data width given for each CCITT IA5 element in Table B."], 12 | ["2", "21", "YYY", "Data not present", "Data values present in Section 4 (Data section) corresponding to the following YYY descriptors shall be limited to data from Classes 01-09, and Class 31."], 13 | ["2", "22", "000", "Quality information follows", "The values of Class 33 elements which follow relate to the data defined by the data present bit-map."], 14 | ["2", "23", "000", "Substituted values operator", "The substituted values which follow relate to the data defined by the data present bit-map."], 15 | ["2", "23", "255", "Substituted values marker operator", "This operator shall signify a data item containing a substituted value; the element descriptor for the substituted value is obtained by the application of the data present bit-map associated with the substituted values operator."], 16 | ["2", "24", "000", "First-order statistical values follow", "The statistical values which follow relate to the data defined by the data present bit-map."], 17 | ["2", "24", "255", "First-order statistical values marker operator", "This operator shall signify a data item containing a first-order statistical value of the type indicated by the preceding 0 08 023 element descriptor; the element descriptor to which the first-order statistic relates is obtained by the application of the data present bit-map associated with the first-order statistical values follow operator; first-order statistical values shall be represented as defined by this element descriptor."], 18 | ["2", "25", "000", "Difference statistical values follow", "The statistical values which follow relate to the data defined by the data present bit-map."], 19 | ["2", "25", "255", "Difference statistical values marker operator", "This operator shall signify a data item containing a difference statistical value of the type indicated by the preceding 0 08 024 element descriptor; the element descriptor to which the difference statistical value relates is obtained by the application of the data present bit-map associated with the difference statistical values follow operator; difference statistical values shall be represented as defined by this element descriptor, but with a reference value of -2n and a data width of (n+1), where n is the data width given by the original descriptor. This special reference value allows the statistical difference values to be centred around zero."], 20 | ["2", "32", "000", "Replaced/retained values follow", "The replaced/retained values which follow relate to the data defined by the data present bit-map."], 21 | ["2", "32", "255", "Replaced/retained value marker operator", "This operator shall signify a data item containing the original of an element which has been replaced by a substituted value. The element descriptor for the retained value is obtained by the application of the data present bit-map associated with the substituted values operator."], 22 | ["2", "35", "000", "Cancel backward data reference", "This operator terminates all previously defined back- ward reference and cancels any previously defined data present bit-map; it causes the next data present bit-map to refer to the data descriptors which immediately precede the operator to which it relates."], 23 | ["2", "36", "000", "Define data present bit-map", "This operator defines the data present bit-map which follows for possible re-use; only one data present bit-map may be defined between this operator and the cancel use defined data present bit-map operator."], 24 | ["2", "37", "000", "Use defined data present bit-map", "This operator causes the defined data present bit-map to be used again."], 25 | ["2", "37", "255", "Cancel use defined data present bit-map", "This operator cancels the re-use of the defined data present bit-map."], 26 | ["2", "41", "000", "Define event", "This operator denotes the beginning of the definition of an event (see Note 19)."], 27 | ["2", "41", "255", "Cancel define event", "This operator denotes the conclusion of the event definition that was begun via the previous 2 41 000 operator."], 28 | ["2", "42", "000", "Define conditioning event", "This operator denotes the beginning of the definition of a conditioning event (see Note 19)."], 29 | ["2", "42", "255", "Cancel define conditioning event", "This operator denotes the conclusion of the conditioning event definition that was begun via the previous 2 42 000 operator."], 30 | ["2", "43", "000", "Categorical forecast values follow", "The values which follow are categorical forecast values (see Note 20)."], 31 | ["2", "43", "255", "Cancel categorical forecast values follow", "This operator denotes the conclusion of the definition of categorical forecast values that was begun via the previous 2 43 000 operator."] 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /pybufrkit/tables/0/0_0/25/MetaD.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "BUFR Table D - List of common sequences", 3 | "headers": ["F", "X", "Category of sequences"], 4 | "entries": [ 5 | ["3", "00", "BUFR table entries sequences"], 6 | ["3", "01", "Location and identification sequences"], 7 | ["3", "02", "Meteorological sequences common to surface data"], 8 | ["3", "03", "Meteorological sequences common to vertical soundings data"], 9 | ["3", "04", "Meteorological sequences common to satellite observations"], 10 | ["3", "05", "Meteorological or hydrological sequences common to hydrological observations"], 11 | ["3", "06", "Meteorological or oceanographic sequences common to oceanographic observations"], 12 | ["3", "07", "Surface report sequences (land)"], 13 | ["3", "08", "Surface report sequences (sea)"], 14 | ["3", "09", "Vertical sounding sequences (conventional data)"], 15 | ["3", "10", "Vertical sounding sequences (satellite data) "], 16 | ["3", "11", "Single level report sequences (conventional data) "], 17 | ["3", "12", "Single level report sequences (satellite data) "], 18 | ["3", "13", "Sequences common to image data "], 19 | ["3", "14", "Reserved "], 20 | ["3", "15", "Oceanographic report sequences "], 21 | ["3", "16", "Synoptic feature sequences"], 22 | ["3", "18", "Radiological report sequences"], 23 | ["3", "21", "Radar report sequences"], 24 | ["3", "22", "Chemical and aerosol sequences"], 25 | ["3", "40", "Additional satellite report sequences"] 26 | ] 27 | } 28 | -------------------------------------------------------------------------------- /pybufrkit/tables/0/98_0/1/TableD.json: -------------------------------------------------------------------------------- 1 | { 2 | "301193": [ "", [ "001007", "001031", "002196", "002221", "002222" ] ], 3 | "301194": [ "", [ "001194", "001012", "001013", "002011", "002012", "301011", "301012", "301023", "007001" ] ], 4 | "301195": [ "", [ "001195", "001012", "001013", "002011", "002012", "301011", "301012", "301023", "007001" ] ], 5 | "301196": [ "", [ "301003", "002011", "002012", "301011", "301012", "301023", "007001" ] ], 6 | "301197": [ "", [ "001006", "001008", "002061", "002062", "002002", "002005", "002070", "002063", "002001" ] ], 7 | "301198": [ "", [ "001011", "001012", "001013", "002011", "002012", "301011", "301012", "301023", "007001" ] ], 8 | "301200": [ "", [ "001032", "033194" ] ], 9 | "301201": [ "", [ "101003", "033193" ] ], 10 | "301202": [ "", [ "001031", "001032" ] ], 11 | "301237": [ 12 | "", [ 13 | "001007", "001012", "002021", "301011", "004004", "004005", "201138", "202131", "004006", "201000", "202000", 14 | "301023" 15 | ] 16 | ], 17 | "301238": [ 18 | "", [ 19 | "002104", "002121", "002113", "002026", "002027", "002111", "002192", "202127", "001013", "202126", "007001", 20 | "202000", "025010", "021194" 21 | ] 22 | ], 23 | "301239": [ "", [ "002111", "002112", "021192", "021193", "021195" ] ], 24 | "301240": [ "", [ "201131", "202129", "022021", "201000", "202000" ] ], 25 | "301241": [ "", [ "201141", "202130", "007001", "201000", "202000" ] ], 26 | "301242": [ "", [ "021207", "021208", "021209", "021210", "021211", "021212" ] ], 27 | "301250": [ "", [ "301193", "301011", "301013", "301021" ] ], 28 | "302205": [ "", [ "201131", "202129", "022021", "201000", "202000" ] ], 29 | "302206": [ "", [ "302205", "201130", "202129", "022011", "201000", "202000", "022001", "011001", "011002" ] ], 30 | "302207": [ "", [ "022193", "022194", "022195", "022196", "022197" ] ], 31 | "302250": [ "", [ "102000", "031001", "020193", "020194", "020012" ] ], 32 | "303249": [ "", [ "002252", "104000", "031001", "002199", "007004", "007004", "013003" ] ], 33 | "303250": [ "", [ "002252", "002023", "007004", "011001", "011002", "002197", "002198", "012193" ] ], 34 | "303251": [ "", [ "002252", "105000", "031001", "002254", "002251", "002197", "002198", "012063" ] ], 35 | "303252": [ "", [ "002252", "105000", "031001", "002254", "002251", "002197", "002198", "012194" ] ], 36 | "304228": [ "", [ "005217", "006217", "007217" ] ], 37 | "304229": [ "", [ "001208", "001209", "001210" ] ], 38 | "304250": [ 39 | "", [ 40 | "002231", "002232", "008012", "007024", "002057", "008021", "004001", "004002", "004003", "004004", "008021", 41 | "004024", "110004", "008021", "004004", "004005", "004006", "008021", "004004", "004005", "004006", "011001", 42 | "011002", "103010", "002231", "007004", "012001" 43 | ] 44 | ], 45 | "309194": [ "", [ "301194", "302004", "101000", "031001", "303014" ] ], 46 | "309195": [ "", [ "301195", "302004", "101000", "031001", "303014" ] ], 47 | "309196": [ "", [ "301196", "302004", "101000", "031001", "303014" ] ], 48 | "309198": [ "", [ "301198", "302004", "101000", "031001", "303014" ] ], 49 | "310193": [ "", [ "301250", "303250", "302250", "303249", "303251" ] ], 50 | "310194": [ "", [ "301250", "303250", "302250", "303249", "303252" ] ], 51 | "310195": [ "", [ "301250", "303250", "304250" ] ], 52 | "310196": [ "", [ "301250", "303249", "303251" ] ], 53 | "310226": [ 54 | "", [ 55 | "310022", "025060", "008021", "301011", "301012", "201138", "202131", "004006", "202000", "201000", "033039", 56 | "033007", "304030", "304031", "002020", "001050", "202127", "304030", "202000", "304031", "201133", "202131", 57 | "004016", "202000", "201000", "301021", "304030", "010035", "005021", "010036", "107000", "031002", "301021", 58 | "005021", "103000", "031001", "002121", "007040", "015037" 59 | ] 60 | ], 61 | "311193": [ 62 | "", [ 63 | "301197", "301011", "301012", "301023", "008004", "007004", "008021", "011001", "011002", "011031", "011034", 64 | "011035", "012001", "012003", "013003", "020041" 65 | ] 66 | ], 67 | "312200": [ 68 | "", [ "301237", "301238", "029002", "021206", "104012", "006232", "102012", "005232", "021205", "021196" ] 69 | ], 70 | "312201": [ "", [ "301237", "101003", "301239", "011012", "011011", "021197" ] ], 71 | "312202": [ 72 | "", [ 73 | "301237", "008022", "011012", "011050", "301240", "022243", "301241", "010050", "021198", "021201", "021202", 74 | "021203", "301242" 75 | ] 76 | ], 77 | "312203": [ "", [ "301237", "008022", "012061", "022050", "021204", "021199", "021214", "021215" ] ], 78 | "312204": [ 79 | "", [ 80 | "312201", "001031", "011012", "011011", "021200", "021213", "004004", "008021", "004024", "055003", "011012", 81 | "011011" 82 | ] 83 | ], 84 | "312207": [ "", [ "312202", "301202", "033191" ] ], 85 | "312208": [ 86 | "", [ 87 | "301202", "008022", "008021", "301011", "301013", "301023", "302205", "011002", "001007", "002021", "301011", 88 | "301013", "301023", "001032", "001192", "302205", "011002" 89 | ] 90 | ], 91 | "312209": [ 92 | "", [ "301202", "001192", "301011", "301013", "301023", "302206", "104000", "022192", "102000", "005232", "022191" ] 93 | ], 94 | "312210": [ 95 | "", [ 96 | "312202", "021192", "015202", "301011", "004004", "004005", "201138", "202131", "004006", "201000", "202000", 97 | "304228", "304229" 98 | ] 99 | ], 100 | "312211": [ 101 | "", [ 102 | "301046", "301011", "301013", "301023", "312031", "101004", "312030", "021110", "101004", "312212", "021111", 103 | "101004", "312212", "021112", "101004", "312212", "021113", "101004", "312212" 104 | ] 105 | ], 106 | "312212": [ "", [ "301023", "321027" ] ] 107 | } -------------------------------------------------------------------------------- /pybufrkit/tables/0/98_0/101/TableD.json: -------------------------------------------------------------------------------- 1 | { 2 | "301193": [ "", [ "001007", "001031", "002196", "002221", "002222" ] ], 3 | "301194": [ "", [ "001194", "001012", "001013", "002011", "002012", "301011", "301012", "301023", "007001" ] ], 4 | "301195": [ "", [ "001195", "001012", "001013", "002011", "002012", "301011", "301012", "301023", "007001" ] ], 5 | "301196": [ "", [ "301003", "002011", "002012", "301011", "301012", "301023", "007001" ] ], 6 | "301197": [ "", [ "001006", "001008", "002061", "002062", "002002", "002005", "002070", "002063", "002001" ] ], 7 | "301198": [ "", [ "001011", "001012", "001013", "002011", "002012", "301011", "301012", "301023", "007001" ] ], 8 | "301200": [ "", [ "001032", "033194" ] ], 9 | "301201": [ "", [ "101003", "033193" ] ], 10 | "301202": [ "", [ "001031", "001032" ] ], 11 | "301237": [ 12 | "", [ 13 | "001007", "001012", "002021", "301011", "004004", "004005", "201138", "202131", "004006", "201000", "202000", 14 | "301023" 15 | ] 16 | ], 17 | "301238": [ 18 | "", [ 19 | "002104", "002121", "002113", "002026", "002027", "002111", "002192", "202127", "001013", "202126", "007001", 20 | "202000", "025010", "021194" 21 | ] 22 | ], 23 | "301239": [ "", [ "002111", "002112", "021192", "021193", "021195" ] ], 24 | "301240": [ "", [ "201131", "202129", "022021", "201000", "202000" ] ], 25 | "301241": [ "", [ "201141", "202130", "007001", "201000", "202000" ] ], 26 | "301242": [ "", [ "021207", "021208", "021209", "021210", "021211", "021212" ] ], 27 | "301250": [ "", [ "301193", "301011", "301013", "301021" ] ], 28 | "302205": [ "", [ "201131", "202129", "022021", "201000", "202000" ] ], 29 | "302206": [ "", [ "302205", "201130", "202129", "022011", "201000", "202000", "022001", "011001", "011002" ] ], 30 | "302207": [ "", [ "022193", "022194", "022195", "022196", "022197" ] ], 31 | "302250": [ "", [ "102000", "031001", "020193", "020194", "020012" ] ], 32 | "303249": [ "", [ "002252", "104000", "031001", "002199", "007004", "007004", "013003" ] ], 33 | "303250": [ "", [ "002252", "002023", "007004", "011001", "011002", "002197", "002198", "012193" ] ], 34 | "303251": [ "", [ "002252", "105000", "031001", "002254", "002251", "002197", "002198", "012063" ] ], 35 | "303252": [ "", [ "002252", "105000", "031001", "002254", "002251", "002197", "002198", "012194" ] ], 36 | "304228": [ "", [ "005217", "006217", "007217" ] ], 37 | "304229": [ "", [ "001208", "001209", "001210" ] ], 38 | "304250": [ 39 | "", [ 40 | "002231", "002232", "008012", "007024", "002057", "008021", "004001", "004002", "004003", "004004", "008021", 41 | "004024", "110004", "008021", "004004", "004005", "004006", "008021", "004004", "004005", "004006", "011001", 42 | "011002", "103010", "002231", "007004", "012001" 43 | ] 44 | ], 45 | "309194": [ "", [ "301194", "302004", "101000", "031001", "303014" ] ], 46 | "309195": [ "", [ "301195", "302004", "101000", "031001", "303014" ] ], 47 | "309196": [ "", [ "301196", "302004", "101000", "031001", "303014" ] ], 48 | "309198": [ "", [ "301198", "302004", "101000", "031001", "303014" ] ], 49 | "310193": [ "", [ "301250", "303250", "302250", "303249", "303251" ] ], 50 | "310194": [ "", [ "301250", "303250", "302250", "303249", "303252" ] ], 51 | "310195": [ "", [ "301250", "303250", "304250" ] ], 52 | "310196": [ "", [ "301250", "303249", "303251" ] ], 53 | "310226": [ 54 | "", [ 55 | "310022", "025060", "008021", "301011", "301012", "201138", "202131", "004006", "202000", "201000", "033039", 56 | "033007", "304030", "304031", "002020", "001050", "202127", "304030", "202000", "304031", "201133", "202131", 57 | "004016", "202000", "201000", "301021", "304030", "010035", "005021", "010036", "107000", "031002", "301021", 58 | "005021", "103000", "031001", "002121", "007040", "015037" 59 | ] 60 | ], 61 | "311193": [ 62 | "", [ 63 | "301197", "301011", "301012", "301023", "008004", "007004", "008021", "011001", "011002", "011031", "011034", 64 | "011035", "012001", "012003", "013003", "020041" 65 | ] 66 | ], 67 | "312200": [ 68 | "", [ "301237", "301238", "029002", "021206", "104012", "006232", "102012", "005232", "021205", "021196" ] 69 | ], 70 | "312201": [ "", [ "301237", "101003", "301239", "011012", "011011", "021197" ] ], 71 | "312202": [ 72 | "", [ 73 | "301237", "008022", "011012", "011050", "301240", "022243", "301241", "010050", "021198", "021201", "021202", 74 | "021203", "301242" 75 | ] 76 | ], 77 | "312203": [ "", [ "301237", "008022", "012061", "022050", "021204", "021199", "021214", "021215" ] ], 78 | "312207": [ "", [ "312202", "301202", "033191" ] ], 79 | "312208": [ 80 | "", [ 81 | "301202", "008022", "008021", "301011", "301013", "301023", "302205", "011002", "001007", "002021", "301011", 82 | "301013", "301023", "001032", "001192", "302205", "011002" 83 | ] 84 | ], 85 | "312209": [ 86 | "", [ "301202", "001192", "301011", "301013", "301023", "302206", "104000", "022192", "102000", "005232", "022191" ] 87 | ], 88 | "312210": [ 89 | "", [ 90 | "312202", "021192", "015202", "301011", "004004", "004005", "201138", "202131", "004006", "201000", "202000", 91 | "304228", "304229" 92 | ] 93 | ], 94 | "312211": [ 95 | "", [ 96 | "301046", "301011", "301013", "301023", "312031", "101004", "312030", "021110", "101004", "312212", "021111", 97 | "101004", "312212", "021112", "101004", "312212", "021113", "101004", "312212" 98 | ] 99 | ], 100 | "312212": [ "", [ "301023", "321027" ] ] 101 | } -------------------------------------------------------------------------------- /pybufrkit/tables/0/98_0/2/TableB.json: -------------------------------------------------------------------------------- 1 | { 2 | "005234": [ "PROFILE NUMBER", "Numeric", 0, 0, 32, "NA", 0, 0 ], 3 | "005236": [ "OBSERVATION IDENTIFIER", "Numeric", 0, 0, 32, "NA", 0, 0 ], 4 | "005237": [ "RECEIVER CHANNEL", "CODE TABLE", 0, 0, 2, "NA", 0, 0 ], 5 | "007200": [ "HEIGHT (high resolution)", "m", 3, -10000000, 26, "NA", 0, 0 ], 6 | "008201": [ "COORDINATES SIGNIFICANCE", "CODE TABLE", 0, 0, 4, "NA", 0, 0 ], 7 | "025192": [ "CONFIDENCE FLAG", "CODE TABLE", 0, 0, 4, "NA", 0, 0 ], 8 | "040214": [ "LIDAR L2B CLASSIFICATION TYPE", "CODE TABLE", 0, 0, 4, "NA", 0, 0 ], 9 | "040215": [ "SATELLITE RANGE", "m", 0, 380000, 18, "NA", 0, 0 ], 10 | "040216": [ "HORIZONTAL OBSERVATION INTEGRATION LENGTH", "m", 0, 0, 26, "NA", 0, 0 ], 11 | "040217": [ "HORIZONTAL LINE OF SIGHT WIND", "m/s", 2, -32767, 16, "NA", 0, 0 ], 12 | "040218": [ "ERROR ESTIMATE OF HORIZONTAL LINE OF SIGHT WIND", "m/s", 2, 0, 15, "NA", 0, 0 ], 13 | "040219": [ "BACKSCATTER RATIO", "Numeric", 3, 500, 20, "NA", 0, 0 ], 14 | "040220": [ "DERIVATIVE WIND TO PRESSURE", "m s-1 Pa-1", 3, -100000, 18, "NA", 0, 0 ], 15 | "040221": [ "DERIVATIVE WIND TO TEMPERATURE", "m s-1 K-1", 3, -100000, 18, "NA", 0, 0 ], 16 | "040222": [ "DERIVATIVE WIND TO BACKSCATTER RATIO", "m/s", 3, -200000, 19, "NA", 0, 0 ] 17 | } -------------------------------------------------------------------------------- /pybufrkit/tables/0/98_0/2/TableD.json: -------------------------------------------------------------------------------- 1 | { 2 | "340192": [ 3 | "", [ 4 | "001007", "002019", "001033", "001034", "004001", "004002", "004003", "004004", "004005", "004007", "005234", 5 | "005236", "005237", "040214", "008201", "005001", "006001", "004016", "008201", "005001", "006001", "004016", 6 | "008201", "005001", "006001", "004016", "008201", "007200", "005021", "007021", "040215", "008201", "007200", 7 | "005021", "007021", "040215", "008201", "007200", "005021", "007021", "040215", "040216", "040217", "040218", 8 | "025192", "010004", "012001", "040219", "040220", "040221", "040222" 9 | ] 10 | ] 11 | } -------------------------------------------------------------------------------- /pybufrkit/tables/0/98_0/2/code_and_flag.json: -------------------------------------------------------------------------------- 1 | {"005237": [[0, "Mie"], [1, "Rayleigh"]], "008201": [[0, "Satellite coordinates"], [1, "Observations coordinates"], [2, "Start of observation"], [3, "End of observation"], [4, "Centre of gravity of observation"], [5, "Top of the observation"], [6, "Bottom of the observation"], [7, "Vertical centre of gravity of the observation"], [8, "RESERVED"], [9, "RESERVED"], [10, "RESERVED"], [11, "RESERVED"], [12, "RESERVED"], [13, "RESERVED"], [14, "RESERVED"], [15, "MISSING VALUE"]], "025192": [[0, "Valid"], [1, "Invalid"]], "040214": [[0, "Clear"], [1, "Could"]]} -------------------------------------------------------------------------------- /pybufrkit/tables/0/98_0/3/TableB.json: -------------------------------------------------------------------------------- 1 | { 2 | "005234": [ "PROFILE NUMBER", "Numeric", 0, 0, 16, "NA", 0, 5 ], 3 | "005236": [ "OBSERVATION IDENTIFIER", "Numeric", 0, 0, 30, "NA", 0, 10 ], 4 | "005237": [ "RECEIVER CHANNEL", "CODE TABLE", 0, 0, 2, "NA", 0, 1 ], 5 | "007200": [ "HEIGHT (high resolution)", "m", 3, -10000000, 26, "NA", 3, 8 ], 6 | "008201": [ "COORDINATES SIGNIFICANCE", "CODE TABLE", 0, 0, 8, "NA", 0, 3 ], 7 | "025192": [ "CONFIDENCE FLAG", "CODE TABLE", 0, 0, 4, "NA", 0, 2 ], 8 | "033192": [ "SCAN LINE QUALITY FLAG FOR SAPHIR/MADRAS", "FLAG TABLE", 0, 0, 10, "FLAG TABLE", 0, 4 ], 9 | "033193": [ "PAYLOAD MODE FOR SAPHIR", "CODE TABLE", 0, 0, 3, "CODE TABLE", 0, 1 ], 10 | "033194": [ "PAYLOAD MODE FOR MADRAS", "CODE TABLE", 0, 0, 3, "CODE TABLE", 0, 1 ], 11 | "033195": [ "SATELLITE MODE FOR SAPHIR/MADRAS", "CODE TABLE", 0, 0, 4, "CODE TABLE", 0, 2 ], 12 | "033196": [ "CHANNEL QUALITY FLAG FOR SAPHIR/MADRAS", "FLAG TABLE", 0, 0, 11, "FLAG TABLE", 0, 4 ], 13 | "033197": [ "CALIBRATION FLAGS FOR SAPHIR/MADRAS", "CODE TABLE", 0, 0, 3, "CODE TABLE", 0, 1 ], 14 | "040214": [ "LIDAR L2B CLASSIFICATION TYPE", "CODE TABLE", 0, 0, 4, "NA", 0, 1 ], 15 | "040215": [ "SATELLITE RANGE", "m", 0, 380000, 18, "NA", 0, 6 ], 16 | "040216": [ "HORIZONTAL OBSERVATION INTEGRATION LENGTH", "m", 0, 0, 26, "NA", 0, 8 ], 17 | "040217": [ "HORIZONTAL LINE OF SIGHT WIND", "m/s", 2, -32767, 16, "NA", 2, 5 ], 18 | "040218": [ "ERROR ESTIMATE OF HORIZONTAL LINE OF SIGHT WIND", "m/s", 2, 0, 15, "NA", 2, 5 ], 19 | "040219": [ "BACKSCATTER RATIO", "Numeric", 3, 500, 20, "NA", 3, 7 ], 20 | "040220": [ "DERIVATIVE WIND TO PRESSURE", "m s-1 Pa-1", 3, -100000, 18, "NA", 3, 6 ], 21 | "040221": [ "DERIVATIVE WIND TO TEMPERATURE", "m s-1 K-1", 3, -100000, 18, "NA", 3, 6 ], 22 | "040222": [ "DERIVATIVE WIND TO BACKSCATTER RATIO", "m/s", 3, -200000, 19, "NA", 3, 6 ] 23 | } -------------------------------------------------------------------------------- /pybufrkit/tables/0/98_0/3/TableD.json: -------------------------------------------------------------------------------- 1 | { 2 | "310195": [ "", [ "310196", "101006", "310197" ] ], 3 | "310196": [ 4 | "", [ 5 | "008070", "001033", "001034", "008070", "001033", "001034", "001007", "002019", "005040", "025075", "201133", 6 | "005041", "201000", "005043", "025070", "033192", "033193", "004001", "004002", "004003", "004004", "004005", 7 | "202131", "201138", "004006", "201000", "202000", "005001", "006001", "202126", "007001", "202000", "007024", 8 | "005021", "007025", "005022", "025081", "033195", "002151", "012064", "002151", "012064", "002151", "012064", 9 | "002151", "012064" 10 | ] 11 | ], 12 | "310197": [ 13 | "", [ 14 | "002150", "025076", "025077", "025078", "033196", "033197", "008065", "013040", "201132", "202129", "012063", 15 | "202000", "201000" 16 | ] 17 | ], 18 | "340192": [ 19 | "", [ 20 | "001007", "002019", "001033", "001034", "004001", "004002", "004003", "004004", "004005", "004007", "005234", 21 | "005236", "005237", "040214", "008201", "005001", "006001", "004016", "008201", "005001", "006001", "004016", 22 | "008201", "005001", "006001", "004016", "008201", "007200", "005021", "007021", "040215", "008201", "007200", 23 | "005021", "007021", "040215", "008201", "007200", "005021", "007021", "040215", "040216", "040217", "040218", 24 | "025192", "010004", "012001", "040219", "040220", "040221", "040222" 25 | ] 26 | ] 27 | } -------------------------------------------------------------------------------- /pybufrkit/tables/0/98_0/3/code_and_flag.json: -------------------------------------------------------------------------------- 1 | {"005237": [[0, "Mie"], [1, "Rayleigh"], [2, "RESERVED"], [3, "MISSING VALUE"]], "008201": [[0, "Satellite coordinates"], [1, "Observations coordinates"], [2, "Start of observation"], [3, "End of observation"], [4, "Horizontal centre of gravity of the observation"], [5, "Vertical centre of gravity of the observatio"], [6, "Top of the observation"], [7, "Bottom of the observation"], [8, "RESERVED"], [9, "RESERVED"], [10, "RESERVED"], [11, "RESERVED"], [12, "RESERVED"], [13, "RESERVED"], [14, "RESERVED"], [255, "MISSING VALUE"]], "025192": [[0, "Valid"], [1, "Invalid"], [2, "RESERVED"], [3, "RESERVED"], [4, "RESERVED"], [5, "RESERVED"], [6, "RESERVED"], [7, "RESERVED"], [8, "RESERVED"], [9, "RESERVED"], [10, "RESERVED"], [11, "RESERVED"], [12, "RESERVED"], [13, "RESERVED"], [14, "RESERVED"], [15, "MISSING"]], "040214": [[0, "Clear"], [1, "Cloud"], [2, "RESERVED"], [3, "RESERVED"], [4, "RESERVED"], [5, "RESERVED"], [6, "RESERVED"], [7, "RESERVED"], [8, "RESERVED"], [9, "RESERVED"], [10, "RESERVED"], [11, "RESERVED"], [12, "RESERVED"], [13, "RESERVED"], [14, "RESERVED"], [15, "RESERVED"]]} -------------------------------------------------------------------------------- /pybufrkit/tablespreparer.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import, print_function 2 | 3 | import argparse 4 | import csv 5 | import io 6 | import json 7 | import os 8 | import zipfile 9 | 10 | try: # py3 11 | from urllib.request import urlopen 12 | except ImportError: # py2 13 | from urllib2 import urlopen 14 | 15 | __all__ = ['prepare_wmo_tables'] 16 | 17 | 18 | def prepare_wmo_tables(version, tag=None, output_dir='.'): 19 | tag = tag or version 20 | data = download_wmo_bufr_tables_release(version, tag) 21 | tables = convert_tables_from_zip(version, data) 22 | write_tables(version, tables, output_dir) 23 | 24 | 25 | def download_wmo_bufr_tables_release(version, tag): 26 | """ 27 | Download WMO BUFR4 tables release of the specified version from its GitHub repo 28 | """ 29 | download_url = 'https://github.com/wmo-im/BUFR4/archive/refs/tags/v{}.zip'.format(tag) 30 | print('Downloading WMO tables version {} from {}'.format(version, download_url)) 31 | ins = urlopen(download_url) 32 | return ins.read() 33 | 34 | 35 | def convert_tables_from_zip(version, data): 36 | print('Converting tables') 37 | zf = zipfile.ZipFile(io.BytesIO(data), 'r') 38 | table_b = {} 39 | table_d = {} 40 | table_code_and_flag = {} 41 | for fileinfo in zf.infolist(): 42 | if fileinfo.filename.startswith('BUFR4-{}{}BUFRCREX_TableB_en_'.format(version, os.path.sep)): 43 | # print('Table B: ' + fileinfo.filename) 44 | table_b.update(process_table_b(zf.read(fileinfo).decode('utf-8'))) 45 | elif fileinfo.filename.startswith('BUFR4-{}{}BUFR_TableD_en_'.format(version, os.path.sep)): 46 | table_d.update(process_table_d(zf.read(fileinfo).decode('utf-8'))) 47 | elif fileinfo.filename.startswith('BUFR4-{}{}BUFRCREX_CodeFlag_en_'.format(version, os.path.sep)): 48 | table_code_and_flag.update(process_table_code_and_flag(zf.read(fileinfo).decode('utf-8'))) 49 | # TODO: MetaA and MetaC 50 | 51 | return { 52 | 'b': table_b, 53 | 'd': table_d, 54 | 'code_and_flag': table_code_and_flag, 55 | } 56 | 57 | 58 | def write_tables(version, tables, output_dir): 59 | base_dir = os.path.join(output_dir, '{}'.format(version)) 60 | print('Saving tables inside folder: {}'.format(base_dir)) 61 | os.makedirs(base_dir, exist_ok=True) 62 | with open(os.path.join(base_dir, 'TableB.json'), 'w') as outs: 63 | json.dump(tables['b'], outs, sort_keys=True) 64 | with open(os.path.join(base_dir, 'TableD.json'), 'w') as outs: 65 | json.dump(tables['d'], outs, sort_keys=True) 66 | with open(os.path.join(base_dir, 'code_and_flag.json'), 'w') as outs: 67 | json.dump(tables['code_and_flag'], outs, sort_keys=True) 68 | print('Done') 69 | 70 | 71 | def process_table_b(content): 72 | lines = csv.reader(io.StringIO(content), quoting=csv.QUOTE_MINIMAL) 73 | next(lines) # skip header 74 | # WMO output is inconsistent and can have extra comma after 3rd column (name) 75 | offset = 0 76 | d = {} 77 | for line in lines: 78 | crex_scale = 0 if line[9 + offset] == '' else int(line[9 + offset]) 79 | crex_data_width = 0 if line[10 + offset] == '' else int(line[10 + offset]) 80 | d[line[2]] = [line[3], line[4 + offset], int(line[5 + offset]), int(line[6 + offset]), int(line[7 + offset]), 81 | line[8 + offset], crex_scale, crex_data_width] 82 | return d 83 | 84 | 85 | def process_table_d(content): 86 | lines = csv.reader(io.StringIO(content), quoting=csv.QUOTE_MINIMAL) 87 | next(lines) # skip header 88 | d = {} 89 | for line in lines: 90 | entry = d.setdefault(line[2], [line[3], []]) 91 | entry[1].append(line[5]) 92 | return d 93 | 94 | 95 | def process_table_code_and_flag(content): 96 | lines = csv.reader(io.StringIO(content), quoting=csv.QUOTE_MINIMAL) 97 | next(lines) # skip header 98 | d = {} 99 | for line in lines: 100 | entry = d.setdefault(line[0], []) 101 | entry.append([line[2], line[3]]) 102 | return d 103 | 104 | 105 | if __name__ == '__main__': 106 | ap = argparse.ArgumentParser( 107 | description='Download BUFR tables published by WMO amd convert them to PyBufrKit format') 108 | ap.add_argument('version', type=int, help='the table version') 109 | ap.add_argument('--tag', help='the release tag (same as the table version if not specified') 110 | ns = ap.parse_args() 111 | prepare_wmo_tables(ns.version, str(ns.version) if ns.tag is None else ns.tag) 112 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [aliases] 2 | test=pytest -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """ 2 | Python toolkit to work with BUFR messages. 3 | """ 4 | import os 5 | 6 | from setuptools import setup 7 | 8 | 9 | def get_version(): 10 | with open(os.path.join(os.path.dirname(__file__), 'pybufrkit', '__init__.py')) as ins: 11 | for line in ins.readlines(): 12 | if line.startswith('__version__'): 13 | return line.split('=')[1].strip()[1:-1] 14 | 15 | 16 | def get_requirements(): 17 | requirements = ['bitstring>=3.1.3', 'six'] 18 | return requirements 19 | 20 | 21 | setup( 22 | name='pybufrkit', 23 | version=get_version(), 24 | platforms=['any'], 25 | packages=['pybufrkit'], 26 | package_dir={'pybufrkit': 'pybufrkit'}, 27 | include_package_data=True, 28 | setup_requires=["pytest-runner"], 29 | install_requires=get_requirements(), 30 | tests_require=['pytest'], 31 | entry_points={ 32 | 'console_scripts': ['pybufrkit = pybufrkit:main'], 33 | }, 34 | 35 | author='Yang Wang', 36 | author_email='ywangd@gmail.com', 37 | description='Python toolkit to work with BUFR files', 38 | long_description=__doc__, 39 | license='MIT', 40 | classifiers=[ 41 | "Development Status :: 5 - Production/Stable", 42 | "Environment :: Console", 43 | "Intended Audience :: Developers", 44 | "Intended Audience :: Science/Research", 45 | "Operating System :: OS Independent", 46 | "License :: OSI Approved :: MIT License", 47 | "Programming Language :: Python :: 2.7", 48 | "Programming Language :: Python :: 3.5", 49 | "Programming Language :: Python :: 3.6", 50 | "Programming Language :: Python :: 3.7", 51 | "Programming Language :: Python :: 3.8", 52 | "Programming Language :: Python :: 3.9", 53 | "Programming Language :: Python :: 3.10", 54 | "Programming Language :: Python :: 3.11", 55 | "Topic :: Utilities", 56 | ], 57 | keywords=['BUFR', 'WMO'], 58 | url='https://github.com/ywangd/pybufrkit', 59 | ) 60 | -------------------------------------------------------------------------------- /tests/benchmark_data/ISMD01_OKPR.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ISMD01_OKPR.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ISND02_LLBD.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ISND02_LLBD.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/IUSD40_OKLI.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/IUSD40_OKLI.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/aaen_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/aaen_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/aben_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/aben_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ahws_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ahws_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/airc_142.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/airc_142.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/airc_144.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/airc_144.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/airs_57.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/airs_57.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/alws_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/alws_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/amda_144.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/amda_144.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/amsa_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/amsa_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/amsb_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/amsb_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/amse_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/amse_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/amsu_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/amsu_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/amv2_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/amv2_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/amv3_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/amv3_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/asbh_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/asbh_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/asbl_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/asbl_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/asca_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/asca_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/asch_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/asch_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ascs_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ascs_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/aseh_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/aseh_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/asel_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/asel_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ashs_139.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ashs_139.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/asr3_190.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/asr3_190.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/atap_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/atap_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ateu_155.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ateu_155.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/atms_201.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/atms_201.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/atov_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/atov_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/avhm_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/avhm_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/avhn_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/avhn_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/avhr_58.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/avhr_58.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/b002_95.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/b002_95.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/b002_96.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/b002_96.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/b003_56.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/b003_56.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/b004_145.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/b004_145.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/b005_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/b005_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/b005_89.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/b005_89.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/b006_96.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/b006_96.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/b007_31.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/b007_31.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/bssh_170.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/bssh_170.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/bssh_176.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/bssh_176.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/bssh_178.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/bssh_178.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/bssh_180.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/bssh_180.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/btem_109.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/btem_109.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/btem_111.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/btem_111.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/buoy_27.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/buoy_27.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/cmwi_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/cmwi_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/cmwn_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/cmwn_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/cnow_28.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/cnow_28.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/cori_156.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/cori_156.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/crex_7.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/crex_7.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/crit_202.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/crit_202.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/csrh_189.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/csrh_189.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/emsg_189.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/emsg_189.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/emsg_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/emsg_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/euwv_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/euwv_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/fy3a_154.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/fy3a_154.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/fy3b_154.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/fy3b_154.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/g2nd_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/g2nd_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/g2to_206.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/g2to_206.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/go15_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/go15_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/goee_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/goee_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/goes_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/goes_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/goga_89.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/goga_89.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/grst_26.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/grst_26.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/gsd1_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/gsd1_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/gsd2_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/gsd2_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/gsd3_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/gsd3_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/gst4_26.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/gst4_26.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/hirb_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/hirb_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/hirs_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/hirs_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ias1_240.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ias1_240.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/iasi_241.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/iasi_241.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ifco_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ifco_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ikco_217.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ikco_217.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/itrg_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/itrg_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/itwt_233.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/itwt_233.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/j2eo_216.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/j2eo_216.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/j2nb_216.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/j2nb_216.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/jaso_214.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/jaso_214.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/jason2.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/jason2.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/kond_209.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/kond_209.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/maer_207.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/maer_207.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/masr_190.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/masr_190.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/meta_140.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/meta_140.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/mhen_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/mhen_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/mhsa_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/mhsa_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/mhsb_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/mhsb_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/mhse_55.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/mhse_55.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/mloz_206.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/mloz_206.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/modi_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/modi_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/modw_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/modw_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/monw_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/monw_87.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/mpco_217.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/mpco_217.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nomi_206.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nomi_206.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nos1_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nos1_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nos2_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nos2_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nos3_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nos3_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nos4_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nos4_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nos5_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nos5_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nos6_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nos6_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nos7_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nos7_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/nos8_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/nos8_208.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ocea_131.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ocea_131.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ocea_132.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ocea_132.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ocea_133.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ocea_133.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ocea_21.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ocea_21.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/pgps_110.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/pgps_110.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/pilo_91.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/pilo_91.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/rada_250.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/rada_250.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/rado_250.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/rado_250.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/s4kn_165.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/s4kn_165.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/sato_84.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/sato_84.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/sb19_206.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/sb19_206.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/sbu8_206.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/sbu8_206.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/sentinel1.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/sentinel1.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ship_11.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ship_11.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ship_12.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ship_12.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ship_13.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ship_13.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ship_14.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ship_14.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ship_19.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ship_19.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ship_9.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ship_9.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/smin_49.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/smin_49.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/smis_49.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/smis_49.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/smiu_49.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/smiu_49.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/smos_203.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/smos_203.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/sn4k_165.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/sn4k_165.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/soil_7.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/soil_7.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/ssbt_127.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/ssbt_127.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/stuk_7.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/stuk_7.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/syno_1.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/syno_1.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/syno_2.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/syno_2.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/syno_3.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/syno_3.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/syno_4.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/syno_4.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/temp_101.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/temp_101.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/temp_102.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/temp_102.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/temp_106.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/temp_106.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/tmr7_129.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/tmr7_129.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/tros_31.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/tros_31.bufr -------------------------------------------------------------------------------- /tests/benchmark_data/wavb_134.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/benchmark_data/wavb_134.bufr -------------------------------------------------------------------------------- /tests/data/207003.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/207003.bufr -------------------------------------------------------------------------------- /tests/data/207003.datadump.cmp: -------------------------------------------------------------------------------- 1 | ###### subset 1 of 2 ###### 2 | 310060 (CrIS (Cross-Track Infrared Sounder) radiance data) 3 | 001007 SATELLITE IDENTIFIER 224 4 | 001033 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE 160 5 | 002019 SATELLITE INSTRUMENTS 620 6 | 002020 SATELLITE CLASSIFICATION 3 7 | 301011 (Year, month, day) 8 | 004001 YEAR 2012 9 | 004002 MONTH 11 10 | 004003 DAY 2 11 | 301012 (Hour, minute) 12 | 004004 HOUR 0 13 | 004005 MINUTE 0 14 | 207003 15 | 004006 SECOND 27.584 16 | 207000 17 | 304030 (Location of platform) 18 | 027031 IN DIRECTION OF 0 DEGREES LONGITUDE, DISTANCE FROM THE EARTH'S C 6675220.0 19 | 028031 IN DIRECTION 90 DEGREES EAST, DISTANCE FROM THE EARTH'S CENTRE 2628450.5 20 | 010031 IN DIRECTION OF THE NORTH POLE, DISTANCE FROM THE EARTH'S CENTRE 696570.75 21 | 301021 (Latitude/longitude (high accuracy)) 22 | 005001 LATITUDE (HIGH ACCURACY) 4.96669 23 | 006001 LONGITUDE (HIGH ACCURACY) 24.54144 24 | 007024 SATELLITE ZENITH ANGLE 25.41 25 | 005021 BEARING OR AZIMUTH 282.91 26 | 007025 SOLAR ZENITH ANGLE 150.05 27 | 005022 SOLAR AZIMUTH 111.28 28 | 008075 ASCENDING/DESCENDING ORBIT QUALIFIER 1 29 | 201133 30 | 005041 SCAN LINE NUMBER 1 31 | 201000 32 | 005045 FIELD OF REGARD NUMBER 9 33 | 005043 FIELD OF VIEW NUMBER 7 34 | 005040 ORBIT NUMBER 5258L 35 | 010001 HEIGHT OF LAND SURFACE 597 36 | 201129 37 | 007002 HEIGHT OR ALTITUDE 829880.0 38 | 201000 39 | 202127 40 | 201125 41 | 021166 LAND FRACTION 1.0 42 | 201000 43 | 202000 44 | 008012 LAND/SEA QUALIFIER 0 45 | 020010 CLOUD COVER (TOTAL) None 46 | 020014 HEIGHT OF TOP OF CLOUD None 47 | 002165 RADIANCE TYPE FLAG 2048 48 | 033075 SCAN LEVEL QUALITY FLAG 0 49 | 107003 50 | # --- 1 of 3 replications --- 51 | 008076 TYPE OF BAND 2 52 | 006029 WAVE NUMBER 65000.0 53 | 006029 WAVE NUMBER 109500.0 54 | 025140 START CHANNEL 1 55 | 025141 END CHANNEL 713 56 | 033076 CALIBRATION QUALITY FLAG 0 57 | 033077 FIELD OF VIEW QUALITY FLAG 1024 58 | # --- 2 of 3 replications --- 59 | 008076 TYPE OF BAND 3 60 | 006029 WAVE NUMBER 121000.0 61 | 006029 WAVE NUMBER 175000.0 62 | 025140 START CHANNEL 714 63 | 025141 END CHANNEL 1146 64 | 033076 CALIBRATION QUALITY FLAG 0 65 | 033077 FIELD OF VIEW QUALITY FLAG 1024 66 | # --- 3 of 3 replications --- 67 | 008076 TYPE OF BAND 4 68 | 006029 WAVE NUMBER 215500.0 69 | 006029 WAVE NUMBER 255000.0 70 | 025140 START CHANNEL 1147 71 | 025141 END CHANNEL 1305 72 | 033076 CALIBRATION QUALITY FLAG 0 73 | 033077 FIELD OF VIEW QUALITY FLAG 1024 74 | 008076 TYPE OF BAND None 75 | 033078 GEOLOCATION QUALITY 0 76 | 033003 QUALITY INFORMATION 0 77 | 104000 78 | ....031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR 5 79 | # --- 1 of 5 replications --- 80 | 201133 81 | 005042 CHANNEL NUMBER 1 82 | 201000 83 | 014044 CHANNEL RADIANCE 0.0462895 84 | # --- 2 of 5 replications --- 85 | 201133 86 | 005042 CHANNEL NUMBER 2 87 | 201000 88 | 014044 CHANNEL RADIANCE 0.0454931 89 | # --- 3 of 5 replications --- 90 | 201133 91 | 005042 CHANNEL NUMBER 3 92 | 201000 93 | 014044 CHANNEL RADIANCE 0.0421172 94 | # --- 4 of 5 replications --- 95 | 201133 96 | 005042 CHANNEL NUMBER 4 97 | 201000 98 | 014044 CHANNEL RADIANCE 0.0453741 99 | # --- 5 of 5 replications --- 100 | 201133 101 | 005042 CHANNEL NUMBER 5 102 | 201000 103 | 014044 CHANNEL RADIANCE 0.0431189 104 | ###### subset 2 of 2 ###### 105 | 310060 (CrIS (Cross-Track Infrared Sounder) radiance data) 106 | 001007 SATELLITE IDENTIFIER 224 107 | 001033 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE 160 108 | 002019 SATELLITE INSTRUMENTS 620 109 | 002020 SATELLITE CLASSIFICATION 3 110 | 301011 (Year, month, day) 111 | 004001 YEAR 2012 112 | 004002 MONTH 11 113 | 004003 DAY 2 114 | 301012 (Hour, minute) 115 | 004004 HOUR 0 116 | 004005 MINUTE 0 117 | 207003 118 | 004006 SECOND 27.584 119 | 207000 120 | 304030 (Location of platform) 121 | 027031 IN DIRECTION OF 0 DEGREES LONGITUDE, DISTANCE FROM THE EARTH'S C 6675220.0 122 | 028031 IN DIRECTION 90 DEGREES EAST, DISTANCE FROM THE EARTH'S CENTRE 2628450.5 123 | 010031 IN DIRECTION OF THE NORTH POLE, DISTANCE FROM THE EARTH'S CENTRE 696570.75 124 | 301021 (Latitude/longitude (high accuracy)) 125 | 005001 LATITUDE (HIGH ACCURACY) 5.05004 126 | 006001 LONGITUDE (HIGH ACCURACY) 24.3926 127 | 007024 SATELLITE ZENITH ANGLE 24.2 128 | 005021 BEARING OR AZIMUTH 281.97 129 | 007025 SOLAR ZENITH ANGLE 150.22 130 | 005022 SOLAR AZIMUTH 111.22 131 | 008075 ASCENDING/DESCENDING ORBIT QUALIFIER 1 132 | 201133 133 | 005041 SCAN LINE NUMBER 1 134 | 201000 135 | 005045 FIELD OF REGARD NUMBER 9 136 | 005043 FIELD OF VIEW NUMBER 8 137 | 005040 ORBIT NUMBER 5258L 138 | 010001 HEIGHT OF LAND SURFACE 538 139 | 201129 140 | 007002 HEIGHT OR ALTITUDE 829880.0 141 | 201000 142 | 202127 143 | 201125 144 | 021166 LAND FRACTION 1.0 145 | 201000 146 | 202000 147 | 008012 LAND/SEA QUALIFIER 0 148 | 020010 CLOUD COVER (TOTAL) None 149 | 020014 HEIGHT OF TOP OF CLOUD None 150 | 002165 RADIANCE TYPE FLAG 2048 151 | 033075 SCAN LEVEL QUALITY FLAG 0 152 | 107003 153 | # --- 1 of 3 replications --- 154 | 008076 TYPE OF BAND 2 155 | 006029 WAVE NUMBER 65000.0 156 | 006029 WAVE NUMBER 109500.0 157 | 025140 START CHANNEL 1 158 | 025141 END CHANNEL 713 159 | 033076 CALIBRATION QUALITY FLAG 0 160 | 033077 FIELD OF VIEW QUALITY FLAG 1024 161 | # --- 2 of 3 replications --- 162 | 008076 TYPE OF BAND 3 163 | 006029 WAVE NUMBER 121000.0 164 | 006029 WAVE NUMBER 175000.0 165 | 025140 START CHANNEL 714 166 | 025141 END CHANNEL 1146 167 | 033076 CALIBRATION QUALITY FLAG 0 168 | 033077 FIELD OF VIEW QUALITY FLAG 1024 169 | # --- 3 of 3 replications --- 170 | 008076 TYPE OF BAND 4 171 | 006029 WAVE NUMBER 215500.0 172 | 006029 WAVE NUMBER 255000.0 173 | 025140 START CHANNEL 1147 174 | 025141 END CHANNEL 1305 175 | 033076 CALIBRATION QUALITY FLAG 0 176 | 033077 FIELD OF VIEW QUALITY FLAG 1024 177 | 008076 TYPE OF BAND None 178 | 033078 GEOLOCATION QUALITY 0 179 | 033003 QUALITY INFORMATION 0 180 | 104000 181 | ....031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR 5 182 | # --- 1 of 5 replications --- 183 | 201133 184 | 005042 CHANNEL NUMBER 1 185 | 201000 186 | 014044 CHANNEL RADIANCE 0.0469285 187 | # --- 2 of 5 replications --- 188 | 201133 189 | 005042 CHANNEL NUMBER 2 190 | 201000 191 | 014044 CHANNEL RADIANCE 0.0458891 192 | # --- 3 of 5 replications --- 193 | 201133 194 | 005042 CHANNEL NUMBER 3 195 | 201000 196 | 014044 CHANNEL RADIANCE 0.041389 197 | # --- 4 of 5 replications --- 198 | 201133 199 | 005042 CHANNEL NUMBER 4 200 | 201000 201 | 014044 CHANNEL RADIANCE 0.0447059 202 | # --- 5 of 5 replications --- 203 | 201133 204 | 005042 CHANNEL NUMBER 5 205 | 201000 206 | 014044 CHANNEL RADIANCE 0.0430633 -------------------------------------------------------------------------------- /tests/data/207003.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ "BUFR", 244, 3 ], 3 | [ 18, 0, 0, 98, 0, false, "0000000", 21, 202, 15, 0, 12, 11, 2, 0, 0, 0 ], 4 | [ 10, "00000000", 2, true, true, "000000", [ 310060 ] ], 5 | [ 6 | 204, "00000000", 7 | [ 8 | [ 9 | 224, 160, 620, 3, 2012, 11, 2, 0, 0, 27.584, 6675220.0, 2628450.5, 696570.75, 4.96669, 24.54144, 25.41, 282.91, 10 | 150.05, 111.28, 1, 1, 9, 7, 5258, 597, 829880.0, 1.0, 0, null, null, 2048, 0, 2, 65000.0, 109500.0, 1, 713, 0, 11 | 1024, 3, 121000.0, 175000.0, 714, 1146, 0, 1024, 4, 215500.0, 255000.0, 1147, 1305, 0, 1024, null, 0, 0, 5, 1, 12 | 0.0462895, 2, 0.0454931, 3, 0.0421172, 4, 0.0453741, 5, 0.0431189 13 | ], 14 | [ 15 | 224, 160, 620, 3, 2012, 11, 2, 0, 0, 27.584, 6675220.0, 2628450.5, 696570.75, 5.05004, 24.3926, 24.2, 281.97, 16 | 150.22, 111.22, 1, 1, 9, 8, 5258, 538, 829880.0, 1.0, 0, null, null, 2048, 0, 2, 65000.0, 109500.0, 1, 713, 0, 17 | 1024, 3, 121000.0, 175000.0, 714, 1146, 0, 1024, 4, 215500.0, 255000.0, 1147, 1305, 0, 1024, null, 0, 0, 5, 1, 18 | 0.0469285, 2, 0.0458891, 3, 0.041389, 4, 0.0447059, 5, 0.0430633 19 | ] 20 | ] 21 | ], 22 | [ "7777" ] 23 | ] 24 | -------------------------------------------------------------------------------- /tests/data/207003.values.cmp: -------------------------------------------------------------------------------- 1 | 1 224 2 | 2 160 3 | 3 620 4 | 4 3 5 | 5 2012 6 | 6 11 7 | 7 2 8 | 8 0 9 | 9 0 10 | 10 27.584 11 | 11 6675220.0 12 | 12 2628450.5 13 | 13 696570.75 14 | 14 4.96669 15 | 15 24.54144 16 | 16 25.41 17 | 17 282.91 18 | 18 150.05 19 | 19 111.28 20 | 20 1 21 | 21 1 22 | 22 9 23 | 23 7 24 | 24 5258 25 | 25 597 26 | 26 829880.0 27 | 27 1.0 28 | 28 0 29 | 29 None 30 | 30 None 31 | 31 2048 32 | 32 0 33 | 33 2 34 | 34 65000.0 35 | 35 109500.0 36 | 36 1 37 | 37 713 38 | 38 0 39 | 39 1024 40 | 40 3 41 | 41 121000.0 42 | 42 175000.0 43 | 43 714 44 | 44 1146 45 | 45 0 46 | 46 1024 47 | 47 4 48 | 48 215500.0 49 | 49 255000.0 50 | 50 1147 51 | 51 1305 52 | 52 0 53 | 53 1024 54 | 54 None 55 | 55 0 56 | 56 0 57 | 57 5 58 | 58 1 59 | 59 0.0462895 60 | 60 2 61 | 61 0.0454931 62 | 62 3 63 | 63 0.0421172 64 | 64 4 65 | 65 0.0453741 66 | 66 5 67 | 67 0.0431189 68 | 1 224 69 | 2 160 70 | 3 620 71 | 4 3 72 | 5 2012 73 | 6 11 74 | 7 2 75 | 8 0 76 | 9 0 77 | 10 27.584 78 | 11 6675220.0 79 | 12 2628450.5 80 | 13 696570.75 81 | 14 5.05004 82 | 15 24.3926 83 | 16 24.2 84 | 17 281.97 85 | 18 150.22 86 | 19 111.22 87 | 20 1 88 | 21 1 89 | 22 9 90 | 23 8 91 | 24 5258 92 | 25 538 93 | 26 829880.0 94 | 27 1.0 95 | 28 0 96 | 29 None 97 | 30 None 98 | 31 2048 99 | 32 0 100 | 33 2 101 | 34 65000.0 102 | 35 109500.0 103 | 36 1 104 | 37 713 105 | 38 0 106 | 39 1024 107 | 40 3 108 | 41 121000.0 109 | 42 175000.0 110 | 43 714 111 | 44 1146 112 | 45 0 113 | 46 1024 114 | 47 4 115 | 48 215500.0 116 | 49 255000.0 117 | 50 1147 118 | 51 1305 119 | 52 0 120 | 53 1024 121 | 54 None 122 | 55 0 123 | 56 0 124 | 57 5 125 | 58 1 126 | 59 0.0469285 127 | 60 2 128 | 61 0.0458891 129 | 62 3 130 | 63 0.041389 131 | 64 4 132 | 65 0.0447059 133 | 66 5 134 | 67 0.0430633 -------------------------------------------------------------------------------- /tests/data/ISMD01_OKPR.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/ISMD01_OKPR.bufr -------------------------------------------------------------------------------- /tests/data/ISMD01_OKPR.json: -------------------------------------------------------------------------------- 1 | [["BUFR", 692, 4], [22, 0, 89, 0, 0, false, "0000000", 0, 2, 0, 13, 0, 2007, 11, 21, 12, 0, 0], [10, "00000000", 7, false, true, "000000", [307080]], [648, "00000000", [[11, 423, "Primda ", 1, 2007, 11, 21, 12, 0, 49.66944, 12.67778, 742.2, 747.0, 92520.0, null, -60.0, 5, null, 92500.0, 749, 1.95, 270.85, 270.45, 97, 4.8, 200.0, 1.12, null, null, 113, 5, 9, 0.0, 62, 61, 60, 1, 5, 9, 59, 0.0, 1, 11, null, null, null, null, 7, null, 8, null, 9, null, null, null, null, null, null, null, null, null, null, 49, -6, 4, 4, -1, null, -24, null, 1.12, -6, 0.0, -1, 0.0, 1.95, -12, 0, null, -12, 0, null, 10.25, 8, 2, -10, 110, 5.0, null, -10, null, null, -360, null, 12.0, null, -24, null, null, -1, null, null, null, null, null, null, -24, null, null, null, null, null, null, null, null, null], [11, 487, "Kocelovice ", 1, 2007, 11, 21, 12, 0, 49.465, 13.83111, 519.0, 521.9, 95220.0, 101620.0, -80.0, 8, null, 92510.0, 750, 2.0, 271.85, 271.75, 99, 4.9, 2700.0, 1.01, null, null, 100, 7, 8, 120.0, 36, 61, 60, 1, 1, 8, 7, 120.0, 1, 12, null, null, null, null, 7, null, 8, null, 9, null, null, null, null, null, null, null, null, null, null, 10, -6, 4, 2, -1, null, -24, null, 1.01, -6, 0.0, -1, 0.0, 2.0, -12, 0, null, -12, 0, null, 10.15, 8, 2, -10, 120, 4.0, null, -10, null, null, -360, null, null, null, -24, null, null, -1, null, null, null, null, null, null, -24, null, null, null, null, null, null, null, null, null], [11, 518, "Praha-Ruzyne ", 1, 2007, 11, 21, 12, 0, 50.10083, 14.25778, 364.0, 365.3, 97130.0, 101640.0, -110.0, 8, null, 92510.0, 750, 2.0, 273.05, 271.15, 87, 1.7, 8000.0, 1.02, null, null, 100, 7, 8, 240.0, 36, 61, 60, 1, 1, 8, 7, 240.0, 1, 12, null, null, null, null, 7, null, 8, null, 9, null, null, null, null, null, null, null, null, null, null, 10, -6, 2, 2, -1, null, -24, null, 1.02, -6, 0.0, -1, 0.0, 2.0, -12, 0, null, -12, 0, null, 10.0, 8, 2, -10, 140, 3.0, null, -10, null, null, -360, null, null, null, -24, null, null, -1, null, null, null, null, null, null, -24, null, null, null, null, null, null, null, null, null], [11, 603, "Liberec ", 1, 2007, 11, 21, 12, 0, 50.77, 15.02417, 397.7, 401.5, 96650.0, 101580.0, -70.0, 5, null, 92510.0, 750, 1.98, 273.65, 271.95, 88, 4.65, 6000.0, 1.0, null, null, 100, 7, 8, 240.0, 36, 61, 60, 1, 1, 8, 7, 240.0, 1, 12, null, null, null, null, 7, null, 8, null, 9, null, null, null, null, null, null, null, null, null, null, 10, -6, 2, 2, -1, null, -24, null, 1.0, -6, 0.0, -1, 0.0, 1.98, -12, 0, null, -12, 0, null, 10.3, 8, 2, -10, 130, 7.0, null, -10, null, null, -360, null, 13.0, null, -24, null, null, -1, null, null, null, null, null, null, -24, null, null, null, null, null, null, null, null, null], [11, 659, "Pribyslav ", 1, 2007, 11, 21, 12, 0, 49.58278, 15.76278, 532.5, 536.4, 95130.0, 101710.0, -130.0, 7, null, 92510.0, 750, 2.01, 271.85, 270.85, 93, 6.24, 1800.0, 0.96, null, null, 100, 7, 8, 120.0, 36, 61, 60, 1, 1, 8, 7, 120.0, 1, 12, null, null, null, null, 7, null, 8, null, 9, null, null, null, null, null, null, null, null, null, null, 10, -6, 4, 2, -1, null, -24, null, 0.96, -6, 0.0, -1, 0.0, 2.01, -12, 0, null, -12, 0, null, 14.08, 8, 2, -10, 140, 7.0, null, -10, null, null, -360, null, 13.0, null, -24, null, null, -1, null, null, null, null, null, null, -24, null, null, null, null, null, null, null, null, null], [11, 723, "Brno-Turany ", 1, 2007, 11, 21, 12, 0, 49.15306, 16.68889, 241.0, 245.7, 98730.0, 101780.0, -120.0, 8, null, 92510.0, 750, 2.0, 275.05, 272.45, 83, 5.4, 8000.0, 1.0, null, null, 100, 7, 8, 450.0, 36, 61, 60, 1, 1, 8, 7, 450.0, 1, 12, null, null, null, null, 7, null, 8, null, 9, null, null, null, null, null, null, null, null, null, null, 10, -6, 2, 2, -1, null, -24, null, 1.0, -6, 0.0, -1, 0.0, 2.0, -12, 0, null, -12, 0, null, 8.0, 8, 2, -10, 160, 3.0, null, -10, null, null, -360, null, null, null, -24, null, null, -1, null, null, null, null, null, null, -24, null, null, null, null, null, null, null, null, null], [11, 782, "Ostrava-Mosnov ", 1, 2007, 11, 21, 12, 0, 49.6975, 18.12083, 250.4, 260.1, 98390.0, 101560.0, -170.0, 7, null, 92510.0, 750, 2.0, 278.65, 273.05, 67, 11.0, 25000.0, 1.0, null, null, 25, 0, 0, 6900.0, 30, 20, 11, 1, 1, 2, 0, 6900.0, 1, 12, null, null, null, null, 7, null, 8, null, 9, null, null, null, null, null, null, null, null, null, null, 508, -6, 10, 10, -1, null, -24, null, 1.0, -6, 0.0, -1, 0.0, 2.0, -12, 0, null, -12, 0, null, 10.0, 8, 2, -10, 250, 6.0, null, -10, null, null, -360, null, null, null, -24, null, null, -1, null, null, null, null, null, null, -24, null, null, null, null, null, null, null, null, null]]], ["7777"]] 2 | -------------------------------------------------------------------------------- /tests/data/IUSK73_AMMC_040000.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/IUSK73_AMMC_040000.bufr -------------------------------------------------------------------------------- /tests/data/IUSK73_AMMC_182300.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/IUSK73_AMMC_182300.bufr -------------------------------------------------------------------------------- /tests/data/JUBE99_EGRR.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/JUBE99_EGRR.bufr -------------------------------------------------------------------------------- /tests/data/amv2_87.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/amv2_87.bufr -------------------------------------------------------------------------------- /tests/data/asr3_190.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/asr3_190.bufr -------------------------------------------------------------------------------- /tests/data/b002_95.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/b002_95.bufr -------------------------------------------------------------------------------- /tests/data/b002_95.json: -------------------------------------------------------------------------------- 1 | [["BUFR", 760, 3], [18, 0, 0, 98, 0, true, "0000000", 2, 95, 13, 1, 12, 10, 31, 0, 0, 0], [52, "00000000", ""], [130, "00000000", 1, true, false, "000000", [1001, 1002, 5002, 6002, 7001, 4001, 4002, 4003, 4004, 4005, 8021, 4025, 11002, 11001, 10051, 12001, 13014, 13003, 25033, 120036, 7006, 25032, 25034, 201116, 8022, 201000, 11003, 11004, 201129, 11050, 201000, 201116, 8022, 201000, 201129, 206008, 21192, 201000, 11006, 11051, 120007, 7006, 25032, 25034, 201116, 8022, 201000, 11003, 11004, 201129, 11050, 201000, 201116, 8022, 201000, 201129, 206008, 21192, 201000, 11006, 11051]], [548, "00000000", [[74, 533, 40.18, -104.73, 1524, 2012, 10, 31, 0, 0, 2, -60, null, null, null, null, null, null, 0, 500, 1, 0, 9, -0.6, 0.1, 3.6, 5, 59, 0.05, 0.6, 750, 1, 0, 9, -1.9, -0.1, 2.8, 5, 59, 0.06, 0.9, 1000, 1, 0, 8, -0.6, 0.1, 2.3, 6, 57, -0.07, 0.4, 1250, 1, 0, 7, 2.9, 1.3, 3.1, 6, 51, -0.17, 0.6, 1500, 1, 0, 7, 5.8, 0.0, 2.5, 10, 47, -0.07, 0.4, 1750, 1, 0, 8, 6.4, -0.5, 2.8, 10, 48, -0.06, 0.4, 2000, 1, 0, 7, 5.8, -0.7, 3.3, 10, 45, 0.0, 0.5, 2250, 1, 0, 8, 6.0, -2.0, 2.7, 10, 45, 0.04, 0.5, 2500, 1, 0, 8, 6.2, -3.7, 2.2, 10, 45, 0.02, 0.5, 2750, 1, 0, 9, 6.3, -5.2, 5.4, 10, 42, 0.07, 0.5, 3000, 1, 0, 9, 6.7, -6.8, 1.9, 10, 44, -0.02, 0.4, 3250, 1, 0, 8, 7.1, -9.1, 1.7, 10, 45, 0.0, 0.4, 3500, 1, 0, 8, 7.1, -11.5, 1.2, 10, 41, -0.04, 0.4, 3750, 1, 0, 9, 9.2, -11.9, 2.5, 10, 39, -0.04, 0.5, 4000, 1, 0, 8, 10.9, -11.7, 2.2, 10, 39, -0.02, 0.4, 4250, 1, 0, 7, 14.6, -10.9, 1.2, 10, 36, -0.05, 0.4, 4500, 1, 0, 8, 14.1, -11.1, 2.4, 7, 33, 0.01, 0.4, 4750, 1, 0, 8, 18.1, -9.2, 2.0, 9, 34, 0.07, 0.5, 5000, 1, 0, 7, 18.4, -9.4, 2.6, 10, 33, 0.01, 0.4, 5250, 1, 0, 4, 18.3, 1.0, 1.9, 4, 31, -0.04, 0.5, 5500, 1, 0, 6, 16.1, 1.0, 1.5, 6, 35, -0.02, 0.4, 5750, null, null, null, null, null, null, null, null, null, null, 6000, null, null, null, null, null, null, null, null, null, null, 6250, null, null, null, null, null, null, null, null, null, null, 6500, null, null, null, null, null, null, null, null, null, null, 6750, null, null, null, null, null, null, null, null, null, null, 7000, null, null, null, null, null, null, null, null, null, null, 7250, null, null, null, null, null, null, null, null, null, null, 7500, 2, 2, 5, 19.7, -9.8, 3.3, 8, 35, 0.0, 0.4, 7750, null, null, null, null, null, null, null, null, null, null, 8000, null, null, null, null, null, null, null, null, null, null, 8250, null, null, null, null, null, null, null, null, null, null, 8500, null, null, null, null, null, null, null, null, null, null, 8750, null, null, null, null, null, null, null, null, null, null, 9000, null, null, null, null, null, null, null, null, null, null, 9250, null, null, null, null, null, null, null, null, null, null, 10250, null, null, null, null, null, null, null, null, null, null, 11250, null, null, null, null, null, null, null, null, null, null, 12250, null, null, null, null, null, null, null, null, null, null, 13250, null, null, null, null, null, null, null, null, null, null, 14250, null, null, null, null, null, null, null, null, null, null, 15250, null, null, null, null, null, null, null, null, null, null, 16250, null, null, null, null, null, null, null, null, null, null]]], ["7777"]] 2 | -------------------------------------------------------------------------------- /tests/data/b002_95.values.cmp: -------------------------------------------------------------------------------- 1 | 1 74 2 | 2 533 3 | 3 40.18 4 | 4 -104.73 5 | 5 1524 6 | 6 2012 7 | 7 10 8 | 8 31 9 | 9 0 10 | 10 0 11 | 11 2 12 | 12 -60 13 | 13 None 14 | 14 None 15 | 15 None 16 | 16 None 17 | 17 None 18 | 18 None 19 | 19 0 20 | 20 500 21 | 21 1 22 | 22 0 23 | 23 9 24 | 24 -0.6 25 | 25 0.1 26 | 26 3.6 27 | 27 5 28 | 28 59 29 | 29 0.05 30 | 30 0.6 31 | 31 750 32 | 32 1 33 | 33 0 34 | 34 9 35 | 35 -1.9 36 | 36 -0.1 37 | 37 2.8 38 | 38 5 39 | 39 59 40 | 40 0.06 41 | 41 0.9 42 | 42 1000 43 | 43 1 44 | 44 0 45 | 45 8 46 | 46 -0.6 47 | 47 0.1 48 | 48 2.3 49 | 49 6 50 | 50 57 51 | 51 -0.07 52 | 52 0.4 53 | 53 1250 54 | 54 1 55 | 55 0 56 | 56 7 57 | 57 2.9 58 | 58 1.3 59 | 59 3.1 60 | 60 6 61 | 61 51 62 | 62 -0.17 63 | 63 0.6 64 | 64 1500 65 | 65 1 66 | 66 0 67 | 67 7 68 | 68 5.8 69 | 69 0.0 70 | 70 2.5 71 | 71 10 72 | 72 47 73 | 73 -0.07 74 | 74 0.4 75 | 75 1750 76 | 76 1 77 | 77 0 78 | 78 8 79 | 79 6.4 80 | 80 -0.5 81 | 81 2.8 82 | 82 10 83 | 83 48 84 | 84 -0.06 85 | 85 0.4 86 | 86 2000 87 | 87 1 88 | 88 0 89 | 89 7 90 | 90 5.8 91 | 91 -0.7 92 | 92 3.3 93 | 93 10 94 | 94 45 95 | 95 0.0 96 | 96 0.5 97 | 97 2250 98 | 98 1 99 | 99 0 100 | 100 8 101 | 101 6.0 102 | 102 -2.0 103 | 103 2.7 104 | 104 10 105 | 105 45 106 | 106 0.04 107 | 107 0.5 108 | 108 2500 109 | 109 1 110 | 110 0 111 | 111 8 112 | 112 6.2 113 | 113 -3.7 114 | 114 2.2 115 | 115 10 116 | 116 45 117 | 117 0.02 118 | 118 0.5 119 | 119 2750 120 | 120 1 121 | 121 0 122 | 122 9 123 | 123 6.3 124 | 124 -5.2 125 | 125 5.4 126 | 126 10 127 | 127 42 128 | 128 0.07 129 | 129 0.5 130 | 130 3000 131 | 131 1 132 | 132 0 133 | 133 9 134 | 134 6.7 135 | 135 -6.8 136 | 136 1.9 137 | 137 10 138 | 138 44 139 | 139 -0.02 140 | 140 0.4 141 | 141 3250 142 | 142 1 143 | 143 0 144 | 144 8 145 | 145 7.1 146 | 146 -9.1 147 | 147 1.7 148 | 148 10 149 | 149 45 150 | 150 0.0 151 | 151 0.4 152 | 152 3500 153 | 153 1 154 | 154 0 155 | 155 8 156 | 156 7.1 157 | 157 -11.5 158 | 158 1.2 159 | 159 10 160 | 160 41 161 | 161 -0.04 162 | 162 0.4 163 | 163 3750 164 | 164 1 165 | 165 0 166 | 166 9 167 | 167 9.2 168 | 168 -11.9 169 | 169 2.5 170 | 170 10 171 | 171 39 172 | 172 -0.04 173 | 173 0.5 174 | 174 4000 175 | 175 1 176 | 176 0 177 | 177 8 178 | 178 10.9 179 | 179 -11.7 180 | 180 2.2 181 | 181 10 182 | 182 39 183 | 183 -0.02 184 | 184 0.4 185 | 185 4250 186 | 186 1 187 | 187 0 188 | 188 7 189 | 189 14.6 190 | 190 -10.9 191 | 191 1.2 192 | 192 10 193 | 193 36 194 | 194 -0.05 195 | 195 0.4 196 | 196 4500 197 | 197 1 198 | 198 0 199 | 199 8 200 | 200 14.1 201 | 201 -11.1 202 | 202 2.4 203 | 203 7 204 | 204 33 205 | 205 0.01 206 | 206 0.4 207 | 207 4750 208 | 208 1 209 | 209 0 210 | 210 8 211 | 211 18.1 212 | 212 -9.2 213 | 213 2.0 214 | 214 9 215 | 215 34 216 | 216 0.07 217 | 217 0.5 218 | 218 5000 219 | 219 1 220 | 220 0 221 | 221 7 222 | 222 18.4 223 | 223 -9.4 224 | 224 2.6 225 | 225 10 226 | 226 33 227 | 227 0.01 228 | 228 0.4 229 | 229 5250 230 | 230 1 231 | 231 0 232 | 232 4 233 | 233 18.3 234 | 234 1.0 235 | 235 1.9 236 | 236 4 237 | 237 31 238 | 238 -0.04 239 | 239 0.5 240 | 240 5500 241 | 241 1 242 | 242 0 243 | 243 6 244 | 244 16.1 245 | 245 1.0 246 | 246 1.5 247 | 247 6 248 | 248 35 249 | 249 -0.02 250 | 250 0.4 251 | 251 5750 252 | 252 None 253 | 253 None 254 | 254 None 255 | 255 None 256 | 256 None 257 | 257 None 258 | 258 None 259 | 259 None 260 | 260 None 261 | 261 None 262 | 262 6000 263 | 263 None 264 | 264 None 265 | 265 None 266 | 266 None 267 | 267 None 268 | 268 None 269 | 269 None 270 | 270 None 271 | 271 None 272 | 272 None 273 | 273 6250 274 | 274 None 275 | 275 None 276 | 276 None 277 | 277 None 278 | 278 None 279 | 279 None 280 | 280 None 281 | 281 None 282 | 282 None 283 | 283 None 284 | 284 6500 285 | 285 None 286 | 286 None 287 | 287 None 288 | 288 None 289 | 289 None 290 | 290 None 291 | 291 None 292 | 292 None 293 | 293 None 294 | 294 None 295 | 295 6750 296 | 296 None 297 | 297 None 298 | 298 None 299 | 299 None 300 | 300 None 301 | 301 None 302 | 302 None 303 | 303 None 304 | 304 None 305 | 305 None 306 | 306 7000 307 | 307 None 308 | 308 None 309 | 309 None 310 | 310 None 311 | 311 None 312 | 312 None 313 | 313 None 314 | 314 None 315 | 315 None 316 | 316 None 317 | 317 7250 318 | 318 None 319 | 319 None 320 | 320 None 321 | 321 None 322 | 322 None 323 | 323 None 324 | 324 None 325 | 325 None 326 | 326 None 327 | 327 None 328 | 328 7500 329 | 329 2 330 | 330 2 331 | 331 5 332 | 332 19.7 333 | 333 -9.8 334 | 334 3.3 335 | 335 8 336 | 336 35 337 | 337 0.0 338 | 338 0.4 339 | 339 7750 340 | 340 None 341 | 341 None 342 | 342 None 343 | 343 None 344 | 344 None 345 | 345 None 346 | 346 None 347 | 347 None 348 | 348 None 349 | 349 None 350 | 350 8000 351 | 351 None 352 | 352 None 353 | 353 None 354 | 354 None 355 | 355 None 356 | 356 None 357 | 357 None 358 | 358 None 359 | 359 None 360 | 360 None 361 | 361 8250 362 | 362 None 363 | 363 None 364 | 364 None 365 | 365 None 366 | 366 None 367 | 367 None 368 | 368 None 369 | 369 None 370 | 370 None 371 | 371 None 372 | 372 8500 373 | 373 None 374 | 374 None 375 | 375 None 376 | 376 None 377 | 377 None 378 | 378 None 379 | 379 None 380 | 380 None 381 | 381 None 382 | 382 None 383 | 383 8750 384 | 384 None 385 | 385 None 386 | 386 None 387 | 387 None 388 | 388 None 389 | 389 None 390 | 390 None 391 | 391 None 392 | 392 None 393 | 393 None 394 | 394 9000 395 | 395 None 396 | 396 None 397 | 397 None 398 | 398 None 399 | 399 None 400 | 400 None 401 | 401 None 402 | 402 None 403 | 403 None 404 | 404 None 405 | 405 9250 406 | 406 None 407 | 407 None 408 | 408 None 409 | 409 None 410 | 410 None 411 | 411 None 412 | 412 None 413 | 413 None 414 | 414 None 415 | 415 None 416 | 416 10250 417 | 417 None 418 | 418 None 419 | 419 None 420 | 420 None 421 | 421 None 422 | 422 None 423 | 423 None 424 | 424 None 425 | 425 None 426 | 426 None 427 | 427 11250 428 | 428 None 429 | 429 None 430 | 430 None 431 | 431 None 432 | 432 None 433 | 433 None 434 | 434 None 435 | 435 None 436 | 436 None 437 | 437 None 438 | 438 12250 439 | 439 None 440 | 440 None 441 | 441 None 442 | 442 None 443 | 443 None 444 | 444 None 445 | 445 None 446 | 446 None 447 | 447 None 448 | 448 None 449 | 449 13250 450 | 450 None 451 | 451 None 452 | 452 None 453 | 453 None 454 | 454 None 455 | 455 None 456 | 456 None 457 | 457 None 458 | 458 None 459 | 459 None 460 | 460 14250 461 | 461 None 462 | 462 None 463 | 463 None 464 | 464 None 465 | 465 None 466 | 466 None 467 | 467 None 468 | 468 None 469 | 469 None 470 | 470 None 471 | 471 15250 472 | 472 None 473 | 473 None 474 | 474 None 475 | 475 None 476 | 476 None 477 | 477 None 478 | 478 None 479 | 479 None 480 | 480 None 481 | 481 None 482 | 482 16250 483 | 483 None 484 | 484 None 485 | 485 None 486 | 486 None 487 | 487 None 488 | 488 None 489 | 489 None 490 | 490 None 491 | 491 None 492 | 492 None 493 | -------------------------------------------------------------------------------- /tests/data/b005_89.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/b005_89.bufr -------------------------------------------------------------------------------- /tests/data/contrived.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/contrived.bufr -------------------------------------------------------------------------------- /tests/data/g2nd_208.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/g2nd_208.bufr -------------------------------------------------------------------------------- /tests/data/g2nd_208.json: -------------------------------------------------------------------------------- 1 | [["BUFR", 921, 4], [22, 0, 98, 0, 0, true, "0000000", 3, 0, 208, 13, 101, 2012, 11, 2, 1, 5, 49], [52, "00000000", ""], [83, "00000000", 18, true, true, "000000", [1211, 310022, 301011, 301013, 301021, 102004, 27001, 28001, 7022, 5040, 5043, 20010, 20016, 13040, 8043, 8044, 33054, 10040, 107000, 31001, 207002, 7004, 7004, 207000, 8090, 15021, 8090, 224000, 236000, 101000, 31001, 31031, 1033, 1032, 8023, 101000, 31001, 224255]], [752, "00000000", [[8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 49, 36.21976, 126.66325, 35.95181, 127.08791, 36.36461, 127.18575, 36.07265, 126.14268, 36.50784, 126.2406, 30.63, null, 2, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 6313630, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 3891157], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 49, 36.33769, 125.7849, 36.06333, 126.21154, 36.49681, 126.30945, 36.17629, 125.2625, 36.6344, 125.36041, 30.17, null, 2, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 6413755, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 4726378], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 50, 36.44759, 124.91692, 36.16654, 125.33954, 36.62256, 125.43745, 36.27037, 124.39873, 36.75261, 124.49645, 29.71, null, 2, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 8398670, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 4892253], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 50, 36.55022, 124.05341, 36.26017, 124.48505, 36.73993, 124.58279, 36.35818, 123.52661, 36.86621, 123.62384, 29.23, null, 2, 2, 64730.0, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 9242961, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 4692011], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 53, 33.62065, 138.34335, 33.28279, 138.70152, 33.72536, 138.86871, 33.51372, 137.81929, 33.93444, 137.97389, 37.21, null, 0, 9, 69150.0, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 2808442, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 3149045], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 53, 33.81627, 137.53329, 33.49635, 137.88345, 33.9186, 138.03894, 33.71188, 137.02885, 34.11495, 137.17325, 36.78, null, 0, 7, 67830.0, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 4130621, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 4380036], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 53, 34.00507, 136.72638, 33.69661, 137.08725, 34.10093, 137.23236, 33.90714, 136.22156, 34.29431, 136.35657, 36.34, null, 0, 7, 66390.0, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -13, 16709026, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 2641536], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 53, 34.37353, 135.07042, 34.08781, 135.44321, 34.46196, 135.57022, 34.28307, 134.5717, 34.64562, 134.69098, 35.46, null, 1, 3, 71990.0, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 5933755, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 5354656], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 54, 34.55106, 134.22897, 34.27228, 134.61809, 34.63536, 134.73776, 34.46466, 133.72124, 34.8192, 133.83426, 35.01, null, 1, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 3351135, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 5183388], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 54, 35.19673, 130.85541, 34.94163, 131.25365, 35.29317, 131.35518, 35.09824, 130.35683, 35.45624, 130.45627, 33.2, null, 1, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 2593253, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 3112014], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 54, 35.34316, 130.00591, 35.09001, 130.4019, 35.44759, 130.50143, 35.23671, 129.51167, 35.60424, 129.60994, 32.74, null, 1, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 4861136, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 5267543], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 55, 35.48327, 129.15547, 35.22847, 129.55934, 35.59537, 129.65765, 35.36909, 128.65471, 35.74944, 128.75235, 32.28, null, 1, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 4796409, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 5595962], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 55, 35.61787, 128.29996, 35.36071, 128.70598, 35.74021, 128.80365, 35.49344, 127.79781, 35.88948, 127.89524, 31.81, null, 2, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 2680197, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 3252751], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 55, 35.74535, 127.44907, 35.48483, 127.85371, 35.87975, 127.95116, 35.60887, 126.94868, 36.02294, 127.04615, 31.35, null, 2, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 3478402, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 3852381], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 55, 35.86825, 126.5851, 35.59993, 127.01021, 36.01262, 127.10767, 35.72162, 126.06444, 36.15678, 126.16203, 30.88, null, 2, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 7956371, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 6367316], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 55, 35.98653, 125.70987, 35.71228, 126.13298, 36.14574, 126.23057, 35.82509, 125.19127, 36.28307, 125.28893, 30.42, null, 2, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 8406036, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 6160189], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 56, 36.09665, 124.84585, 35.81532, 125.26793, 36.27122, 125.36559, 35.91985, 124.32841, 36.40204, 124.42597, 29.96, null, 2, 0, null, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 7187199, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 4445258], [8, 4, 220, 98, 1, 2012, 11, 2, 1, 5, 56, 36.38744, 122.26145, 36.07874, 122.69321, 36.6105, 122.7897, 36.16206, 121.73622, 36.72465, 121.83141, 28.56, null, 2, 3, 67060.0, null, 5, "10102-44-0 ", 0, 1, 1, 10000.0, 101325.0, -12, 4180346, -127, 0, 0, 5, 1, 1, 0, 0, 1, 98, 81, 9, 2, -13, 2313097]]], ["7777"]] 2 | -------------------------------------------------------------------------------- /tests/data/jaso_214.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/jaso_214.bufr -------------------------------------------------------------------------------- /tests/data/mpco_217.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/mpco_217.bufr -------------------------------------------------------------------------------- /tests/data/multi_invalid_messages.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/multi_invalid_messages.bufr -------------------------------------------------------------------------------- /tests/data/ncep.352.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/ncep.352.bufr -------------------------------------------------------------------------------- /tests/data/prepbufr.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/prepbufr.bufr -------------------------------------------------------------------------------- /tests/data/profiler_european.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/profiler_european.bufr -------------------------------------------------------------------------------- /tests/data/profiler_european.json: -------------------------------------------------------------------------------- 1 | [ 2 | [ "BUFR", 426, 3 ], 3 | [ 18, 0, 0, 98, 0, true, "0000000", 2, 96, 13, 1, 14, 12, 31, 21, 59, 0 ], 4 | [ 52, "00000000", "" ], 5 | [ 26, "00000000", 1, true, false, "000000", [ 301032, 321021, 25020, 25021, 8021, 4025, 101000, 31001, 321022 ] ], 6 | [ 7 | 318, 8 | "00000000", 9 | [ 10 | [ 11 | 8, 59, 2, 2014, 12, 31, 21, 59, 43.38, -3.04, 62, 6, 4, 6.0, 1290000000.0, 62, 0, 64, 2, 27, 32, 195, 21, 0, 51, 12 | 0.9, 21, 0, 0.11, -13, 255, 21, 0, 103, 0.6, 21, 0, 0.22, -7, 316, 21, 0, 78, 0.4, 21, 0, 0.42, -5, 376, 21, 0, 13 | 359, 0.7, 21, 0, 0.39, -5, 436, 21, 0, 345, 2.3, 21, 0, 0.4, -7, 496, 21, 0, 336, 2.6, 21, 0, 0.43, -9, 557, 21, 14 | 0, 339, 2.6, 21, 0, 0.43, -12, 617, 21, 0, 338, 1.7, 21, 0, 0.38, -12, 677, 21, 0, 329, 1.1, 21, 0, 0.26, -7, 15 | 737, 16 | 21, 0, 16, 1.2, 21, 0, 0.28, -13, 798, 21, 0, 33, 2.8, 21, 0, 0.57, -18, 858, 21, 0, 338, 2.6, 21, 0, 0.76, -25, 17 | 918, 21, 1, null, null, 21, 1, null, -26, 978, 21, 1, null, null, 21, 1, null, -27, 1039, 21, 1, null, null, 21, 18 | 1, null, -27, 1099, 21, 1, null, null, 21, 1, null, -28, 1159, 21, 1, null, null, 21, 1, null, -27, 1219, 21, 1, 19 | null, null, 21, 1, null, -28, 1280, 21, 1, null, null, 21, 1, null, -27, 1340, 21, 1, null, null, 21, 1, null, 20 | -25, 1400, 21, 1, null, null, 21, 1, null, -28, 1460, 21, 1, null, null, 21, 1, null, -28, 1521, 21, 1, null, 21 | null, 21, 1, null, -28, 1581, 21, 1, null, null, 21, 1, null, -28, 1641, 21, 1, null, null, 21, 1, null, -28, 22 | 1701, 21, 1, null, null, 21, 1, null, -28, 1762, 21, 1, null, null, 21, 1, null, -28, 1822, 21, 1, null, null, 23 | 21, 24 | 1, null, -28, 1882, 21, 1, null, null, 21, 1, null, -27, 1942, 21, 1, null, null, 21, 1, null, -28, 2003, 21, 1, 25 | null, null, 21, 1, null, -28, 2063, 21, 1, null, null, 21, 1, null, -28 26 | ] 27 | ] 28 | ], 29 | [ "7777" ] 30 | ] 31 | -------------------------------------------------------------------------------- /tests/data/profiler_european.values.cmp: -------------------------------------------------------------------------------- 1 | 1 8 2 | 2 59 3 | 3 2 4 | 4 2014 5 | 5 12 6 | 6 31 7 | 7 21 8 | 8 59 9 | 9 43.38 10 | 10 -3.04 11 | 11 62 12 | 12 6 13 | 13 4 14 | 14 6.0 15 | 15 1290000000.0 16 | 16 62 17 | 17 0 18 | 18 64 19 | 19 2 20 | 20 27 21 | 21 32 22 | 22 195 23 | 23 21 24 | 24 0 25 | 25 51 26 | 26 0.9 27 | 27 21 28 | 28 0 29 | 29 0.11 30 | 30 -13 31 | 31 255 32 | 32 21 33 | 33 0 34 | 34 103 35 | 35 0.6 36 | 36 21 37 | 37 0 38 | 38 0.22 39 | 39 -7 40 | 40 316 41 | 41 21 42 | 42 0 43 | 43 78 44 | 44 0.4 45 | 45 21 46 | 46 0 47 | 47 0.42 48 | 48 -5 49 | 49 376 50 | 50 21 51 | 51 0 52 | 52 359 53 | 53 0.7 54 | 54 21 55 | 55 0 56 | 56 0.39 57 | 57 -5 58 | 58 436 59 | 59 21 60 | 60 0 61 | 61 345 62 | 62 2.3 63 | 63 21 64 | 64 0 65 | 65 0.4 66 | 66 -7 67 | 67 496 68 | 68 21 69 | 69 0 70 | 70 336 71 | 71 2.6 72 | 72 21 73 | 73 0 74 | 74 0.43 75 | 75 -9 76 | 76 557 77 | 77 21 78 | 78 0 79 | 79 339 80 | 80 2.6 81 | 81 21 82 | 82 0 83 | 83 0.43 84 | 84 -12 85 | 85 617 86 | 86 21 87 | 87 0 88 | 88 338 89 | 89 1.7 90 | 90 21 91 | 91 0 92 | 92 0.38 93 | 93 -12 94 | 94 677 95 | 95 21 96 | 96 0 97 | 97 329 98 | 98 1.1 99 | 99 21 100 | 100 0 101 | 101 0.26 102 | 102 -7 103 | 103 737 104 | 104 21 105 | 105 0 106 | 106 16 107 | 107 1.2 108 | 108 21 109 | 109 0 110 | 110 0.28 111 | 111 -13 112 | 112 798 113 | 113 21 114 | 114 0 115 | 115 33 116 | 116 2.8 117 | 117 21 118 | 118 0 119 | 119 0.57 120 | 120 -18 121 | 121 858 122 | 122 21 123 | 123 0 124 | 124 338 125 | 125 2.6 126 | 126 21 127 | 127 0 128 | 128 0.76 129 | 129 -25 130 | 130 918 131 | 131 21 132 | 132 1 133 | 133 None 134 | 134 None 135 | 135 21 136 | 136 1 137 | 137 None 138 | 138 -26 139 | 139 978 140 | 140 21 141 | 141 1 142 | 142 None 143 | 143 None 144 | 144 21 145 | 145 1 146 | 146 None 147 | 147 -27 148 | 148 1039 149 | 149 21 150 | 150 1 151 | 151 None 152 | 152 None 153 | 153 21 154 | 154 1 155 | 155 None 156 | 156 -27 157 | 157 1099 158 | 158 21 159 | 159 1 160 | 160 None 161 | 161 None 162 | 162 21 163 | 163 1 164 | 164 None 165 | 165 -28 166 | 166 1159 167 | 167 21 168 | 168 1 169 | 169 None 170 | 170 None 171 | 171 21 172 | 172 1 173 | 173 None 174 | 174 -27 175 | 175 1219 176 | 176 21 177 | 177 1 178 | 178 None 179 | 179 None 180 | 180 21 181 | 181 1 182 | 182 None 183 | 183 -28 184 | 184 1280 185 | 185 21 186 | 186 1 187 | 187 None 188 | 188 None 189 | 189 21 190 | 190 1 191 | 191 None 192 | 192 -27 193 | 193 1340 194 | 194 21 195 | 195 1 196 | 196 None 197 | 197 None 198 | 198 21 199 | 199 1 200 | 200 None 201 | 201 -25 202 | 202 1400 203 | 203 21 204 | 204 1 205 | 205 None 206 | 206 None 207 | 207 21 208 | 208 1 209 | 209 None 210 | 210 -28 211 | 211 1460 212 | 212 21 213 | 213 1 214 | 214 None 215 | 215 None 216 | 216 21 217 | 217 1 218 | 218 None 219 | 219 -28 220 | 220 1521 221 | 221 21 222 | 222 1 223 | 223 None 224 | 224 None 225 | 225 21 226 | 226 1 227 | 227 None 228 | 228 -28 229 | 229 1581 230 | 230 21 231 | 231 1 232 | 232 None 233 | 233 None 234 | 234 21 235 | 235 1 236 | 236 None 237 | 237 -28 238 | 238 1641 239 | 239 21 240 | 240 1 241 | 241 None 242 | 242 None 243 | 243 21 244 | 244 1 245 | 245 None 246 | 246 -28 247 | 247 1701 248 | 248 21 249 | 249 1 250 | 250 None 251 | 251 None 252 | 252 21 253 | 253 1 254 | 254 None 255 | 255 -28 256 | 256 1762 257 | 257 21 258 | 258 1 259 | 259 None 260 | 260 None 261 | 261 21 262 | 262 1 263 | 263 None 264 | 264 -28 265 | 265 1822 266 | 266 21 267 | 267 1 268 | 268 None 269 | 269 None 270 | 270 21 271 | 271 1 272 | 272 None 273 | 273 -28 274 | 274 1882 275 | 275 21 276 | 276 1 277 | 277 None 278 | 278 None 279 | 279 21 280 | 280 1 281 | 281 None 282 | 282 -27 283 | 283 1942 284 | 284 21 285 | 285 1 286 | 286 None 287 | 287 None 288 | 288 21 289 | 289 1 290 | 290 None 291 | 291 -28 292 | 292 2003 293 | 293 21 294 | 294 1 295 | 295 None 296 | 296 None 297 | 297 21 298 | 298 1 299 | 299 None 300 | 300 -28 301 | 301 2063 302 | 302 21 303 | 303 1 304 | 304 None 305 | 305 None 306 | 306 21 307 | 307 1 308 | 308 None 309 | 309 -28 310 | -------------------------------------------------------------------------------- /tests/data/rado_250.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/rado_250.bufr -------------------------------------------------------------------------------- /tests/data/uegabe.bufr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ywangd/pybufrkit/013d803e1ab56b781600c01324915d67f5a4a61f/tests/data/uegabe.bufr -------------------------------------------------------------------------------- /tests/data/uegabe.json: -------------------------------------------------------------------------------- 1 | [["BUFR", 494, 4], [22, 0, 78, 0, 1, true, "0000000", 2, 4, 213, 13, 0, 2015, 7, 12, 5, 0, 0], [18, "00000000", ""], [22, "00000000", 1, true, false, "000000", [204004, 31021, 309052, 204000, 101000, 31001, 205008]], [420, "00000000", [[6, null, 10, null, 618, null, "\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff\u00ff", null, 80, null, 4, null, 8, null, null, null, 18, null, 2015, null, 7, null, 12, null, 5, null, 1, null, 0, null, 49.69273, null, 7.32633, null, 376.0, null, 377.0, null, null, null, null, null, 0, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 13, null, null, null, 65536, null, 100000.0, null, 163, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, 131072, null, 97500.0, null, null, null, null, null, null, null, 287.95, null, 284.65, null, 240, null, 3.0, null, null, null, 65536, null, 92500.0, null, 823, null, null, null, null, null, 287.15, null, 277.15, null, 265, null, 7.0, null, null, null, 65536, null, 85000.0, null, 1534, null, null, null, null, null, 283.95, null, 280.05, null, 270, null, 15.0, null, null, null, 65536, null, 70000.0, null, 3140, null, null, null, null, null, 278.35, null, 254.35, null, 270, null, 9.0, null, null, null, 65536, null, 50000.0, null, 5800, null, null, null, null, null, 260.65, null, 256.45, null, 270, null, 20.0, null, null, null, 65536, null, 40000.0, null, 7470, null, null, null, null, null, 249.05, null, 243.05, null, 280, null, 20.0, null, null, null, 65536, null, 30000.0, null, 9500, null, null, null, null, null, 233.65, null, 233.05, null, 280, null, 25.0, null, null, null, 65536, null, 25000.0, null, 10720, null, null, null, null, null, 223.25, null, 220.65, null, 280, null, 29.0, null, null, null, 32768, null, 20400.0, null, null, null, null, null, null, null, 214.05, null, 209.85, null, 275, null, 26.0, null, null, null, 65536, null, 20000.0, null, 12150, null, null, null, null, null, 214.05, null, 207.05, null, 275, null, 29.0, null, null, null, 65536, null, 15000.0, null, 13970, null, null, null, null, null, 217.45, null, 186.45, null, 275, null, 22.0, null, null, null, 65536, null, 10000.0, null, 16560, null, null, null, null, null, 220.05, null, 183.05, null, 290, null, 5.0, 1, null, null, null, 16384, null, null, null, null, null, null, null, null, null, null, 0]]], ["7777"]] 2 | -------------------------------------------------------------------------------- /tests/data/uegabe.values.cmp: -------------------------------------------------------------------------------- 1 | 1 6 2 | 2 None 3 | 3 10 4 | 4 None 5 | 5 618 6 | 6 None 7 | 7 '\xff\xff\xff\xff\xff\xff\xff\xff\xff' 8 | 8 None 9 | 9 80 10 | 10 None 11 | 11 4 12 | 12 None 13 | 13 8 14 | 14 None 15 | 15 None 16 | 16 None 17 | 17 18 18 | 18 None 19 | 19 2015 20 | 20 None 21 | 21 7 22 | 22 None 23 | 23 12 24 | 24 None 25 | 25 5 26 | 26 None 27 | 27 1 28 | 28 None 29 | 29 0 30 | 30 None 31 | 31 49.69273 32 | 32 None 33 | 33 7.32633 34 | 34 None 35 | 35 376.0 36 | 36 None 37 | 37 377.0 38 | 38 None 39 | 39 None 40 | 40 None 41 | 41 None 42 | 42 None 43 | 43 0 44 | 44 None 45 | 45 None 46 | 46 None 47 | 47 None 48 | 48 None 49 | 49 None 50 | 50 None 51 | 51 None 52 | 52 None 53 | 53 None 54 | 54 None 55 | 55 None 56 | 56 None 57 | 57 None 58 | 58 13 59 | 59 None 60 | 60 None 61 | 61 None 62 | 62 65536L 63 | 63 None 64 | 64 100000.0 65 | 65 None 66 | 66 163 67 | 67 None 68 | 68 None 69 | 69 None 70 | 70 None 71 | 71 None 72 | 72 None 73 | 73 None 74 | 74 None 75 | 75 None 76 | 76 None 77 | 77 None 78 | 78 None 79 | 79 None 80 | 80 None 81 | 81 None 82 | 82 131072L 83 | 83 None 84 | 84 97500.0 85 | 85 None 86 | 86 None 87 | 87 None 88 | 88 None 89 | 89 None 90 | 90 None 91 | 91 None 92 | 92 287.95 93 | 93 None 94 | 94 284.65 95 | 95 None 96 | 96 240 97 | 97 None 98 | 98 3.0 99 | 99 None 100 | 100 None 101 | 101 None 102 | 102 65536L 103 | 103 None 104 | 104 92500.0 105 | 105 None 106 | 106 823 107 | 107 None 108 | 108 None 109 | 109 None 110 | 110 None 111 | 111 None 112 | 112 287.15 113 | 113 None 114 | 114 277.15 115 | 115 None 116 | 116 265 117 | 117 None 118 | 118 7.0 119 | 119 None 120 | 120 None 121 | 121 None 122 | 122 65536L 123 | 123 None 124 | 124 85000.0 125 | 125 None 126 | 126 1534 127 | 127 None 128 | 128 None 129 | 129 None 130 | 130 None 131 | 131 None 132 | 132 283.95 133 | 133 None 134 | 134 280.05 135 | 135 None 136 | 136 270 137 | 137 None 138 | 138 15.0 139 | 139 None 140 | 140 None 141 | 141 None 142 | 142 65536L 143 | 143 None 144 | 144 70000.0 145 | 145 None 146 | 146 3140 147 | 147 None 148 | 148 None 149 | 149 None 150 | 150 None 151 | 151 None 152 | 152 278.35 153 | 153 None 154 | 154 254.35 155 | 155 None 156 | 156 270 157 | 157 None 158 | 158 9.0 159 | 159 None 160 | 160 None 161 | 161 None 162 | 162 65536L 163 | 163 None 164 | 164 50000.0 165 | 165 None 166 | 166 5800 167 | 167 None 168 | 168 None 169 | 169 None 170 | 170 None 171 | 171 None 172 | 172 260.65 173 | 173 None 174 | 174 256.45 175 | 175 None 176 | 176 270 177 | 177 None 178 | 178 20.0 179 | 179 None 180 | 180 None 181 | 181 None 182 | 182 65536L 183 | 183 None 184 | 184 40000.0 185 | 185 None 186 | 186 7470 187 | 187 None 188 | 188 None 189 | 189 None 190 | 190 None 191 | 191 None 192 | 192 249.05 193 | 193 None 194 | 194 243.05 195 | 195 None 196 | 196 280 197 | 197 None 198 | 198 20.0 199 | 199 None 200 | 200 None 201 | 201 None 202 | 202 65536L 203 | 203 None 204 | 204 30000.0 205 | 205 None 206 | 206 9500 207 | 207 None 208 | 208 None 209 | 209 None 210 | 210 None 211 | 211 None 212 | 212 233.65 213 | 213 None 214 | 214 233.05 215 | 215 None 216 | 216 280 217 | 217 None 218 | 218 25.0 219 | 219 None 220 | 220 None 221 | 221 None 222 | 222 65536L 223 | 223 None 224 | 224 25000.0 225 | 225 None 226 | 226 10720 227 | 227 None 228 | 228 None 229 | 229 None 230 | 230 None 231 | 231 None 232 | 232 223.25 233 | 233 None 234 | 234 220.65 235 | 235 None 236 | 236 280 237 | 237 None 238 | 238 29.0 239 | 239 None 240 | 240 None 241 | 241 None 242 | 242 32768L 243 | 243 None 244 | 244 20400.0 245 | 245 None 246 | 246 None 247 | 247 None 248 | 248 None 249 | 249 None 250 | 250 None 251 | 251 None 252 | 252 214.05 253 | 253 None 254 | 254 209.85 255 | 255 None 256 | 256 275 257 | 257 None 258 | 258 26.0 259 | 259 None 260 | 260 None 261 | 261 None 262 | 262 65536L 263 | 263 None 264 | 264 20000.0 265 | 265 None 266 | 266 12150 267 | 267 None 268 | 268 None 269 | 269 None 270 | 270 None 271 | 271 None 272 | 272 214.05 273 | 273 None 274 | 274 207.05 275 | 275 None 276 | 276 275 277 | 277 None 278 | 278 29.0 279 | 279 None 280 | 280 None 281 | 281 None 282 | 282 65536L 283 | 283 None 284 | 284 15000.0 285 | 285 None 286 | 286 13970 287 | 287 None 288 | 288 None 289 | 289 None 290 | 290 None 291 | 291 None 292 | 292 217.45 293 | 293 None 294 | 294 186.45 295 | 295 None 296 | 296 275 297 | 297 None 298 | 298 22.0 299 | 299 None 300 | 300 None 301 | 301 None 302 | 302 65536L 303 | 303 None 304 | 304 10000.0 305 | 305 None 306 | 306 16560 307 | 307 None 308 | 308 None 309 | 309 None 310 | 310 None 311 | 311 None 312 | 312 220.05 313 | 313 None 314 | 314 183.05 315 | 315 None 316 | 316 290 317 | 317 None 318 | 318 5.0 319 | 319 1 320 | 320 None 321 | 321 None 322 | 322 None 323 | 323 16384L 324 | 324 None 325 | 325 None 326 | 326 None 327 | 327 None 328 | 328 None 329 | 329 None 330 | 330 None 331 | 331 None 332 | 332 None 333 | 333 None 334 | 334 0 335 | -------------------------------------------------------------------------------- /tests/test_Benchmark.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import os 5 | import sys 6 | import logging 7 | import unittest 8 | 9 | from pybufrkit.decoder import Decoder 10 | 11 | logging.basicConfig(stream=sys.stdout, 12 | format="%(levelname)s: %(funcName)s: %(message)s") 13 | 14 | BASE_DIR = os.path.dirname(__file__) 15 | DATA_DIR = os.path.join(BASE_DIR, 'benchmark_data') 16 | 17 | 18 | class BenchMarkTests(unittest.TestCase): 19 | def setUp(self): 20 | self.decoder = Decoder() 21 | 22 | def test(self): 23 | for filename in os.listdir(DATA_DIR): 24 | with open(os.path.join(DATA_DIR, filename), 'rb') as ins: 25 | print(filename) 26 | bufr_message = self.decoder.process(ins.read(), wire_template_data=True) 27 | self.assertIsNotNone(bufr_message) 28 | -------------------------------------------------------------------------------- /tests/test_Decoder.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import os 5 | import unittest 6 | import functools 7 | 8 | from six import PY3, binary_type, text_type 9 | # noinspection PyUnresolvedReferences 10 | from six.moves import range 11 | 12 | from pybufrkit.decoder import Decoder 13 | 14 | BASE_DIR = os.path.dirname(__file__) 15 | DATA_DIR = os.path.join(BASE_DIR, 'data') 16 | 17 | 18 | def read_bufr_file(file_name): 19 | with open(os.path.join(DATA_DIR, file_name), 'rb') as ins: 20 | s = ins.read() 21 | return s 22 | 23 | 24 | class DecoderTests(unittest.TestCase): 25 | def setUp(self): 26 | self.decoder = Decoder() 27 | self.filename_stubs = [ 28 | 'IUSK73_AMMC_182300', 29 | 'rado_250', # uncompressed with 222000, 224000, 236000 30 | '207003', # compressed with delayed replication 31 | 'amv2_87', # compressed with 222000 32 | 'b005_89', # compressed with 222000 and 224000 (1st order stats) 33 | 'profiler_european', # uncompressed with 204001 associated fields 34 | 'jaso_214', # compressed with 204001 associated fields 35 | 'uegabe', # uncompressed with 204004 associated fields 36 | 'asr3_190', # compressed with complex replication and 222000, 224000 37 | 'b002_95', # uncompressed with skipped local descriptors 38 | 'g2nd_208', # compressed with identical string values for all subsets 39 | 'ISMD01_OKPR', # compressed with different string values for subsets 40 | 'mpco_217', 41 | ] 42 | 43 | def tearDown(self): 44 | pass 45 | 46 | def _compare(self, bufr_message, cmp_file_name): 47 | with open(os.path.join(DATA_DIR, cmp_file_name)) as ins: 48 | lines = ins.readlines() 49 | 50 | next_line = functools.partial(next, iter(lines)) 51 | for idx_subset in range(len(bufr_message.template_data.value.decoded_values_all_subsets)): 52 | for idx, value in enumerate(bufr_message.template_data.value.decoded_values_all_subsets[idx_subset]): 53 | cmp_line = next_line().strip() 54 | if value is None: 55 | line = '{} {}'.format(idx + 1, repr(value)) 56 | assert line == cmp_line, \ 57 | 'At file {} line {}: {} != {}'.format(cmp_file_name, idx + 1, line, cmp_line) 58 | elif isinstance(value, (binary_type, text_type)): 59 | # TODO: better to decode all ascii bytes to unicode string 60 | if isinstance(value, binary_type) and PY3: 61 | line = '{} {}'.format(idx + 1, repr(value)[1:]) 62 | else: 63 | line = '{} {}'.format(idx + 1, repr(value)) 64 | assert line == cmp_line, \ 65 | 'At file {} line {}: {} != {}'.format(cmp_file_name, idx + 1, line, cmp_line) 66 | else: 67 | field = cmp_line.split()[1] 68 | if field.endswith('L'): 69 | field = field[:-1] 70 | cmp_value = eval(field) 71 | assert abs(value - cmp_value) < 1.0e6, \ 72 | 'At file {} line {}: {} != {}'.format(cmp_file_name, idx + 1, value, cmp_value) 73 | 74 | def _print_values(self, bufr_message): 75 | for idx_subset in range(len(bufr_message.template_data.value.decoded_values_all_subsets)): 76 | for idx, value in enumerate(bufr_message.template_data.value.decoded_values_all_subsets[idx_subset]): 77 | print(idx + 1, repr(value)) 78 | 79 | def do_test(self, filename_stub): 80 | s = read_bufr_file(filename_stub + '.bufr') 81 | bufr_message = self.decoder.process(s, filename_stub) 82 | self._compare(bufr_message, filename_stub + '.values.cmp') 83 | 84 | def test_decode(self): 85 | print() 86 | for filename_stub in self.filename_stubs: 87 | print(filename_stub) 88 | self.do_test(filename_stub) 89 | -------------------------------------------------------------------------------- /tests/test_Encoder.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | import os 4 | import unittest 5 | 6 | from pybufrkit.encoder import Encoder 7 | from pybufrkit.decoder import Decoder 8 | import six 9 | # noinspection PyUnresolvedReferences 10 | from six.moves import range 11 | 12 | BASE_DIR = os.path.dirname(__file__) 13 | DATA_DIR = os.path.join(BASE_DIR, 'data') 14 | 15 | 16 | class EncoderTests(unittest.TestCase): 17 | def setUp(self): 18 | self.encoder = Encoder(ignore_declared_length=True) 19 | self.decoder = Decoder() 20 | 21 | self.filename_stubs = [ 22 | 'IUSK73_AMMC_182300', 23 | 'rado_250', # uncompressed with 222000, 224000, 236000 24 | '207003', # compressed with delayed replication 25 | 'amv2_87', # compressed with 222000 26 | 'b005_89', # compressed with 222000 and 224000 (1st order stats) 27 | 'profiler_european', # uncompressed with 204001 associated fields 28 | 'jaso_214', # compressed with 204001 associated fields 29 | 'uegabe', # uncompressed with 204004 associated fields 30 | 'asr3_190', # compressed with complex replication and 222000, 224000 31 | 'b002_95', # uncompressed with skipped local descriptors 32 | 'g2nd_208', # compressed with identical string values for all subsets 33 | 'ISMD01_OKPR', # compressed with different string values for subsets 34 | 'mpco_217', 35 | ] 36 | 37 | def tearDown(self): 38 | pass 39 | 40 | def do_test(self, filename_stub): 41 | with open(os.path.join(DATA_DIR, filename_stub + '.json')) as ins: 42 | s = ins.read() 43 | bufr_message_encoded = self.encoder.process(s) 44 | bufr_message_decoded = self.decoder.process(bufr_message_encoded.serialized_bytes) 45 | 46 | assert len(bufr_message_encoded.template_data.value.decoded_values_all_subsets) == \ 47 | len(bufr_message_decoded.template_data.value.decoded_values_all_subsets) 48 | 49 | for idx_subset in range(len(bufr_message_encoded.template_data.value.decoded_values_all_subsets)): 50 | encoder_values = bufr_message_encoded.template_data.value.decoded_values_all_subsets[idx_subset] 51 | decoder_values = bufr_message_decoded.template_data.value.decoded_values_all_subsets[idx_subset] 52 | assert len(encoder_values) == len(decoder_values) 53 | for idx_value in range(len(encoder_values)): 54 | if isinstance(encoder_values[idx_value], six.text_type): 55 | encoder_value = encoder_values[idx_value].encode('latin-1') 56 | else: 57 | encoder_value = encoder_values[idx_value] 58 | assert encoder_value == decoder_values[idx_value], \ 59 | '{!r} != {!r}'.format(encoder_value, decoder_values[idx_value]) 60 | 61 | def test_encode(self): 62 | print() 63 | for filename_stub in self.filename_stubs: 64 | print(filename_stub) 65 | self.do_test(filename_stub) 66 | -------------------------------------------------------------------------------- /tests/test_Encoder_arguments.py: -------------------------------------------------------------------------------- 1 | from pybufrkit.encoder import Encoder 2 | from pybufrkit.decoder import Decoder 3 | 4 | CONTRIVED_JSON = """[["BUFR", 94, 4], [22, 0, 1, 0, 0, false, "0000000", 2, 4, 0, 18, 0, 2016, 2, 18, 23, 0, 0], [25, "00000000", 2, true, false, "000000", [301001, 105002, 102000, 31001, 8002, 20011, 8002, 301011, 20011]], [35, "00000000", [[94, 461, 2, 1, 2, 3, 4, 21, 3, 5, 6, 7, 8, 9, 10, 22, 2016, 2, 18, 1], [95, 888, 3, 12, 11, 10, 9, 8, 7, 22, 2, 6, 5, 4, 3, 21, 2017, 1, 1, 2]]], ["7777"]]""" 5 | 6 | 7 | def test_overriding_master_table_version(): 8 | encoder = Encoder(master_table_version=31) 9 | bufr_message = encoder.process(CONTRIVED_JSON) 10 | assert 31 == bufr_message.master_table_version.value 11 | assert 31 == Decoder().process(bufr_message.serialized_bytes).master_table_version.value 12 | -------------------------------------------------------------------------------- /tests/test_NodePathParser.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import os 5 | import unittest 6 | 7 | from pybufrkit.dataquery import NodePathParser 8 | from pybufrkit.errors import PathExprParsingError 9 | 10 | BASE_DIR = os.path.dirname(__file__) 11 | 12 | 13 | class NodePathParserTests(unittest.TestCase): 14 | def setUp(self): 15 | self.parser = NodePathParser() 16 | 17 | def test(self): 18 | slice_all = slice(None, None, None) 19 | 20 | p1 = self.parser.parse('/001001') 21 | assert p1.subset_slice == slice_all 22 | assert len(p1.components) == 1 23 | assert p1.components[0] == ('/', '001001', slice_all) 24 | 25 | p2 = self.parser.parse('@[0] / 103008 / 001001[:].008321[::]') 26 | assert p2.subset_slice == 0 27 | assert len(p2.components) == 3 28 | assert p2.components[0] == ('/', '103008', slice_all) 29 | assert p2.components[1] == ('/', '001001', slice(None, None)) 30 | assert p2.components[2] == ('.', '008321', slice_all) 31 | 32 | p3 = self.parser.parse('@[0:10] /001008[1]. A01008') 33 | assert p3.subset_slice == slice(0, 10, None) 34 | assert p3.components[0] == ('/', '001008', 1) 35 | assert p3.components[1] == ('.', 'A01008', slice_all) 36 | 37 | p4 = self.parser.parse('@[-1] / 001008[::-1]') 38 | assert p4.subset_slice == slice(-1, None, None) 39 | assert p4.components[0] == ('/', '001008', slice(None, None, -1)) 40 | 41 | p5 = self.parser.parse('@[0::10]/301011/004001') 42 | assert p5.subset_slice == slice(0, None, 10) 43 | assert p5.components[0] == ('/', '301011', slice_all) 44 | assert p5.components[1] == ('/', '004001', slice_all) 45 | 46 | p6 = self.parser.parse('@[-2] / 001011[-10]') 47 | assert p6.subset_slice == slice(-2, -1, None) 48 | assert p6.components[0] == ('/', '001011', slice(-10, -9, None)) 49 | 50 | p7 = self.parser.parse('001001') 51 | assert p7.subset_slice == slice_all 52 | assert p7.components[0] == ('>', '001001', slice_all) 53 | 54 | p8 = self.parser.parse('>001001') 55 | assert p8.subset_slice == slice_all 56 | assert p8.components[0] == ('>', '001001', slice_all) 57 | 58 | p9 = self.parser.parse('/ 103002 > 010009[2] . A03101') 59 | assert p9.subset_slice == slice_all 60 | assert p9.components[0] == ('/', '103002', slice_all) 61 | assert p9.components[1] == ('>', '010009', 2) 62 | assert p9.components[2] == ('.', 'A03101', slice_all) 63 | 64 | p10 = self.parser.parse('@[0] > 020012') 65 | assert p10.subset_slice == 0 66 | assert p10.components[0] == ('>', '020012', slice_all) 67 | 68 | p11 = self.parser.parse('@[0] > 302035 / 302004 > 020012') 69 | assert p11.subset_slice == 0 70 | assert p11.components[0] == ('>', '302035', slice_all) 71 | assert p11.components[1] == ('/', '302004', slice_all) 72 | assert p11.components[2] == ('>', '020012', slice_all) 73 | 74 | def test_errors(self): 75 | with self.assertRaises(PathExprParsingError): 76 | self.parser.parse('') 77 | 78 | with self.assertRaises(PathExprParsingError): 79 | self.parser.parse('/') 80 | 81 | with self.assertRaises(PathExprParsingError): 82 | self.parser.parse('@/') 83 | 84 | with self.assertRaises(PathExprParsingError): 85 | self.parser.parse('/[0]') 86 | 87 | with self.assertRaises(PathExprParsingError): 88 | self.parser.parse('/001001[]') 89 | 90 | with self.assertRaises(PathExprParsingError): 91 | self.parser.parse('/001001[a]') 92 | 93 | with self.assertRaises(PathExprParsingError): 94 | self.parser.parse('/001001[:::]') 95 | 96 | with self.assertRaises(PathExprParsingError): 97 | self.parser.parse('@[:].001001') 98 | 99 | with self.assertRaises(PathExprParsingError): 100 | self.parser.parse('.001001') 101 | 102 | with self.assertRaises(PathExprParsingError): 103 | self.parser.parse('section_length') 104 | -------------------------------------------------------------------------------- /tests/test_Tables.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | import unittest 3 | 4 | from pybufrkit.renderer import FlatTextRenderer 5 | from pybufrkit.tables import TableGroupCacheManager 6 | from pybufrkit.descriptors import flat_member_ids 7 | 8 | 9 | table_group_01_cmp = """340009 (Normalized differential vegetation index (NDVI)) 10 | 001007 SATELLITE IDENTIFIER 11 | 001031 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE 12 | 002019 SATELLITE INSTRUMENTS 13 | 002020 SATELLITE CLASSIFICATION 14 | 301011 (Year, month, day) 15 | 004001 YEAR 16 | 004002 MONTH 17 | 004003 DAY 18 | 301013 (Hour, minute, second) 19 | 004004 HOUR 20 | 004005 MINUTE 21 | 004006 SECOND 22 | 005040 ORBIT NUMBER 23 | 201136 24 | 005041 SCAN LINE NUMBER 25 | 201000 26 | 025071 FRAME COUNT 27 | 005001 LATITUDE (HIGH ACCURACY) 28 | 005001 LATITUDE (HIGH ACCURACY) 29 | 006001 LONGITUDE (HIGH ACCURACY) 30 | 006001 LONGITUDE (HIGH ACCURACY) 31 | 107064 32 | 106032 33 | 008012 LAND/SEA QUALIFIER 34 | 008013 DAY/NIGHT QUALIFIER 35 | 008065 SUN-GLINT INDICATOR 36 | 008072 PIXEL(S) TYPE 37 | 013039 TERRAIN TYPE (ICE/SNOW) 38 | 040015 NORMALIZED DIFFERENTIAL VEGETATION INDEX (NDVI)""" 39 | 40 | table_group_02_cmp = """340008 (IASI sequence combining PC scores, channel selection and enhanced data) 41 | 001007 SATELLITE IDENTIFIER 42 | 001031 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE 43 | 002019 SATELLITE INSTRUMENTS 44 | 002020 SATELLITE CLASSIFICATION 45 | 004001 YEAR 46 | 004002 MONTH 47 | 004003 DAY 48 | 004004 HOUR 49 | 004005 MINUTE 50 | 202131 51 | 201138 52 | 004006 SECOND 53 | 201000 54 | 202000 55 | 005001 LATITUDE (HIGH ACCURACY) 56 | 006001 LONGITUDE (HIGH ACCURACY) 57 | 007024 SATELLITE ZENITH ANGLE 58 | 005021 BEARING OR AZIMUTH 59 | 007025 SOLAR ZENITH ANGLE 60 | 005022 SOLAR AZIMUTH 61 | 005043 FIELD OF VIEW NUMBER 62 | 005040 ORBIT NUMBER 63 | 201133 64 | 005041 SCAN LINE NUMBER 65 | 201000 66 | 201132 67 | 025070 MAJOR FRAME COUNT 68 | 201000 69 | 202126 70 | 007001 HEIGHT OF STATION 71 | 202000 72 | 103003 73 | 025140 START CHANNEL 74 | 025141 END CHANNEL 75 | 033060 GQISFLAGQUAL - INDIVIDUAL IASI-SYSTEM QUALITY FLAG 76 | 033061 GQISQUALINDEX - INDICATOR FOR INSTRUMENT NOISE PERFORMANCE (CONTRIBUTIONS FROM SPECTRAL AND RADIOMETRIC CALIBRATION) 77 | 033062 GQISQUALINDEXLOC - INDICATOR FOR GEOMETRIC QUALITY INDEX 78 | 033063 GQISQUALINDEXRAD - INDICATOR FOR INSTRUMENT NOISE PERFORMANCE (CONTRIBUTIONS FROM RADIOMETRIC CALIBRATION) 79 | 033064 GQISQUALINDEXSPECT - INDICATOR FOR INSTRUMENT NOISE PERFORMANCE (CONTRIBUTIONS FROM SPECTRAL CALIBRATION) 80 | 033065 GQISSYSTECSONDQUAL - OUTPUT OF SYSTEM TEC (TECHNICAL EXPERTISE CENTRE) QUALITY FUNCTION 81 | 040020 GQISFLAGQUALDETAILED - QUALITY FLAG FOR THE SYSTEM 82 | 101010 83 | 340002 (IASI Level 1c band description) 84 | 025140 START CHANNEL 85 | 025141 END CHANNEL 86 | 025142 CHANNEL SCALE FACTOR 87 | 104000 88 | ....031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR 89 | 201136 90 | 005042 CHANNEL NUMBER 91 | 201000 92 | 014046 SCALED IASI RADIANCE 93 | 108003 94 | 025140 START CHANNEL 95 | 025141 END CHANNEL 96 | 040026 SCORE QUANTIZATION FACTOR 97 | 040016 RESIDUAL RMS IN BAND 98 | 025062 DATABASE IDENTIFICATION 99 | 101000 100 | ....031002 EXTENDED DELAYED DESCRIPTOR REPLICATION FACTOR 101 | 040017 NON-NORMALIZED PRINCIPAL COMPONENT SCORE 102 | 002019 SATELLITE INSTRUMENTS 103 | 025051 AVHRR CHANNEL COMBINATION 104 | 101007 105 | 340004 (IASI Level 1c AVHRR single scene) 106 | 005060 Y ANGULAR POSITION FROM CENTRE OF GRAVITY 107 | 005061 Z ANGULAR POSITION FROM CENTRE OF GRAVITY 108 | 025085 FRACTION OF CLEAR PIXELS IN HIRS FOV 109 | 105006 110 | 005042 CHANNEL NUMBER 111 | 025142 CHANNEL SCALE FACTOR 112 | 014047 SCALED MEAN AVHRR RADIANCE 113 | 025142 CHANNEL SCALE FACTOR 114 | 014048 SCALED STANDARD DEVIATION AVHRR RADIANCE 115 | 020081 CLOUD AMOUNT IN SEGMENT 116 | 008029 SURFACE TYPE 117 | 020083 AMOUNT OF SEGMENT COVERED BY SCENE 118 | 008029 SURFACE TYPE 119 | 040018 GIACAVGIMAGIIS - AVERAGE OF IMAGER MEASUREMENTS 120 | 040019 GIACVARIMAGIIS - VARIANCE OF IMAGER MEASUREMENTS 121 | 040021 FRACTION OF WEIGHTED AVHRR PIXEL IN IASI FOV COVERED WITH SNOW/ICE 122 | 040022 NUMBER OF MISSING, BAD OR FAILED AVHRR PIXELS""" 123 | 124 | 125 | class TablesTests(unittest.TestCase): 126 | 127 | def setUp(self): 128 | self.table_group = TableGroupCacheManager.get_table_group(master_table_version=29) 129 | self.flat_text_renderer = FlatTextRenderer() 130 | 131 | def tearDown(self): 132 | pass 133 | 134 | def test_table_group_01(self): 135 | template = self.table_group.lookup(340009) 136 | assert self.flat_text_renderer.render(template) == table_group_01_cmp 137 | assert flat_member_ids(template) == [ 138 | 1007, 1031, 2019, 2020, 4001, 4002, 4003, 4004, 4005, 4006, 5040, 139 | 201136, 5041, 201000, 25071, 5001, 5001, 6001, 6001, 140 | 107064, 106032, 8012, 8013, 8065, 8072, 13039, 40015] 141 | 142 | def test_table_group_02(self): 143 | template = self.table_group.lookup(340008) 144 | assert self.flat_text_renderer.render(template) == table_group_02_cmp 145 | -------------------------------------------------------------------------------- /tests/test_TemplateCompiler.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | import os 4 | import json 5 | import unittest 6 | 7 | from pybufrkit.tables import TableGroupCacheManager 8 | from pybufrkit.templatecompiler import TemplateCompiler, loads_compiled_template 9 | from pybufrkit.decoder import Decoder 10 | 11 | BASE_DIR = os.path.dirname(__file__) 12 | DATA_DIR = os.path.join(BASE_DIR, 'data') 13 | 14 | 15 | class TemplateCompilerTests(unittest.TestCase): 16 | def setUp(self): 17 | self.template_compiler = TemplateCompiler() 18 | 19 | def test_compile_serialize_and_deserialize(self): 20 | table_group = TableGroupCacheManager.get_table_group() 21 | descriptor_ids = [ 22 | x.strip() for x in 23 | '311001, 222000, 101018, 31031, 1031, 1032, 101018, 33007'.split(',') 24 | ] 25 | template = table_group.template_from_ids(*descriptor_ids) 26 | compiled_template = self.template_compiler.process(template, table_group) 27 | 28 | reconstructed_compiled_template = loads_compiled_template( 29 | json.dumps(compiled_template.to_dict())) 30 | 31 | assert reconstructed_compiled_template.to_dict() == compiled_template.to_dict() 32 | 33 | def test_compiled_vs_noncompiled(self): 34 | decoder_noncompiled = Decoder() 35 | decoder_compiled = Decoder(compiled_template_cache_max=200) 36 | benchmark_data_dir = os.path.join(BASE_DIR, 'benchmark_data') 37 | 38 | for filename in os.listdir(benchmark_data_dir): 39 | with open(os.path.join(benchmark_data_dir, filename), 'rb') as ins: 40 | s = ins.read() 41 | 42 | bufr_message_1 = decoder_noncompiled.process(s) 43 | bufr_message_2 = decoder_compiled.process(s) 44 | assert bufr_message_1.template_data.value.decoded_descriptors_all_subsets == \ 45 | bufr_message_2.template_data.value.decoded_descriptors_all_subsets 46 | 47 | assert bufr_message_1.template_data.value.decoded_values_all_subsets == \ 48 | bufr_message_2.template_data.value.decoded_values_all_subsets 49 | 50 | assert bufr_message_1.template_data.value.bitmap_links_all_subsets == \ 51 | bufr_message_2.template_data.value.bitmap_links_all_subsets 52 | -------------------------------------------------------------------------------- /tests/test_TemplateData.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | import os 4 | import unittest 5 | 6 | from pybufrkit.decoder import Decoder 7 | from pybufrkit.renderer import NestedTextRenderer 8 | 9 | BASE_DIR = os.path.dirname(__file__) 10 | DATA_DIR = os.path.join(BASE_DIR, 'data') 11 | 12 | 13 | def read_bufr_file(file_name): 14 | with open(os.path.join(DATA_DIR, file_name), 'rb') as ins: 15 | s = ins.read() 16 | return s 17 | 18 | 19 | class TemplateDataTests(unittest.TestCase): 20 | def setUp(self): 21 | self.decoder = Decoder() 22 | self.filename_stubs = [ 23 | 'IUSK73_AMMC_182300', 24 | 'rado_250', # uncompressed with 222000, 224000, 236000 25 | '207003', # compressed with delayed replication 26 | 'amv2_87', # compressed with 222000 27 | 'b005_89', # compressed with 222000 and 224000 (1st order stats) 28 | 'profiler_european', # uncompressed with 204001 associated fields 29 | 'jaso_214', # compressed with 204001 associated fields 30 | 'uegabe', # uncompressed with 204004 associated fields 31 | 'asr3_190', # compressed with complex replication and 222000, 224000 32 | 'b002_95', # uncompressed with skipped local descriptors 33 | 'g2nd_208', # compressed with identical string values for all subsets 34 | 'ISMD01_OKPR', # compressed with different string values for subsets 35 | 'mpco_217', 36 | ] 37 | 38 | def do_test(self, filename_stub): 39 | s = read_bufr_file(filename_stub + '.bufr') 40 | bufr_message = self.decoder.process(s, filename_stub) 41 | 42 | if filename_stub in ('207003', 'rado_250'): 43 | with open(os.path.join(DATA_DIR, 44 | '{}.datadump.cmp'.format(filename_stub))) as ins: 45 | cmp_str = ins.read() 46 | dump_str = NestedTextRenderer().render(bufr_message.template_data.value) 47 | # TODO: this is to fix the inconsistent int and long of bitstring on different OS 48 | dump_str = dump_str.replace( 49 | '005040 ORBIT NUMBER 5258\n', '005040 ORBIT NUMBER 5258L\n') 50 | assert dump_str == cmp_str, dump_str 51 | else: 52 | NestedTextRenderer().render(bufr_message.template_data.value) 53 | 54 | def test_template_data(self): 55 | print() 56 | for filename_stub in self.filename_stubs: 57 | print(filename_stub) 58 | self.do_test(filename_stub) 59 | -------------------------------------------------------------------------------- /tests/test_bufr.py: -------------------------------------------------------------------------------- 1 | from pybufrkit.bufr import BufrMessage 2 | 3 | 4 | def test_bufr_message(): 5 | bufr_message = BufrMessage() 6 | assert bufr_message.master_table_number.value == 0 7 | assert bufr_message.originating_subcentre.value == 0 8 | -------------------------------------------------------------------------------- /tests/test_commands.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | import os 4 | import tempfile 5 | import shutil 6 | 7 | from pybufrkit.commands import command_encode 8 | 9 | BASE_DIR = os.path.dirname(__file__) 10 | DATA_DIR = os.path.join(BASE_DIR, 'data') 11 | 12 | 13 | class NS(object): 14 | 15 | def __init__(self, m): 16 | self._m = m 17 | 18 | def __getattr__(self, item): 19 | return self.__dict__['_m'].get(item, None) 20 | 21 | 22 | def test_command_encode_with_append(): 23 | input_file = os.path.join(DATA_DIR, 'IUSK73_AMMC_182300.json') 24 | output_dir = tempfile.mkdtemp() 25 | output_file = os.path.join(output_dir, 'out.bufr') 26 | with open(output_file, 'wb') as outs: 27 | outs.write(b'IOBI01 SBBR 011100\r\r\n') 28 | ns = NS( 29 | {'filename': input_file, 'output_filename': output_file, 'append': True, 'json': True, ', attributed': False}) 30 | 31 | command_encode(ns) 32 | with open(output_file, 'rb') as ins: 33 | assert ins.read().startswith(b'IOBI01 SBBR 011100\r\r\n') 34 | 35 | shutil.rmtree(output_dir, ignore_errors=True) 36 | 37 | 38 | def test_command_encode_with_preamble(): 39 | input_file = os.path.join(DATA_DIR, 'IUSK73_AMMC_182300.json') 40 | output_dir = tempfile.mkdtemp() 41 | output_file = os.path.join(output_dir, 'out.bufr') 42 | ns = NS( 43 | {'filename': input_file, 'output_filename': output_file, 'append': False, 'json': True, ', attributed': False, 44 | 'preamble': 'IOBI01 SBBR 011100\r\r\n'}) 45 | 46 | command_encode(ns) 47 | with open(output_file, 'rb') as ins: 48 | assert ins.read().startswith(b'IOBI01 SBBR 011100\r\r\n') 49 | 50 | shutil.rmtree(output_dir, ignore_errors=True) 51 | -------------------------------------------------------------------------------- /tests/test_generate_message.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import os 5 | import unittest 6 | 7 | from pybufrkit.decoder import Decoder, generate_bufr_message 8 | 9 | BASE_DIR = os.path.dirname(__file__) 10 | DATA_DIR = os.path.join(BASE_DIR, 'data') 11 | 12 | 13 | def read_bufr_file(file_name): 14 | with open(os.path.join(DATA_DIR, file_name), 'rb') as ins: 15 | s = ins.read() 16 | return s 17 | 18 | 19 | class MessageGeneratorTests(unittest.TestCase): 20 | 21 | def setUp(self): 22 | self.decoder = Decoder() 23 | 24 | def test_can_continue_on_error(self): 25 | bufr_messages = [m for m in generate_bufr_message( 26 | self.decoder, 27 | read_bufr_file('multi_invalid_messages.bufr'), 28 | continue_on_error=True)] 29 | assert len(bufr_messages) == 1, 'expect one good message' 30 | 31 | def test_can_filter_message(self): 32 | bufr_messages = [m for m in generate_bufr_message( 33 | self.decoder, 34 | read_bufr_file('multi_invalid_messages.bufr'), 35 | filter_expr='${%data_category} == 2')] 36 | assert len(bufr_messages) == 1, 'expect one message to be filtered' 37 | -------------------------------------------------------------------------------- /tests/test_mdquery.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import pytest 4 | 5 | from pybufrkit.errors import MetadataExprParsingError 6 | from pybufrkit.decoder import Decoder 7 | from pybufrkit.mdquery import MetadataExprParser, MetadataQuerent 8 | 9 | BASE_DIR = os.path.dirname(__file__) 10 | DATA_DIR = os.path.join(BASE_DIR, 'data') 11 | 12 | 13 | def read_bufr_file(file_name): 14 | with open(os.path.join(DATA_DIR, file_name), 'rb') as ins: 15 | s = ins.read() 16 | return s 17 | 18 | 19 | metadata_expr_parser = MetadataExprParser() 20 | md_querent = MetadataQuerent(metadata_expr_parser) 21 | decoder = Decoder() 22 | 23 | 24 | def test_simple_query(): 25 | s = read_bufr_file('jaso_214.bufr') 26 | bufr_message = decoder.process(s) 27 | assert md_querent.query(bufr_message, '%length') == 5004 28 | assert md_querent.query(bufr_message, '%edition') == 3 29 | 30 | 31 | def test_default_is_first_match(): 32 | s = read_bufr_file('jaso_214.bufr') 33 | bufr_message = decoder.process(s) 34 | assert md_querent.query(bufr_message, '%section_length') == 18 35 | 36 | 37 | def test_explicit_section_index(): 38 | s = read_bufr_file('jaso_214.bufr') 39 | bufr_message = decoder.process(s) 40 | assert md_querent.query(bufr_message, '%3.section_length') == 154 41 | assert md_querent.query(bufr_message, '%4.section_length') == 4768 42 | 43 | 44 | def test_unexpanded_descriptors(): 45 | s = read_bufr_file('jaso_214.bufr') 46 | bufr_message = decoder.process(s) 47 | assert md_querent.query(bufr_message, '%unexpanded_descriptors') == [ 48 | 1007, 25060, 1033, 2048, 2048, 5040, 201134, 49 | 7001, 201000, 202131, 7005, 202000, 301011, 50 | 301012, 4007, 5001, 6001, 8029, 8074, 8012, 51 | 25095, 25096, 25097, 204001, 31021, 22070, 52 | 204000, 8023, 22070, 21128, 123002, 8076, 53 | 204001, 31021, 201129, 21062, 201000, 204000, 54 | 8023, 21062, 204001, 31021, 201134, 7001, 55 | 201000, 204000, 202131, 7005, 202000, 8023, 56 | 202131, 7001, 202000, 21128, 204001, 31021, 57 | 2173, 204000, 107003, 201130, 2121, 201000, 58 | 204001, 31021, 12163, 204000, 104002, 2023, 59 | 202129, 11012, 202000, 13090, 13091 60 | ] 61 | 62 | 63 | def test_stripping_whites(): 64 | s = read_bufr_file('jaso_214.bufr') 65 | bufr_message = decoder.process(s) 66 | assert md_querent.query(bufr_message, ' %length ') == 5004 67 | 68 | 69 | def test_non_exist_metadata(): 70 | s = read_bufr_file('jaso_214.bufr') 71 | bufr_message = decoder.process(s) 72 | assert md_querent.query(bufr_message, '%blahblah') is None 73 | 74 | 75 | def test_non_exist_section(): 76 | s = read_bufr_file('jaso_214.bufr') 77 | bufr_message = decoder.process(s) 78 | assert md_querent.query(bufr_message, '%9.length') is None 79 | 80 | 81 | def test_error_no_leading_dollar_sign(): 82 | with pytest.raises(MetadataExprParsingError): 83 | metadata_expr_parser.parse('length') 84 | 85 | 86 | def test_error_invalid_section_index(): 87 | with pytest.raises(MetadataExprParsingError): 88 | metadata_expr_parser.parse('%a.length') 89 | -------------------------------------------------------------------------------- /tests/test_mismatched_bitmap.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import logging 5 | import os 6 | import sys 7 | 8 | from pybufrkit.decoder import Decoder 9 | from pybufrkit.renderer import FlatTextRenderer 10 | 11 | logging.basicConfig(stream=sys.stdout, 12 | format="%(levelname)s: %(funcName)s: %(message)s") 13 | 14 | BASE_DIR = os.path.dirname(__file__) 15 | DATA_DIR = os.path.join(BASE_DIR, 'data') 16 | 17 | compare = """ 249 001031 IDENTIFICATION OF ORIGINATING/GENERATING CENTRE (SEE NOTE 10) None 18 | 250 001032 GENERATING APPLICATION None 19 | 251 033036 NOMINAL CONFIDENCE THRESHOLD -> 16 None 20 | 252 033036 NOMINAL CONFIDENCE THRESHOLD -> 17 None 21 | 253 033036 NOMINAL CONFIDENCE THRESHOLD -> 18 None 22 | 254 033036 NOMINAL CONFIDENCE THRESHOLD None 23 | <<<<<< section 5 >>>>>> 24 | stop_signature = b'7777'""" 25 | 26 | 27 | def test_mismatched_bitmap(): 28 | decoder = Decoder() 29 | with open(os.path.join(DATA_DIR, 'ncep.352.bufr'), 'rb') as ins: 30 | bufr_message = decoder.process(ins.read()) 31 | output = FlatTextRenderer().render(bufr_message) 32 | 33 | assert output.endswith(compare) 34 | -------------------------------------------------------------------------------- /tests/test_nodepath.py: -------------------------------------------------------------------------------- 1 | from pybufrkit.dataquery import NodePath, PathComponent 2 | 3 | 4 | def test_node_path_str(): 5 | np = NodePath('') 6 | np.add_component(PathComponent('/', '001001', slice(None, None, None))) 7 | assert str(np) == '/001001[::]' 8 | 9 | np = NodePath('') 10 | np.subset_slice = 0 11 | np.add_component(PathComponent('/', '001001', 2)) 12 | assert str(np) == '@[0]/001001[2]' 13 | 14 | np = NodePath('') 15 | np.subset_slice = slice(0, 7, 1) 16 | np.add_component(PathComponent('/', '001002', slice(None, None, None))) 17 | np.add_component(PathComponent('.', '031001', slice(0, None, None))) 18 | assert str(np) == '@[0:7:1]/001002[::].031001[0::]' 19 | -------------------------------------------------------------------------------- /tests/test_optional_parameter.py: -------------------------------------------------------------------------------- 1 | from pybufrkit.decoder import Decoder 2 | from pybufrkit.encoder import Encoder 3 | 4 | # Special thanks to https://github.com/ReallyNiceGuy for identifying the bug and providing the test case. 5 | data = [ 6 | [ 7 | b'BUFR', 8 | 0, # file length (will be calculated) 9 | 4 10 | ], 11 | [0, # section length (will be calculated) 12 | 0, # master table 13 | 0, # centre 14 | 0, # subcentre 15 | 0, # sequence number 16 | False, # has section 2 (no) 17 | '0000000', # flag bits 18 | 6, # data category 19 | 0, # i18n subcategory 20 | 2, # data local subcategory 21 | 11, # master table version 22 | 10, # local table version 23 | 0, # year 24 | 0, # month 25 | 0, # day 26 | 0, # hour 27 | 0, # min 28 | 0, # sec 29 | b'\xff\xff'], # Extra bytes 30 | [0, # section length (will be calculated) 31 | '00000000', # reserved bits 32 | 1, # subsets 33 | True, # is observation 34 | False, # is compressed 35 | '000000', # flag bits 36 | # Definition follows 37 | [] 38 | ], 39 | [ 40 | 0, # section length (will be calculated) 41 | '00000000', # flag bits 42 | [ 43 | [ 44 | ] # flat data 45 | ] 46 | ], 47 | [b'7777'] 48 | ] 49 | 50 | 51 | def test_optional_parameter(): 52 | encoder = Encoder() 53 | bufr_message = encoder.process(data) 54 | assert bufr_message.sections[1].section_length.value == 24 55 | assert bufr_message.local_bytes.value == b'\xff\xff' 56 | 57 | decoder = Decoder() 58 | decoded = decoder.process(bufr_message.serialized_bytes) 59 | assert decoded.sections[1].section_length.value == 24 60 | assert decoded.local_bytes.value == b'\xff\xff' 61 | -------------------------------------------------------------------------------- /tests/test_optional_parameter_v2_even.py: -------------------------------------------------------------------------------- 1 | from pybufrkit.decoder import Decoder 2 | from pybufrkit.encoder import Encoder 3 | 4 | data = [ 5 | [ 6 | b'BUFR', 7 | 0, # file length (will be calculated) 8 | 2 9 | ], 10 | [0, # section length (will be calculated) 11 | 0, # master table 12 | 0, # centre 13 | 0, # sequence number 14 | False, # has section 2 (no) 15 | '0000000', # flag bits 16 | 6, # data category 17 | 0, # data local subcategory 18 | 11, # master table version 19 | 10, # local table version 20 | 25, # year 21 | 3, # month 22 | 25, # day 23 | 13, # hour 24 | 45, # min 25 | b'localdata', # Extra bytes 26 | ], 27 | [0, # section length (will be calculated) 28 | '00000000', # reserved bits 29 | 1, # subsets 30 | True, # is observation 31 | False, # is compressed 32 | '000000', # flag bits 33 | # Definition follows 34 | [] 35 | ], 36 | [ 37 | 0, # section length (will be calculated) 38 | '00000000', # flag bits 39 | [ 40 | [ 41 | ] # flat data 42 | ] 43 | ], 44 | [b'7777'] 45 | ] 46 | 47 | 48 | def test_optional_parameter_v2(): 49 | encoder = Encoder() 50 | bufr_message = encoder.process(data) 51 | print(bufr_message.serialized_bytes) 52 | assert bufr_message.sections[1].section_length.value == 26 53 | assert bufr_message.local_bytes.value == b'localdata' 54 | 55 | decoder = Decoder() 56 | decoded = decoder.process(bufr_message.serialized_bytes) 57 | assert decoded.sections[1].section_length.value == 26 58 | assert decoded.local_bytes.value == b'localdata' 59 | -------------------------------------------------------------------------------- /tests/test_optional_parameter_v2_odd.py: -------------------------------------------------------------------------------- 1 | from pybufrkit.decoder import Decoder 2 | from pybufrkit.encoder import Encoder 3 | 4 | data = [ 5 | [ 6 | b'BUFR', 7 | 0, # file length (will be calculated) 8 | 2 9 | ], 10 | [0, # section length (will be calculated) 11 | 0, # master table 12 | 0, # centre 13 | 0, # sequence number 14 | False, # has section 2 (no) 15 | '0000000', # flag bits 16 | 6, # data category 17 | 0, # data local subcategory 18 | 11, # master table version 19 | 10, # local table version 20 | 25, # year 21 | 3, # month 22 | 25, # day 23 | 13, # hour 24 | 45, # min 25 | b'local_data', # Extra bytes 26 | ], 27 | [0, # section length (will be calculated) 28 | '00000000', # reserved bits 29 | 1, # subsets 30 | True, # is observation 31 | False, # is compressed 32 | '000000', # flag bits 33 | # Definition follows 34 | [] 35 | ], 36 | [ 37 | 0, # section length (will be calculated) 38 | '00000000', # flag bits 39 | [ 40 | [ 41 | ] # flat data 42 | ] 43 | ], 44 | [b'7777'] 45 | ] 46 | 47 | 48 | def test_optional_parameter_v2(): 49 | encoder = Encoder() 50 | bufr_message = encoder.process(data) 51 | print(bufr_message.serialized_bytes) 52 | assert bufr_message.sections[1].section_length.value == 28 53 | assert bufr_message.local_bytes.value == b'local_data' 54 | 55 | decoder = Decoder() 56 | decoded = decoder.process(bufr_message.serialized_bytes) 57 | assert decoded.sections[1].section_length.value == 28 58 | assert decoded.local_bytes.value == b'local_data\x00' 59 | -------------------------------------------------------------------------------- /tests/test_prepbufr.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import logging 5 | import os 6 | import sys 7 | import unittest 8 | 9 | from pybufrkit.decoder import Decoder, generate_bufr_message 10 | from pybufrkit.renderer import FlatTextRenderer 11 | 12 | logging.basicConfig(stream=sys.stdout, 13 | format="%(levelname)s: %(funcName)s: %(message)s") 14 | 15 | BASE_DIR = os.path.dirname(__file__) 16 | DATA_DIR = os.path.join(BASE_DIR, 'data') 17 | 18 | compare = """ 405 012004 T2MS TABLE B ENTRY - 2-METER TEMPERATURE 294.6 19 | 406 013198 Q2MS TABLE B ENTRY - 2-METER SPECIFIC HUMIDITY 0.0083 20 | 407 013232 WXTS TABLE B ENTRY - SNOW PRECIP TYPE 0 21 | 408 013233 WXTP TABLE B ENTRY - ICE PELLET PRECIP TYPE 0 22 | 409 013234 WXTZ TABLE B ENTRY - FREEZING RAIN PRECIP TYPE 0 23 | 410 013235 WXTR TABLE B ENTRY - RAIN PRECIP TYPE 0 24 | 411 031001 DRF8BIT 3 25 | 412 S63255 1 bits 0 26 | 413 S63255 1 bits 0 27 | 414 S63255 1 bits 0 28 | <<<<<< section 5 >>>>>> 29 | """ 30 | 31 | 32 | class PrepBufrTests(unittest.TestCase): 33 | def setUp(self): 34 | self.decoder = Decoder() 35 | 36 | def test(self): 37 | output = [] 38 | with open(os.path.join(DATA_DIR, 'prepbufr.bufr'), 'rb') as ins: 39 | for bufr_message in generate_bufr_message(self.decoder, ins.read()): 40 | output.append(FlatTextRenderer().render(bufr_message)) 41 | 42 | lines = [line for line in ('\n'.join(output)).splitlines(True) 43 | if not line.startswith('TableGroupKey') and not line.startswith('stop_signature')] 44 | assert ''.join(lines).endswith(compare) 45 | -------------------------------------------------------------------------------- /tests/test_script.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | from __future__ import absolute_import 3 | 4 | import os 5 | 6 | from pybufrkit.decoder import Decoder 7 | from pybufrkit.script import process_embedded_query_expr, ScriptRunner 8 | 9 | BASE_DIR = os.path.dirname(__file__) 10 | DATA_DIR = os.path.join(BASE_DIR, 'data') 11 | 12 | decoder = Decoder() 13 | 14 | 15 | def read_bufr_file(file_name): 16 | with open(os.path.join(DATA_DIR, file_name), 'rb') as ins: 17 | s = ins.read() 18 | return s 19 | 20 | 21 | def test_pragma(): 22 | # Default value 23 | code = 'print("something")' 24 | runner = ScriptRunner(code) 25 | assert runner.pragma['data_values_nest_level'] == 1 26 | 27 | # Override from inside script 28 | code = '#$ data_values_nest_level = 4\nprint("something")' 29 | runner = ScriptRunner(code) 30 | assert runner.pragma['data_values_nest_level'] == 4 31 | 32 | # Override from method keyword 33 | runner = ScriptRunner(code, data_values_nest_level=0) 34 | assert runner.pragma['data_values_nest_level'] == 0 35 | 36 | 37 | def test_embedded_query(): 38 | script = 'length = ${%length}; v = ${001001}' 39 | s, variables = process_embedded_query_expr(script) 40 | assert s == 'length = PBK_0; v = PBK_1' 41 | 42 | 43 | def test_no_processing_comments(): 44 | script = 'length = ${%length} # length = ${%length}\nsomething = ${001001}' 45 | s, variables = process_embedded_query_expr(script) 46 | assert s == 'length = PBK_0 # length = ${%length}\nsomething = PBK_1' 47 | 48 | 49 | def test_single_var_for_multi_instances_of_same_query_expr(): 50 | script = 'length = ${%length}\nanother_length = ${%length}' 51 | s, variables = process_embedded_query_expr(script) 52 | assert s == 'length = PBK_0\nanother_length = PBK_0' 53 | 54 | 55 | def test_assignment(): 56 | s = read_bufr_file('jaso_214.bufr') 57 | bufr_message = decoder.process(s) 58 | script = 'print("The length is", ${%length})\na = ${%originating_centre}' 59 | variables = ScriptRunner(script).run(bufr_message) 60 | assert variables['a'] == 98 61 | 62 | 63 | def test_variable_injection(): 64 | s = read_bufr_file('jaso_214.bufr') 65 | bufr_message = decoder.process(s, file_path='FILE.bufr') 66 | script = 'a = PBK_FILENAME' 67 | variables = ScriptRunner(script).run(bufr_message) 68 | assert variables['a'] == 'FILE.bufr' 69 | -------------------------------------------------------------------------------- /tests/test_tablespreparer.py: -------------------------------------------------------------------------------- 1 | import pytest 2 | 3 | from pybufrkit.tablespreparer import prepare_wmo_tables 4 | 5 | 6 | @pytest.mark.skip 7 | def test_tables_preparer(): 8 | prepare_wmo_tables(35) 9 | prepare_wmo_tables(36) 10 | -------------------------------------------------------------------------------- /tests/test_utils.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from pybufrkit.decoder import Decoder 4 | from pybufrkit.renderer import FlatTextRenderer, NestedTextRenderer, FlatJsonRenderer, NestedJsonRenderer 5 | from pybufrkit.utils import nested_json_to_flat_json, flat_text_to_flat_json, nested_text_to_flat_json 6 | 7 | BASE_DIR = os.path.dirname(__file__) 8 | DATA_DIR = os.path.join(BASE_DIR, 'data') 9 | 10 | FILES = ( 11 | '207003.bufr', 12 | 'amv2_87.bufr', 13 | 'asr3_190.bufr', 14 | 'b002_95.bufr', 15 | 'b005_89.bufr', 16 | 'contrived.bufr', 17 | 'g2nd_208.bufr', 18 | 'ISMD01_OKPR.bufr', 19 | 'IUSK73_AMMC_040000.bufr', 20 | 'IUSK73_AMMC_182300.bufr', 21 | 'jaso_214.bufr', 22 | 'mpco_217.bufr', 23 | 'profiler_european.bufr', 24 | 'rado_250.bufr', 25 | 'uegabe.bufr', 26 | ) 27 | 28 | 29 | def read_bufr_file(file_name): 30 | with open(os.path.join(DATA_DIR, file_name), 'rb') as ins: 31 | s = ins.read() 32 | return s 33 | 34 | 35 | decoder = Decoder() 36 | flat_text_renderer = FlatTextRenderer() 37 | nested_text_renderer = NestedTextRenderer() 38 | flat_json_renderer = FlatJsonRenderer() 39 | nested_json_renderer = NestedJsonRenderer() 40 | 41 | 42 | def test_nested_json_to_flat_json(): 43 | def func(filename): 44 | s = read_bufr_file(filename) 45 | bufr_message = decoder.process(s) 46 | nested = nested_json_renderer.render(bufr_message) 47 | flat = flat_json_renderer.render(bufr_message) 48 | assert flat == nested_json_to_flat_json(nested) 49 | 50 | for filename in FILES: 51 | func(filename) 52 | 53 | 54 | def test_flat_text_to_flat_json(): 55 | def func(filename): 56 | s = read_bufr_file(filename) 57 | bufr_message = decoder.process(s) 58 | flat_text = flat_text_renderer.render(bufr_message) 59 | flat_json = flat_text_to_flat_json(flat_text) 60 | assert flat_json == flat_json_renderer.render(bufr_message) 61 | 62 | for filename in FILES: 63 | func(filename) 64 | 65 | 66 | def test_nested_text_to_flat_json(): 67 | def func(filename): 68 | s = read_bufr_file(filename) 69 | bufr_message = decoder.process(s) 70 | nested_text = nested_text_renderer.render(bufr_message) 71 | flat_json = nested_text_to_flat_json(nested_text) 72 | assert flat_json == flat_json_renderer.render(bufr_message) 73 | 74 | for filename in FILES: 75 | func(filename) 76 | -------------------------------------------------------------------------------- /tests/test_value_255_for_031001.py: -------------------------------------------------------------------------------- 1 | from __future__ import absolute_import 2 | from __future__ import print_function 3 | 4 | import logging 5 | import os 6 | import sys 7 | import unittest 8 | 9 | from pybufrkit.decoder import Decoder 10 | from pybufrkit.encoder import Encoder 11 | from pybufrkit.renderer import FlatTextRenderer 12 | from pybufrkit.utils import flat_text_to_flat_json 13 | 14 | logging.basicConfig(stream=sys.stdout, 15 | format="%(levelname)s: %(funcName)s: %(message)s") 16 | 17 | BASE_DIR = os.path.dirname(__file__) 18 | DATA_DIR = os.path.join(BASE_DIR, 'data') 19 | 20 | compare = """ 2536 006002 LONGITUDE (COARSE ACCURACY) 162.24 21 | 2537 005002 LATITUDE (COARSE ACCURACY) -37.01 22 | 2538 006002 LONGITUDE (COARSE ACCURACY) 161.45 23 | 2539 005002 LATITUDE (COARSE ACCURACY) -37.22 24 | 2540 006002 LONGITUDE (COARSE ACCURACY) 160.57 25 | 2541 020008 CLOUD DISTRIBUTION FOR AVIATION 10 26 | 2542 020012 CLOUD TYPE 9 27 | 2543 008007 DIMENSIONAL SIGNIFICANCE None 28 | 2544 008011 METEOROLOGICAL FEATURE None 29 | <<<<<< section 5 >>>>>> 30 | stop_signature = b'7777'""" 31 | 32 | class TestValue255For031001(unittest.TestCase): 33 | 34 | def test_uncompressed(self): 35 | output = self.decode() 36 | json = flat_text_to_flat_json(output) 37 | 38 | with self.assertRaises(FileNotFoundError): 39 | encoder = Encoder() 40 | encoder.process(json) 41 | 42 | encoder = Encoder(fallback_or_ignore_missing_tables=True) 43 | bufr_message = encoder.process(json) 44 | 45 | assert FlatTextRenderer().render(bufr_message) == output 46 | 47 | def test_compressed(self): 48 | output = self.decode().replace('is_compressed = False', 'is_compressed = True') 49 | json = flat_text_to_flat_json(output) 50 | 51 | encoder = Encoder(fallback_or_ignore_missing_tables=True) 52 | bufr_message = encoder.process(json) 53 | # output from compressed message has a different length due to compression 54 | compressed_output = FlatTextRenderer().render(bufr_message) 55 | self.assert_output(compressed_output) 56 | 57 | decoder = Decoder() 58 | decoded = decoder.process(bufr_message.serialized_bytes) 59 | assert FlatTextRenderer().render(decoded) == compressed_output 60 | 61 | 62 | def decode(self): 63 | decoder = Decoder() 64 | with open(os.path.join(DATA_DIR, 'JUBE99_EGRR.bufr'), 'rb') as ins: 65 | bufr_message = decoder.process(ins.read()) 66 | output = FlatTextRenderer().render(bufr_message) 67 | self.assert_output(output) 68 | return output 69 | 70 | def assert_output(self, output): 71 | assert '1901 031001 DELAYED DESCRIPTOR REPLICATION FACTOR 255' in output 72 | assert output.endswith(compare) --------------------------------------------------------------------------------