示例#1
0
def _get_dispersion_time_window(fires_manager):
    start = Config.get('dispersion', 'start')
    num_hours = Config.get('dispersion', 'num_hours')
    if start and num_hours:
        return {
            'start': start,
            'end': start + datetime.timedelta(hours=num_hours)
        }
示例#2
0
    def __init__(self, dest_dir, **kwargs):
        fl = (kwargs.get('fire_locations_filename') or Config.get(
            'extrafiles', 'firescsvs', 'fire_locations_filename'))
        self._fire_locations_pathname = os.path.join(dest_dir, fl)

        fe = (kwargs.get('fire_events_filename')
              or Config.get('extrafiles', 'firescsvs', 'fire_events_filename'))
        self._fire_events_pathname = os.path.join(dest_dir, fe)
示例#3
0
 def log_status(self, status, step, action, **extra_fields):
     if not getattr(self, '_status_logger'):
         # init_time will be converted to string if it's datetime.date[time]
         init_time = (Config.get('dispersion', 'start', allow_missing=True)
                      or self.today)
         sl_config = Config.get('statuslogging')
         setattr(self, '_status_logger',
                 StatusLogger(init_time, **sl_config))
     self._status_logger.log(status, step, action, **extra_fields)
示例#4
0
    def __init__(self, fire_failure_handler):
        super(Consume, self).__init__(fire_failure_handler)

        self.species = self.species and [e.upper() for e in self.species]

        all_fuel_loadings = (Config.get('emissions','fuel_loadings')
            or Config.get('consumption','fuel_loadings'))
        self.fuel_loadings_manager = FuelLoadingsManager(
            all_fuel_loadings=all_fuel_loadings)
示例#5
0
def _get_met_finder(fires_manager):
    met_root_dir = _get_met_root_dir(fires_manager)
    met_format = Config.get('findmetdata', 'met_format').lower()
    if met_format == "arl":
        arl_config = Config.get('findmetdata', 'arl')
        logging.debug("ARL config: %s", arl_config)
        return arlfinder.ArlFinder(met_root_dir, **arl_config)
    else:
        raise BlueSkyConfigurationError(
            "Invalid or unsupported met data format: '{}'".format(met_format))
示例#6
0
def _get_dirs(fires_manager):
    handle_existing = Config.get('dispersion', 'handle_existing')

    output_dir = Config.get('dispersion', 'output_dir')
    if not output_dir:
        raise ValueError("Specify dispersion output directory")
    create_dir_or_handle_existing(output_dir, handle_existing)

    working_dir = Config.get('dispersion', 'working_dir')
    if working_dir:
        create_dir_or_handle_existing(working_dir, handle_existing)

    return output_dir, working_dir
示例#7
0
def _get_accepted_forecasts_config():
    accepted_forecasts_config = Config().get('findmetdata',
                                             'accepted_forecasts')
    if accepted_forecasts_config:
        for k in ('init_times', 'met_file_name_pattern'):
            if not accepted_forecasts_config.get(k):
                raise BlueSkyConfigurationError(
                    "Config 'findmetdata' > "
                    "'accepted_forecasts' settings must define '{}'".format(k))

        accepted_forecasts_config['init_times'] = sorted([
            to_datetime(i, extra_formats=["%Y%m%d%H"])
            for i in accepted_forecasts_config.get('init_times', [])
        ])
    return accepted_forecasts_config
示例#8
0
    def __init__(self, lookup):
        self.lookup = lookup

        # Is this necessary?
        for attr, val in Config.get('fuelbeds').items():
            if attr.startswith('truncation_'):
                setattr(self, attr.replace('truncation_', ''), val)
示例#9
0
def get_working_and_output_dirs(module_name, require_output_dir=True):
    config = Config().get(module_name)

    handle_existing = config.get('handle_existing')

    output_dir = config.get('output_dir')
    if not output_dir and require_output_dir:
        raise ValueError("Specify {} output directory".format(module_name))
    if output_dir:
        create_dir_or_handle_existing(output_dir, handle_existing)

    working_dir = config.get('working_dir')
    if working_dir:
        create_dir_or_handle_existing(working_dir, handle_existing)

    return output_dir, working_dir
示例#10
0
def run(fires_manager):
    """runs the findmetdata module

    Args:
     - fires_manager -- bluesky.models.fires.FiresManager object
    """
    logging.info("Running findmetdata module")
    fires_manager.processed(__name__, __version__)

    # TODO: For playground, there will be only one file containing data for
    # any particular hour.  Allow config to specify using simplified logic
    # for this scenario.  Otherwise, use more complicated logic in
    # arlfinder.ArlFinder (or put both code paths in ArlFinder?)

    met_finder = _get_met_finder(fires_manager)
    time_windows = _get_time_windows(fires_manager)

    wait_config = Config.get('findmetdata', 'wait')

    @io.wait_for_availability(wait_config)
    def _find():
        files = []
        for time_window in time_windows:
            logging.debug("Findmetdata time window: %s to %s",
                          time_window['start'], time_window['end'])
            files.extend(
                met_finder.find(time_window['start'],
                                time_window['end']).get('files', []))

        if not files:
            raise BlueSkyUnavailableResourceError("No met files found")

        return files

    fires_manager.met = {"files": _find()}
示例#11
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)
示例#12
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)
示例#13
0
    def __init__(self, fires_manager):
        """Constructor

        args:
         - fires_manager -- FiresManager object whose fires are to be merged
        """
        self._fires_manager = fires_manager
        self._skip_failures = not not Config.get(self.ACTION, 'skip_failures')
示例#14
0
def run(fires_manager):
    """Runs emissions module

    Args:
     - fires_manager -- bluesky.models.fires.FiresManager object
    """
    logging.info("Running fuelbeds module")
    fires_manager.processed(__name__,
                            __version__,
                            fccsmap_version=fccsmap.__version__)

    logging.debug('Using FCCS version %s',
                  Config.get('fuelbeds', 'fccs_version'))

    for fire in fires_manager.fires:
        with fires_manager.fire_failure_handler(fire):
            if not fire.get('activity'):
                raise ValueError(
                    "Activity information required to look up fuelbeds")

            for a in fire['activity']:
                if not a.get('location'):
                    raise ValueError(
                        "activity location information required to look up fuelbeds"
                    )
                # TODO: instead of instantiating a new FccsLookUp and Estimator
                #   for each activity object, create AK and non-AK lookup and
                #   estimator objects that are reused, and set reference to
                #   correct one here
                # TODO: is_alaska from lat,lng, not from 'state'
                lookup = FccsLookUp(
                    is_alaska=a['location'].get('state') == 'AK',
                    **Config.get('fuelbeds'))
                Estimator(lookup).estimate(a)

    # TODO: Add fuel loadings data to each fuelbed object (????)
    #  If we do so here, use bluesky.modules.consumption.FuelLoadingsManager
    #  (which should maybe be moved to a common module if to be used here)
    #     fm = FuelLoadingsManager()
    #     for fire in fires_manager.fires:
    #       for fb in get_fuel_loadings():
    #         fb['fuel_loadings'] = fm.get_fuel_loadings(fb['fccs_id'])
    #  Note: probably no need to do this here since we do it in the
    #  consumption module

    fires_manager.summarize(fuelbeds=summarize(fires_manager.fires))
示例#15
0
def get_dispersion_model(fires_manager):
    if fires_manager.dispersion and fires_manager.dispersion.get('model'):
        return fires_manager.dispersion['model']
    model = Config.get('dispersion', 'model')
    if model:
        return model.lower()

    raise ValueError(
        "Dispersion model must be specified if visualizing dispersion")
示例#16
0
def _get_dest_dir(fires_manager):
    dest_dir = Config.get('extrafiles', 'dest_dir')
    if not dest_dir:
        raise BlueSkyConfigurationError("Specify extrafiles destination dir "
            "('config' > 'extrafiles' > 'dest_dir')")

    dest_dir = os.path.abspath(dest_dir)
    if not os.path.exists(dest_dir):
        os.makedirs(dest_dir)

    return dest_dir
示例#17
0
    def __init__(self, fires_manager):
        model = Config.get('plumerising', 'model').lower()
        fires_manager.processed(__name__, __version__,
            plumerise_version=plumerise_version, model=model)

        logging.debug('Generating %s plumerise compution function', model)
        generator = getattr(self, '_{}'.format(model), None)
        if not generator:
            raise BlueSkyConfigurationError(
                "Invalid plumerise model: '{}'".format(model))

        config = Config.get('plumerising', model)
        self._compute_func = generator(config)

        if config.get('working_dir'):
            fires_manager.plumerising = {
                'output': {
                    'directory': config['working_dir']
                }
            }
示例#18
0
def _get_time(fires_manager):
    start = Config.get('dispersion', 'start')
    num_hours = Config.get('dispersion', 'num_hours')

    if not start or num_hours is None:
        s = fires_manager.earliest_start  # needed for 'start' and 'num_hours'
        if not s:
            raise ValueError("Unable to determine dispersion 'start'")
        if not start:
            start = s

        if not num_hours and start == s:
            e = fires_manager.latest_end  # needed only for num_hours
            if e and e > s:
                num_hours = int((e - s).total_seconds() / SECONDS_PER_HOUR)
        if not num_hours:
            raise ValueError("Unable to determine dispersion 'num_hours'")

    logging.debug("Dispersion window: %s for %s hours", start, num_hours)
    return start, num_hours
示例#19
0
def _use_default_ecoregion(fires_manager, a, exc=None):
    default_ecoregion = Config.get('consumption', 'default_ecoregion')
    if default_ecoregion:
        logging.debug('Using default ecoregion %s', default_ecoregion)
        a['location']['ecoregion'] = default_ecoregion
    else:
        logging.debug('No default ecoregion')
        if exc:
            raise exc
        else:
            raise ValueError("No default ecoregion specified.")
示例#20
0
def _get_met_root_dir(fires_manager):
    # Note: ArlFinder will raise an exception if met_root_dir is undefined
    # or is not a valid directory
    # TODO: specify domain instead of met_root_dir, and somehow configure (not
    # in the code, since this is open source), per domain, the root dir, arl file
    # name pattern, etc.
    met_root_dir = Config.get('findmetdata', 'met_root_dir')
    if not met_root_dir:
        raise BlueSkyConfigurationError("Config setting 'met_root_dir' "
                                        "required by findmetdata module")
    logging.debug("Met root dir: %s", met_root_dir)
    return met_root_dir
示例#21
0
 def _ingest_activity_heat(self, activity, src):
     if Config.get('ingestion', 'keep_heat'):
         logging.debug("Ingesting heat")
         # TODO: look for value in src['heat|HEAT']['summary']['total'] first
         heat = self._get_numeric_val(src, "heat", "HEAT")
         if heat is not None:
             logging.debug("Recording heat in activity object")
             activity["heat"] = {
                 "summary": {
                     "total": heat
                 }
             }
示例#22
0
    def __init__(self, dest_dir, **kwargs):
        ptinv = (kwargs.get('ptinv_filename')
                 or Config.get('extrafiles', 'smokeready', 'ptinv_filename'))
        self._ptinv_pathname = os.path.join(dest_dir, ptinv)

        ptday = (kwargs.get('ptday_filename')
                 or Config.get('extrafiles', 'smokeready', 'ptday_filename'))
        self._ptday_pathname = os.path.join(dest_dir, ptday)

        pthour = (kwargs.get('pthour_filename')
                  or Config.get('extrafiles', 'smokeready', 'pthour_filename'))
        self._pthour_pathname = os.path.join(dest_dir, pthour)

        separate_smolder = (kwargs.get('separate_smolder') or Config.get(
            'extrafiles', 'smokeready', 'separate_smolder'))
        self._separate_smolder = separate_smolder

        write_ptinv_totals = (kwargs.get('write_ptinv_totals') or Config.get(
            'extrafiles', 'smokeready', 'write_ptinv_totals'))
        self._write_ptinv_totals = write_ptinv_totals

        write_ptday_file = (kwargs.get('write_ptday_file') or Config.get(
            'extrafiles', 'smokeready', 'write_ptday_file'))
        self._write_ptday_file = write_ptday_file

        # Pull the file year out of the dynamically set timestamp
        self.file_year = int(pthour.split('-')[1][:4])
示例#23
0
def run(fires_manager):
    """runs the export module

    Args:
     - fires_manager -- bluesky.models.fires.FiresManager object
    """
    modes = [m.lower() for m in Config.get('export', 'modes')]
    fires_manager.processed(__name__, __version__, modes=modes)

    extra_exports = Config.get('export', 'extra_exports')

    exporters = []
    for mode in modes:
        exporter_klass = EXPORTERS.get(mode)
        if not exporter_klass:
            raise BlueSkyConfigurationError(
                "Invalid exporter - {}".format(exporter_klass))

        exporters.append(exporter_klass(extra_exports))

    # Note: export modules update fires_manager with export info, since that
    # info needs to be in the fires_manager before it's dumped to json
    for exporter in exporters:
        exporter.export(fires_manager)
示例#24
0
    def __init__(self, fires_manager):
        """Constructor

        args:
         - fires_manager -- FiresManager object whose fires are to be merged
        """
        super(FireActivityFilter, self).__init__(fires_manager)
        self._filter_config = Config.get('filter')
        self._filter_fields = set(self._filter_config.keys()) - set(
            ['skip_failures'])
        if not self._filter_fields:
            if not self._skip_failures:
                raise self.FilterError(self.NO_FILTERS_MSG)
            # else, just log and return
            logging.warning(self.NO_FILTERS_MSG)
示例#25
0
def run(fires_manager):
    """Split each of the fire's activity windows to be able to process points
    separately.

    Args:
     - fires_manager -- bluesky.models.fires.FiresManager object
    """
    logging.info("Running merge module")
    fires_manager.processed(__name__, __version__)
    record_original_activity = Config.get(
        'splitactivity', 'record_original_activity')

    for fire in fires_manager.fires:
        with fires_manager.fire_failure_handler(fire):
            _split(fire, record_original_activity)
示例#26
0
    def _ingest_activity_emissions(self, activity, src):
        if Config.get('ingestion', 'keep_emissions'):
            logging.debug("Ingesting emissions")
            emissions = {"summary": {}}
            for e in self.EMISSIONS_SPECIES:
                keys = [e] if hasattr(e, "lower") else e
                keys = [i for j in [(e, e.lower()) for e in keys] for i in j]
                # TODO: look for value in src['emissions']['summary'][k],
                #  for any k in keys, first
                v = self._get_numeric_val(src, *keys)
                if v is not None:
                    emissions["summary"][keys[0]] = v

            if emissions["summary"]:
                logging.debug("Recording emissions in activity object")
                activity["emissions"] = emissions
示例#27
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
示例#28
0
def _validate_input(fires_manager):
    ecoregion_lookup = None  # instantiate only if necessary
    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 computing consumption")
            for a in fire.activity:
                for k in ('fuelbeds', 'location'):
                    if not a.get(k):
                        raise ValueError("Missing activity '{}' data required "
                                         "for computing consumption".format(k))
                # only 'area' is required from location
                if not a['location'].get('area'):
                    raise ValueError("Fire activity location data must "
                                     "define area for computing consumption")
                if not a['location'].get('ecoregion'):
                    # import EcoregionLookup here so that, if fires do have
                    # ecoregion defined, consumption can be run without mapscript
                    # and other dependencies installed
                    try:
                        latlng = LatLng(a['location'])
                        if not ecoregion_lookup:
                            from bluesky.ecoregion.lookup import EcoregionLookup
                            implemenation = Config.get(
                                'consumption',
                                'ecoregion_lookup_implemenation')
                            ecoregion_lookup = EcoregionLookup(implemenation)
                        a['location']['ecoregion'] = ecoregion_lookup.lookup(
                            latlng.latitude, latlng.longitude)
                        if not a['location']['ecoregion']:
                            logging.warning("Failed to look up ecoregion for "
                                            "{}, {}".format(
                                                latlng.latitude,
                                                latlng.longitude))
                            _use_default_ecoregion(fires_manager, a)

                    except exceptions.MissingDependencyError as e:
                        _use_default_ecoregion(fires_manager, a, e)

                for fb in a['fuelbeds']:
                    if not fb.get('fccs_id') or not fb.get('pct'):
                        raise ValueError(
                            "Each fuelbed must define 'fccs_id' and 'pct'")
示例#29
0
def get_targets():
    vis_config = Config().get('visualization')
    targets = vis_config['targets']

    # 'visualization' > 'target' supported for backwards compatibility
    if vis_config.get('target'):
        # this will only be hit if it's an older config specifying
        # 'visualization' > 'target'
        targets = [vis_config['target']]

    targets = [t.lower() for t in targets]
    logging.info("Visualizatin targets '%s'", "', '".join(targets))

    invalid = [t for t in targets if t not in vis_config]
    if invalid:
        raise ValueError("Invalid visualization target(s): '{}'".format(
            "','".join(invalid)))

    return targets
示例#30
0
    def dump(self):
        # Don't include 'modules' in the output. The modules to be run may have
        # been specified on the command line or in the input json. Either way,
        # 'processing' contains a record of what modules were run (though it may
        # be fewer modules than what were requested, which would be the case
        # if there was a failure).  We don't want to include 'modules' in the
        # output because that breaks the ability to pipe the results into
        # another run of bsp.
        # TODO: keep track of whether modules were specified in the input
        # json or on the command line, and add them to the output if they
        # were in the input

        return dict(self._meta,
                    fires=self.fires,
                    today=self.today,
                    run_id=self.run_id,
                    counts=self.counts,
                    bluesky_version=__version__,
                    run_config=Config.get())