167 lines
5.9 KiB
Python
167 lines
5.9 KiB
Python
# Python program to analyze cards
|
|
import matplotlib.pyplot as plt
|
|
import readCardFile as rcf
|
|
import math
|
|
import os, sys
|
|
|
|
def main(sl = 100):
|
|
# Setup Data
|
|
slices = int(sl) # number of horizontal slices to evaluate
|
|
#downhole = rcf.readFile("{0}/{1}".format(os.getcwd(), "testCard.csv"))[1] # read in CSV file output from POConsole/POCloud
|
|
downhole = rcf.readFile()[1]
|
|
num_points = len(downhole)
|
|
|
|
dh_pos = list(map(lambda x: x[0], downhole))
|
|
dh_pos_max = max(dh_pos)
|
|
dh_pos_min = min(dh_pos)
|
|
|
|
dh_lod = list(map(lambda x: x[1], downhole))
|
|
dh_lod_max = max(dh_lod)
|
|
dh_lod_min = min(dh_lod)
|
|
|
|
max_p = (dh_pos_max, dh_lod[dh_pos.index(dh_pos_max)])
|
|
min_p = (dh_pos_min, dh_lod[dh_pos.index(dh_pos_min)])
|
|
|
|
def determine_d_pos(min, max, num_slices):
|
|
return (max - min) / num_slices
|
|
|
|
d_pos = determine_d_pos(dh_pos_min, dh_pos_max, slices)
|
|
|
|
def distribute_positions(min, max, num_slices, dp):
|
|
""" distributes positions equally between the max and min values. Returns a list of positions """
|
|
p_targ = []
|
|
|
|
for i in range(0, num_slices):
|
|
p_targ.append(min + i * dp)
|
|
return p_targ
|
|
|
|
position_targets = distribute_positions(dh_pos_min, dh_pos_max, slices, d_pos)
|
|
|
|
def lineresolve(x1,x2,y1,y2,targ):
|
|
m = ((y2-y1)/(x2-x1))
|
|
b = y1 - m * x1
|
|
return(m * targ + b)
|
|
|
|
|
|
def find_top_slices():
|
|
""" finds the top slices of a card. Returns a list of (position,load) tuples"""
|
|
t_slices = []
|
|
last_pos_index = 0
|
|
for i in range(0,slices):
|
|
targ = position_targets[i]
|
|
for j in range(last_pos_index, num_points -1):
|
|
if (dh_pos[j] <= targ and dh_pos[j+1] > targ):
|
|
found_i = j
|
|
next_i = j+1
|
|
fake_load = lineresolve(dh_pos[found_i], dh_pos[next_i], dh_lod[found_i], dh_lod[next_i], targ)
|
|
t_slices.append((targ, fake_load))
|
|
last_pos_index = found_i
|
|
break
|
|
return t_slices
|
|
|
|
top_slices = find_top_slices()
|
|
print("== TOP ==")
|
|
for i in top_slices:
|
|
print("{0} - {1}".format(i[0], i[1]))
|
|
|
|
def find_bot_slices():
|
|
""" finds the top slices of a card. Returns a list of (position,load) tuples"""
|
|
b_slices = []
|
|
last_pos_index = 0
|
|
for i in range(0,slices):
|
|
targ = position_targets[i]
|
|
for j in range(0, num_points -1):
|
|
if (dh_pos[j] > targ and dh_pos[j+1] <= targ):
|
|
found_i = j
|
|
next_i = j+1
|
|
fake_load = lineresolve(dh_pos[found_i], dh_pos[next_i], dh_lod[found_i], dh_lod[next_i], targ)
|
|
|
|
b_slices.append((targ, fake_load))
|
|
#last_pos_index = found_i
|
|
break
|
|
return b_slices
|
|
|
|
bot_slices = find_bot_slices()
|
|
print("== BOTTOM ==")
|
|
for i in bot_slices:
|
|
print("{0} - {1}".format(i[0], i[1]))
|
|
|
|
def distance_to_line(x0,y0):
|
|
""" Finds the perpendicular distance from a point to the line between max and min points"""
|
|
x1 = min_p[0]
|
|
x2 = max_p[0]
|
|
# y1 = min_p[1]
|
|
# y2 = max_p[1]
|
|
y1 = dh_lod_min
|
|
y2 = dh_lod_max
|
|
|
|
d = abs((y2-y1)*x0 - (x2-x1)*y0 + x2*y1 - y2*x1) / math.sqrt(math.pow(y2-y1,2) + math.pow(x2-x1,2))
|
|
return d
|
|
|
|
top_d = []
|
|
bot_d = []
|
|
|
|
# Here's where we get the distance from each point to the line
|
|
for i in range(1,slices):
|
|
try:
|
|
top_d.append(distance_to_line(top_slices[i][0], top_slices[i][1]))
|
|
except Exception:
|
|
print("Error - top_d, index: {0}".format(i))
|
|
|
|
|
|
try:
|
|
bot_d.append(distance_to_line(bot_slices[i][0], bot_slices[i][1]))
|
|
except Exception:
|
|
print("Error - bot_d, index: {0}".format(i))
|
|
|
|
top_cor_i = top_d.index(max(top_d))
|
|
bot_cor_i = bot_d.index(max(bot_d))
|
|
top_corner = top_slices[top_cor_i]
|
|
bot_corner = bot_slices[bot_cor_i]
|
|
|
|
tubing_movement = top_corner[0] - dh_pos_min
|
|
fillage = (bot_corner[0] - dh_pos_min)/(dh_pos_max - (dh_pos_min + tubing_movement)) * 100
|
|
print("=================================================")
|
|
print("Tubing Movement: {0} in.".format(round(tubing_movement,3)))
|
|
print("Fill Percent: {0}%".format(round(fillage, 3)))
|
|
|
|
|
|
#determine difference between gas interference and incomplete fill
|
|
po_area = 0.0
|
|
actual_area = 0.0
|
|
bot_last = bot_slices[-1]
|
|
gas_line = []
|
|
for i in range(bot_cor_i, len(bot_slices)):
|
|
gas_line_load = lineresolve(bot_corner[0], bot_last[0], bot_corner[1], bot_last[1], bot_slices[i][0])
|
|
gas_line.append((bot_slices[i][0], gas_line_load))
|
|
po_area = po_area + (bot_last[0] - gas_line_load) * d_pos
|
|
actual_area = actual_area + abs(gas_line_load - bot_slices[i][1]) * d_pos
|
|
area_ratio = actual_area / po_area
|
|
print ("\nFull Area: {0}\nActual Area: {1}".format(po_area, actual_area))
|
|
print("\nIncomplete Fillage Score:{0}%\nGas Interference Score:{1}%".format(round(area_ratio*100,3), round((1-area_ratio)*100,3)))
|
|
|
|
print("=================================================")
|
|
|
|
|
|
plt.figure()
|
|
plt.subplot(211)
|
|
plt.plot(list(map(lambda x: x[0], downhole)), list(map(lambda x: x[1], downhole)) ,'r')
|
|
plt.plot(list(map(lambda x: x[0], top_slices)), list(map(lambda x: x[1], top_slices)) ,'b')
|
|
plt.plot(list(map(lambda x: x[0], bot_slices)), list(map(lambda x: x[1], bot_slices)) ,'g')
|
|
plt.plot(list(map(lambda x: x[0], gas_line)), list(map(lambda x: x[1], gas_line)) ,'m')
|
|
|
|
plt.subplot(212)
|
|
plt.plot(list(map(lambda x: x[0], top_slices))[1:], top_d ,'r')
|
|
plt.plot(list(map(lambda x: x[0], bot_slices))[1:], bot_d ,'y')
|
|
#ax2.axvline(x=top_corner[0])
|
|
#ax2.axvline(x=bot_corner[0])
|
|
|
|
plt.grid(True)
|
|
plt.show()
|
|
|
|
if __name__ == "__main__":
|
|
if len(sys.argv) > 1:
|
|
main(sys.argv[1])
|
|
else:
|
|
main()
|