Beispiel #1
0
    def handle(self, *args, **options):
        vals = FireDepartment.objects.filter(dist_model_score__isnull=True)

        dists = []

        with PostgresBackend(dict(host='localhost')) as backend:
            for fd in vals:
                results = backend.get_firespread_counts(query=RESIDENTIAL_FIRES_BY_FDID_STATE, query_params=(fd.fdid, fd.state))
                ahs_building_size = ahs_building_areas(fd.fdid, fd.state)

                if ahs_building_size is not None:
                    results.update(dict(building_area_draw=ahs_building_size))
                dist = DIST(floor_extent=False, **results)

                try:
                    fd.dist_model_score = dist.gibbs_sample()
                except ZeroDivisionError:
                    continue

                #print 'Updating {0} with the new DIST score: {1}.'.format(fd.name, fd.dist_model_score)

                if not options.get('dry_run'):
                    fd.save()

                dists.append((fd.id, fd.dist_model_score))

        print 'Updated dist scores: ', dists
Beispiel #2
0
def update_performance_score(id, dry_run=False):
    """
    Updates department performance scores.
    """

    try:
        cursor = connections['nfirs'].cursor()
        fd = FireDepartment.objects.get(id=id)
    except (ConnectionDoesNotExist, FireDepartment.DoesNotExist):
        return

    cursor.execute(RESIDENTIAL_FIRES_BY_FDID_STATE, (fd.fdid, fd.state))
    results = dictfetchall(cursor)
    old_score = fd.dist_model_score
    counts = dict(object_of_origin=0, room_of_origin=0, floor_of_origin=0, building_of_origin=0, beyond=0)

    for result in results:
        if result['fire_sprd'] == '1':
            counts['object_of_origin'] += result['count']

        if result['fire_sprd'] == '2':
            counts['room_of_origin'] += result['count']

        if result['fire_sprd'] == '3':
            counts['floor_of_origin'] += result['count']

        if result['fire_sprd'] == '4':
            counts['building_of_origin'] += result['count']

        if result['fire_sprd'] == '5':
            counts['beyond'] += result['count']

    ahs_building_size = ahs_building_areas(fd.fdid, fd.state)

    if ahs_building_size is not None:
        counts['building_area_draw'] = ahs_building_size

    response_times = response_time_distributions.get('{0}-{1}'.format(fd.fdid, fd.state))

    if response_times:
        counts['arrival_time_draw'] = LogNormalDraw(*response_times, multiplier=60)

    try:
        dist = DIST(floor_extent=False, **counts)
        fd.dist_model_score = dist.gibbs_sample()

    except (NotEnoughRecords, ZeroDivisionError):
        fd.dist_model_score = None

    print 'updating fdid: {2} from: {0} to {1}.'.format(old_score, fd.dist_model_score, fd.id)

    if dry_run:
        return

    fd.save()
Beispiel #3
0
def update_performance_score(id, dry_run=False):
    """
    Updates department performance scores.
    """

    print "updating performance score for {}".format(id)

    try:
        cursor = connections['nfirs'].cursor()
        fd = FireDepartment.objects.get(id=id)
    except (ConnectionDoesNotExist, FireDepartment.DoesNotExist):
        return

    # Hack to get around inline SQL string execution and argument escaping in a tuple
    fds = ["''{}''".format(x) for x in fd.fdids]

    RESIDENTIAL_FIRES_BY_FDID_STATE = """
    SELECT *
    FROM crosstab(
      'select COALESCE(y.risk_category, ''N/A'') as risk_category, fire_sprd, count(*)
        FROM joint_buildingfires a left join (
          SELECT state,
            fdid,
            inc_date,
            inc_no,
            exp_no,
            geom,
            x.parcel_id,
            x.risk_category
          FROM (select * from joint_incidentaddress a
             left join parcel_risk_category_local b using (parcel_id)
             ) AS x
        ) AS y using (state, inc_date, exp_no, fdid, inc_no)
    where a.state='%(state)s' and a.fdid in ({fds}) and prop_use in (''419'',''429'',''439'',''449'',''459'',''460'',''462'',''464'',''400'')
        and fire_sprd is not null and fire_sprd != ''''
    group by risk_category, fire_sprd
    order by risk_category, fire_sprd ASC')
    AS ct(risk_category text, "object_of_origin" bigint, "room_of_origin" bigint, "floor_of_origin" bigint, "building_of_origin" bigint, "beyond" bigint);
    """.format(fds=','.join(fds))

    cursor.execute(RESIDENTIAL_FIRES_BY_FDID_STATE, {'state': fd.state})

    results = dictfetchall(cursor)

    all_counts = dict(object_of_origin=0,
                      room_of_origin=0,
                      floor_of_origin=0,
                      building_of_origin=0,
                      beyond=0)

    risk_mapping = {'Low': 1, 'Medium': 2, 'High': 4, 'N/A': 5}

    ahs_building_size = ahs_building_areas(fd.fdid, fd.state)

    for result in results:

        if result.get('risk_category') not in risk_mapping:
            continue

        dist_model = dist_model_for_hazard_level(result.get('risk_category'))

        # Use floor draws based on the LogNormal of the structure type distribution for med/high risk categories
        # TODO: Detect support for number_of_floors_draw on risk model vs being explicit on hazard levels used :/
        if result.get('risk_category') in ['Medium', 'High']:
            rm, _ = fd.firedepartmentriskmodels_set.get_or_create(
                level=risk_mapping[result['risk_category']])
            if rm.floor_count_coefficients:
                pass
                # TODO
                # dist_model.number_of_floors_draw = LogNormalDraw(*rm.floor_count_coefficients)

        counts = dict(object_of_origin=result['object_of_origin'] or 0,
                      room_of_origin=result['room_of_origin'] or 0,
                      floor_of_origin=result['floor_of_origin'] or 0,
                      building_of_origin=result['building_of_origin'] or 0,
                      beyond=result['beyond'] or 0)

        # add current risk category to the all risk category
        for key, value in counts.items():
            all_counts[key] += value

        if ahs_building_size is not None:
            counts['building_area_draw'] = ahs_building_size

        response_times = response_time_distributions.get('{0}-{1}'.format(
            fd.fdid, fd.state))

        if response_times:
            counts['arrival_time_draw'] = LogNormalDraw(*response_times,
                                                        multiplier=60)

        record, _ = fd.firedepartmentriskmodels_set.get_or_create(
            level=risk_mapping[result['risk_category']])
        old_score = record.dist_model_score

        try:
            dist = dist_model(floor_extent=False, **counts)
            record.dist_model_score = dist.gibbs_sample()
            record.dist_model_score_fire_count = dist.total_fires
            print 'updating fdid: {2} - {3} performance score from: {0} to {1}.'.format(
                old_score, record.dist_model_score, fd.id,
                HazardLevels(record.level).name)

        except (NotEnoughRecords, ZeroDivisionError):
            print 'Error updating DIST score: {}.'.format(
                traceback.format_exc())
            record.dist_model_score = None

        if not dry_run:
            record.save()

    # Clear out scores for missing hazard levels
    if not dry_run:
        missing_categories = set(risk_mapping.keys()) - set(
            map(lambda x: x.get('risk_category'), results))
        for r in missing_categories:
            print 'clearing {0} level from {1} due to missing categories in aggregation'.format(
                r, fd.id)
            record, _ = fd.firedepartmentriskmodels_set.get_or_create(
                level=risk_mapping[r])
            record.dist_model_score = None
            record.save()

    record, _ = fd.firedepartmentriskmodels_set.get_or_create(
        level=HazardLevels.All.value)
    old_score = record.dist_model_score
    dist_model = dist_model_for_hazard_level('All')

    try:
        if ahs_building_size is not None:
            all_counts['building_area_draw'] = ahs_building_size

        response_times = response_time_distributions.get('{0}-{1}'.format(
            fd.fdid, fd.state))

        if response_times:
            all_counts['arrival_time_draw'] = LogNormalDraw(*response_times,
                                                            multiplier=60)

        dist = dist_model(floor_extent=False, **all_counts)
        record.dist_model_score = dist.gibbs_sample()
        print 'updating fdid: {2} - {3} performance score from: {0} to {1}.'.format(
            old_score, record.dist_model_score, fd.id,
            HazardLevels(record.level).name)

    except (NotEnoughRecords, ZeroDivisionError):
        print 'Error updating DIST score: {}.'.format(traceback.format_exc())
        record.dist_model_score = None

    if not dry_run:
        record.save()

    print "...updated performance score for {}".format(id)