Mercurial > repos > mb2013 > nepenthes_3dpca
diff ReConstructor.py @ 13:fc4bc4ab91b7 draft
Uploaded
author | mb2013 |
---|---|
date | Tue, 20 May 2014 03:28:13 -0400 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ReConstructor.py Tue May 20 03:28:13 2014 -0400 @@ -0,0 +1,597 @@ +# Reconstruction of faces of a .ply file, +# based on the symmetry plane +# MB +import math +from math import * +import sys +import numpy +from time import gmtime, strftime + +# Function main, +def main(): + var_col = 0 + name_file_ply = sys.argv[1] + output = open('new_coordinates2.ply', 'w') + file_ply = open(name_file_ply) + out_log = open(str(sys.argv[15]), 'w') + + out_log.write('Start time: %s\n\nInput user:\n'%(time())) + x_1 = sys.argv[9] + x_2 = sys.argv[10] + y_1 = sys.argv[11] + y_2 = sys.argv[12] + z_1 = sys.argv[13] + z_2 = sys.argv[14] + # to function 'user input side' + side = user_input_side(out_log) + # to function 'user input sections' + number_of_boxes_hor,number_of_boxes_ver,number_of_boxes_z = user_input_sections(out_log) + # to function 'user input factor stdev' + factor = user_input_factor_stdev(out_log) + # to function user input colors + col_r, col_g, col_b = user_input_colors(out_log) + # to function 'extracting header' + var_header, var_vertex_nm,var_face_nm = extracting_header(file_ply) + # to funtion 'array coordinates' + matrix, matrix2,matrix3 = array_coordinates(name_file_ply, var_vertex_nm, var_header, var_face_nm) + # to function 'calc min max' + amin,amax = calc_min_max(out_log, matrix, x_1,x_2,y_1,y_2,z_1,z_2) + + # to function 'range sections' + steps_x,steps_y,steps_z,x_window_min_x,x_window_max_x = range_sections(amin,amax, + number_of_boxes_hor, number_of_boxes_ver, + number_of_boxes_z) + # to function 'create list ranges' + newlist = create_list_ranges(amin,amax,number_of_boxes_hor, number_of_boxes_ver, + number_of_boxes_z, x_window_min_x, x_window_max_x,steps_x,steps_y,steps_z) + # to function 'create list coordinates' + newlist2, indexlist = create_list_coordinates(newlist) + # to function 'fill sections coordinates' + newlist, indexlist = fill_sections_coordinates(newlist, newlist2, matrix, indexlist) + # to function 'calc sections' + difference, differencemean = calc_sections(number_of_boxes_ver,number_of_boxes_hor,number_of_boxes_z,newlist) + # to function 'calc mean stdev' + mean_percentage, std_percentage = calc_mean_stdev(differencemean,factor) + # to function 'calc range' + left_range, right_range = calc_range(mean_percentage,std_percentage) + # to function 'collect mirror values' + total, listindexcount, listindex, listindextotalcount, totalcount = collect_mirror_values(out_log, side, output, + right_range, left_range, + mean_percentage, std_percentage, + newlist, indexlist, difference, + number_of_boxes_hor,number_of_boxes_ver,number_of_boxes_z, + col_r, col_g, col_b) + + # to function 'find original faces' + m_face,m_face_square = find_original_faces(matrix2,matrix3, listindex) + + # to function 'replace index values' + out_faces = replace_index_values(m_face,listindex,listindextotalcount) + out_faces_2 = [] + # if there are square faces, do function replace index values again + if len(m_face_square)!= 0: + out_faces_2 = replace_index_values(m_face_square,listindex,listindextotalcount) + output.close() + + # to function 'write output' + write_output(name_file_ply, out_log, totalcount, var_header, var_vertex_nm, var_face_nm,out_faces, out_faces_2) + #a = strftime("%a, %d %b %Y %H:%M:%S", gmtime()) + + out_log.write('End time: %s'%(time())) + out_log.close() # close log + +# Function time +def time(): + a = strftime("%a, %d %b %Y %H:%M:%S", gmtime()) + return a + +# Function user input side +def user_input_side(out_log): # user input side + side = int(sys.argv[3]) + if side == 0: + out_log.write('Left side of object is correct') + else: + out_log.write('Right side of object is correct') + return side + +# Function user input sections +def user_input_sections(out_log): + # number of boxes on x axis, this will be multiplied. + number_of_boxes_hor = int(sys.argv[4]) + # number of boxes on y axis + number_of_boxes_ver = int(sys.argv[5]) + # number of boxes on z axis + number_of_boxes_z = int(sys.argv[6]) + out_log.write("number of boxes x axis:\t%s\nnumber of boxes y axis:\t%s\nnumber of boxes z axis:\t%s\n\n"% + ((number_of_boxes_hor *2),(number_of_boxes_ver), (number_of_boxes_z))) + + return number_of_boxes_hor, number_of_boxes_ver, number_of_boxes_z + +# Function user input colors of reconstructed surface +def user_input_colors(out_log): + col = sys.argv[8] + # four colors can be chosen + if int(col) == 0: + out_log.write('color is pink\n') + col_r = 236 + col_g = 149 + col_b = 221 + elif int(col) == 1: + out_log.write('color is blue\n') + col_r = 192 + col_g = 245 + col_b = 250 + elif int(col) == 2: + out_log.write('color is green\n') + col_r = 0 + col_g = 255 + col_b = 0 + else: + out_log.write('color is red\n') + col_r = 255 + col_g = 0 + col_b = 0 + + return col_r, col_g, col_b + +# Function user input factor standard deviation +def user_input_factor_stdev(out_log): + factor = int(sys.argv[7]) + out_log.write("Factor standard deviation:\t%s\n\n"%(factor)) + + return factor + +# Function extracting values of header ply file +def extracting_header(file_ply): + for x in range(0, 20): + readheader = file_ply.readline().strip().split() + if readheader[0] == 'end_header': # when the words 'end_header' are found + var_header = x # var_header is line number + if readheader[0] == "element" and readheader[1] == "vertex": # when 'element vertex' found + var_vertex_nm = readheader[2] # amount of vertexen + if readheader[0] == "element" and readheader[1] == "face": # when 'element face' found + var_face_nm = readheader[2] # amount of faces + file_ply.close() + + return var_header, var_vertex_nm,var_face_nm + +# Function extracting coordintates of ply file +def array_coordinates(name_file_ply, var_vertex_nm, var_header,var_face_nm): + file1 = open(name_file_ply) + matrix = numpy.zeros((int(var_vertex_nm),3)) # creating empty numpy array of amount of vertexen + matrix2 = numpy.empty((int(var_face_nm),3)) # creating empty numpy array of amount of triangle faces + matrix3 = numpy.empty((int(var_face_nm),4)) # creating empty numpy array of amounf of square faces 4 + count = 0 # counter for vertexen + count2 = 0 # counter for faces + # Putting all the vertexen and faces in a matrix + for a in range(0, (int(var_header) + int(var_vertex_nm) + int(var_face_nm) + 1)): + line = file1.readline().strip().split() # reading every line + if int(var_header) < a < (int(var_vertex_nm)+ int(var_header)+1): #vertexen + matrix[count][0] = float(line[0]) # x coordinate + matrix[count][1] = float(line[1]) # y coordinate + matrix[count][2] = float(line[2]) # z coordinate + count += 1 # counter + 1 for next line in matrix + if a > (int(var_vertex_nm)+ int(var_header)): # faces + if len(line) == 4: # if triangle faces exists + matrix2[count2][0] = int(line[1]) # first coordinate for face + matrix2[count2][1] = int(line[2]) # second coordinate for face + matrix2[count2][2] = int(line[3]) # third coordinate for face + #check1 = True + + + if len(line) == 5: # if square faces exists + matrix3[count2][0] = int(line[1]) # first coordinate for face + matrix3[count2][1] = int(line[2]) # second coordinate for face + matrix3[count2][2] = int(line[3]) # third coordinate for face + matrix3[count2][3] = int(line[4]) # fourth coordinate for face + #check2 = True + count2 += 1 # counter + 1 for next line in matrix + file1.close() + + # to function calc_histogram + calc_histogram(matrix) + + return matrix,matrix2,matrix3 + +# Function histogram +def calc_histogram(matrix): # histogram of x,y, z coordinates + out_histo = open(str(sys.argv[16]), 'w') # open output + x_co = numpy.array(matrix[:,0]) + histo_x = numpy.histogram(x_co, bins = 50) # calculate x coordinate distribution + y_co = numpy.array(matrix[:,1]) + histo_y = numpy.histogram(y_co, bins = 50) # calculate y coordinate distribution + z_co = numpy.array(matrix[:,2]) + histo_z = numpy.histogram(z_co, bins = 50) # calculate z coordinate distribution + + # write histogram output + out_histo.write("x nm point\tx coordinate\ty nm point\ty coordinate\tz nm point\tz coordinate\n") + for item in range(0,len(histo_x[0])): + out_histo.write("%s\t%s\t\t%s\t%s\t\t%s\t%s\n"%(histo_x[0][item], histo_x[1][item], + histo_y[0][item], histo_y[1][item], + histo_z[0][item], histo_z[1][item], )) + + + out_histo.close() #close histogram output + +# Function calculation minimum and maximum of x,y and z +def calc_min_max(out_log, matrix, x_1,x_2,y_1,y_2,z_1,z_2): + amin = numpy.amin(matrix, axis = 0) #minima of x y and z + amax = numpy.amax(matrix, axis = 0) #maxima of x y and z + # if user input max and min values, change the min and max + if x_1 != 'standard': + amin[0] = int(x_1) + if x_2 != 'standard': + amax[0] = int(x_2) + if y_1 != 'standard': + amin[1] = int(y_1) + if y_2 != 'standard': + amax[1] = int(y_2) + if z_1 != 'standard': + amin[2] = int(z_1) + if z_2 != 'standard': + amax[2] = int(z_2) + + + # write to log + out_log.write("lowest x:\t%s\nhighest x:\t%s\nlowest y:\t%s\nhighest y:\t%s\nlowest z:\t%s\nhighest z:\t%s\n\n" + %(amin[0],amax[0],amin[1],amax[1],amin[2],amax[2])) + + return amin, amax + +# Function calculating range for sections +def range_sections(amin,amax,number_of_boxes_hor, number_of_boxes_ver,number_of_boxes_z): + # Find the highest absolute x because the boxes on the x axis has to be mirrored in the symmetry plane + if abs(amax[0]) < abs(amin[0]): # if the highest x is absolute smaller than the lowest x: + x_window_min_x = amin[0] # lowest x is lowest windows x + x_window_max_x= amin[0] *-1 # lowest x * -1 is highest windows x + steps_x = abs(amin[0]) / number_of_boxes_hor # length of x boxes + else: + x_window_min_x = amax[0] *-1 # highest x *-1 is lowest windows x + x_window_max_x = amin[0] # highest x is highest window x + steps_x = abs(amax[0]) / number_of_boxes_hor # length of x boxes + + #Calculating range of y boxes + steps_y = (abs(amax[1]) + abs(amin[1])) / number_of_boxes_ver + + #Calculating range of z boxes + steps_z = (abs(amax[2]) + abs(amin[2])) / number_of_boxes_z + + return steps_x, steps_y, steps_z, x_window_min_x,x_window_max_x + +# Function create list ranges of each section +def create_list_ranges(amin,amax,number_of_boxes_hor, number_of_boxes_ver,number_of_boxes_z, + x_window_min_x, x_window_max_x,steps_x,steps_y,steps_z): # creat list with ranges of each section + #creating the list with the ranges for every section + y_window_min = amin[1] + y_window_max = amin[1] + z_window_min = amin[2] + newlist = [] + sublist = [] + y_window_min2 = y_window_min + z_window_min2 = z_window_min + + # From front to back, from floor to ceiling + for a in range(0,int(number_of_boxes_ver)): #number of rows + x_window_min = x_window_min_x + x_window_min2 = x_window_min_x + steps_x + y_window_min = y_window_min2 + y_window_min2+= steps_y + z_window_min = amin[2] + z_window_min2 = z_window_min + for c in range(0,int(number_of_boxes_z)): # in z direction + z_window_min = z_window_min2 + z_window_min2 += steps_z + x_window_min = x_window_min_x + x_window_min2 = x_window_min_x + steps_x + for b in range(0, int((2*number_of_boxes_hor))): #number of columns + sublist.append(x_window_min) + sublist.append(x_window_min2) + sublist.append(y_window_min) + sublist.append(y_window_min2) + sublist.append(z_window_min) + sublist.append(z_window_min2) + newlist.append(sublist) + sublist = [] + x_window_min = x_window_min2 + x_window_min2 += steps_x + + return newlist + +# Function create list coordinates in sections +def create_list_coordinates(newlist): # create list coordinates in sections + #empty the list but maintaining the structure + newlist2=[] + newlist2sub = [] + newlistsub = [] + for x in range(0,len(newlist)): + for y in range(5,-1,-1): + newlist2sub.append(newlist[x].pop(y)) + newlist2.append(newlist2sub) + newlist2sub = [] + + # creating empty index list for storing line index of coordinates + indexlist = [] + for x in range(0,len(newlist)): + indexlist.append([]) + + return newlist2, indexlist + +# Function fill list sections with coordinates +def fill_sections_coordinates(newlist,newlist2,matrix,indexlist): # fill list sections with coordinates + #Filling the sections with the coordinates + for y in range(0,len(newlist2)): #notice the ranges are in reverse order of each section + rows_vertex = (numpy.where((matrix[:,0]>= float(newlist2[y][5])) + & (matrix[:,0] < float(newlist2[y][4])) + & (matrix[:,1] >= float(newlist2[y][3])) + & (matrix[:,1] < float(newlist2[y][2])) + & (matrix[:,2] >= float(newlist2[y][1])) + & (matrix[:,2] < float(newlist2[y][0])))) + + vertex_new = matrix[list(rows_vertex)] + newlist[y].append((vertex_new)) + indexlist[y].append((rows_vertex)) + + return newlist, indexlist + +# Function calculate mean and number of coordinates sections +def calc_sections(number_of_boxes_ver,number_of_boxes_hor,number_of_boxes_z,newlist): + #Selecting the sections on the symmetry axis and calculating the mean of every section + counter = 0 + counter2 = 0 + counter3 = 0 + row_count = 0 + difference = [] #whit sections which are empty + differencemean = [] #without sections which are empty + total = 0 + for x in range(0, (int(number_of_boxes_ver)*int(number_of_boxes_hor) * int(number_of_boxes_z))): # through all the lists/sections + if counter % (int (number_of_boxes_hor)*2) == 0: + counter = 0 + if counter3 == (int(number_of_boxes_hor)): + counter2 += (int(number_of_boxes_hor)) + counter3 = 0 + + first_pos = (newlist[counter2][0]) # coordinates of left section + last_pos = (newlist[counter2 + (int(number_of_boxes_hor)*2 -1)- counter][0]) # coordinates of right section + if len(first_pos) == 0: # If there are no coordinates in a section + number_coordinates_box1 = len(first_pos) + mean1 = 2000 + mean3 = '' + + else: + number_coordinates_box1 = len(first_pos) + for e in range(0,len(first_pos)): # If there are coordinates in a section + total += float(first_pos[e][0]) + mean1 = total/len(first_pos) + mean3 = mean1 + total = 0 + + if len(last_pos) == 0: # If there are no coordinates in a section + number_coordinates_box2 = len(last_pos) + mean2 = 1000 + mean4 = '' + + else: + number_coordinates_box2 = len(last_pos) + + for e in range(0,len(last_pos)): # If there are coordinates in a section + total += float(last_pos[e][0]) + mean2 = total/len(last_pos) + mean4 = mean2 + total = 0 + number_coordinates_box1 = len(first_pos) + number_coordinates_box2 = len(last_pos) + + # if number of coordinates in sections deviate to much, + if (abs(number_coordinates_box1 - number_coordinates_box2) > (number_coordinates_box1 / 2.0) + ) and(abs(number_coordinates_box1 - number_coordinates_box2) > (number_coordinates_box2 / 2.0)): + mean1 = 3000 + mean2 = 4000 + + difference.append(float(abs(mean2 + mean1))) #the means of every sections + counter += 2 + counter2 += 1 + counter3 += 1 + + try: + differencemean.append(abs(mean4 + mean3)) # the mean without empty sections + except: + continue + + return difference, differencemean + +# Function calculating the mean and the standard deviation +def calc_mean_stdev(differencemean, factor): + mean_percentage = numpy.mean(differencemean) #calculating the mean without empty sections + std_percentage = numpy.std(differencemean) # calculating the standard deviation of the list without the empty sections + std_percentage = std_percentage * factor + + return mean_percentage, std_percentage + +# Function calculating range of accepted differences +def calc_range(mean_percentage,std_percentage): + left_range = float(mean_percentage) - float(std_percentage) #left range mean minus one standard deviation + right_range = float(mean_percentage) + (float(std_percentage) )# right range mean plus one standard deviation + if left_range > 0: + left_range = 0 + return left_range, right_range + +# Function collecting incorrect coordinates +def collect_mirror_values(out_log, side, output, right_range, left_range,mean_percentage, + std_percentage, newlist, indexlist,difference, + number_of_boxes_hor,number_of_boxes_ver,number_of_boxes_z, + col_r, col_g, col_b): + + # Collecting the values of the sections which have to be mirrored + out_log.write('mean x difference:\t%s\nstandarddeviation mean x difference:\t%s\nrange:\t%s - %s\n\n'% + ((mean_percentage),(std_percentage),(left_range),(right_range))) + y = 0 + counter = 0 + counter2 = 0 + sub = [] + total = [] + left_range = "%.10f"%(left_range) + indexcount = 0 + facecount = 0 + totalcount = 0 + listindex = [] + listindexsub = [] + listindexcount = [] + listindextotalcount = [] + + for x in range(0, len(difference)): + difference_x = "%.10f"%(difference[x]) + if counter %(int(number_of_boxes_hor)) == 0 and x != 0: + counter = 0 + counter2 += (int(number_of_boxes_hor)) + counter += 1 + counter2 += 1 #left side counter + + # if left side of the object is correct + if side == 0: + if (float(difference_x) < float(left_range)) or (float(difference_x) > float(right_range)): + if len(newlist[counter2 -1][0]) != 0: + sub = (newlist[counter2 -1][0]) #coordinates in list + for y in range(0, len(sub)): + i = sub[y] + index_a = indexlist[counter2 -1][0][0][y] + try: + listindex.append(int(index_a)) # index number + listindextotalcount.append(int(totalcount)) + listindexsub.append(int(index_a)) # index number + listindexsub.append(totalcount) # index number of new coordinate + + except: + continue + listindexcount.append(listindexsub) # index number original + listindexsub = [] + number= float(sub[y][0]) * -1 # x coordinate * -1 for mirroring at symmetry plane + sub[y][0] = number + total.append(sub[y]) + totalcount += 1 + # writing new coordinates to output + output.write('%s %s %s %s %s %s\n'%(sub[y][0], float(sub[y][1]), float(sub[y][2]),(col_r), (col_g), (col_b))) + + + # if right side of the object is correct + if side == 1: + dif = (int(number_of_boxes_hor)) - counter + counter3 = counter2 + (dif*2) + 1 # right side counter + + if (float(difference[x] )> float(right_range)) or (float(difference[x]) < float(left_range)): + if len(newlist[counter3 -1][0]) != 0: + sub = (newlist[counter3 -1][0]) # coordinates in list + for y in range(0, len(sub)): + i = sub[y] + index_a = indexlist[counter3 -1][0][0][y] + try: + listindex.append(int(index_a))# index number + listindextotalcount.append(int(totalcount)) + listindexsub.append(int(index_a)) # index number + listindexsub.append(totalcount)# index number of new coordinate + except: + continue + listindexcount.append(listindexsub)# index number original + listindexsub = [] + number= float(sub[y][0]) * -1 # x coordinate * -1 for mirroring at symmetry plane + sub[y][0] = number + total.append(sub[y]) + totalcount += 1 + # writing new coordinates to output + output.write('%s %s %s %s %s %s\n'%(sub[y][0], float(sub[y][1]), float(sub[y][2]),(col_r), (col_g), (col_b))) + + return total, listindexcount, listindex, listindextotalcount,totalcount + +# Function extract original faces for corrected coordinates +def find_original_faces(matrix2, matrix3, listindex): + # finding the original faces of kopied points + ix = numpy.in1d(matrix2.ravel(),listindex).reshape(matrix2.shape) # finding where the listindex is the same as the matrix + rows, cols = numpy.where(ix) # finding index of the faces + m_face = matrix2[list(set(rows))] # extracting the rows with those faces + m_face_square = [] + # if square faces present + if matrix3[-1][0] != 0: + ix_square = numpy.in1d(matrix3.ravel(),listindex).reshape(matrix3.shape) # finding where the listindex is the same as the matrix + rows_square, cols3 = numpy.where(ix_square) # finding index of the faces + m_face_square = matrix3[list(set(rows_square))] # extracting the rows with those faces + return m_face, m_face_square + +# Function replacing index values +def replace_index_values(m_face,listindex,listindextotalcount): + c = [] + array_oi = numpy.array(m_face) + maxn = numpy.amax(array_oi) + palette = list(range(int(maxn))) + palette = numpy.array(palette) + key = numpy.array(listindex) + listindextotalcount = numpy.array(listindextotalcount) + + # sorting the lists which have to be replaced + order= numpy.argsort(key) # sorting of the array key + litc_sorted = listindextotalcount[order] # sorting the palette + key_sorted = key[order] # sorting the key + + palette2 = list(range(int(maxn))) # creating list with all possible values in it with max the highest number in the faces + key2 = [] + + counter = 0 + for item in range(0,int(maxn)): # make array containing what have to be changed + if (counter < len(key_sorted)) and item == (key_sorted[counter]): + key2.append(litc_sorted[counter]) + counter += 1 + else: + key2.append(numpy.nan) + + key2 = numpy.array(key2) # converten of list to array + index_f = numpy.digitize(array_oi.reshape(-1,), palette2)-1 # indexing which numbers has to be changed + out_sub =(key2[index_f].reshape(array_oi.shape)) # new array creating with changed values + out_faces = out_sub[~numpy.isnan(out_sub).any(axis=1)] # extracting the faces with not changed values, (nan) + + return out_faces + +# Function write output +def write_output(name_file_ply, out_log, totalcount, var_header, var_vertex_nm, var_face_nm,out_faces,out_faces_2): # write output + outfile2 = open(str(sys.argv[2]), 'w')#writing the output file + file1 = open(name_file_ply) + g = 0 + for d in range(0,(int(var_header) + int(var_vertex_nm) + int(var_face_nm) + 1)): + line2 = file1.readline().strip() + readline2 = line2.strip().split() + if readline2[0] == "element" and readline2[1] == "vertex": + outfile2.write("element vertex %s\n"%(int(var_vertex_nm) + totalcount)) #number of vertexen changing + + elif readline2[0] == "element" and readline2[1] == "face": + outfile2.write("element face %s\n"%(int(var_face_nm) + len(out_faces) + len(out_faces_2)))#number of faces changing + + elif (int(var_header) < d < (int(var_header) + int(var_vertex_nm))): #rotated vertexen, with original color code + outfile2.write('%s\n'%(line2)) + g += 1 + + elif (int(var_header) + int(var_vertex_nm)) == d: #for new vertexen, with color code 0,0,0 + outfile2.write('%s\n'%(line2)) #the last original vertex + g += 1 + with open('new_coordinates2.ply') as infile: + for line in infile: + outfile2.write(line) + + else: #everything left + outfile2.write('%s\n'%(line2)) + + #writing new faces to output + for z in range(0,len(out_faces)): + outfile2.write("3 %s %s %s\n"%((int(out_faces[z][0])+ int(var_vertex_nm)), + (int(out_faces[z][1])+ int(var_vertex_nm)), (int(out_faces[z][2])+ int(var_vertex_nm)))) + #writing new square faces to output + if len(out_faces_2) != 0: + for x in range(0,len(out_faces_2)): + outfile2.write("4 %s %s %s %s\n"%((int(out_faces_2[z][0])+ int(var_vertex_nm)), + (int(out_faces_2[z][1])+ int(var_vertex_nm)), (int(out_faces_2[z][2])+ int(var_vertex_nm)), + (int(out_faces_2[z][3] + int(var_vertex_nm))))) + + out_log.write('number of reconstructed faces:\t%s\n\n'%(len(out_faces) + len(out_faces_2))) + outfile2.close() + + +main() + + +