Repository: UCBerkeleySETI/blimpy (language: python)

Issue:
Add rawhdr command line utility and a callable function
```rawhdr  FILEPATH``` - command line utility to print all of the guppi header fields.

```blimpy.rawhdr.get_obsnchan(FILEPATH)``` - callable function to retrieve the number of observation (coarse) channels.
Add rawhdr command line utility and a callable function
```rawhdr  FILEPATH``` - command line utility to print all of the guppi header fields.

```blimpy.rawhdr.get_obsnchan(FILEPATH)``` - callable function to retrieve the number of observation (coarse) channels.
Add rawhdr command line utility and a callable function
```rawhdr  FILEPATH``` - command line utility to print all of the guppi header fields.

```blimpy.rawhdr.get_obsnchan(FILEPATH)``` - callable function to retrieve the number of observation (coarse) channels.


Discussion / hints:

Fix patch:
diff --git a/VERSION-HISTORY.md b/VERSION-HISTORY.md
index 5056d28b..cfbfb414 100644
--- a/VERSION-HISTORY.md
+++ b/VERSION-HISTORY.md
@@ -3,6 +3,8 @@ This file is a version history of turbo_seti amendments, beginning with version
 <br>
 |    Date    | Version | Contents |
 | :--: | :--: | :-- |
+| 2021-03-08 | 2.0.9 | Implemented enhancement #182 - rawhdr utility (get header from raw files). |
+| | | Amended setup.cfg to enable hdf5plugin to be installed optimized by installation. |
 | 2021-03-05 | 2.0.8 | Yanked NUMBA from requirements.txt and waterfall.py due to observed instability in a large data array. |
 | 2021-03-04 | 2.0.7 | Fix issue #177 - Amend waterfall.py by adding a \_\_del\_\_ function to ensure that HDF5 files are closed. |
 | | | Fix issue #178 - Introduce a new utility (calcload) to calculate max_load for Waterfall. |
diff --git a/blimpy/__init__.py b/blimpy/__init__.py
index e3ca7b70..fc587cb8 100644
--- a/blimpy/__init__.py
+++ b/blimpy/__init__.py
@@ -14,6 +14,7 @@
     from . import h52fil
     from . import bl_scrunch
     from . import calcload
+    from . import rawhdr
 except:
     print("Warning: Cannot import HDF5 utilities")
 
diff --git a/blimpy/rawhdr.py b/blimpy/rawhdr.py
new file mode 100644
index 00000000..cb0c7422
--- /dev/null
+++ b/blimpy/rawhdr.py
@@ -0,0 +1,37 @@
+r'''
+Read the specified raw file.
+Print the entire header.
+Highlight the number of observation channels.
+'''
+
+import sys
+import blimpy
+from argparse import ArgumentParser
+
+
+def get_obsnchan(filepath):
+    gr = blimpy.GuppiRaw(filepath)
+    header, data_idx = gr.read_header()
+    return header['OBSNCHAN']
+
+
+def cmd_tool(args=None):
+    p = ArgumentParser(description='Calculate the Waterfall max_load value needed to load the data array for a given file.')
+    p.add_argument('filepath', type=str, help='Name of raw guppi file path to access')   
+    if args is None:
+        args = p.parse_args()
+    else:
+        args = p.parse_args(args)
+
+    print('Getting the header from {}.\n'.format(args.filepath))
+    with open(args.filepath, 'rb') as fh:
+        while True:
+            buffer = fh.read(80).decode("utf-8").strip()
+
+            print('\t', buffer)
+            if buffer[0:3] == "END":
+                break
+    print('\nThe number of observation channels:', get_obsnchan(args.filepath))
+
+if __name__ == "__main__":
+    cmd_tool()
diff --git a/setup.py b/setup.py
index 70c60e28..57206e24 100644
--- a/setup.py
+++ b/setup.py
@@ -3,7 +3,7 @@
 """
 from setuptools import setup, find_packages
 
-__version__ = '2.0.8'
+__version__ = '2.0.9'
 
 with open("README.md", "r") as fh:
     long_description = fh.read()
@@ -19,7 +19,8 @@
         'bl_scrunch = blimpy.bl_scrunch:cmd_tool',
         'matchfils = blimpy.match_fils:cmd_tool',
         'bldice = blimpy.dice:cmd_tool',
-        'calcload = blimpy.calcload:cmd_tool'
+        'calcload = blimpy.calcload:cmd_tool',
+        'rawhdr = blimpy.rawhdr:cmd_tool'
      ]
 }
 


Test patch:
diff --git a/tests/test_guppi.py b/tests/test_guppi.py
index d2c7c73b..c7a9d47d 100644
--- a/tests/test_guppi.py
+++ b/tests/test_guppi.py
@@ -1,15 +1,21 @@
+import os
 import numpy as np
 
 import blimpy as bl
 from tests.data import voyager_raw, voyager_block1
 
 def test_guppi():
+
     gr = bl.guppi.GuppiRaw(voyager_raw)
+    header, data_idx = gr.read_header()
+    nchans = header['OBSNCHAN']
+    assert (nchans == 64), 'test_guppi: OBSNCHAN should be 64 but observed to be {}'.format(nchans)
+
     h1, data_block_x1, data_block_y1 = gr.read_next_data_block_int8()
     h2, data_block_x2, data_block_y2 = gr.read_next_data_block_int8()
 
     assert not np.array_equal(data_block_x1, data_block_x2) and not np.array_equal(data_block_y1, data_block_y2) \
-        , "Data read from two blocks should not be equal"
+        , "test_guppi: Data read from two blocks should not be equal"
 
     gr = bl.guppi.GuppiRaw(voyager_raw)
     h1, data_block_1 = gr.read_next_data_block()
@@ -17,12 +23,12 @@ def test_guppi():
     data_block_reference_1 = np.load(voyager_block1)
 
     assert np.array_equal(data_block_1[:, :1000, :], data_block_reference_1) \
-        , "Data read should be consistent with previous versions"
+        , "test_guppi: Data read should be consistent with previous versions"
 
     data_block_casted_1 = np.append(data_block_x1, data_block_y1, axis=2).astype('float32').view('complex64')
 
     assert np.array_equal(data_block_1, data_block_casted_1) \
-        , "Reading as int8 then casting should be equal to reading directly as complex64"
+        , "test_guppi: Reading as int8 then casting should be equal to reading directly as complex64"
 
 # We have to keep instantiating objects because
 # the plotting routines read data in a manner
@@ -44,6 +50,18 @@ def test_fil_header():
     gr = bl.guppi.GuppiRaw(voyager_raw)
     gr.generate_filterbank_header()
 
+def test_rawhdr():
+    from blimpy.rawhdr import cmd_tool
+    args = [voyager_raw]
+    cmd_tool(args)
+
+def test_get_obsnchan():
+    nchans = bl.rawhdr.get_obsnchan(voyager_raw)
+    assert (nchans == 64), 'test_get_obsnchan: OBSNCHAN should be 64 but observed to be {}'.format(nchans)
+
 if __name__ == "__main__":
     test_guppi()
-    print("OK")
+    test_rawhdr()
+    test_get_obsnchan()
+
+