Esempio n. 1
0
    def get_shapes(self, max_area, max_distance_meters):
        "return the shapes [census tracts] that touch the center of max_area + max_distance"

        query = {
            'geometry': {
                '$near':
                SON([('$geometry',
                      SON([('type', 'Point'),
                           ('coordinates', [longitude, latitude])])),
                     ('$maxDistance', max_distance_meters)])
            }
        }

        for shp in self.db.GENZ2010_140.find(query):
            # add population to properties
            p = shp['properties']

            # for later use
            p['label'] = "{} {} [{}]".format(
                state_name(p['STATE']), county_name(p['STATE'], p['COUNTY']),
                p['TRACT'])

            pop = {}
            # lookup population and area
            raw_pop = int(
                self.census.sf1.state_county_tract("P0010001", p['STATE'],
                                                   p['COUNTY'],
                                                   p['TRACT'])[0]["P0010001"])
            pop['raw'] = raw_pop
            #print("raw population: {}".format(raw_pop))

            # compute area in our radius
            county_shape = shape(shp['geometry'])
            isect = county_shape.intersection(max_area)

            # save the intersection for later use.
            shp['intersection'] = isect

            pop['area'] = county_shape.area
            frac_contained = float(isect.area) / float(county_shape.area)
            pop['frac_contained'] = frac_contained
            #print("contained: {}".format(frac_contained))

            # compute effective population
            #print("contained population: {}".format(frac_contained * raw_pop))
            pop['effective'] = frac_contained * raw_pop

            p['population'] = pop

            # filter out areas with very low population
            # the mongodb geo query may be not exact
            if frac_contained * raw_pop < 0.1:
                print("WARN: clipping: {}".format(p['label']))
                pprint(pop)
                continue

            yield shp
Esempio n. 2
0
def plot_shapes(ax,
                shapes,
                filled=False,
                show_states=False,
                fc=None,
                alpha=0.16):
    # have to buffer the results to see how many colors to generate

    if fc == None:
        if filled:
            color_list = plt.cm.Dark2(np.linspace(0, 1, len(shapes)))
            fc = lambda x: color_list[x]
        else:
            fc = lambda x: 'none'

    states = set()
    geoid = {}
    # get the shapes covered by the coverage area.
    for i, shp in enumerate(shapes):
        p = shp['properties']

        #track states we hit
        if p['STATE'] not in states:
            states.add(p['STATE'])
        # also store the goeid so we dont plot again later
        geoid[p['GEO_ID']] = shp

        if p['LSAD'] == 'Tract':
            label = "{} {} [{}]".format(state_name(p['STATE']),
                                        county_name(p['STATE'], p['COUNTY']),
                                        p['TRACT'])
        else:
            label = p['NAME']

        #print ("-"*10 + label + "-"*10)
        #pprint(p['population'])

        ec = 'black'
        lw = 1

        if 'population' in p:
            if p['population']['effective'] < 0.01:
                ec = 'blue'
                lw = 2
                #was fc = color_list[i],

        patches = make_patch(shp['geometry'],
                             fc=fc(i),
                             lw=lw,
                             ec=ec,
                             label=label,
                             alpha=alpha)
        for p in patches:
            ax.add_patch(p)
Esempio n. 3
0
    def _add_pop_to_shape_intersct(self, shp, max_area):
        "add the population inside the intersection of shp and max_area, shp is assumed to be a census tract."
        # add population to properties

        p = shp['properties']

        #print(p)

        # for later use
        p['label'] = "{} {} [{}]".format(state_name(p['STATE']),
                                         county_name(p['STATE'], p['COUNTY']),
                                         p['TRACT'])

        pop = {}
        # lookup population and area try mongo first.
        searchdoc = {
            'state': p["STATE"],
            'county': p['COUNTY'],
            'tract': p['TRACT'],
            'variable.P0010001': {
                '$exists': True
            }
        }
        #print("searchdoc: ",end="")
        #pprint(searchdoc)
        cdoc = self.census_col.find_one(searchdoc)

        if cdoc != None:
            #print("Hit.")
            raw_pop = cdoc['variable']['P0010001']
        else:
            raw_pop = int(
                self.census.sf1.state_county_tract("P0010001", p['STATE'],
                                                   p['COUNTY'],
                                                   p['TRACT'])[0]["P0010001"])
            insdoc = {
                'state': p["STATE"],
                'county': p['COUNTY'],
                'tract': p['TRACT'],
                'variable': {
                    'P0010001': raw_pop
                }
            }
            #print("inserting: ", end="")
            #pprint(insdoc)

            self.census_col.insert_one(insdoc)

        pop['raw'] = raw_pop
        #print("raw population: {}".format(raw_pop))

        county_shape = shape(shp['geometry'])
        if max_area != None:

            # compute area in our radius
            isect = county_shape.intersection(max_area)
            union = county_shape.union(max_area)
            # save the intersection for later use.
            shp['intersection'] = mapping(isect)
            shp['union'] = mapping(union)

            pop['area'] = county_shape.area
            frac_contained = float(isect.area) / float(county_shape.area)
            pop['frac_contained'] = frac_contained
            #print("contained: {}".format(frac_contained))
        else:
            shp['intersection'] = shp['geometry']
            shp['union'] = shp['geometry']
            pop['area'] = county_shape.area
            frac_contained = 1.0
            pop['frac_contained'] = 1.0

        # compute effective population
        #print("contained population: {}".format(frac_contained * raw_pop))
        pop['effective'] = frac_contained * raw_pop

        p['population'] = pop

        shp['properties'] = p
        # add area
        compute_land_area(shp)
Esempio n. 4
0
    # have to buffer the results to see how many colors to generate
    results = list(pbps.get_shapes(area, dist))
    color_list = plt.cm.Dark2(np.linspace(0, 1, len(results)))

    # get the shapes covered by the coverage area.
    for i, shp in enumerate(results):
        p = shp['properties']

        #track states we hit
        if p['STATE'] not in states:
            states.add(p['STATE'])
        # also store the goeid so we dont plot again later
        geoid[p['GEO_ID']] = shp

        label = "{} {} [{}]".format(state_name(p['STATE']),
                                    county_name(p['STATE'], p['COUNTY']),
                                    p['TRACT'])

        #print ("-"*10 + label + "-"*10)
        #pprint(p['population'])

        ec = 'black'
        lw = 2
        if p['population']['effective'] < 0.01:
            ec = 'blue'
            lw = 4
        patches = make_patch(shp['geometry'],
                             fc=color_list[i],
                             lw=lw,
                             ec=ec,
Esempio n. 5
0
def plot_single_place(outputfmt, placename, cover_by_place_q):
    #ps = PopulationBasedPointSampler()

    connection = pymongo.MongoClient(
        'mongodb://*****:*****@eg-mongodb.bucknell.edu/ym015')
    db = connection.get_default_database()
    e = Elevation()  # to look up point elevations.

    query = {'name': placename}

    cover_by_place = []
    lossbynumbase = {}
    loss_threshold = {}
    # qfilter = {'_id':1}
    # if not os.path.exists(outputfmt.format(placename, i, 'elevation')):
    # 	qfilter ['shapes'] = 1
    # 	qfilter ['points'] = 1

    # have to talk out the filter for just id to comptue other values.
    cursor = db['POINTS'].find(query, {
        '_id': 1,
        'LSAD': 1,
        'state': 1,
        'points': 1,
        'shapes': 1,
        'shape_ids': 1
    },
                               no_cursor_timeout=True)  #.limit(2)
    state = None
    for i, pointdoc in enumerate(cursor):
        state = pointdoc['state']
        print("{}: {} of {}.".format(placename, i + 1, cursor.count()))
        lqry = {'point_docid': pointdoc['_id'], 'tx_height': 5, 'rx_height': 1}
        #lqry = {'point_docid': pointdoc['_id']}

        if not os.path.exists(outputfmt.format(placename, i, 'loss')):
            if i == 0:
                for rsltdoc in db['POINTRESULTS'].find(lqry, {
                        'nodes': 1,
                        'num_basestations': 1,
                        'loss_threshold': 1
                }):
                    lossbynumbase[rsltdoc['num_basestations']] = [
                        x['min_loss'] for x in rsltdoc['nodes']
                        if not math.isnan(x['min_loss'])
                    ]
                    loss_threshold[rsltdoc['num_basestations']] = [
                        rsltdoc['loss_threshold']
                    ]
            else:
                for rsltdoc in db['POINTRESULTS'].find(lqry, {
                        'nodes': 1,
                        'num_basestations': 1,
                        'loss_threshold': 1
                }):
                    lossbynumbase[rsltdoc['num_basestations']] += [
                        x['min_loss'] for x in rsltdoc['nodes']
                        if not math.isnan(x['min_loss'])
                    ]
                    loss_threshold[rsltdoc['num_basestations']].append(
                        rsltdoc['loss_threshold'])

        #cqry = {'point_docid': pointdoc['_id'], 'tx_height': 5, 'rx_height': 1, 'num_basestations': 1}
        cqry = {'point_docid': pointdoc['_id'], 'num_basestations': 1}
        cover_by_place += [
            x['connected']
            for x in db['POINTRESULTS'].find(cqry, {'connected': 1})
        ]

        #skip the rest, for now.
        #continue

        #print(lossbynumbase)
        #print(loss_threshold)

        # stats are the same, so only do it once.
        if i == 0:

            if (not os.path.exists(outputfmt.format(placename, i, 'elevation'))) or \
             (not os.path.exists(outputfmt.format(placename, i, 'stats'))):

                fig = plt.figure(figsize=(8, 8))
                ax = plt.subplot(111)

                if pointdoc['LSAD'] == 'County':
                    c_shp_query = {
                        'properties.NAME': placename,
                        'properties.STATE': pointdoc['state']
                    }
                    c_shp = list(db['GENZ2010_050'].find(c_shp_query))

                    #plot_shapes(ax, city_shp, filled= True, show_states = True, fc=lambda x:'red', alpha=0.99)
                    plot_shapes(ax, c_shp, filled=False, show_states=True)

                elif pointdoc['LSAD'] == 'city':
                    city_shp_query = {
                        'properties.NAME': placename,
                        'properties.STATE': pointdoc['state']
                    }
                    city_shp = list(db['GENZ2010_160'].find(city_shp_query))

                    #plot_shapes(ax, city_shp, filled= True, show_states = True, fc=lambda x:'red', alpha=0.99)
                    plot_shapes(ax, city_shp, filled=False, show_states=True)
                else:
                    print(
                        "WARN: unknown LSAD: {}, not plotting outline".format(
                            pointdoc['LSAD']))

                if 'shapes' not in pointdoc:
                    print("getting shapes...")
                    sqry = {'_id': {'$in': pointdoc['shape_ids']}}
                    shapes = list(db['GENZ2010_140'].find(sqry))
                else:
                    shapes = pointdoc['shapes']

                plot_shapes(ax, shapes, filled=True, show_states=True)

                # this is one way to do it
                # tract_shp = list(ps.get_tract_shapes_in_area(city_shp[0]))
                # plot_shapes(ax, tract_shp, filled= True, show_states = True)

                elev_data = []
                for pt in pointdoc['points']:
                    ax.plot(pt['coordinates'][0],
                            pt['coordinates'][1],
                            '.',
                            color='black',
                            ms=4,
                            lw=2,
                            alpha=0.75)
                    elev_data.append(e.lookup(pt['coordinates']))

                ax.ticklabel_format(useOffset=False, style="plain")

                ax.set_title("{}, {}".format(placename, state_name(state)))
                ax.axis('equal')

                plt.tight_layout()
                plt.savefig(outputfmt.format(placename, i, 'tracts'))
                plt.close(fig)

                # show elevation distribution
                fig = plt.figure(figsize=(8, 8))
                ax = plt.subplot(111)
                ax.hist(elev_data,
                        normed=1,
                        fill=False,
                        ec="black",
                        lw=3,
                        hatch=".")
                ax.set_title(placename)
                ax.set_xlabel('Elevation (meters)')
                ax.set_ylabel('Rate')
                ax.axis('tight')
                plt.savefig(outputfmt.format(placename, i, 'elevation'))
                plt.close(fig)

                print("{} has {} tracts.".format(placename, len(shapes)))
                areas = [
                    sh['properties']['area']['effective'] / (1000.0**2)
                    for sh in shapes if 'area' in sh['properties']
                ]  # convert meters to KM
                pops = [
                    sh['properties']['population']['effective'] / 1000.0
                    for sh in shapes if 'area' in sh['properties']
                ]

                #print (areas)
                #print (pops)
                print('total pop: ', sum(pops), 'median: ', numpy.median(pops))
                print('total area: ', sum(areas), 'median: ',
                      numpy.median(areas))

            if not os.path.exists(outputfmt.format(placename, i, 'stats')):

                if areas != None and pops != None:
                    fig = plt.figure(figsize=(8, 4))

                    ax = plt.subplot(121)
                    ax.hist(areas,
                            normed=0,
                            fill=False,
                            ec='black',
                            lw=3,
                            hatch='/')
                    ax.set_title("Area")
                    ax.set_xlabel('Square Kilometers')
                    ax.set_ylabel('Count')

                    ax.axis('normal')

                    ax = plt.subplot(122)
                    ax.set_title("Population")
                    ax.hist(pops,
                            normed=0,
                            fill=False,
                            ec='black',
                            lw=3,
                            hatch='x')
                    ax.set_xlabel('Population (Thousands)')
                    ax.set_ylabel('Count')

                    ax.axis('normal')

                    #ax.violinplot ([areas, pops], showmeans=False, showmedians=True)
                    #ax.set_xticklabels(['Area', 'Population'])

                    plt.tight_layout()
                    plt.savefig(outputfmt.format(placename, i, 'stats'))
                    plt.close(fig)

    #if not os.path.exists(outputfmt.format(placename, i, 'loss')):
    if 1:
        # show loss distribution
        fig = plt.figure(figsize=(8, 4))
        ax = plt.subplot(111)

        bases = sorted(lossbynumbase.keys())

        if len(bases) > 0:
            # print ('plot bases: ', end="")
            # pprint(bases)

            # print ('loss values: ', end="")
            # pprint ([lossbynumbase[bs] for bs in bases])

            ax.violinplot([lossbynumbase[bs] for bs in bases],
                          bases,
                          showmeans=False,
                          showmedians=True)

            # print('medians are: ', end="")
            # pprint([numpy.median(loss_threshold[i]) for i in bases])

            ax.plot(bases, [numpy.median(loss_threshold[i]) for i in bases],
                    '--',
                    alpha=0.5,
                    color='green',
                    lw=2)

            ax.set_title("{}, {}".format(placename, state_name(state)))
            ax.set_xlabel('Number of basestations')
            ax.set_ylabel('Loss (dB)')
            ax.axis('tight')
            plt.tight_layout()
            plt.savefig(outputfmt.format(placename, i, 'loss'))
            plt.close(fig)
        else:
            print(lossbynumbase)
            print(bases)
    cover_by_place_q.put((placename, cover_by_place))