Example #1
0
def _run_fire(hourly_fractions, fire):
    if (hourly_fractions and len(fire.activity) > 1
            and set([len(e)
                     for p, e in hourly_fractions.items()]) != set([24])):
        # TODO: Support this scenario, but make sure
        # len(hourly_fractions) equals the total number of hours
        # represented by all activity objects, and pass the appropriate
        # slice into each instantiation of StaticTimeProfiler
        # (or build this into StaticProfiler???)
        raise BlueSkyConfigurationError(
            "Only 24-hour repeatable time "
            "profiles supported for fires with multiple activity windows")

    _validate_fire(fire)
    for a in fire.activity:
        tw = parse_datetimes(a, 'start', 'end')
        profiler = StaticTimeProfiler(tw['start'],
                                      tw['end'],
                                      hourly_fractions=hourly_fractions)
        # convert timeprofile to dict with dt keys
        a['timeprofile'] = {}
        fields = list(profiler.hourly_fractions.keys())
        for i in range(len(list(profiler.hourly_fractions.values())
                           [0])):  # each phase should have same len
            hr = profiler.start_hour + (i * profiler.ONE_HOUR)
            a['timeprofile'][hr.isoformat()] = {
                p: profiler.hourly_fractions[p][i]
                for p in fields
            }
Example #2
0
def run(fires_manager):
    """Runs plumerise module

    Args:
     - fires_manager -- bluesky.models.fires.FiresManager object
    """
    fires_manager.processed(__name__, __version__)
    if not fires_manager.met:
        raise ValueError(NO_MET_ERROR_MSG)

    arl_profiler = arlprofiler.ArlProfiler(fires_manager.met.get('files'),
                                           time_step=Config().get(
                                               'localmet', 'time_step'))
    logging.debug("Extracting localmet data for %d fires",
                  len(fires_manager.fires))
    for fire in fires_manager.fires:
        with fires_manager.fire_failure_handler(fire):
            # Make sure fire has at least some locations, but
            # iterate first through activice areas and then through
            # locations in order to get utc_offset and time windows
            if not fire.locations:
                raise ValueError(NO_ACTIVITY_ERROR_MSG)

            for aa in fire.active_areas:
                utc_offset = parse_utc_offset(aa.get('utc_offset'))
                tw = parse_datetimes(aa, 'start', 'end')
                for loc in aa.locations:
                    latlng = LatLng(loc)
                    # parse_utc_offset makes sure utc offset is defined and valid
                    loc['localmet'] = arl_profiler.profile(
                        latlng.latitude, latlng.longitude, tw['start'],
                        tw['end'], utc_offset)
Example #3
0
def _infer_time_windows_from_fires(fires_manager):
    time_windows = []

    if fires_manager.fires:
        logging.debug("Met time window determined from fire activity data")
        # Find earliest and latest datetimes that include all fire activity periods
        # TODO: be more intelligent with possible gaps, so that met files for times
        #  when no fire is growing are excluded ?
        for fire in fires_manager.fires:
            with fires_manager.fire_failure_handler(fire):
                if 'activity' in fire:
                    # parse_utc_offset makes sure utc offset is defined and valid
                    for a in fire.activity:
                        utc_offset = parse_utc_offset(
                            a.get('location', {}).get('utc_offset'))
                        offset = datetime.timedelta(hours=utc_offset)
                        tw = parse_datetimes(a, 'start', 'end')
                        if tw['start'] > tw['end']:
                            raise ValueError(
                                "Invalid activity time window - start: {}, end: {}"
                                .format(tw['start'], tw['end']))
                        start = tw['start'] - offset
                        end = tw['end'] - offset
                        time_windows.append({'start': start, 'end': end})

    return time_windows
Example #4
0
def _infer_time_windows_from_fires(fires_manager):
    time_windows = []

    if fires_manager.fires:
        logging.debug("Met time window determined from fire activity data")
        # Find earliest and latest datetimes that include all fire activity periods
        # TODO: be more intelligent with possible gaps, so that met files for times
        #  when no fire is growing are excluded ?
        for fire in fires_manager.fires:
            with fires_manager.fire_failure_handler(fire):
                for aa in fire.active_areas:
                    # TODO: Because of the following:
                    #   a) start, end, & utc_offset are allowed to be set
                    #      per specified point or perimeter rather than per
                    #      active area, and
                    #   b) accessing [perim|sp].[start|end|utc_offset] will fallback
                    #      on aa's values if not defined in the sp,perim,
                    #  then maybe we should iterate through the aa's locations (sp,perim)
                    #  and execute the following logic on each location. We'd need to
                    #  make sure that time window merging and other downstream logic
                    #  aren't broken or negatively affected.
                    utc_offset = parse_utc_offset(aa.get('utc_offset'))
                    offset = datetime.timedelta(hours=utc_offset)
                    tw = parse_datetimes(aa, 'start', 'end')
                    if tw['start'] > tw['end']:
                        raise ValueError(
                            "Invalid activity time window - start: {}, end: {}"
                            .format(tw['start'], tw['end']))
                    start = tw['start'] - offset
                    end = tw['end'] - offset
                    time_windows.append({'start': start, 'end': end})

    return time_windows
Example #5
0
def _get_profiler(hourly_fractions, fire, active_area):
    tw = parse_datetimes(active_area, 'start', 'end')

    # Use FepsTimeProfiler for Rx fires and StaticTimeProfiler for WF,
    # Unless custom hourly_fractions are specified, in which case
    # Static Time Profiler is used for all fires.
    # If ignition_start and ignition_end aren't specified for Rx fires,
    # FepsTimeProfiler will assume 9am-12pm
    # TODO: add config setting to use FEPS for Rx even if custom
    #   hourly_fractions are specified (or the converse - i.e. alwys use
    #   FEPS for rx and add setting to turn on use of hourly_fractions,
    #   if specified, for Rx)
    if fire.type == 'rx' and not hourly_fractions:
        ig_start = active_area.get('ignition_start') and parse_datetime(
            active_area['ignition_start'], k='ignition_start')
        ig_end = active_area.get('ignition_end') and parse_datetime(
            active_area['ignition_end'], k='ignition_end')
        # TODO: pass in duff_fuel_load, total_above_ground_consumption,
        #    total_below_ground_consumption, moisture_category,
        #    relative_humidity, wind_speed, and duff_moisture_content,
        #    if defined?
        return FepsTimeProfiler(tw['start'],
                                tw['end'],
                                local_ignition_start_time=ig_start,
                                local_ignition_end_time=ig_end,
                                fire_type=FireType.RX)

    else:
        return StaticTimeProfiler(tw['start'],
                                  tw['end'],
                                  hourly_fractions=hourly_fractions)
Example #6
0
def run(fires_manager):
    """Runs plumerise module

    Args:
     - fires_manager -- bluesky.models.fires.FiresManager object
    """
    logging.info("Running localmet module")
    fires_manager.processed(__name__, __version__)
    if not fires_manager.met:
        raise ValueError("Specify met files to use in localmet")

    arl_profiler = ArlProfiler(fires_manager.met.get('files'),
                               time_step=Config.get('localmet', 'time_step'))
    logging.debug("Extracting localmet data for %d fires",
                  len(fires_manager.fires))
    for fire in fires_manager.fires:
        with fires_manager.fire_failure_handler(fire):
            if not fire.get('activity'):
                raise ValueError("Missing activity data required for localmet")
            for a in fire['activity']:
                latlng = LatLng(a.get('location'))
                # parse_utc_offset makes sure utc offset is defined and valid
                utc_offset = parse_utc_offset(
                    a.get('location', {}).get('utc_offset'))
                tw = parse_datetimes(a, 'start', 'end')
                a['localmet'] = arl_profiler.profile(latlng.latitude,
                                                     latlng.longitude,
                                                     tw['start'], tw['end'],
                                                     utc_offset)
Example #7
0
def _get_configured_time_windows(fires_manager):
    time_window = Config.get('findmetdata', 'time_window')
    if time_window:
        logging.debug("Met time window specified in the config")
        time_window = parse_datetimes(time_window, 'first_hour', 'last_hour')
        # met data finder doesn't require round hours, but ....
        if (not is_round_hour(time_window['first_hour'])
                or not is_round_hour(time_window['last_hour'])):
            raise BlueSkyConfigurationError(
                "Met first and last hours must be round hours")
        time_window = {
            'start': time_window['first_hour'],
            'end':
            time_window['last_hour']  # TODO: round this up to the next hour?
        }
        return time_window
Example #8
0
def _get_profiler(hourly_fractions, fire, active_area):
    tw = parse_datetimes(active_area, 'start', 'end')

    # Use FepsTimeProfiler for Rx fires and StaticTimeProfiler for WF,
    # Unless custom hourly_fractions are specified, in which case
    # Static Time Profiler is used for all fires.
    # If ignition_start and ignition_end aren't specified for Rx fires,
    # FepsTimeProfiler will assume 9am-12pm
    # TODO: add config setting to use FEPS for Rx even if custom
    #   hourly_fractions are specified (or the converse - i.e. alwys use
    #   FEPS for rx and add setting to turn on use of hourly_fractions,
    #   if specified, for Rx)
    if fire.type == 'rx' and not hourly_fractions:
        ig_start = active_area.get('ignition_start') and parse_datetime(
            active_area['ignition_start'], k='ignition_start')
        ig_end = active_area.get('ignition_end') and parse_datetime(
            active_area['ignition_end'], k='ignition_end')
        # TODO: pass in duff_fuel_load, total_above_ground_consumption,
        #    total_below_ground_consumption, moisture_category,
        #    relative_humidity, wind_speed, and duff_moisture_content,
        #    if defined?
        return FepsTimeProfiler(tw['start'],
                                tw['end'],
                                local_ignition_start_time=ig_start,
                                local_ignition_end_time=ig_end,
                                fire_type=FireType.RX)

    else:
        model_name = Config().get("timeprofile", "model").lower()
        if model_name == "ubc-bsf-feps":
            wfrtConfig = Config().get('timeprofile', 'ubc-bsf-feps')
            working_dir = wfrtConfig.get('working_dir')
            delete_if_no_error = wfrtConfig.get(
                'delete_working_dir_if_no_error')
            with osutils.create_working_dir(
                    working_dir=working_dir,
                    delete_if_no_error=delete_if_no_error) as wdir:
                fire_working_dir = os.path.join(
                    wdir, "feps-timeprofile-{}".format(fire.id))
                if not os.path.exists(fire_working_dir):
                    os.makedirs(fire_working_dir)
                return ubcbsffeps.UbcBsfFEPSTimeProfiler(
                    active_area, fire_working_dir, wfrtConfig)
        else:
            return StaticTimeProfiler(tw['start'],
                                      tw['end'],
                                      hourly_fractions=hourly_fractions)
Example #9
0
def run(fires_manager):
    """Runs plumerise module

    Args:
     - fires_manager -- bluesky.models.fires.FiresManager object
    """
    fires_manager.processed(__name__, __version__)
    if not fires_manager.met:
        raise ValueError(NO_MET_ERROR_MSG)

    start_utc = None
    end_utc = None

    # keep array of references to locations passed into arlprofiler,
    # to update with local met data after bulk profiler is called
    locations = []
    # actual array of locations to pass into arlprofiler
    profiler_locations = []
    for fire in fires_manager.fires:
        with fires_manager.fire_failure_handler(fire):
            # Make sure fire has at least some locations, but
            # iterate first through activice areas and then through
            # locations in order to get utc_offset and time windows
            if not fire.locations:
                raise ValueError(NO_ACTIVITY_ERROR_MSG)

            for aa in fire.active_areas:
                # parse_utc_offset makes sure utc offset is defined and valid
                utc_offset = parse_utc_offset(aa.get('utc_offset'))
                tw = parse_datetimes(aa, 'start', 'end')

                # subtract utc_offset, since we want to get back to utc
                loc_start_utc = tw['start'] - datetime.timedelta(
                    hours=utc_offset)
                start_utc = min(start_utc,
                                loc_start_utc) if start_utc else loc_start_utc

                loc_end_utc = tw['end'] - datetime.timedelta(hours=utc_offset)
                end_utc = min(end_utc, loc_end_utc) if end_utc else loc_end_utc

                for loc in aa.locations:
                    latlng = LatLng(loc)
                    p_loc = {
                        'latitude': latlng.latitude,
                        'longitude': latlng.longitude
                    }

                    locations.append(loc)
                    profiler_locations.append(p_loc)

    if len(locations) != len(profiler_locations):
        raise RuntimeError(FAILED_TO_COMPILE_INPUT_ERROR_MSG)

    if not start_utc or not end_utc:
        raise RuntimeError(NO_START_OR_END_ERROR_MSG)

    arl_profiler = arlprofiler.ArlProfiler(fires_manager.met.get('files'),
                                           time_step=Config().get(
                                               'localmet', 'time_step'))
    logging.debug("Extracting localmet data for %d locations",
                  len(profiler_locations))

    localmet = arl_profiler.profile(start_utc, end_utc, profiler_locations)

    if len(localmet) != len(locations):
        raise RuntimeError(PROFILER_RUN_ERROR_MSG)

    for i in range(len(localmet)):
        locations[i]['localmet'] = localmet[i]