"""Support on working with local measurement files."""importjsonimportosimportdatetimeimportwarningsfromtabulateimporttabulateimportpandasaspdfromjii_multispeq.measurementimportanalyzeas_analyze
[docs]deflist_files(directory='./local/'):""" List all local files in the provided directory :param directory: Directory :type directory: str :return: None :rtype: None """ifnotos.path.exists(directory):raiseValueError("Selected directory does not exist.")tbl_content=[]forroot,_,filesinos.walk(directory):tbl_content=[]forfileinfiles:iffile.lower().endswith('.json'):file_path=os.path.join(root,file)try:withopen(file_path,'r',encoding='utf-8')asfp:data=json.load(fp)exceptjson.JSONDecodeError:warnings.warn('Error: Invalid JSON (%s)'%file_path)continuectime=os.path.getctime(file_path)date_str=datetime.datetime.fromtimestamp(ctime).strftime('%Y-%m-%d %H:%M')name_str='n/a'notes_str='n/a'type_str='single'ifisinstance(data,list)andlen(data)>1:type_str="multi (%s)"%len(data)ifisinstance(data,dict):if'created_at'indata:date_str=datetime.datetime.fromisoformat(data['created_at']).strftime('%Y-%m-%d %H:%M')if'name'indata:name_str=data['name']if'notes'indata:notes_str="n/a"ifdata['notes']==""elsedata['notes']tbl_content.append([file,date_str,type_str,name_str,notes_str])iflen(tbl_content)>0:print("\n├─ %s (%s)\n"%(root,len(tbl_content)))table=tabulate(tbl_content,headers=['File','Date','Type','Name','Notes'])print(table)
[docs]defload_files(directory=None,recursive=False,fn=None):""" Load files from selected directories into a dictionary. :param directory: Measurements in one or multiple directories :type directory: str or list[str] :param recursive: Recursive listing of files and subdirectories :type recursive: bool :param fn: Function to analyze the provided data :type fn: function :return: Dictionary with Measurements :rtype: list[dict] :raise ValueError: if directory is not provided with a sting or list :raise ValueError: if recursive is not True or False :raise ValueError: if no valid function is provided """ifdirectoryisNone:warnings.warn("No directroy selected")return[]ifnotisinstance(directory,(str,list)):raiseValueError("Directory needs to be provided as a string or list")if(notfnisNone)&(nothasattr(fn,'__call__')):raiseException("No function is provided")ifisinstance(directory,str):directory=[directory]files_all=[]fordirindirectory:ifnotos.path.exists(dir):warnings.warn("Directory %s does not exist"%dir)continue# If recursive directory selection is usedifrecursive:forroot,_,filesinos.walk(dir):forfileinfiles:iffile.lower().endswith('.json'):files_all.append(os.path.join(root,file))else:forfileinos.listdir(dir):filepath=os.path.join(dir,file)ifos.path.isfile(filepath)andfilepath.lower().endswith('.json'):files_all.append(filepath)# Remove duplicates that may occure when recursive is used with multiple directoriesfiles_all=list(set(files_all))# Now gather data from all files to return one list[dict]data=[]forfile_pathinfiles_all:try:withopen(file_path,'r',encoding='utf-8')asfp:data.append(json.load(fp))exceptjson.JSONDecodeError:warnings.warn('Error: Invalid JSON (%s)'%file_path)continue## Run function on every elementif(notfnisNone)&(hasattr(fn,'__call__')):data[:]=[_analyze(itm,fn)foritmindata]returndata
[docs]defload_files_df(directory=None,recursive=False,fn=None):""" Load files from selected directories into a dataframe. :param directory: Measurements in one or multiple directories :type directory: str or list[str] :param recursive: Recursive listing of files and subdirectories :type recursive: bool :param fn: Function to analyze the provided data :type fn: function :return: Dataframe with Measurements :rtype: pandas.DataFrame """## Load all files and apply function if selecteddata=load_files(directory,recursive,fn)## Now the data can be added to the dataframedf=pd.DataFrame(data)returndf