def Vtrace(cdata, param, fig=None): """ Calculate position of next V-trace from fitted model . Args: cdata (?): TODO param (?): TODO fit (None or integer): figure handle. """ cc = cdata[0] psi = param[-1] q = np.array([10, 0]).reshape((2, 1)) p1 = cc + pgeometry.rot2D(psi).dot(q) p2 = cc + pgeometry.rot2D(np.pi + psi).dot(q) pp = np.array(np.hstack((p1, cc, p2))) pp = np.array(np.hstack((p1, p2))) if fig is not None: plt.figure(fig) pgeometry.plotPoints(pp, '--k', markersize=20, linewidth=3, label='scan line') pgeometry.plotPoints(pp, '.y', markersize=20) plt.legend(numpoints=1, fontsize=14, loc=0) psi, slope = __calcSlope(pp) return pp, cc, slope
def findCoulombDirection(im, ptx, step, widthmv=8, fig=None, verbose=1): """ Find direction of Coulomb peak using second order derivative """ cwidth = 2. * widthmv / np.abs(step) resizefactor = 2 * np.abs(step) # resize to .5 mv/pixel flow, ll = flowField(im, fig=None, blocksize=int(1.5 * 2 * widthmv), resizefactor=resizefactor) ptxf = resizefactor * ptx # [:,::-1] val = getValuePixel(flow, ptxf) l = getValuePixel(ll[:, :, 0], ptxf) if verbose: print('findCoulombDirection: initial: %s' % str(val)) # improve estimate by taking a local average valr = pgeometry.rot2D(np.pi / 2).dot(val.reshape((2, 1))) sidesteps = np.arange(-6, 6.01, 3).reshape((-1, 1)) * \ np.matrix(valr.reshape((1, 2))) pts = ptx + .5 * np.array(sidesteps) ptsf = ptxf + resizefactor * sidesteps valx = np.array([getValuePixel(flow, p) for p in ptsf]) a = pgeometry.directionMean(valx) val = np.array([np.sin(a), np.cos(a)]).flatten() val *= np.sign(val[1] - val[0]) if verbose: print('findCoulombDirection: final: %s' % str(val)) if fig is not None: showCoulombDirection(ptx, val, im=im, dd=None, fig=fig) return val
def createCross(param, samplesize, l=20, w=2.5, lsegment=10, H=100, scale=None, lines=range(4), istep=1, centermodel=True, linesegment=True, addX=True, verbose=0): """ Create a cross model The parameters are [x, y, width, alpha_1, ..., alpha_4, [rotation of polarization line] ] With the optional parameters psi (angle of transition line) The x, y, width are in mV. Angles in radians Args: param (array): parameters of the model samplesize (int): size of image patch in pixels l, w, lsegment (float): parameters of the model in mV?. lsegment is the length of the 4 addition lines w is width of lines in the model l is not used by default istep (float): scan resolution in pixel/mV scale (None): parameter not used any more addX (bool): if True add polarization line to model H (float): intensity of cross linesegment (bool): if True create line segments instead of full lines Returns: modelpatch, (cc, lp, hp, ip, opr, w, H, lsegment): return data """ aa = param[3:7] psi = np.pi / 4 if len(param) > 7: psi = param[7] if verbose: print('createCross: psi set to %.1f [def]' % np.rad2deg(psi)) if samplesize is None: cc = param[0:2].reshape((2, 1)) else: # if scale is None: # scale = np.mean(samplesize) samplesize = np.array(samplesize).flatten() if centermodel: cc = np.array(samplesize).reshape((2, 1)) / 2 - .5 else: cc = np.array(param[0:2] / istep).reshape((2, 1)) # lp and hp are the triple points lp = cc + pgeometry.rot2D(psi + np.pi / 2).dot(np.array([[param[2] / istep], [0]])) hp = cc - pgeometry.rot2D(psi + np.pi / 2).dot(np.array([[param[2] / istep], [0]])) op = np.zeros((5, 2)) opr = np.zeros((4, 2)) ip = np.zeros((5, 2)) # loop over all 4 line segments for ii, a in enumerate(aa): if ii == 0 or ii == 1: ip[ii].flat = lp else: ip[ii].flat = hp opr[ii] = ip[ii] + ((lsegment / istep) * pgeometry.rot2D(a).dot(np.array([[1], [0]]))).flat if samplesize is not None: modelpatch = np.zeros([samplesize.flat[1], samplesize.flat[0]]) for ii in lines: if linesegment: x0 = ip[ii] x1x = np.array(x0 + lsegment / istep * (pgeometry.rot2D(aa[ii]).dot(np.array([[1], [0]]))).T).flatten() lineSegment(modelpatch, x0=x0, x1=x1x, w=w / istep, l=None, H=H) else: raise Exception('code not used any more?') semiLine(modelpatch, x0=ip[ii], theta=aa[ii], w=w / istep, l=l / istep, H=H) if addX: lx = np.linalg.norm(hp - lp, ord=2) lineSegment(modelpatch, x0=np.array(hp.reshape((2, 1))), x1=np.array(lp.reshape((2, 1))), w=w / istep, l=lx, H=H) else: modelpatch = None modelpatch = np.minimum(modelpatch, H) return modelpatch, (cc, lp, hp, ip, opr, w, H, lsegment)
def costFunctionLine(pp, imx, istep, maxshift=12, verbose=0, fig=None, maxangle=np.deg2rad(70), ksizemv=12, dthr=8, dwidth=3, alldata=None, px=None): """ Cost function for line fitting pp (list or array): line parameters imx (numpy array): image to fit to istep (float) px (array): translational offset to operate from """ istepmodel = .5 samplesize = [ int(imx.shape[1] * istep / istepmodel), int(imx.shape[0] * istep / istepmodel) ] LW = 2 # [mV] LL = 15 # [mV] H = costFunctionLine.scaling0.copy() H[0, 0] = istep / istepmodel H[1, 1] = istep / istepmodel #patch=linetools.sampleImage(im, pp, samplesize, fig=11, clearfig=True, nrsub=1) dsize = (samplesize[0], samplesize[1]) patch = cv2.warpPerspective(imx.astype(np.float32), H, dsize, None, (cv2.INTER_LINEAR), cv2.BORDER_CONSTANT, -1) pm0 = np.array(pp[0:2]).reshape((1, 2)) / istepmodel # [pixel] if px is None: pxpatch = [patch.shape[1] / 2, patch.shape[0] / 2] else: pxpatch = (float(istep) / istepmodel) * np.array(px) pm = pm0 + pxpatch #modelpatch, cdata=createCross(param, samplesize, centermodel=False, istep=istepmodel, verbose=0) lowv = np.percentile(imx, 1) highv = np.percentile(imx, 95) theta = pp[2] if verbose: print('costFunctionLine: sample line patch: lowv %.1f, highv %.1f' % (lowv, highv)) # print(px) linepatch = lowv + np.zeros((samplesize[1], samplesize[0])) lineSegment(linepatch, pm, theta=pp[2], w=LW / istepmodel, l=LL / istepmodel, H=highv - lowv, ml=-6 / istepmodel) #plt.figure(99); plt.clf(); plt.imshow(lineseg, interpolation='nearest'); plt.colorbar() #plt.figure(99); plt.clf(); plt.imshow(linepatch-lineseg, interpolation='nearest'); plt.colorbar() #plt.figure(99); plt.clf(); plt.imshow(linepatch, interpolation='nearest'); plt.colorbar() dd = patch - (linepatch) cost = np.linalg.norm(dd) cost0 = cost if 1: ddx0 = np.linalg.norm(pm0) # [pixel] ddx = np.linalg.norm(pm0) # [pixel] if verbose: print( 'costFunctionLine: calculate additonal costs: dist %.1f [mV]' % (ddx * istepmodel)) ddx = pmatlab.smoothstep(ddx, dthr / istepmodel, dwidth / istepmodel) if verbose >= 2: print(' ddx: %.3f, thr %.3f' % (ddx, dthr / istepmodel)) cost += 100000 * ddx #cost = sLimits(cost, plocal, pm, maxshift, maxangle) if fig is not None: pmatlab.cfigure(fig) plt.clf() plt.imshow(patch, interpolation='nearest') plt.title('patch: cost %.2f, dist %.1f' % (cost, ddx0 * istep)) plt.colorbar() pm = pm.flatten() #plt.plot(pm0.flatten()[0], pm0.flatten()[1], 'dk', markersize=12, label='initial starting point?') plt.plot(pm[0], pm[1], '.g', markersize=24, label='fitted point') plt.plot(pxpatch[0], pxpatch[1], '.m', markersize=18, label='offset for parameters') qq = np.array( pm.reshape(2, 1) + (LL / istepmodel) * pmatlab.rot2D(theta).dot(np.array([[1, -1], [0, 0]]))) plt.plot(qq[0, :], qq[1, :], '--k', markersize=24, linewidth=2) # print(pm) plt.axis('image') # plt.colorbar() pmatlab.cfigure(fig + 1) plt.clf() plt.imshow(linepatch, interpolation='nearest') plt.title('line patch') plt.plot(px[0], px[1], '.m', markersize=24) plt.axis('image') plt.colorbar() pmatlab.tilefigs([fig, fig + 1]) if verbose >= 2: pmatlab.cfigure(fig + 2) plt.clf() xx = np.arange(0, 20, .1) xxstep = istepmodel * pmatlab.smoothstep( xx / istepmodel, dthr / istepmodel, (1 / dwidth) / istepmodel) plt.plot(xx, xxstep, '.-b', label='distance step') plt.xlabel('Distance [mV]') plt.legend() if verbose: print('costFucntion: cost: base %.2f -> final %.2f' % (cost0, cost)) if verbose >= 2: ww = np.abs(dd).mean(axis=0) print('costFunction: dd %s ' % ww) return cost