def extractVidDistribution(self, site): """ Extracts parts of video frames from vid file as distributions for sampling pick locations. Normalized video intensities serve as weights in the distribution. """ # Go through picks for pick in self.picks_full[site]: # Print picks info print('PICK frame', pick.frame) print('GC: Cx, Cy', pick.cx_gc, pick.cy_gc) # Get coordinates of the max. longitudinal uncertanty phase_max = pick.phase + self.phase_direction[ site] * self.longitudinal_std[site] x, y, z = greatCircle(phase_max, pick.theta0, pick.phi0) theta_max, phi_max = cartesianToPolar(x, y, z) # Get the image position of the max. longitudinal uncertanty cx_max, cy_max = coordinatesSkyToImage( theta_max, phi_max, self.met.exact_plates[site], self.met.scale_plates[site], pick.hx, pick.hy) # Calculate the angle of the vector made by the original GC pick and the max. long. pick angle = np.arctan2(pick.cy_gc - cy_max, pick.cx_gc, cx_max) print('Angle:', np.degrees(angle)) # Extract the desired frame img = self.vids[site].frames[pick.frame].img_data ##### TEMP!! break
def determinePhaseProgression(self): """ Determines if the meteor progresses through time with the rising GC phase or not. """ # Do this for both sites for site in self.met.sites: # Take the first and the last pick fp = self.picks_full[site][0] lp = self.picks_full[site][-1] # Calculate the angle between picks dist = vectorAngle(np.r_[fp.x_gc, fp.y_gc, fp.z_gc], np.r_[lp.x_gc, lp.y_gc, lp.z_gc]) # Take a small step in phase forward from the first pick sp = greatCircle(fp.phase + np.radians(0.5), fp.theta0, fp.phi0) # Check if the the rising phase is approaching the last pick or not if vectorAngle(np.r_[sp], np.r_[lp.x_gc, lp.y_gc, lp.z_gc]) < dist: # If the distance to the last pick is smaller with the positive phase step, set phase as + self.phase_direction[site] = 1 else: # Set phase progression as negative self.phase_direction[site] = -1
def _pointDist(x): """ Calculates the Cartesian distance from a point defined in polar coordinates, and a point on a great circle. """ # Convert the pick to Cartesian coordinates point = polarToCartesian(phi, theta) # Get the point on the great circle circle = greatCircle(x, theta0, phi0) # Return the distance from the pick to the great circle return np.sqrt((point[0] - circle[0])**2 + (point[1] - circle[1])**2 + (point[2] - circle[2])**2)
def calcProjection(self): """ Calculates the projection of the pick to the great circle. """ # Find the phase angle of the closes point on great circle to the original point self.phase = greatCirclePhase(self.theta, self.phi, self.theta0, self.phi0) # Calculate the projected point self.x_gc, self.y_gc, self.z_gc = greatCircle(self.phase, self.theta0, self.phi0) # Convert the point to polar coordinates self.theta_gc, self.phi_gc = cartesianToPolar(self.x_gc, self.y_gc, self.z_gc)
def samplePicks(self, n): """ Sample picks from distributions defined by the transverse and longitudinal uncertainties. """ # Determine the directon of phase progression of the meteor through time self.determinePhaseProgression() # Draw n number of trajectories for i in range(n): # Init a new trajectory on each drawing traj = TrajPoints() # Draw picks for all sites for site in self.met.sites: # Init the trajectory picks for this site traj.picks[site] = [] # Go through all picks in this site for pick in self.picks_full[site]: # Make a new pick copy new_pick = copy.deepcopy(pick) # Generate a transverse pick uncertanty trans_dev = np.random.normal(0, self.transverse_std[site]) # Generate a longitudinal uncertanty (only take the front half of the Gaussian) longi_dev = np.abs( np.random.normal(0, self.longitudinal_std[site])) # Draw a pick from the great circle with the drawn offset draw_x, draw_y, draw_z = greatCircle( new_pick.phase + self.phase_direction[site] * longi_dev, new_pick.theta0 + trans_dev, new_pick.phi0) # Set the drawn coordinates to the pick new_pick.draw_x, new_pick.draw_y, new_pick.draw_z = draw_x, draw_y, draw_z # Calculate the polar coordinates of the drawn pick new_pick.theta_draw, new_pick.phi_draw = cartesianToPolar( draw_x, draw_y, draw_z) # Add pick to the trajectory traj.picks[site].append(new_pick) # Add the drawn trajectory to the list of trajectories self.trajectories.append(traj)
def greatCircleToImage(phase, theta0, phi0, exact, scale, hx_centre, hy_centre): """ Take a point on the great circle, and return its coordinates on an image. """ # Get the great circle position in Cartesian coordinates x, y, z = greatCircle(phase, theta0, phi0) # Convert the GC cartesian coordinates to polar theta, phi = cartesianToPolar(x, y, z) # Get the image position of a point on the GC cx, cy = coordinatesSkyToImage(theta, phi, exact, scale, hx_centre, hy_centre) return cx, cy
def fitGreatCircle(self): """ Fits a great circle to the picks. """ # Go though all sites for site in self.met.sites: # Extract frames frames = np.array(met.picks[site])[:, 0] # Extract mirror positions on each frame hx_data, hy_data = np.hsplit( np.array(met.picks[site])[:, 22:24], 2) # Extract original centroids cx_data, cy_data = np.hsplit(np.array(met.picks[site])[:, 2:4], 2) # Extract UNIX time ts_data, tu_data = np.hsplit( np.array(met.picks[site])[:, 11:13], 2) time_data = ts_data + tu_data / 1000000 # Init theta, phi arrays theta = np.zeros_like(cx_data) phi = np.zeros_like(cx_data) # Calculate (theta, phi) from image coordinates for i in range(len(cx_data)): theta[i], phi[i] = coordinatesImageToSky( cx_data[i], cy_data[i], met.exact_plates[site], met.scale_plates[site], hx_data[i], hy_data[i]) # Convert (theta, phi) to Cartesian coordinates x, y, z = polarToCartesian(phi, theta) # Add (0, 0, 0) to the data (as the great circel should go through the origin) x = np.append(x, 0) y = np.append(y, 0) z = np.append(z, 0) # Regular grid covering the domain of the data X, Y = np.meshgrid(np.arange(-1.0, 1.0, 0.1), np.arange(-1.0, 1.0, 0.1)) # Fit the great circle C, theta0, phi0 = fitGreatCircle(x, y, z) # Store great circle parameters self.theta0[site], self.phi0[site] = theta0, phi0 print('GC params:', theta0, phi0) # evaluate it on grid Z = C[0] * X + C[1] * Y + C[2] # plot points and fitted surface fig = plt.figure() ax = fig.gca(projection='3d') # Plot the original points ax.scatter(x, y, z) # Plot the best fit plane ax.plot_surface(X, Y, Z, rstride=1, cstride=1, alpha=0.2) # Plot fitted great circle t_array = np.arange(0, 2 * np.pi, 0.01) ax.scatter(*greatCircle(t_array, theta0, phi0), c='b', s=5) # Plot the zero of the great circle ax.scatter(*greatCircle(0, theta0, phi0), c='r', s=100) # Define plane normal N = greatCircle(np.pi / 2.0, theta0 + np.pi / 2.0, phi0) # Store as great circle normal self.N[site] = N # Plot the plane normal ax.scatter(*N, c='g', s=100) print('Normal', N) # Calculate STDDEV of angle deviations from picks to the plane sin_s = 0 cos_s = 0 for pick in np.c_[x, y, z][:-1]: dev_angle = vectorAngle(pick, N) - np.pi / 2 # print np.degrees(dev_angle)*3600 sin_s += np.sin(dev_angle) cos_s += np.cos(dev_angle) sin_s = sin_s / len(met.picks[site]) cos_s = cos_s / len(met.picks[site]) stddev = np.sqrt(-np.log(sin_s**2 + cos_s**2)) print('GC stddev in arcsec: ', np.degrees(stddev) * 3600) # Store as stddev in transverse direction self.transverse_std[site] = stddev ######### ### TO DO: ### DETERMINE LONGITUDINAL UNCERTANTY (20 arcsecs TEMP value) self.longitudinal_std[site] = np.radians(20 / 3600.0) ######## # Init a list of picks for this site self.picks_full[site] = [] # Generate a list of pick object for fr, cx, cy, hx, hy, theta_pick, phi_pick, unix_time in zip( frames, cx_data, cy_data, hx_data, hy_data, theta, phi, time_data): # Init a new pick pick = PickInfo(theta_pick, phi_pick) # Set the pick frame pick.frame = int(fr) # Set pick UNIX time pick.unix_time = unix_time # Set original pick centroids pick.cx = cx pick.cy = cy # Set mirror position of frame centre pick.hx = hx pick.hy = hy # Set the great circle parameters of the pick pick.theta0 = self.theta0[site] pick.phi0 = self.phi0[site] # Calculate the pick projection to the great circle pick.calcProjection() # Calculate image position of the great circle pick pick.cx_gc, pick.cy_gc = coordinatesSkyToImage( pick.theta_gc, pick.phi_gc, self.met.exact_plates[site], self.met.scale_plates[site], pick.hx, pick.hy) # Add the pick to the list of all picks self.picks_full[site].append(pick) # Plot the projections of original points to the fitted great circle for pick in self.picks_full[site]: print(pick.theta, pick.phi, pick.phase) ax.scatter(pick.x_gc, pick.y_gc, pick.z_gc, c='yellow') # ### Plot the projection of the first point on the great circle # # Get the phase of the great circle for the fist point # phase0 = greatCirclePhase(theta[0], phi[0], theta0, phi0) # print 'Phase:', phase0 # ax.scatter(*greatCircle(phase0, theta0, phi0), c='yellow', s=200) # ### plt.xlim([-1, 1]) plt.ylim([-1, 1]) ax.set_zlim(-1, 1) ax.set_aspect('equal') # plt.show() plt.clf() #plt.close() plt.plot(theta, phi) gc_theta, gc_phi = cartesianToPolar( *greatCircle(t_array, theta0, phi0)) plt.plot(gc_theta, gc_phi, color='r') # plt.show() plt.close()