예제 #1
0
    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)
예제 #3
0
    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
예제 #4
0
파일: transport.py 프로젝트: hetland/paegan
    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
예제 #6
0
    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
예제 #7
0
파일: shoreline.py 프로젝트: hetland/paegan
    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
예제 #8
0
    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
예제 #9
0
    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