@@ -144,18 +144,14 @@ def _build_stage_kwargs(args):
144144
145145 # Check for --pipeline-skip-stages argument
146146 elif getattr (args , 'pipeline_skip_stages' , None ):
147- # Build a list of all steps except the skipped ones
148147 skip = [s .strip () for s in args .pipeline_skip_stages .split (',' )]
149148 try :
150- from ...pipeline .registry import StageRegistry
151149 from ...pipeline .config import PipelineConfig
152- registry = StageRegistry .get_instance ()
153- all_steps = registry .list_stages ()
154- selected_steps = [s for s in all_steps if s not in skip ]
155- # Build pipeline config with selected steps
156- config = PipelineConfig ()
157- for step_name in selected_steps :
158- config .add_stage (step_name )
150+ config = PipelineConfig .from_resource ("default" )
151+ config .pipeline = [
152+ stage for stage in config .pipeline
153+ if stage .name not in skip
154+ ]
159155 stage_kwargs ['pipeline_config' ] = config
160156 except Exception :
161157 # If registry fails, just pass the skip info and let read() handle it
@@ -272,6 +268,7 @@ def _write_processing_protocol(
272268 protocol ["handlers_applied" ] = metadata .get ("handlers_applied" )
273269 protocol ["variable_mappings" ] = metadata .get ("variable_mappings" )
274270 protocol ["derived_parameters" ] = metadata .get ("derived_parameters" )
271+ protocol ["transformations" ] = metadata .get ("transformations" )
275272 unit_conversions = _format_unit_conversions (metadata .get ("unit_conversions" ))
276273 if unit_conversions is not None :
277274 protocol ["unit_conversions" ] = unit_conversions
@@ -296,6 +293,112 @@ def _write_processing_protocol(
296293 json .dump (protocol , f , indent = 2 , sort_keys = True )
297294
298295
296+ def _format_example_value (value ) -> str :
297+ """Format one scalar preview value without verbose dtype wrappers."""
298+ try :
299+ import numpy as np
300+ except Exception :
301+ np = None
302+
303+ if np is not None :
304+ if isinstance (value , np .datetime64 ):
305+ return np .datetime_as_string (value )
306+ if isinstance (value , np .timedelta64 ):
307+ return str (value )
308+ if isinstance (value , np .generic ):
309+ value = value .item ()
310+
311+ if isinstance (value , bytes ):
312+ try :
313+ return value .decode ("utf-8" )
314+ except UnicodeDecodeError :
315+ return value .hex ()
316+ if isinstance (value , float ):
317+ return f"{ value :.6g} "
318+ return str (value )
319+
320+
321+ def _example_selector (array , max_values : int ) -> tuple [dict , str , int ]:
322+ """Return a small indexer and sampled dimension for an array preview."""
323+ if not array .dims :
324+ return {}, "" , 1
325+
326+ sample_dim = "time" if "time" in array .dims else array .dims [- 1 ]
327+ sample_count = min (int (array .sizes [sample_dim ]), max_values )
328+ indexer = {}
329+ for dim in array .dims :
330+ if dim == sample_dim :
331+ indexer [dim ] = slice (0 , sample_count )
332+ else :
333+ indexer [dim ] = 0
334+ return indexer , sample_dim , sample_count
335+
336+
337+ def _format_example_selector (array , indexer : dict , sample_dim : str ) -> str :
338+ """Describe the small indexer used for an example preview."""
339+ if not array .dims :
340+ return ""
341+
342+ parts = []
343+ for dim in array .dims :
344+ selector = indexer [dim ]
345+ if dim == sample_dim :
346+ parts .append (f"{ dim } =0:{ selector .stop } " )
347+ continue
348+
349+ label = "0"
350+ if dim in array .coords and array .coords [dim ].size :
351+ try :
352+ label = _format_example_value (array .coords [dim ].isel ({dim : 0 }).values )
353+ except Exception :
354+ label = "0"
355+ parts .append (f"{ dim } ={ label } " )
356+ return ", " .join (parts )
357+
358+
359+ def _format_array_example (name : str , array , max_values : int = 5 ) -> str :
360+ """Format a bounded example line for one xarray coordinate or variable."""
361+ indexer , sample_dim , _sample_count = _example_selector (array , max_values )
362+ subset = array .isel (indexer ) if indexer else array
363+
364+ try :
365+ values = subset .values
366+ except Exception as exc :
367+ return f" { name } : <failed to read preview: { exc } >"
368+
369+ try :
370+ import numpy as np
371+ flat = np .asarray (values ).reshape (- 1 )
372+ except Exception :
373+ flat = [values ]
374+
375+ preview = ", " .join (
376+ _format_example_value (value )
377+ for value in list (flat )[:max_values ]
378+ )
379+ selector_text = _format_example_selector (array , indexer , sample_dim )
380+ selector_text = f" [{ selector_text } ]" if selector_text else ""
381+ return (
382+ f" { name } { selector_text } : dims={ array .dims } , "
383+ f"shape={ tuple (array .shape )} , values=[{ preview } ]"
384+ )
385+
386+
387+ def _print_dataset_example (dataset , max_values : int = 5 ) -> None :
388+ """Print bounded examples without materializing the whole Dataset."""
389+ print (f"Example values (up to { max_values } values per variable):" )
390+
391+ if dataset .coords :
392+ print ("\n Coordinates:" )
393+ for name , array in dataset .coords .items ():
394+ print (_format_array_example (name , array , max_values = max_values ))
395+
396+ if dataset .data_vars :
397+ print ("\n Data variables:" )
398+ for name , array in dataset .data_vars .items ():
399+ print (_format_array_example (name , array , max_values = max_values ))
400+
401+
299402class ConvertCommand (BaseCommand ):
300403 """Handle file conversion with lazy loading."""
301404
@@ -428,8 +531,7 @@ def execute(self, args: argparse.Namespace) -> CommandResult:
428531 elif args .schema == 'info' :
429532 data .info ()
430533 elif args .schema == 'example' :
431- df = data .to_dataframe ()
432- print (df .head ())
534+ _print_dataset_example (data )
433535
434536 # Write processing protocol if requested
435537 if want_protocol :
0 commit comments