     }
   #endif
 
-    while (1)
-    {
-        SharedPointer<io::ReadData> h_read_data( read_data_file->next( batch_size ) );
-        if (h_read_data == NULL)
-            break;
-
+    io::SequenceDataHost<DNA_N> h_read_data;
+
+    while (io::next( &h_read_data, read_data_file.get(), batch_size ))
+    {
         // build the device side representation
-        const io::ReadDataDevice d_read_data( *h_read_data );
-
-        const uint32 n_read_symbols = h_read_data->read_index()[ h_read_data->size() ];
+        const io::SequenceDataDevice<DNA_N> d_read_data( h_read_data );
+
+        const uint32 n_read_symbols = h_read_data.bps();
 
         fprintf(stderr,"  %u reads, avg: %u bps, max: %u bps\n",
-            h_read_data->size(),
-            h_read_data->avg_read_len(),
-            h_read_data->max_read_len());
+            h_read_data.size(),
+            h_read_data.avg_sequence_len(),
+            h_read_data.max_sequence_len());
 
         if (TEST_MASK & GOTOH)
         {

                batch_score_profile_all(
                    aln::make_gotoh_aligner<aln::GLOBAL,aln::TextBlockingTag>( scoring ),
                    d_read_data.size(),
                    d_read_data.read_index(),
                    d_read_data.read_stream_storage(),
                    d_read_data.max_read_len(),
                    n_read_symbols,
                    nvbio::raw_pointer( d_ref_storage ),
                    ref_length,


            std::vector<int8_t> unpacked_reads( n_read_symbols );

            typedef io::SequenceDataHost<DNA_N>::const_plain_view_type read_view_type;
            typedef read_view_type::sequence_stream_type read_stream_type;

            const read_view_type reads_view = h_read_data;

            const read_stream_type packed_reads( reads_view.sequence_stream() );

            #pragma omp parallel for
            for (int i = 0; i < int( n_read_symbols ); ++i)
