def setUp(self): start_lat = 38 start_lon = -76 start_depth = -5 temp_time = datetime.utcnow() self.start_time = datetime(temp_time.year, temp_time.month, temp_time.day, temp_time.hour) self.loc = Location4D(latitude=start_lat, longitude=start_lon, depth=start_depth, time=self.start_time) # Generate time,u,v,z as randoms # 48 timesteps at an hour each = 2 days of running self.times = range(0, 172800, 3600) # in seconds self.u = [] self.v = [] self.z = [] for w in xrange(0, 48): self.z.append(random.gauss(0, 0.0001)) # gaussian in m/s self.u.append(abs(AsaRandom.random())) # random function in m/s self.v.append(abs(AsaRandom.random())) # random function in m/s self.particles = [] # Create particles for i in xrange(0, 3): p = Particle() p.location = self.loc self.particles.append(p) # Create a transport instance with horiz and vert dispersions self.transport_model = Transport(horizDisp=0.05, vertDisp=0.00003)
def setUp(self): start_lat = 38 start_lon = -76 start_depth = -5 temp_time = datetime.utcnow() self.start_time = datetime(temp_time.year, temp_time.month, temp_time.day, temp_time.hour) self.loc = Location4D(latitude=start_lat, longitude=start_lon, depth=start_depth, time=self.start_time) # Generate time,u,v,z as randoms # 48 timesteps at an hour each = 2 days of running self.times = list(range(0, 172800, 3600)) # in seconds self.u = [] self.v = [] self.z = [] for w in range(0, 48): self.z.append(random.gauss(0, 0.0001)) # gaussian in m/s self.u.append(abs(AsaRandom.random())) # random function in m/s self.v.append(abs(AsaRandom.random())) # random function in m/s self.particles = [] # Create particles for i in range(0, 3): p = Particle() p.location = self.loc self.particles.append(p) # Create a transport instance with horiz and vert dispersions self.transport_model = Transport(horizDisp=0.05, vertDisp=0.00003)
def move(self, particle, u, v, w, modelTimestep, **kwargs): """ Returns the lat, lon, H, and velocity of a projected point given a starting lat and lon (dec deg), a depth (m) below sea surface (positive up), u, v, and w velocity components (m/s), a horizontal and vertical displacement coefficient (m^2/s) H (m), and a model timestep (s). GreatCircle calculations are done based on the Vincenty Direct method. Returns a dict like: { 'latitude': x, 'azimuth': x, 'reverse_azimuth': x, 'longitude': x, 'depth': x, 'u': x 'v': x, 'w': x, 'distance': x, 'angle': x, 'vertical_distance': x, 'vertical_angle': x } """ logger.debug("U: %s, V: %s, W: %s" % (str(u), str(v), str(w))) # IMPORTANT: # If we got no data from the model, we are using the last available value stored in the particles! if (u is None) or (u is not None and math.isnan(u)): u = particle.last_u() if (v is None) or (v is not None and math.isnan(v)): v = particle.last_v() if (w is None) or (w is not None and math.isnan(w)): w = particle.last_w() particle.u_vector = u particle.v_vector = v particle.w_vector = w if particle.halted: u, v, w = 0, 0, 0 else: u += AsaRandom.random() * ((2 * self._horizDisp / modelTimestep)** 0.5) # u transformation calcualtions v += AsaRandom.random() * ((2 * self._horizDisp / modelTimestep)** 0.5) # v transformation calcualtions w += AsaRandom.random() * ((2 * self._vertDisp / modelTimestep)** 0.5) # w transformation calculations result = AsaTransport.distance_from_location_using_u_v_w( u=u, v=v, w=w, timestep=modelTimestep, location=particle.location) result['u'] = u result['v'] = v result['w'] = w return result
def move(self, particle, u, v, w, modelTimestep, **kwargs): """ Returns the lat, lon, H, and velocity of a projected point given a starting lat and lon (dec deg), a depth (m) below sea surface (positive up), u, v, and w velocity components (m/s), a horizontal and vertical displacement coefficient (m^2/s) H (m), and a model timestep (s). GreatCircle calculations are done based on the Vincenty Direct method. Returns a dict like: { 'latitude': x, 'azimuth': x, 'reverse_azimuth': x, 'longitude': x, 'depth': x, 'u': x 'v': x, 'w': x, 'distance': x, 'angle': x, 'vertical_distance': x, 'vertical_angle': x } """ logger.debug("U: %s, V: %s, W: %s" % (str(u),str(v),str(w))) # IMPORTANT: # If we got no data from the model, we are using the last available value stored in the particles! if (u is None) or (u is not None and math.isnan(u)): u = particle.last_u() if (v is None) or (v is not None and math.isnan(v)): v = particle.last_v() if (w is None) or (w is not None and math.isnan(w)): w = particle.last_w() particle.u_vector = u particle.v_vector = v particle.w_vector = w if particle.halted: u,v,w = 0,0,0 else: u += AsaRandom.random() * ((2 * self._horizDisp / modelTimestep) ** 0.5) # u transformation calcualtions v += AsaRandom.random() * ((2 * self._horizDisp / modelTimestep) ** 0.5) # v transformation calcualtions w += AsaRandom.random() * ((2 * self._vertDisp / modelTimestep) ** 0.5) # w transformation calculations result = AsaTransport.distance_from_location_using_u_v_w(u=u, v=v, w=w, timestep=modelTimestep, location=particle.location) result['u'] = u result['v'] = v result['w'] = w return result
def __reverse(self, **kwargs): """ Reverse particle just off of the shore in the direction that it came in. Adds a slight random factor to the distance and angle it is reversed in. """ #st = time.clock() start_point = kwargs.pop('start_point') hit_point = kwargs.pop('hit_point') reverse_azimuth = kwargs.pop('reverse_azimuth') reverse_distance = kwargs.get('reverse_distance', None) if reverse_distance is None: reverse_distance = 100 # Randomize the reverse angle slightly (+/- 5 degrees) random_azimuth = reverse_azimuth + AsaRandom.random() * 5 count = 0 nudge_distance = 0.01 nudge_point = AsaGreatCircle.great_circle(distance=nudge_distance, azimuth=reverse_azimuth, start_point=hit_point) nudge_loc = Location4D(latitude=nudge_point['latitude'], longitude=nudge_point['longitude'], depth=start_point.depth) # Find point just offshore to do testing with. Try 15 times (~350m). This makes sure the start_point is in the water # for the next call to intersect (next while loop). while self.intersect(single_point=nudge_loc.point) and count < 16: nudge_distance *= 2 nudge_point = AsaGreatCircle.great_circle(distance=nudge_distance, azimuth=reverse_azimuth, start_point=hit_point) nudge_loc = Location4D(latitude=nudge_point['latitude'], longitude=nudge_point['longitude'], depth=start_point.depth) count += 1 # We tried 16 times and couldn't find a point. This should totally never happen. if count == 16: logger.warn("LOOK: Could not find location in water to do shoreline calculation with. Assuming particle did not move from original location") return start_point # Keep trying to throw particle back, halfing the distance each time until it is in water. # Only half it 6 times before giving up and returning the point which the particle came from. count = 0 # Distance amount to half each iteration changing_distance = reverse_distance new_point = AsaGreatCircle.great_circle(distance=reverse_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) # We don't want to reverse further than the current spatial buffer, because we will reindex the # source file everytime we reverse, which will slow down the calculations considerably. while (not self._spatial_query_object.contains(new_loc.point) or self.intersect(start_point=nudge_loc.point, end_point=new_loc.point)) and count < 6: changing_distance /= 2 new_point = AsaGreatCircle.great_circle(distance=changing_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) count += 1 # We tried 10 times and the particle was still on shore, return the point the particle started from. # No randomization. if count == 6: logger.warn("LOOK: Could not react particle with shoreline. Assuming particle did not move from original location") return start_point #logger.info("Reaction time: %f" % (time.clock() - st)) return new_loc
def __reverse(self, **kwargs): """ Reverse particle just off of the shore in the direction that it came in. Adds a slight random factor to the distance and angle it is reversed in. """ start_point = kwargs.pop('start_point') hit_point = kwargs.pop('hit_point') distance = kwargs.pop('distance') azimuth = kwargs.pop('azimuth') reverse_azimuth = kwargs.pop('reverse_azimuth') reverse_distance = kwargs.get('reverse_distance', None) if reverse_distance is None: reverse_distance = 100 # Randomize the reverse angle slightly (+/- 5 degrees) random_azimuth = reverse_azimuth + AsaRandom.random() * 5 count = 0 nudge_distance = 0.01 nudge_point = AsaGreatCircle.great_circle(distance=nudge_distance, azimuth=reverse_azimuth, start_point=hit_point) nudge_loc = Location4D(latitude=nudge_point['latitude'], longitude=nudge_point['longitude'], depth=start_point.depth) # Find point just offshore to do testing with. Try 15 times (~350m). This makes sure the start_point is in the water # for the next call to intersect (next while loop). while self.intersect(single_point=nudge_loc.point) and count < 16: nudge_distance *= 2 nudge_point = AsaGreatCircle.great_circle(distance=nudge_distance, azimuth=reverse_azimuth, start_point=hit_point) nudge_loc = Location4D(latitude=nudge_point['latitude'], longitude=nudge_point['longitude'], depth=start_point.depth) count += 1 # We tried 16 times and couldn't find a point. This should totally never happen. if count == 16: logger.debug("WOW. Could not find location in water to do shoreline calculation with. Assuming particle did not move from original location") return start_point # Keep trying to throw particle back, halfing the distance each time until it is in water. # Only half it 12 times before giving up and returning the point which the particle came from. count = 0 # Distance amount to half each iteration changing_distance = reverse_distance new_point = AsaGreatCircle.great_circle(distance=reverse_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) while self.intersect(start_point=nudge_loc.point, end_point=new_loc.point) and count < 12: changing_distance /= 2 new_point = AsaGreatCircle.great_circle(distance=changing_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) count += 1 # We tried 10 times and the particle was still on shore, return the point the particle started from. # No randomization. if count == 12: logger.debug("Could not react particle with shoreline. Assuming particle did not move from original location") return start_point return new_loc
def __reverse(self, **kwargs): """ Reverse particle just off of the shore in the direction that it came in. Adds a slight random factor to the distance and angle it is reversed in. """ start_point = kwargs.pop('start_point') hit_point = kwargs.pop('hit_point') distance = kwargs.pop('distance') azimuth = kwargs.pop('azimuth') reverse_azimuth = kwargs.pop('reverse_azimuth') reverse_distance = kwargs.get('reverse_distance', None) if reverse_distance is None: reverse_distance = 100 # Randomize the reverse angle slightly (+/- 5 degrees) random_azimuth = reverse_azimuth + AsaRandom.random() * 5 # Nudge the hitpoint off of the shore by a tiny bit to test shoreline intersection in while loop. nudged_hit_point = AsaGreatCircle.great_circle(distance=0.01, azimuth=random_azimuth, start_point=hit_point) nudged_hit_location = Location4D(latitude=nudged_hit_point['latitude'], longitude=nudged_hit_point['longitude'], depth=start_point.depth) new_point = AsaGreatCircle.great_circle(distance=reverse_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) # Keep trying to throw particle back, halfing the distance each time until it is in water. # Only half it 10 times before giving up and returning the point which the particle came from. count = 0 # Distance amount to half each iteration changing_distance = reverse_distance while self.intersect(start_point=nudged_hit_location.point, end_point=new_loc.point) and count < 10: changing_distance /= 2 new_point = AsaGreatCircle.great_circle(distance=changing_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) count += 1 # We tried 10 times and the particle was still on shore, return the point the particle started from. # No randomization. if count == 10: logger.warn("Could not react particle with shoreline. Assuming particle did not move from original location") new_loc = start_point return new_loc
def __reverse(self, **kwargs): """ Reverse particle just off of the shore in the direction that it came in. Adds a slight random factor to the distance and angle it is reversed in. """ start_point = kwargs.pop('start_point') hit_point = kwargs.pop('hit_point') distance = kwargs.pop('distance') azimuth = kwargs.pop('azimuth') reverse_azimuth = kwargs.pop('reverse_azimuth') reverse_distance = kwargs.get('reverse_distance', None) if reverse_distance is None: reverse_distance = 100 # Randomize the reverse angle slightly (+/- 5 degrees) random_azimuth = reverse_azimuth + AsaRandom.random() * 5 count = 0 nudge_distance = 0.01 nudge_point = AsaGreatCircle.great_circle(distance=nudge_distance, azimuth=reverse_azimuth, start_point=hit_point) nudge_loc = Location4D(latitude=nudge_point['latitude'], longitude=nudge_point['longitude'], depth=start_point.depth) # Find point just offshore to do testing with. Try 15 times (~350m). This makes sure the start_point is in the water # for the next call to intersect (next while loop). while self.intersect(single_point=nudge_loc.point) and count < 16: nudge_distance *= 2 nudge_point = AsaGreatCircle.great_circle(distance=nudge_distance, azimuth=reverse_azimuth, start_point=hit_point) nudge_loc = Location4D(latitude=nudge_point['latitude'], longitude=nudge_point['longitude'], depth=start_point.depth) count += 1 # We tried 16 times and couldn't find a point. This should totally never happen. if count == 16: logger.debug( "WOW. Could not find location in water to do shoreline calculation with. Assuming particle did not move from original location" ) return start_point # Keep trying to throw particle back, halfing the distance each time until it is in water. # Only half it 12 times before giving up and returning the point which the particle came from. count = 0 # Distance amount to half each iteration changing_distance = reverse_distance new_point = AsaGreatCircle.great_circle(distance=reverse_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) while self.intersect(start_point=nudge_loc.point, end_point=new_loc.point) and count < 12: changing_distance /= 2 new_point = AsaGreatCircle.great_circle(distance=changing_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) count += 1 # We tried 10 times and the particle was still on shore, return the point the particle started from. # No randomization. if count == 12: logger.debug( "Could not react particle with shoreline. Assuming particle did not move from original location" ) return start_point return new_loc
def __reverse(self, **kwargs): """ Reverse particle just off of the shore in the direction that it came in. Adds a slight random factor to the distance and angle it is reversed in. """ #st = time.clock() start_point = kwargs.pop('start_point') hit_point = kwargs.pop('hit_point') reverse_azimuth = kwargs.pop('reverse_azimuth') reverse_distance = kwargs.get('reverse_distance', None) if reverse_distance is None: reverse_distance = 100 # Randomize the reverse angle slightly (+/- 5 degrees) random_azimuth = reverse_azimuth + AsaRandom.random() * 5 count = 0 nudge_distance = 0.01 nudge_point = AsaGreatCircle.great_circle(distance=nudge_distance, azimuth=reverse_azimuth, start_point=hit_point) nudge_loc = Location4D(latitude=nudge_point['latitude'], longitude=nudge_point['longitude'], depth=start_point.depth) # Find point just offshore to do testing with. Try 15 times (~350m). This makes sure the start_point is in the water # for the next call to intersect (next while loop). while self.intersect(single_point=nudge_loc.point) and count < 16: nudge_distance *= 2 nudge_point = AsaGreatCircle.great_circle(distance=nudge_distance, azimuth=reverse_azimuth, start_point=hit_point) nudge_loc = Location4D(latitude=nudge_point['latitude'], longitude=nudge_point['longitude'], depth=start_point.depth) count += 1 # We tried 16 times and couldn't find a point. This should totally never happen. if count == 16: logger.warn( "LOOK: Could not find location in water to do shoreline calculation with. Assuming particle did not move from original location" ) return start_point # Keep trying to throw particle back, halfing the distance each time until it is in water. # Only half it 6 times before giving up and returning the point which the particle came from. count = 0 # Distance amount to half each iteration changing_distance = reverse_distance new_point = AsaGreatCircle.great_circle(distance=reverse_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) # We don't want to reverse further than the current spatial buffer, because we will reindex the # source file everytime we reverse, which will slow down the calculations considerably. while (not self._spatial_query_object.contains(new_loc.point) or self.intersect(start_point=nudge_loc.point, end_point=new_loc.point)) and count < 6: changing_distance /= 2 new_point = AsaGreatCircle.great_circle(distance=changing_distance, azimuth=random_azimuth, start_point=hit_point) new_loc = Location4D(latitude=new_point['latitude'], longitude=new_point['longitude'], depth=start_point.depth) count += 1 # We tried 10 times and the particle was still on shore, return the point the particle started from. # No randomization. if count == 6: logger.warn( "LOOK: Could not react particle with shoreline. Assuming particle did not move from original location" ) return start_point #logger.info("Reaction time: %f" % (time.clock() - st)) return new_loc