[docs]defsetLocaleUTF8():"""Fix the Jupyter locale which is not UTF-8 by default on Windows."""locOld=locale.getpreferredencoding(False).lower()defgetpreferredencoding(do_setlocale=True):return"utf-8"locale.getpreferredencoding=getpreferredencodinglocNew=locale.getpreferredencoding(False)iflocOld!=locNew:print(f"Updated locale from {locOld} -> {locNew}.")
[docs]defisList(obj):"""Return true if the provided object is list-like including a numpy array but not a string. >>> isList([1, 2, 'a']) True >>> isList(tuple((1, 2, 'a'))) True >>> import numpy >>> isList(numpy.arange(5)) True >>> isList("dummy") False >>> isList(None) False """returnisinstance(obj,(list,tuple,np.ndarray))
[docs]defappendToPATH(parentPath,subdirs=None,verbose=False):"""Adds the given path with each subdirectory to the PATH environment variable."""parentPath=Path(parentPath)ifnotparentPath.is_dir():return# nothing to doifsubdirsisNone:subdirs=["."]sep=";"ifisWindows()else":"PATH=os.environ["PATH"].split(sep)forpathinsubdirs:path=parentPath/pathifverbose:print(indent,path,"[exists: {}]".format(path.is_dir()))ifpathnotinPATH:PATH.append(str(path))os.environ["PATH"]=sep.join(PATH)
[docs]defaddEnvScriptsToPATH():"""Prepends the *Scripts* directory of the current Python environment base directory to systems PATH variable. It is intended for Conda (Miniforge) environments on Windows that do not have this in their PATH environment variable, causing them to miss many commands provided from this location. """envPath=[pforpinsys.pathifp.endswith("Lib")]ifnotenvPath:return# probably not a Miniforge environmentenvPath=envPath[0]envPath=Path(envPath).parent/"Scripts"sep=";"ifisWindows()else":"environPATH=os.environ["PATH"].split(sep)# print(environPATH)ifenvPath.exists()andstr(envPath)notinenvironPATH:environPATH=[str(envPath)]+environPATHos.environ["PATH"]=sep.join(environPATH)
[docs]defcheckWinFor7z():"""Extend the PATH environment variable for access to the 7-zip executable."""ifnotisWindows():return# tests below are intended for Windowssevenzippath=r"C:\Program Files\7-Zip"ifnotos.path.isdir(sevenzippath):print("7-Zip not found in '{}'.\n".format(sevenzippath)+"7-Zip is required for managing data files and results!.")returnprint("Adding the following directory to $PATH:")appendToPATH(sevenzippath)print("\nUpdated PATH:")forpathinos.environ["PATH"].split(";"):print(indent,path)
[docs]defextract7z(fn,workdir=None):assertos.path.isfile(os.path.join(workdir,fn)),"Provided 7z archive '{}' not found!".format(fn)print("Extracting archived McDLS results:")proc=subprocess.run(["7z","x",fn],cwd=workdir,stdout=subprocess.PIPE,stderr=subprocess.PIPE,)print(proc.stdout.decode(errors="ignore"))iflen(proc.stderr):print("## stderr:\n",proc.stderr.decode(errors="ignore"))
[docs]defsetPackage(globalsdict):"""Sets the current directory of the notebook as python package to make relative module imports work. Usage: `setPackage(globals())` """path=Path().resolve()searchpath=str(path.parent)ifsearchpathnotinsys.path:sys.path.insert(0,searchpath)globalsdict["__package__"]=path.nameglobalsdict["__name__"]=path.nameprint(f"Setting the current directory as package '{path.name}':\n{path}.")
[docs]defgrouper(iterable,n,fillvalue=None):"""Returns an iterator over a list of tuples (grouping) for a given flat iterable."""args=[iter(iterable)]*nreturnitertools.zip_longest(*args,fillvalue=fillvalue)
[docs]deffmtErr(val,std,precision=2,width=None):"""Formats a given value and its stdandard deviation to physics notation, e.g. '1.23(4)'."""ifwidthisNone:width=""fmt="{:"+str(width)+"."+str(precision)+"f}({:.0f})"# print("fmtErr val:", val, "std:", std)returnfmt.format(val,std*10**(precision))
[docs]defupdatedDict(d,key,value):"""Implements the \\|= operator for dict in Python version <3.9."""dd=copy.copy(d)dd[key]=valuereturndd