The overall functions should be used in the sequence below

Each of the functions calls sub functions in the flow presented in the graph below

(old, replaced)

An example of the original image is shown below,

**FilterBackground(image):** as the image is messy, this function take the connected convexHull to clean up everything outside this hull.

image (numpy 2d uint8 array): the original image

**GetEventPositions(pic,debug_mode=0):**get all the three tip points and also the vertex point

pic (numpy 2d uint8 array): the original image

debug_mode (bool): plot some debug features, this should be turned off in batch mode

return (numpy array 3*2, (float)*2): three tip points, and the vertex point

(currently not used)**GetEventPositions_(pic,debug_mode=0, center_width = 12, quadrant_thresh=100, center_thresh=300, err_thresh =12, spread_thresh=6 ):** get all the three tip points and also the vertex point

pic (numpy 2d uint8 array): the original image

debug_mode (bool): plot some debug features, this should be turned off in batch mode

center_width (float): not used for now

quadrant_thresh (float): threshold for number of pixel in the reaction product part

center_thresh (float): threshold for the beam part

err_thresh (float): threshold for average distance to the fit

spread_thresh (float): threshold for x,y spread out

**AveDist(x,y,k,b): **calculate the average distance from (x,y) to a straight line with (k,b) parameters.

x (numpy float array): the x positions

y (numpy float array): the y positions

k (float): the slope of the line

b (float): the y-intercept of the line

return (float): average distance from (x,y) to the line (k,b)

**r2(x,y,k,b): **just to calculate the r2 score of the fitting

parameters are the same to function above

return (float): r2 score

(currently not sued)**VertexPos_(fits,y0): **using all fitting results and the y position from the right most tip point to estimate the vertex position

The function divide the calculation to 2 scenarios. 1. you have 2 or 3 fitted lines, then you just pick the parameters of the first two lines for the calculation. 2. if you have only 1 line and this one will not be you center line (because of previous fitting condition), you assume the center line is straight on y0.

fits ([int,float,float,float]*3): fit results for three parts of the image

return (float,float): (x,y)

**VertexPos(image_,ps):** estimate the vertex position

The function calculate the minimal distance for each pixel points to each of the three lines (semi-open rays from the vertex point to the direction of the tip point). If a pixel is on the closed end of the ray, a high penalty (1e5) will be given in distance calculation.

image_ (numpy 2d uint8 array): the filtered image

ps_ (numpy array 3×2): three positions of the tip points

return (float,float): (x,y)

**tbjcfit(xs,ys): **use SVD to calculate the least square DISTANCE (not y) fitting

xs (numpy float array): the x positions

ys (numpy float array): the y positions

return (int,float,float,float):(number of pixels, k,b,average distance)

**GetFit(image_, part_thresh=60, err_thresh =1.2,spread_thresh=6):** this function extract the x,y positions of each pixel above 0 value. Then fit the x,y points using tbjcfit. The results will be filtered through a few conditions to see if the fitting is good, like if the average distance from the points to the line is within the err_thresh and if the scattered positions does give a reasonable line shape distribution.

image_ (numpy 2d uint8 array): the part of the image you want to obtain a line fitting

part_thresh (float): if the number of pixels in the image is large enough for a fitting

err_thresh (float):the average distance to the fitting line of all the points

spread_thresh (float):the threshold for requiring a spread out distributed data on either x or y axis

return (numpy 2d uint8 array): a copy of filtered image

**GetLineInfo(p1,p2, L_thre = -5): **calculate the length and angle between two points

p1 (float,float): the tip point

p2 (float,float): the vertex point

L_thre = -5: not used for now

**GetEventInfo(points,p0): **calculate the length and angle for between each pair of the tip point and the vertex point

points ((float,float)*3): the positions of the tip points

p0 (float,float): the position of the vertex point

return ((float,float)*3,float): (theta,length) for each pair, and the reaction range

**Distance(contours,n1,n2):** calculate the minimum distance between two contour

contours [numpy.array (n,1,2)]:all the contours

n1 (int): index of the first contour

n2 (int): index of the second contour

return (float): the minimum distance

**Groups(contours): **combine all adjacent contours

contours [numpy.array (n,1,2)]:all the contours

return ((float)*n, (float)*n): grouped contours

**convexHull(thresh, debug_mode = 0): **calculated the convexHull using the largest grouped contour

thresh (numpy 2d uint8 array): image after preliminary processing

return ((float,float)*n): the hull points

**MaxEnclosedTriangle(hull): **calculate the maximum enclosed triangle using the hull points

hull ((float,float)*n): the hull points

return (int, int, int): index of the hull points to form the maximum enclosed triangle

**TipFinder(thresh, debug_mode = 0): **return the position of the tip on the maximum enclosed triangle

thresh (numpy 2d uint8 array): image after preliminary processing

return ((float,float)*3): the position of the tip on the maximum enclosed triangle