"""Extract scalar values from .npz result files.Use the ``llg3d.extract`` command line tool to extract scalar values from .npz resultfiles:.. command-output:: llg3d.extract --helpExtract the total execution time from a ``run.npz`` file:.. command-output:: llg3d.extract run.npz results/metrics/total_time :cwd: ../executeExtract both the total execution time and the time per iteration:.. command-output:: llg3d.extract run.npz results/metrics/total_time \ results/metrics/time_per_ite :cwd: ../execute"""importargparsefrompathlibimportPathimportnumpyasnpfromllg3d.ioimportRunResults,load_results
[docs]def_navigate(value:object,levels:list[str]):""" Recursively navigate through nested structures using keys. Tries subscript access (dicts/arrays) first, then attribute access (objects). Args: value: The current value to navigate. levels: List of keys/attributes to navigate through. Returns: The final value after navigating through all levels. """ifnotlevels:returnvaluek=levels[0]try:# Try dict/array subscript accessnext_value=value[k]# type: ignoreexcept(TypeError,KeyError,IndexError):# Fallback to attribute accessnext_value=getattr(value,k)return_navigate(next_value,levels[1:])
[docs]defextract_values(input:Path|RunResults,*keys:str)->list[ExtractedValue]:""" Extract scalar values from a .npz file or a RunResults object. Args: input: Path to the .npz result file or a RunResults object *keys: tuple of keys of the scalar values to extract (slash-separated for nested keys) Returns: The list of extracted scalar values Raises: ValueError: If one of the extracted values is not a scalar """ifisinstance(input,Path):results=load_results(input)else:results=inputvalues:list[ExtractedValue]=[]forkeyinkeys:# Split path into levelslevels:list[str]=key.split("/")raw_value=_navigate(results,levels)# Handle numpy scalars and arrays with shape ()ifisinstance(raw_value,np.ndarray):ifraw_value.shape!=():raiseValueError(f"Extracted value for key '{key}' is not a scalar.")value=raw_value.item()# Convert numpy scalar to Python scalarelse:value=raw_valueifnotisinstance(value,(float,int,str,bool,np.integer,np.floating)):raiseValueError(f"Extracted value for key '{key}' is not a scalar.")values.append(value)returnvalues
[docs]defmain():# pragma: no cover"""Parse command line arguments and print simulation info."""parser=argparse.ArgumentParser(description="Extract scalar values from .npz result files.",formatter_class=argparse.ArgumentDefaultsHelpFormatter,)parser.add_argument("filename",help="Path to the .npz result file",type=Path)parser.add_argument("keys",nargs="+",help=("Key(s) of the scalar value(s) to extract (slash-separated for nested keys)"),)args=parser.parse_args()values=extract_values(args.filename,*args.keys)print(" ".join(map(str,values)))