Source code for tomopal.post.analysis

#  Copyright (c) 2020. Robin Thibaut, Ghent University

import os
import re
from collections import Counter

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd


[docs]def read_res(file): """Reads ABEM type output text files. Lowers the columns and removes special characters.""" data = pd.read_csv(file, delimiter="\t") data.columns = [re.sub("[^A-Za-z0-9]+", "", col.lower()) for col in data.columns] return data
[docs]def export(file, normal_reciprocal): """Export (n, 2) normal, reciprocal measurement to text file""" np.savetxt(file, normal_reciprocal)
[docs]def display(nor_rec): # Plot plt.plot(nor_rec[:, 0], nor_rec[:, 1], "ko") plt.show()
[docs]def hist(nor_rec: np.array, bins: int, quantile: float = None): """Plot histogram :param nor_rec: np.array: Array (n, 2) containing n normal and reciprocal measurements :param quantile: float: Quantile threshold :param bins: int: Number of bins """ if quantile is None: quantile = 1 # Create DF and compute relative (%) reciprocal error diff = pd.DataFrame( data=np.abs(np.subtract(nor_rec[:, 0], nor_rec[:, 1]) / nor_rec[:, 0]), columns=["diff"], ) # Display some statistics print(diff.describe()) # Extracts value corresponding to desired quantile vt = diff.quantile(quantile).values[0] # Cut diffT = diff[diff["diff"] <= vt] # Plot diffT.hist(bins=bins) plt.xlabel("Reciprocal error (%)", weight="bold", size=12) plt.ylabel("Count", weight="bold", size=12) plt.title("Histogram of reciprocal error", weight="bold", size=12) plt.show()
[docs]class Reciprocal:
[docs] def __init__(self, normal_file, reciprocal_file, stack_tres): """ :param normal_file: str: path to the normal measurements file :param reciprocal_file: str: path to the reciprocal measurements file :param stack_tres: float: Measurements repeatability (var %) threshold """ self.fN = normal_file self.fR = reciprocal_file self.ts = stack_tres
[docs] def parse(self): """ Reads the results text files and parses them. It will cut data above repeatability threshold. :return: resNR, varNR - two np arrays of pairs of resistance and repeatability error """ # Read normal and reciprocal data pN = read_res(self.fN) pR = read_res(self.fR) # Filter stack error pN = pN[pN["var"] < self.ts] pR = pR[pR["var"] < self.ts] # Extract normal and reciprocal subsets abmnN = pN[["ax", "bx", "mx", "nx", "rohm", "var"]] abmnR = pR[["ax", "bx", "mx", "nx", "rohm", "var"]] # Concatenate them conc = pd.concat([abmnN, abmnR]) # To use a dict as a key you need to turn it into something that may be hashed first. If the dict you wish to # use as key consists of only immutable values, you can create a hashable representation of it with frozenset conc["id"] = conc.apply( lambda row: frozenset(Counter(row[["ax", "bx", "mx", "nx"]]).keys()), axis=1 ) # noqa # Group by same identifiers = same electrode pairs df1 = conc.groupby("id")["rohm"].apply(np.array).reset_index(name="rhos") # Extract list containing res values [N, R] rhos = [d for d in df1.rhos.values if len(d) == 2] # Flatten and reshape resNR = np.array([item for sublist in rhos for item in sublist]).reshape( (-1, 2) ) # Extract repeatability error as well: df2 = conc.groupby("id")["var"].apply(np.array).reset_index(name="vars") # Extract list containing var values [N, R] var = [d for d in df2.vars.values if len(d) == 2] # Flatten and reshape varNR = np.array([item for sublist in var for item in sublist]).reshape((-1, 2)) return resNR, varNR
if __name__ == "__main__": # Directories cwd = os.path.dirname(os.getcwd()) data_dir = os.path.join(cwd, "misc") # Files fN = os.path.join(data_dir, "Project27_Gradient8_1.txt") fR = os.path.join(data_dir, "Project27_Grad_8_R_1.txt") # Initiate and parse ro = Reciprocal(fN, fR, stack_tres=0.5) res_nr, var_nr = ro.parse() # Plot histogram hist(res_nr, quantile=0.99, bins=20) # Linear plot display(res_nr)