diff --git a/sammy/src/io/CMakeLists.txt b/sammy/src/io/CMakeLists.txt
index 10a4c64a62e4391c5e12462b7ea0d045be93b911..99491c78fb4ca1d9a0d7e62536202331a21b5e66 100644
--- a/sammy/src/io/CMakeLists.txt
+++ b/sammy/src/io/CMakeLists.txt
@@ -2,15 +2,18 @@ INCLUDE(SammyPackageSetup)
 
 TRIBITS_PACKAGE(io)
 
+find_package(HDF5 REQUIRED COMPONENTS C CXX HL)
 
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../sammy_conf.h.in sammy_conf.h @ONLY)
 
-INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR})
+INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}
+                    ${HDF5_INCLUDE_DIR})
 
 
 # Set headers
 SET(HEADERS ExperimentalParametersIO.h
             odfIO.h
+            hdf5IO.h
             interface/cpp/ExperimentalParametersIOInterface.h 
 )
 
@@ -18,6 +21,7 @@ APPEND_SET(IO_SOURCES
 
         ExperimentalParametersIO.cpp
         odfIO.cpp
+        hdf5IO.cpp
         interface/cpp/ExperimentalParametersIOInterface.cpp
         interface/fortran/ExperimentalParametersIO_M.f90   
         interface/fortran/ExperimentalParametersIO_I.f90      
@@ -36,3 +40,15 @@ INSTALL(FILES ${HEADERS} DESTINATION "src/io")
 TRIBITS_ADD_TEST_DIRECTORIES(tests)
 
 TRIBITS_PACKAGE_POSTPROCESS()
+
+
+# --------------------------------------------
+# Build separate executable to convert ODF
+# to HDF5 files, install to normal location
+# --------------------------------------------
+
+add_executable(readodf readodf.cpp)
+target_link_libraries(readodf PRIVATE HDF5::HDF5
+                                      SammyIOUtilsLib)
+install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/readodf  DESTINATION "bin/")
+
diff --git a/sammy/src/io/hdf5IO.cpp b/sammy/src/io/hdf5IO.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..188df114fef65fb4f4c45af0cbd9e4edf5295028
--- /dev/null
+++ b/sammy/src/io/hdf5IO.cpp
@@ -0,0 +1,11 @@
+#include "hdf5IO.h"
+
+namespace sammy {
+    
+    hdf5IO::hdf5IO() {}
+
+    void hdf5IO::writeODFtoHDF5(){
+        std::cout << "hello world" << std::endl;
+    }
+
+}
\ No newline at end of file
diff --git a/sammy/src/io/hdf5IO.h b/sammy/src/io/hdf5IO.h
new file mode 100644
index 0000000000000000000000000000000000000000..2113c59d325cf472a67fbb9f017003db935f9547
--- /dev/null
+++ b/sammy/src/io/hdf5IO.h
@@ -0,0 +1,25 @@
+#ifndef SAMMY_HDF5IO_H
+#define SAMMY_HDF5IO_H
+
+#include <vector>
+#include <fstream> // ifstream
+#include <iostream>
+#include "hdf5.h"
+
+namespace sammy{
+
+    class hdf5IO {
+    
+    public:
+        hdf5IO();
+        virtual ~hdf5IO() {}
+
+        /****************************************
+         * Write data from ODF file into HDF5
+         ***************************************/
+        void writeODFtoHDF5();
+        
+    };
+}
+
+#endif /* SAMMY_HDF5IO_H */
\ No newline at end of file
diff --git a/sammy/src/io/odfIO.cpp b/sammy/src/io/odfIO.cpp
index 885d94e04b15559e47fc02b5bf6e17f522453dc4..02b5b0b15c9baf426d222175c129699045e50497 100644
--- a/sammy/src/io/odfIO.cpp
+++ b/sammy/src/io/odfIO.cpp
@@ -16,7 +16,7 @@ namespace sammy{
             fs.read( (char*)&tmp2, 1 );
             fs.read( (char*)&tmp3, 1 );
             fs.read( (char*)&tmp4, 1 );
-            // std::cout << "1,2,3,4 = " << (int)tmp1<<","<< (int)tmp2<<","<< (int)tmp3<<","<< (int)tmp4<<","<<std::endl;
+            // to print: std::cout << "tmp1 = " << (int)tmp1 << std::endl;
             if((tmp2 & 0x7f) == 0){      
                 if(tmp1+tmp3+tmp4 != 0) {
                     tmp1=tmp2=tmp3=0;
@@ -39,8 +39,15 @@ namespace sammy{
         return value;
     }
 
+    int odfIO::readInteger(std::ifstream &fs){
+        size_t intsize = sizeof(int);
+        int val;
+        fs.read( (char*)&val, intsize );
+        return val;
+    }
+
     std::vector<double> odfIO::getSection(int start, int readSize, int section, 
-                                          header &hd, std::ifstream &in){
+                                          odfHeader &hd, std::ifstream &in){
         in.seekg(0,std::ios::beg);
         std::vector<double> dataSec;
         int block,skipped,channel,max;
@@ -62,7 +69,7 @@ namespace sammy{
         int read = 0;
         for(int i=0;i<max;i++){
             if(      hd.mode == 3 ) dataSec[read] = readFloat(in,hd.unix);
-            else if( hd.mode == 1 ) dataSec[read] = readFloat(in,hd.unix); // needs to read integer not float
+            else if( hd.mode == 1 ) dataSec[read] = readInteger(in);
             read++;
         }
         in.ignore(intsize*2); // skip over two ints in the block which contain no data
@@ -74,7 +81,7 @@ namespace sammy{
 
             for( int i=0; i<125 && read<readSize; i++ ) {
                 if(     hd.mode == 3) dataSec[read] = readFloat(in,hd.unix);
-                else if(hd.mode == 1) dataSec[read] = readFloat(in,hd.unix); // needs to read integer not float
+                else if(hd.mode == 1) dataSec[read] = readInteger(in);
                 read++;
             }
             in.ignore(intsize*2); // skip over two ints in the block which contain no data
@@ -83,11 +90,31 @@ namespace sammy{
         return dataSec;
     }
 
-    void odfIO::readHeader(std::ifstream &in, header &head){
+    std::vector<std::vector<double>> odfIO::getAllSections(odfHeader &head, 
+                                                           std::ifstream &in){
+        // --- go to start of file ---
+        in.seekg(0, std::ios::beg);
+
+        std::vector<std::vector<double>> data;
+        data.resize(head.numSection);
+
+        // --- grab each section ---
+        for( int section=1; section<=head.numSection; ++section ){
+            data[section-1].resize(head.numChan);
+            data[section-1] = getSection(0,head.numChan,section,head,in);
+        }
+
+        return data;
+    }
+
+    void odfIO::readHeader(std::ifstream &in, odfHeader &head){
         size_t intsize = sizeof(int);
         int bytes_per_block = 512;
         int bytes_per_word = 4;
         // comments based on OPRODF manual: Jack Craven, report no. ORNL/CSD/TM-45, 1978
+        //  ** keep in mind that changes may have happened between that report and
+        //  ** the writing of the files!!! For example it seems that 36 bit ints are no 
+        //  ** longer used. 
         in.read( (char*)&head.mode,       intsize ); // 0,1,3 for 18-bit ints, 36-bit ints, floating-point vals
         in.read( (char*)&head.source,     intsize ); // 0,1,2 for SEL, CSISRS, or ENDF/B data
         in.read( (char*)&head.irun,       intsize ); // run number
@@ -142,7 +169,7 @@ namespace sammy{
         int bytes_to_scalars = (head.nsblks) * bytes_per_block;
     }
 
-    void odfIO::printHeader(header &head){
+    void odfIO::printHeader(odfHeader &head){
         std::cout << "mode       = " << head.mode       << std::endl       
                   << "source     = " << head.source     << std::endl     
                   << "irun       = " << head.irun       << std::endl       
diff --git a/sammy/src/io/odfIO.h b/sammy/src/io/odfIO.h
index 34f24b874ad98f036153d9fbc86fb37cb9b834b3..687637102290c95b7542e04f0c7c80f1682be871 100644
--- a/sammy/src/io/odfIO.h
+++ b/sammy/src/io/odfIO.h
@@ -7,35 +7,43 @@
 
 namespace sammy{
 
+    /****************************************
+     * Object for ODF header info
+     ***************************************/
+    struct odfHeader {
+        // variables explained in readHeader()
+        int mode, source, irun;
+        int ncblks, ncwrds, nsblks, nswrds, ncstrt, ncntrs, nxstrt, nxwrds;
+        int npblks, npwrds, ndtype, numSection, ifb, numChan;
+        int zan, awr, mat, mf, mt; // ENDF identifiers
+        int varswt,dctswt,strt,ndwend;
+        bool unix;
+        std::vector<int> ndtbl;
+    };
+
     class odfIO {
     
     public:
         odfIO();
         virtual ~odfIO() {}
 
-        /****************************************
-         * Object for ODF header info
-         ***************************************/
-        struct header {
-            // variables explained in readHeader()
-            int mode, source, irun;
-            int ncblks, ncwrds, nsblks, nswrds, ncstrt, ncntrs, nxstrt, nxwrds;
-            int npblks, npwrds, ndtype, numSection, ifb, numChan;
-            int zan, awr, mat, mf, mt; // ENDF identifiers
-            int varswt,dctswt,strt,ndwend;
-            bool unix;
-            std::vector<int> ndtbl;
-        };
-
         /****************************************
          * Read a single floating point value, based on whether it is in
          * VAX-VMS format (?) or unix, from an ODF file
          * 
          * @param fs a reference to the ODF file stream
          * @param unix whether or not the format is unix-style
+         * @return val the stored value
          ***************************************/
         double readFloat(std::ifstream &fs, bool unix);
 
+        /****************************************
+         * Read a single integer
+         * @param fs a reference to the ODF file stream
+         * @return val the stored value
+         ***************************************/
+        int readInteger(std::ifstream &fs);
+
         /****************************************
          * Read one section of data. Sections are typcially energy, transmission,
          * cross section, etc. 
@@ -43,9 +51,23 @@ namespace sammy{
          * @param start what channel to start in
          * @param readSize how many channels to read
          * @param section which section to read from
+         * @param head a struct containing the header info
+         * @param in the input data file stream
+         * @return dataSec all requested channels of requested section
          ***************************************/
         std::vector<double> getSection(int start, int readSize, int section, 
-                                       header &hd, std::ifstream &in);
+                                       odfHeader &head, std::ifstream &in);
+
+        /****************************************
+         * Read all sections of data into double-vector, grabbing all info.
+         * This calls getSection() for all sections and channels
+         * 
+         * @param head a struct containing the header info
+         * @param in the input data file stream
+         * @return data all channels and all sections of data
+         ***************************************/
+        std::vector<std::vector<double>> getAllSections(odfHeader &head, 
+                                                        std::ifstream &in);
 
         /****************************************
          * Read the ODF header 
@@ -53,14 +75,14 @@ namespace sammy{
          * @param fs a reference to the ODF file stream
          * @param head an ODF-header struct
          ***************************************/
-        void readHeader(std::ifstream &in, header &head);
+        void readHeader(std::ifstream &in, odfHeader &head);
 
         /****************************************
          * Print the ODF header 
          * 
          * @param head an ODF-header struct
          ***************************************/
-        void printHeader(header &head);
+        void printHeader(odfHeader &head);
         
     };
 }
diff --git a/sammy/src/io/readodf.cpp b/sammy/src/io/readodf.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..81fae8410b9202f17f36a5316fbb5ccfa70921b7
--- /dev/null
+++ b/sammy/src/io/readodf.cpp
@@ -0,0 +1,163 @@
+#include <iostream>
+// #include "hdf5.h"
+#include "H5Cpp.h"
+#include "odfIO.h"
+
+#define MAX_NAME_LEN 32
+
+int main(int argc, char const *argv[])
+{
+    // -------------------------------------------------------------------------
+    // --- Grabbing the input args
+    // -------------------------------------------------------------------------
+    if( argc < 3 ){
+        std::cerr << "Wrong number of arguments given." << std::endl
+                  << "Specify input ODF file and output HDF5 file." << std::endl;
+        return -1;
+    }
+    
+    std::string  odfFilename = argv[1];
+    std::string hdf5Filename = argv[2];
+
+    std::cout << "Reading from file: " << odfFilename << std::endl;
+    std::cout << "Writing to file:   " << hdf5Filename << std::endl;
+
+    // -------------------------------------------------------------------------
+    // --- Read ODF file
+    // -------------------------------------------------------------------------
+    sammy::odfIO odf;
+    sammy::odfHeader head;
+    std::vector<std::vector<double>> data;
+
+    // --- Open file ---
+    std::ifstream in( odfFilename, std::ios::in | std::ios::binary );
+    // --- kill bad open  ---
+    if( !in.is_open() ){
+        std::cerr << "Error opening file: " << odfFilename << std::endl;
+        return 1;
+    }
+
+    // --- read header ---
+    odf.readHeader(in, head);
+
+    // --- read data sections ---
+    data = odf.getAllSections(head, in);
+
+    in.close();
+
+    // -------------------------------------------------------------------------
+    // --- Output HDF5 file
+    // -------------------------------------------------------------------------
+    
+    char sectnames[11][MAX_NAME_LEN] = {"energy","trans","dtrans",
+                              "cro","dcro","cs","zero","co","zero","idk","dcs"};
+
+    // make dataset 
+    double dset_data[data.size()][data[0].size()];
+    for( size_t i=0;i<data.size();++i ){
+        std::copy(data[i].begin(),data[i].end(), dset_data[i]);
+    }
+
+    // write 2 datasets: data and data section names
+
+    // data space
+    hsize_t ddim[2];
+    ddim[0] = head.numSection;
+    ddim[1] = head.numChan;
+
+    int drank = sizeof(ddim) / sizeof(hsize_t);
+
+    std::string dataname("/data/sections");
+
+    // section names space
+    hsize_t sdim[1];
+    sdim[0] = head.numSection;
+
+    int srank = sizeof(sdim) / sizeof(hsize_t);
+
+    std::string sectionnames("/data/sectnames");
+
+
+    // open file and write
+    H5::DataSpace dspace(drank,ddim);
+    H5::DataSpace sspace(srank,sdim);
+    H5::H5File  *file = new H5::H5File(hdf5Filename,H5F_ACC_TRUNC);
+    H5::Group   *group = new H5::Group( file->createGroup( "/data" ));
+
+    H5::DataSet *dataset = new H5::DataSet(file->createDataSet(dataname,H5::PredType::NATIVE_DOUBLE,dspace));
+    H5::DataSet *nameset = new H5::DataSet(file->createDataSet(sectionnames,H5::StrType(H5::PredType::C_S1, MAX_NAME_LEN),sspace));
+
+    dataset->write(dset_data,H5::PredType::NATIVE_DOUBLE);
+    nameset->write(sectnames,H5::StrType(H5::PredType::C_S1, MAX_NAME_LEN));
+
+    delete file;
+    delete dataset;
+    delete nameset;
+
+    
+    /* old
+
+    // --- setup with HDF types ---
+    hid_t   file_id, dataspace_id, dataset_id, group_id, name_dataspace_id;
+    hid_t   name_dataset_id;
+    herr_t  status;
+    hsize_t dims[2];
+
+    //energy,trans,dtrans,cro,dcro,cs,zero,co,zero,idk,dcs
+
+    dims[0] = data.size();
+    dims[1] = data[0].size();
+    dataspace_id = H5Screate_simple(2, dims, NULL);
+
+    // --- open file ---
+    file_id = H5Fcreate(hdf5Filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
+
+    // --- make a dataset group ---
+    group_id = H5Gcreate2(file_id,"data",H5P_DEFAULT,H5P_DEFAULT,H5P_DEFAULT);
+
+    // --- create dataset ---
+    // H5T_IEEE_F64LE is an HDF5 predefined datatype for 64 bit floating point,
+    // little endian. Might replace with H5T_NATIVE_DOUBLE
+    dataset_id = H5Dcreate2(file_id, "/data/sections", H5T_IEEE_F64LE, dataspace_id, 
+                            H5P_DEFAULT, H5P_DEFAULT, H5P_DEFAULT);
+
+    double dset_data[data.size()][data[0].size()];
+    for( size_t i=0;i<data.size();++i ){
+        std::copy(data[i].begin(),data[i].end(), dset_data[i]);
+    }
+
+    // --- Write the dataset to file --- 
+    status = H5Dwrite(dataset_id, H5T_NATIVE_DOUBLE, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+                      dset_data);
+
+
+    // --- write column names for dataset ---
+    std::vector<std::string> colnames; 
+    colnames.resize(11);
+    colnames = {"energy","trans","dtrans","cro","dcro","cs",
+                                "zero","co","zero","idk","dcs"};
+    std::string name = "energy";
+    const char* cname = name.c_str();
+
+    hid_t datatype = H5Tcopy (H5T_C_S1);
+    size_t MAX_NAME_LENGTH = 32;
+    H5Tset_size (datatype, H5T_VARIABLE);
+    hsize_t name_dims[1];
+    name_dims[0] = 1;
+    name_dataspace_id = H5Screate_simple(1, name_dims, NULL);
+    name_dataset_id = H5Dcreate2(file_id, "/data/colnames", datatype, 
+                                 name_dataspace_id, H5P_DEFAULT, H5P_DEFAULT, 
+                                 H5P_DEFAULT);
+    for( auto name : colnames ){
+        const char* cname = name.c_str();
+        status = H5Dwrite(name_dataset_id, datatype, H5S_ALL, H5S_ALL, H5P_DEFAULT,
+                      &cname);
+    }
+
+
+    status = H5Fclose(file_id);
+
+    */
+
+    return 0;
+}
\ No newline at end of file