示例#1
0
 def test_insufficient(self):
     expected_err_msg = ("Insufficient location data required "
                         "for determining single lat/lng for location")
     with raises(ValueError) as e_info:
         locationutils.LatLng({})
     assert e_info.value.args[0] == expected_err_msg
     with raises(ValueError) as e_info:
         locationutils.LatLng({'latitude': 46.0})
     assert e_info.value.args[0] == expected_err_msg
示例#2
0
    def test_invalid_location_data(self):
        with raises(ValueError) as e_info:
            locationutils.LatLng(None)
        assert e_info.value.args[0] == locationutils.INVALID_LOCATION_DATA

        with raises(ValueError) as e_info:
            locationutils.LatLng(1)
        assert e_info.value.args[0] == locationutils.INVALID_LOCATION_DATA

        with raises(ValueError) as e_info:
            locationutils.LatLng("SDFSDF")
        assert e_info.value.args[0] == locationutils.INVALID_LOCATION_DATA
示例#3
0
 def test_invalid(self):
     expected_err_msg = ("Invalid location data required for "
                         "determining single lat/lng for activity window")
     with raises(ValueError) as e_info:
         locationutils.LatLng(None)
     assert e_info.value.args[0] == expected_err_msg
     with raises(ValueError) as e_info:
         locationutils.LatLng(1)
     assert e_info.value.args[0] == expected_err_msg
     with raises(ValueError) as e_info:
         locationutils.LatLng("SDFSDF")
     assert e_info.value.args[0] == expected_err_msg
示例#4
0
    def test_active_area_with_specified_points_missing_lat_lng_info(self):
        active_area = {
            "start": "2014-05-27T17:00:00",
            "end": "2014-05-28T17:00:00",
            'specified_points': [
                {
                    'lat': 23.0,
                    'lng': "SDF"
                },  # invalid
            ]
        }
        with raises(ValueError) as e_info:
            locationutils.LatLng(active_area)
        assert e_info.value.args[
            0] == locationutils.MISSING_OR_INVALID_LAT_LNG_FOR_SPECIFIED_POINT

        active_area = {
            "start": "2014-05-27T17:00:00",
            "end": "2014-05-28T17:00:00",
            'specified_points': [
                {
                    'lng': -120.0
                },  # missing 'lat'
            ]
        }
        with raises(ValueError) as e_info:
            locationutils.LatLng(active_area)
        assert e_info.value.args[
            0] == locationutils.MISSING_OR_INVALID_LAT_LNG_FOR_SPECIFIED_POINT

        active_area = {
            "start":
            "2014-05-27T17:00:00",
            "end":
            "2014-05-28T17:00:00",
            'specified_points': [
                {
                    'area': 34,
                    'lat': 45.0,
                    'lng': -120.0
                },
                {
                    'lat': 23.0
                }  # missing 'lng'
            ]
        }
        with raises(ValueError) as e_info:
            locationutils.LatLng(active_area)
        assert e_info.value.args[
            0] == locationutils.MISSING_OR_INVALID_LAT_LNG_FOR_SPECIFIED_POINT
示例#5
0
    def _get_central_lat_lng(self):
        if len(self._input_data['fires']) > 1:
            # input data could possibly specifu multiple fires at
            # the same location, but we won't bother trying to accept that
            self._handle_error(400, ErrorMessages.SINGLE_FIRE_ONLY)

        fire = fires.Fire(self._input_data['fires'][0])

        try:
            locations = fire.locations
        except ValueError as e:
            # fire.locations includes validation of the location data
            self._handle_error(400, ErrorMessages.INVALID_FIRE_LOCATION_INFO)

        if not locations:
            self._handle_error(400, ErrorMessages.NO_ACTIVITY_INFO)

        centroids = []
        for loc in locations:
            try:
                latlng = locationutils.LatLng(loc)
                centroids.append((latlng.latitude, latlng.longitude))
            except Exception as e:
                self._handle_error(400,
                                   ErrorMessages.INVALID_FIRE_LOCATION_INFO)

        if len(centroids) > 1:
            multi_point = {
                "type": 'MultiPoint',
                "coordinates": [[e[1], e[0]] for e in centroids]
            }
            coords = get_centroid(multi_point)
            return (coords[1], coords[0])
        else:
            return centroids[0]
示例#6
0
文件: setup.py 项目: meersens/bluesky
    def write(self, start, met_files, working_dir, locations):

        with open(os.path.join(working_dir, 'CONTROL'), 'w') as f:
            f.write(start.strftime("%Y %m %d %H\n"))

            # TODO: is this correct?
            num_trajectries = len(locations) * len(self._config['heights'])
            f.write("{}\n".format(num_trajectries))

            for loc in locations:
                latlng = locationutils.LatLng(loc)
                for h in self._config['heights']:
                    f.write("{} {} {}\n".format(latlng.latitude,
                        latlng.longitude, h))

            f.write("{}\n".format(self._num_hours))
            f.write("{}\n".format(self._config['vertical_motion']))
            f.write("{}\n".format(self._config['top_of_model_domain']))
            # TODO: should the next line be configurable instead of beting
            #   set to the number of met files?  e.g.:
            #     f.write("{}\n".format(self._config['num_simultaneous_met_files']))
            f.write("{}\n".format(len(met_files)))

            for m in met_files:
                f.write("./\n")  # met grid directory
                f.write("{}\n".format(os.path.basename(m)))  # met grid file (ARL format)

            f.write("./\n")  # output directoroy
            f.write("{}\n".format(self._config['output_file_name']))
示例#7
0
    def _set_lat_lng(self, fire):
        lat_lngs = [locationutils.LatLng(l) for l in fire.locations]

        def get_min_max(vals):
            return min(vals), max(vals), sum(vals) / len(vals)

        min_lat, max_lat, avg_lat = get_min_max([ll.latitude for ll in lat_lngs])
        min_lng, max_lng, avg_lng = get_min_max([ll.longitude for ll in lat_lngs])

        def format_str(mi, ma):
            return "{} to {}".format(mi, ma) if mi != ma else mi

        self['lat_lng'] = {
            'lat': {
                'min': min_lat,
                'max': max_lat,
                'avg': avg_lat,
                'pretty_str': format_str(min_lat, max_lat),
            },
            'lng': {
                'min': min_lng,
                'max': max_lng,
                'avg': avg_lng,
                'pretty_str': format_str(min_lng, max_lng)
            }
        }
示例#8
0
    def _set_per_location_data(self, fire):
        self['active_areas'] = []
        for i, aa in enumerate(fire.active_areas):
            # set location ids

            self['active_areas'].append({
                "id": "#{} {} - {}".format(i, aa['start'], aa['end']),
                "start": aa['start'],
                "end": aa['end'],
                'locations': []
            })
            for j, loc in enumerate(aa.locations):
                lat_lng = locationutils.LatLng(loc)
                emissions = self._get_location_emissions(loc)
                timeprofiled_emissions = self._get_location_timeprofiled_emissions(
                    aa, loc, emissions)
                self['active_areas'][-1]['locations'].append({
                    "start": aa["start"],
                    "end": aa["end"],
                    "lat": lat_lng.latitude,
                    "lng": lat_lng.longitude,
                    "area": loc["area"],
                    "id": "#{}/#{} {},{}".format(
                        i, j, lat_lng.latitude, lat_lng.longitude),
                    "fuelbeds": self.fuelbeds_list_to_dict(
                        fuelbeds.summarize([self._wrap_loc_in_fire(loc)])),
                    'consumption_by_category': self._get_location_consumption(loc),
                    "emissions": emissions,
                    'timeprofiled_emissions': timeprofiled_emissions,
                    "plumerise": self._get_location_plumerise(loc)
                })
示例#9
0
    def _get_centroid(self, fires):
        points = [{
            'lng': float(f.longitude),
            'lat': float(f.latitude)
        } for f in fires]

        return locationutils.LatLng({'specified_points': points})
示例#10
0
 def test_valid_perimeter(self):
     latlng = locationutils.LatLng({
         "polygon": [[-100.0, 35.0], [-101.0, 35.0], [-101.0, 31.0],
                     [-99.0, 31.0], [-100.0, 35.0]]
     })
     assert latlng.latitude == 33
     assert latlng.longitude == -100.25
示例#11
0
 def test_no_location_info(self):
     active_area = {
         "start": "2014-05-27T17:00:00",
         "end": "2014-05-28T17:00:00"
     }
     with raises(ValueError) as e_info:
         locationutils.LatLng(active_area)
     assert e_info.value.args[0] == locationutils.MISSING_LOCATION_INFO
示例#12
0
 def test_geojson_point(self):
     latlng = locationutils.LatLng({
         "geojson": {
             "type": "Point",
             "coordinates": [-121.4522115, 47.4316976]
         }
     })
     assert latlng.latitude == 47.4316976
     assert latlng.longitude == -121.4522115
示例#13
0
 def test_active_area_with_perimeter(self):
     latlng = locationutils.LatLng({
         "perimeter": {
             "polygon": [[-100.0, 35.0], [-101.0, 35.0], [-101.0, 31.0],
                         [-99.0, 31.0], [-100.0, 35.0]]
         }
     })
     assert latlng.latitude == 33
     assert latlng.longitude == -100.25
示例#14
0
 def test_geojson_multi_point(self):
     latlng = locationutils.LatLng({
         "geojson": {
             "type": "MultiPoint",
             "coordinates": [[100.0, 4.5], [101.0, 1.0]]
         }
     })
     assert latlng.latitude == 2.75
     assert latlng.longitude == 100.5
示例#15
0
 def test_geojson_linestring(self):
     latlng = locationutils.LatLng({
         "geojson": {
             "type": "LineString",
             "coordinates": [[100.0, 2.0], [101.0, 1.0]]
         }
     })
     assert latlng.latitude == 1.5
     assert latlng.longitude == 100.5
示例#16
0
    def test_perimeter_invalid_coordinates(self):
        perimeter = {
            "polygon": [["SDF", 47.43], [-121.39, 47.43], [-121.39, 47.40],
                        [-121.45, 47.40], [-121.45, 47.43]]
        }

        with raises(ValueError) as e_info:
            locationutils.LatLng(perimeter)
        assert e_info.value.args[
            0] == locationutils.MISSING_OR_INVALID_COORDINATES_FOR_PERIMETER
示例#17
0
 def test_single_lat_lng(self):
     latlng = locationutils.LatLng({
         "utc_offset": "-07:00",
         "longitude": -119.7615805,
         "area": 10000,
         "ecoregion": "western",
         "latitude": 37.909644
     })
     assert latlng.latitude == 37.909644
     assert latlng.longitude == -119.7615805
示例#18
0
 def test_geojson_polygon_no_holes(self):
     latlng = locationutils.LatLng({
         "geojson": {
             "type":
             "Polygon",
             "coordinates": [[[100.0, 5.0], [101.0, 0.0], [101.0, 1.0],
                              [100.0, 1.0], [100.0, 5.0]]]
         }
     })
     assert latlng.latitude == 2.4
     assert latlng.longitude == 100.4
示例#19
0
 def test_geojson_multi_linestring(self):
     latlng = locationutils.LatLng({
         "geojson": {
             "type":
             "MultiLineString",
             "coordinates": [[[100.0, -3.0], [101.0, 1.0]],
                             [[102.0, 2.0], [103.0, 3.0]]]
         }
     })
     assert latlng.latitude == 0.75
     assert latlng.longitude == 101.5
示例#20
0
 def _aggregate_locations(self):
     locations_by_lat_lng = defaultdict(lambda: {"lines": []})
     for fire in self._fires_manager.fires:
         for loc in fire.locations:
             latlng = locationutils.LatLng(loc)
             new_loc = locations_by_lat_lng[(latlng.latitude,
                                             latlng.longitude)]
             # The following line only has to be done if not
             # new_loc.get('fire'), but doesn't hurt to do again
             new_loc.update(fire=fire, latlng=latlng)
             new_loc['lines'].extend(
                 loc.get('trajectories', {}).get('lines', []))
     self._distinct_locations = list(locations_by_lat_lng.values())
示例#21
0
 def test_active_area_with_perimeter_invalid_coordinates(self):
     active_area = {
         "start": "2014-05-27T17:00:00",
         "end": "2014-05-28T17:00:00",
         "perimeter": {
             "polygon": [["SDF", 47.43], [-121.39, 47.43], [-121.39, 47.40],
                         [-121.45, 47.40], [-121.45, 47.43]]
         }
     }
     with raises(ValueError) as e_info:
         locationutils.LatLng(active_area)
     assert e_info.value.args[
         0] == locationutils.MISSING_OR_INVALID_COORDINATES_FOR_PERIMETER
示例#22
0
        def _f(fire, working_dir):
            # TODO: create and change to working directory here (per fire),
            #   above (one working dir per all fires), or below (per activity
            #   window)...or just let plumerise create temp workingdir (as
            #   it's currently doing?
            for aa in fire.active_areas:
                start = aa.get('start')
                if not start:
                    raise ValueError(MISSING_START_TIME_ERROR_MSG)
                start = datetimeutils.parse_datetime(aa.get('start'), 'start')

                if not aa.get('timeprofile'):
                    raise ValueError(MISSING_TIMEPROFILE_ERROR_MSG)

                for loc in aa.locations:
                    if not loc.get('consumption', {}).get('summary'):
                        raise ValueError(MISSING_CONSUMPTION_ERROR_MSG)

                    # Fill in missing sunrise / sunset
                    if any([
                            loc.get(k) is None
                            for k in ('sunrise_hour', 'sunset_hour')
                    ]):

                        # default: UTC
                        utc_offset = datetimeutils.parse_utc_offset(
                            loc.get('utc_offset', 0.0))

                        # Use NOAA-standard sunrise/sunset calculations
                        latlng = locationutils.LatLng(loc)
                        s = sun.Sun(lat=latlng.latitude, lng=latlng.longitude)
                        d = start.date()
                        # just set them both, even if one is already set
                        loc["sunrise_hour"] = s.sunrise_hr(d, utc_offset)
                        loc["sunset_hour"] = s.sunset_hr(d, utc_offset)

                    fire_working_dir = _get_fire_working_dir(fire, working_dir)
                    plumerise_data = pr.compute(aa['timeprofile'],
                                                loc['consumption']['summary'],
                                                loc,
                                                working_dir=fire_working_dir)
                    loc['plumerise'] = plumerise_data['hours']

                    if config.get("load_heat"):
                        if 'fuelbeds' not in loc:
                            raise ValueError(
                                "Fuelbeds should exist before loading heat in plumerise"
                            )
                        loc["fuelbeds"][0]["heat"] = _loadHeat(
                            fire_working_dir)
示例#23
0
 def test_geojson_polygon_holes(self):
     latlng = locationutils.LatLng({
         "geojson": {
             "type":
             "Polygon",
             "coordinates": [[[100.0, 5.0], [101.0, 0.0], [101.0, 1.0],
                              [100.0, 1.0], [100.0, 5.0]],
                             [[100.8, 0.8], [100.8, 0.2], [100.2, 0.2],
                              [100.2, 0.8], [100.8, 0.8]]]
         }
     })
     # centroid computation only considers outer polygon boundary
     assert latlng.latitude == 2.4
     assert latlng.longitude == 100.4
示例#24
0
 def test_active_area_with_single_specified_point(self):
     latlng = locationutils.LatLng({
         "start":
         "2014-05-27T17:00:00",
         "end":
         "2014-05-28T17:00:00",
         'specified_points': [{
             'area': 34,
             'lat': 45.0,
             'lng': -120.0
         }]
     })
     assert latlng.latitude == 45.0
     assert latlng.longitude == -120.0
示例#25
0
    def _add_location(self, fire, aa, loc, activity_fields, utc_offset,
                      loc_num):
        if any([not loc.get(f) for f in activity_fields]):
            raise ValueError("Each active area must have {} in "
                             "order to compute {} dispersion".format(
                                 ','.join(activity_fields),
                                 self.__class__.__name__))
        if any([not fb.get('emissions') for fb in loc['fuelbeds']]):
            raise ValueError(
                "Missing emissions data required for computing dispersion")

        heat = self._get_heat(fire, loc)
        plumerise, timeprofile = self._get_plumerise_and_timeprofile(
            loc, utc_offset)
        emissions = self._get_emissions(loc)
        timeprofiled_emissions = self._get_timeprofiled_emissions(
            timeprofile, emissions)
        timeprofiled_area = {
            dt: e.get('area_fraction') * loc['area']
            for dt, e in timeprofile.items()
        }

        # consumption = datautils.sum_nested_data(
        #     [fb.get("consumption", {}) for fb in a['fuelbeds']], 'summary', 'total')
        consumption = loc['consumption']['summary']

        latlng = locationutils.LatLng(loc)

        f = Fire(
            id="{}-{}".format(fire.id, loc_num),
            # See note above, in _merge_two_fires, about why
            # original_fire_ids is a set instead of scalar
            original_fire_ids=set([fire.id]),
            meta=fire.get('meta', {}),
            start=aa['start'],
            end=aa['end'],
            area=loc['area'],
            latitude=latlng.latitude,
            longitude=latlng.longitude,
            utc_offset=utc_offset,
            plumerise=plumerise,
            timeprofiled_emissions=timeprofiled_emissions,
            timeprofiled_area=timeprofiled_area,
            consumption=consumption)
        if heat:
            f['heat'] = heat
        self._fires.append(f)
示例#26
0
    def _write_to_json(self):
        """Maintains bluesky's fires output structure, but including only
        trajectory data.
        """
        json_data = {"fires": []}
        for fire in self._fires_manager.fires:
            json_data["fires"].append({"id": fire.id, "locations": []})
            for loc in fire.locations:
                lines = loc.get('trajectories', {}).get('lines', [])
                latlng = locationutils.LatLng(loc)
                json_data["fires"][-1]["locations"].append({
                    "lines": lines,
                    "lat": latlng.latitude,
                    "lng": latlng.longitude
                })

        self._write_file(self._json_file_name, json_data)
示例#27
0
 def test_geojson_multi_polygon_one(self):
     latlng = locationutils.LatLng({
         "geojson": {
             "type":
             "MultiPolygon",
             "coordinates": [[[[-121.4522115, 47.4316976],
                               [-121.3990506, 47.4316976],
                               [-121.3990506, 47.4099293],
                               [-121.4522115, 47.4099293],
                               [-121.4522115, 47.4316976]]]]
         },
         "ecoregion": "southern",
         "state": "KS",
         "country": "USA",
         "slope": 20.0,
         "elevation": 2320.0,
         "max_humid": 70.0,
         "utc_offset": "-07:00"
     })
     assert latlng.latitude == 47.4316976
     assert latlng.longitude == -121.4522115
示例#28
0
 def test_geojson_multi_polygon_one(self):
     latlng = locationutils.LatLng({
         "geojson": {
             "type":
             "MultiPolygon",
             "coordinates": [[[[102.0, 2.0], [103.0, 2.0], [103.0, 3.0],
                               [102.0, 3.0], [102.0, 2.0]]],
                             [[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0],
                               [100.0, 1.0], [100.0, 0.0]],
                              [[100.2, 0.2], [100.2, 0.8], [100.8, 0.8],
                               [100.8, 0.2], [100.2, 0.2]]]]
         },
         "ecoregion": "southern",
         "state": "KS",
         "country": "USA",
         "slope": 20.0,
         "elevation": 2320.0,
         "max_humid": 70.0,
         "utc_offset": "-07:00"
     })
     assert latlng.latitude == 1.4
     assert latlng.longitude == 101.4
示例#29
0
 def test_active_area_with_specified_points_and_perimeter(self):
     latlng = locationutils.LatLng({
         "start":
         "2014-05-27T17:00:00",
         "end":
         "2014-05-28T17:00:00",
         'specified_points': [{
             'area': 34,
             'lat': 45.0,
             'lng': -120.0
         }, {
             'area': 20,
             'lat': 35.0,
             'lng': -121.0
         }],
         "perimeter": {
             "polygon": [[-100.0, 35.0], [-101.0, 35.0], [-101.0, 31.0],
                         [-99.0, 31.0], [-100.0, 35.0]]
         }
     })
     assert latlng.latitude == 40.0
     assert latlng.longitude == -120.5
示例#30
0
    def _write_to_geojson(self):
        """Flattens trajectory data into a FeatureCollection of trajectory
        line Features (one Feature per line)

        TODO: group by fire, and then by location, and then by start hour,
        if possible.
        """
        geojson_data = {
            "type": "FeatureCollection",
            "features": []
        }
        for fire in self._fires_manager.fires:
            for loc in fire.locations:
                latlng = locationutils.LatLng(loc)
                geojson_data['features'].append(
                    self._get_location_feature(fire, loc, latlng))
                lines = loc.get('trajectories', {}).get('lines', [])
                for line in lines:
                    geojson_data['features'].append(
                        self._get_line_feature(fire, latlng, line))

        self._write_file(self._geojson_file_name, geojson_data)