def TafelSlopeVPerDec(rawd, interd, var='I(A)', vshift=-(.187-0.045), boolDevFrac=0.5, boolDevNOut=3, dyDevFrac=0.2, dyDevNOut=5, dyDevAbs = 0., dx=1., maxFracOutliers=0.5, critSegVRange=0.04, critSegIEnd=3.e-5, critSegVEnd=0.36, SavGolPts=10): # initialize the arrays to hold Tafel values (considered both # intermediate data and figures of merit) interd['Tafel_slopeVperdec'] = [] interd['Tafel_estart'] = [] interd['Tafel_fitVrange'] = [] interd['Tafel_logExCurrent'] = [] booldn_segstart = 3 * boolDevNOut dn_segstart = 3 * dyDevNOut inter.calcsegind(rawd, interd, SGpts=SavGolPts) # breaks experiment into segments inter.calccurvregions(rawd, interd, SGpts=SavGolPts) # runs on all segments linsub = inter.calcLinSub(rawd, interd, var=var) # returns 1 if successful, 0 if not if not linsub: interd['Tafel_slopeVperdec'] = float('nan') interd['Tafel_estart'] = float('nan') interd['Tafel_fitVrange'] = float('nan') interd['Tafel_logExCurrent'] = float('nan') return float('nan') inter.SegSG(rawd, interd, SGpts=SGpts, order=1, k=var+'_LinSub') for seg in range(len(interd['segprops_dlist'])): inds=interd['segprops_dlist'][seg]['inds'] i=interd['I(A)_LinSub_SG'][inds] v=rawd['Ewe(V)'][inds]+vshift posinds=numpy.where(i>zero_thresh) invboolarr=numpy.float32(i<=zero_thresh) istart_segs, len_segs, fitdy_segs, fitinterc_segs=inter.findzerosegs( invboolarr, boolDevFrac, boolDevNOut, booldn_segstart, SGnpts=SavGolPts, dx=dx, maxfracoutliers=maxFracOutliers) if len(istart_segs)==0: # no Tafel segments interd['Tafel_slopeVperdec'].append(float('nan')) interd['Tafel_estart'].append(float('nan')) interd['Tafel_fitVrange'].append(float('nan')) interd['Tafel_logExCurrent'].append(float('nan')) continue ind=numpy.argmax(len_segs) i0=istart_segs[ind] i1=i0+len_segs[ind] taffitinds=numpy.arange(i0, i1) interd['segprops_dlist'][seg]['TafelFitInds']=inds[taffitinds] i=i[i0:i1] i[i<zero_thresh]=zero_thresh #needed due to outliers v=v[i0:i1] il=numpy.log10(i) try: istart_segs, len_segs, fitdy_segs, fitinterc_segs, dy=inter.findlinearsegs( il, dyDevFrac, dyDevNOut, dn_segstart, dydev_abs=dyDevAbs, dx=dx, critdy_fracmaxdy=None) except: interd['Tafel_slopeVperdec'].append(float('nan')) interd['Tafel_estart'].append(float('nan')) interd['Tafel_fitVrange'].append(float('nan')) interd['Tafel_logExCurrent'].append(float('nan')) continue if len(istart_segs)==0: # no Tafel segments interd['Tafel_slopeVperdec'].append(float('nan')) interd['Tafel_estart'].append(float('nan')) interd['Tafel_fitVrange'].append(float('nan')) interd['Tafel_logExCurrent'].append(float('nan')) continue #only take those segments covering a certain V range and with a min current for the top 10th of the V range # in the segment and positive slope for there on out and then take the steepest one. ind=None maxdy=0 npts=critSegVRange/dx npts2=max(2, npts//10+1) for count2, (it0, slen, dyv) in enumerate(zip(istart_segs, len_segs, fitdy_segs)): if slen<npts: continue it1=it0+slen if numpy.mean(i[it1-npts2:it1])<critSegIEnd: continue if numpy.mean(v[it1-npts2:it1])<critSegVEnd: continue if numpy.any(dy[it1:]<0.): continue if dyv>maxdy: maxdy=dyv ind=count2 if ind is None: # no Tafel segments interd['Tafel_slopeVperdec'].append(float('nan')) interd['Tafel_estart'].append(float('nan')) interd['Tafel_fitVrange'].append(float('nan')) interd['Tafel_logExCurrent'].append(float('nan')) continue i0=istart_segs[ind] i1=i0+len_segs[ind] tafinds=numpy.arange(i0, i1) it=il[tafinds] vt=v[tafinds] fitdy, fitint=numpy.polyfit(vt, it, 1) interd['Tafel_slopeVperdec'].append(1./fitdy) interd['Tafel_estart'].append(v[0]) interd['Tafel_fitVrange'].append(vt.max()-vt.min()) interd['Tafel_logExCurrent'].append(fitint) interd['segprops_dlist'][seg]['TafelInds']=inds[taffitinds][tafinds] #FOMs (the entire list): return interd['Tafel_slopeVperdec']
def TafelSlopeVPerDec(rawd, interd, var='I(A)', vk='Ewe(V)_E0', boolDevFrac=0.5, boolDevNOut=3, dyDevFrac=0.2, dyDevNOut=5, dyDevAbs = 0., dx=1., maxFracOutliers=0.5, critSegVRange=0.04, critSegIEnd=3.e-5, critSegVEnd=0.36, SavGolPts=10, inverty=False): # initialize the arrays to hold Tafel values (considered both # intermediate data and figures of merit) interd['TafelSlope'] = [] interd['TafelEstart'] = [] interd['TafelFitErange'] = [] interd['TafelLogIex'] = [] booldn_segstart = 3 * boolDevNOut dn_segstart = 3 * dyDevNOut inter.calcsegind(rawd, interd, SGpts=SavGolPts) # breaks experiment into segments inter.calccurvregions(rawd, interd, SGpts=SavGolPts, inverty=inverty) # runs on all segments linsub = inter.calcLinSub(rawd, interd, var=var, inverty=inverty) # returns 1 if successful, 0 if not if inverty: yinv=-1. else: yinv=1. if not linsub: nanlist=[float('nan')]*len(interd['segprops_dlist']) interd['TafelSlope'] = nanlist interd['TafelEstart'] = nanlist interd['TafelFitErange'] = nanlist interd['TafelLogIex'] = nanlist return float('nan') inter.SegSG(rawd, interd, SGpts=SGpts, order=1, k=var+'_LinSub') for seg in range(len(interd['segprops_dlist'])): inds=interd['segprops_dlist'][seg]['inds'] i=interd['I(A)_LinSub_SG'][inds]*yinv # if i.sum()==0.:#LinSub attempted on all segments, here each segment is tried until 1 works # continue if vk in rawd.keys(): v = rawd[vk] else: v = interd[vk] v=v[inds] posinds=numpy.where(i>zero_thresh) invboolarr=numpy.float32(i<=zero_thresh) istart_segs, len_segs, fitdy_segs, fitinterc_segs=inter.findzerosegs( invboolarr, boolDevFrac, boolDevNOut, booldn_segstart, SGnpts=SavGolPts, dx=dx, maxfracoutliers=maxFracOutliers) if len(istart_segs)==0: # no Tafel segments interd['TafelSlope'].append(float('nan')) interd['TafelEstart'].append(float('nan')) interd['TafelFitVrange'].append(float('nan')) interd['TafelLogIex'].append(float('nan')) continue ind=numpy.argmax(len_segs) i0=istart_segs[ind] i1=i0+len_segs[ind] taffitinds=numpy.arange(i0, i1) interd['segprops_dlist'][seg]['TafelFitInds']=inds[taffitinds] i=i[i0:i1] i[i<zero_thresh]=zero_thresh #needed due to outliers v=v[i0:i1] il=numpy.log10(i) try: istart_segs, len_segs, fitdy_segs, fitinterc_segs, dy=inter.findlinearsegs( il, dyDevFrac, dyDevNOut, dn_segstart, dydev_abs=dyDevAbs, dx=dx, critdy_fracmaxdy=None) except: interd['TafelSlope'].append(float('nan')) interd['TafelEstart'].append(float('nan')) interd['TafelFitVrange'].append(float('nan')) interd['Tafel_logExCurrent'].append(float('nan')) continue if len(istart_segs)==0: # no Tafel segments interd['TafelSlope'].append(float('nan')) interd['TafelEstart'].append(float('nan')) interd['TafelFitVrange'].append(float('nan')) interd['TafelLogIex'].append(float('nan')) continue #only take those segments covering a certain V range and with a min current for the top 10th of the V range # in the segment and positive slope for there on out and then take the steepest one. ind=None maxdy=0 npts=critSegVRange/dx npts2=max(2, npts//10+1) for count2, (it0, slen, dyv) in enumerate(zip(istart_segs, len_segs, fitdy_segs)): if slen<npts: continue it1=it0+slen if numpy.mean(i[it1-npts2:it1])<critSegIEnd: continue if numpy.mean(v[it1-npts2:it1])<critSegVEnd: continue if numpy.any(dy[it1:]<0.): continue if dyv>maxdy: maxdy=dyv ind=count2 if ind is None: # no Tafel segments interd['TafelSlope'].append(float('nan')) interd['TafelEstart'].append(float('nan')) interd['TafelFitVrange'].append(float('nan')) interd['TafelLogIex'].append(float('nan')) continue i0=istart_segs[ind] i1=i0+len_segs[ind] tafinds=numpy.arange(i0, i1) it=il[tafinds] vt=v[tafinds] fitdy, fitint=numpy.polyfit(vt, it, 1) interd['TafelSlope'].append(1./fitdy) interd['TafelEstart'].append(v[0]) interd['TafelFitVrange'].append(vt.max()-vt.min()) interd['TafelLogIex'].append(fitint) interd['segprops_dlist'][seg]['TafelInds']=inds[taffitinds][tafinds] #FOMs (the entire list): fomarr=numpy.array(interd['TafelSlope']) #in interd there is a fom for each segment but save the first not NaN one as scalar FOM goodinds=numpy.where(numpy.logical_not(numpy.isnan(fomarr)))[0] if len(goodinds)==0: return float('nan') return fomarr[goodinds[0]]