@@ -305,6 +305,10 @@ Series::setIterationEncoding(IterationEncoding ie)
305305 setIterationFormat (BASEPATH);
306306 setAttribute (" iterationEncoding" , std::string (" groupBased" ));
307307 break ;
308+ case IterationEncoding::stepBased:
309+ setIterationFormat (BASEPATH);
310+ setAttribute (" iterationEncoding" , std::string (" stepBased" ));
311+ break ;
308312 }
309313 return *this ;
310314}
@@ -321,9 +325,10 @@ Series::setIterationFormat(std::string const& i)
321325 if ( written () )
322326 throw std::runtime_error (" A files iterationFormat can not (yet) be changed after it has been written." );
323327
324- if ( *m_iterationEncoding == IterationEncoding::groupBased )
328+ if ( *m_iterationEncoding == IterationEncoding::groupBased ||
329+ *m_iterationEncoding == IterationEncoding::stepBased )
325330 if ( basePath () != i && (openPMD () == " 1.0.1" || openPMD () == " 1.0.0" ) )
326- throw std::invalid_argument (" iterationFormat must not differ from basePath " + basePath () + " for groupBased data" );
331+ throw std::invalid_argument (" iterationFormat must not differ from basePath " + basePath () + " for group- or stepBased data" );
327332
328333 setAttribute (" iterationFormat" , i);
329334 return *this ;
@@ -515,6 +520,7 @@ Series::flush_impl( iterations_iterator begin, iterations_iterator end )
515520 flushFileBased ( begin, end );
516521 break ;
517522 case IE::groupBased:
523+ case IE::stepBased:
518524 flushGroupBased ( begin, end );
519525 break ;
520526 }
@@ -654,6 +660,7 @@ Series::flushFileBased( iterations_iterator begin, iterations_iterator end )
654660 }
655661}
656662
663+ // @todo rename as flushGroupStepBased
657664void
658665Series::flushGroupBased ( iterations_iterator begin, iterations_iterator end )
659666{
@@ -722,7 +729,19 @@ Series::flushGroupBased( iterations_iterator begin, iterations_iterator end )
722729 it->second .m_writable ->parent = getWritable ( &iterations );
723730 it->second .parent = getWritable ( &iterations );
724731 }
725- it->second .flushGroupBased (it->first );
732+ switch ( *m_iterationEncoding )
733+ {
734+ using IE = IterationEncoding;
735+ case IE::groupBased:
736+ it->second .flushGroupBased ( it->first );
737+ break ;
738+ case IE::stepBased:
739+ it->second .flushStepBased ( it->first );
740+ break ;
741+ default :
742+ throw std::runtime_error (
743+ " [Series] Internal control flow error" );
744+ }
726745 if ( *it->second .m_closed == Iteration::CloseStatus::ClosedInFrontend )
727746 {
728747 // the iteration has no dedicated file in group-based mode
@@ -805,6 +824,15 @@ Series::readFileBased( )
805824 << " time series with fileBased iteration "
806825 " encoding. Loaded file is groupBased.\n " ;
807826 }
827+ else if ( encoding == " stepBased" )
828+ {
829+ // @todo should we throw? test this path
830+ *m_iterationEncoding = IterationEncoding::stepBased;
831+ std::cerr << " Series constructor called with iteration "
832+ " regex '%T' suggests loading a "
833+ << " time series with fileBased iteration "
834+ " encoding. Loaded file is stepBased.\n " ;
835+ }
808836 else
809837 throw std::runtime_error (
810838 " Unknown iterationEncoding: " + encoding );
@@ -859,6 +887,7 @@ Series::readFileBased( )
859887 " Please specify '%0<N>T' or open as read-only." );
860888}
861889
890+ // @todo rename as readGroupStepBased
862891void
863892Series::readGroupBased ( bool do_init )
864893{
@@ -881,6 +910,8 @@ Series::readGroupBased( bool do_init )
881910 std::string encoding = Attribute (*aRead.resource ).get < std::string >();
882911 if ( encoding == " groupBased" )
883912 *m_iterationEncoding = IterationEncoding::groupBased;
913+ else if ( encoding == " stepBased" )
914+ *m_iterationEncoding = IterationEncoding::stepBased;
884915 else if ( encoding == " fileBased" )
885916 {
886917 *m_iterationEncoding = IterationEncoding::fileBased;
@@ -996,23 +1027,50 @@ Series::read()
9961027 IOHandler->enqueue (IOTask (&iterations, pOpen));
9971028
9981029 readAttributes ();
999- iterations.readAttributes ();
1030+ /*
1031+ * __step__ changes over steps, so reread that.
1032+ */
1033+ iterations.readAttributes ( /* reread = */ true );
10001034
10011035 /* obtain all paths inside the basepath (i.e. all iterations) */
1002- Parameter< Operation::LIST_PATHS > pList;
1003- IOHandler->enqueue (IOTask (&iterations, pList));
1004- IOHandler->flush ();
1005-
1006- for ( auto const & it : *pList.paths )
1036+ switch (*m_iterationEncoding)
10071037 {
1008- Iteration& i = iterations[std::stoull (it)];
1009- if ( i.closedByWriter ( ) )
1038+ using IE = IterationEncoding;
1039+ case IE::groupBased:
1040+ case IE::fileBased:
10101041 {
1011- continue ;
1042+ Parameter< Operation::LIST_PATHS > pList;
1043+ IOHandler->enqueue (IOTask (&iterations, pList));
1044+ IOHandler->flush ();
1045+
1046+ for ( auto const & it : *pList.paths )
1047+ {
1048+ Iteration& i = iterations[std::stoull (it)];
1049+ if ( i.closedByWriter ( ) )
1050+ {
1051+ continue ;
1052+ }
1053+ pOpen.path = it;
1054+ IOHandler->enqueue (IOTask (&i, pOpen));
1055+ i.read ();
1056+ }
10121057 }
1013- pOpen.path = it;
1014- IOHandler->enqueue (IOTask (&i, pOpen));
1015- i.read ();
1058+ break ;
1059+ case IE::stepBased:
1060+ {
1061+ Parameter< Operation::READ_ATT > aRead;
1062+ uint64_t index = 0 ;
1063+ if ( iterations.containsAttribute ( " __step__" ) )
1064+ {
1065+ index = iterations.getAttribute ( " __step__" )
1066+ .get < uint64_t >();
1067+ }
1068+ Iteration & i = iterations[ index ];
1069+ pOpen.path = " " ;
1070+ IOHandler->enqueue ( IOTask ( &i, pOpen ) );
1071+ i.read ();
1072+ }
1073+ break ;
10161074 }
10171075}
10181076
@@ -1063,6 +1121,7 @@ Series::advance(
10631121 {
10641122 using IE = IterationEncoding;
10651123 case IE::groupBased:
1124+ case IE::stepBased:
10661125 flushGroupBased ( begin, end );
10671126 break ;
10681127 case IE::fileBased:
@@ -1131,8 +1190,10 @@ Series::advance(
11311190 // not closed on a per-iteration basis
11321191 // We will treat it as such nonetheless
11331192 *iteration.m_closed = Iteration::CloseStatus::ClosedInBackend;
1193+ break ;
11341194 }
1135- break ;
1195+ case IE::stepBased: // no action necessary
1196+ break ;
11361197 }
11371198 }
11381199
@@ -1157,7 +1218,9 @@ Series::openIteration( uint64_t index, Iteration iteration )
11571218 pOpen.path = auxiliary::replace_first ( basePath (), " %T/" , " " );
11581219 IOHandler->enqueue ( IOTask ( &iterations, pOpen ) );
11591220 /* open iteration path */
1160- pOpen.path = std::to_string ( index );
1221+ pOpen.path = *m_iterationEncoding == IterationEncoding::stepBased
1222+ ? " "
1223+ : std::to_string ( index );
11611224 IOHandler->enqueue ( IOTask ( &iteration, pOpen ) );
11621225 switch ( *iteration.m_closed )
11631226 {
@@ -1297,6 +1360,7 @@ SeriesIterator::operator++()
12971360 {
12981361 using IE = IterationEncoding;
12991362 case IE::groupBased:
1363+ case IE::stepBased:
13001364 {
13011365 // since we are in group-based iteration layout, it does not
13021366 // matter which iteration we begin a step upon
0 commit comments