Skip to content
This repository was archived by the owner on Jan 18, 2023. It is now read-only.

Commit d09971b

Browse files
committed
Add lat/lng
1 parent a1976ec commit d09971b

File tree

10 files changed

+163
-76
lines changed

10 files changed

+163
-76
lines changed

firststreet/__main__.py

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
parser.add_argument("-limit", "--limit", help="Example: 100", required=False, default="100")
2525
parser.add_argument("-log", "--log", help="Example: False", required=False, default="True")
2626
parser.add_argument("-f", "--file", help="Example: ./sample.txt", required=False)
27+
parser.add_argument("-e", "--extra_param", required=False)
2728

2829
argument = parser.parse_args()
2930

@@ -58,49 +59,49 @@
5859
limit = int(argument.limit)
5960

6061
if argument.product == 'adaptation.get_detail':
61-
fs.adaptation.get_detail(search_items, csv=True, limit=limit)
62+
fs.adaptation.get_detail(search_items, csv=True, limit=limit, extra_param=argument.extra_param)
6263

6364
elif argument.product == 'adaptation.get_summary':
64-
fs.adaptation.get_summary(search_items, argument.location, csv=True, limit=limit)
65+
fs.adaptation.get_summary(search_items, argument.location, csv=True, limit=limit, extra_param=argument.extra_param)
6566

6667
elif argument.product == 'adaptation.get_details_by_location':
67-
fs.adaptation.get_details_by_location(search_items, argument.location, csv=True, limit=limit)
68+
fs.adaptation.get_details_by_location(search_items, argument.location, csv=True, limit=limit, extra_param=argument.extra_param)
6869

6970
elif argument.product == 'probability.get_depth':
70-
fs.probability.get_depth(search_items, csv=True, limit=limit)
71+
fs.probability.get_depth(search_items, csv=True, limit=limit, extra_param=argument.extra_param)
7172

7273
elif argument.product == 'probability.get_chance':
73-
fs.probability.get_chance(search_items, csv=True, limit=limit)
74+
fs.probability.get_chance(search_items, csv=True, limit=limit, extra_param=argument.extra_param)
7475

7576
elif argument.product == 'probability.get_count_summary':
76-
fs.probability.get_count_summary(search_items, csv=True, limit=limit)
77+
fs.probability.get_count_summary(search_items, csv=True, limit=limit, extra_param=argument.extra_param)
7778

7879
elif argument.product == 'probability.get_cumulative':
79-
fs.probability.get_cumulative(search_items, csv=True, limit=limit)
80+
fs.probability.get_cumulative(search_items, csv=True, limit=limit, extra_param=argument.extra_param)
8081

8182
elif argument.product == 'probability.get_count':
82-
fs.probability.get_count(search_items, argument.location, csv=True, limit=limit)
83+
fs.probability.get_count(search_items, argument.location, csv=True, limit=limit, extra_param=argument.extra_param)
8384

8485
elif argument.product == 'historic.get_event':
85-
fs.historic.get_event(search_items, csv=True, limit=limit)
86+
fs.historic.get_event(search_items, csv=True, limit=limit, extra_param=argument.extra_param)
8687

8788
elif argument.product == 'historic.get_summary':
88-
fs.historic.get_summary(search_items, argument.location, csv=True, limit=limit)
89+
fs.historic.get_summary(search_items, argument.location, csv=True, limit=limit, extra_param=argument.extra_param)
8990

9091
elif argument.product == 'historic.get_events_by_location':
91-
fs.historic.get_events_by_location(search_items, argument.location, csv=True, limit=limit)
92+
fs.historic.get_events_by_location(search_items, argument.location, csv=True, limit=limit, extra_param=argument.extra_param)
9293

9394
elif argument.product == 'location.get_detail':
94-
fs.location.get_detail(search_items, argument.location, csv=True, limit=limit)
95+
fs.location.get_detail(search_items, argument.location, csv=True, limit=limit, extra_param=argument.extra_param)
9596

9697
elif argument.product == 'location.get_summary':
97-
fs.location.get_summary(search_items, argument.location, csv=True, limit=limit)
98+
fs.location.get_summary(search_items, argument.location, csv=True, limit=limit, extra_param=argument.extra_param)
9899

99100
elif argument.product == 'fema.get_nfip':
100-
fs.fema.get_nfip(search_items, argument.location, csv=True, limit=limit)
101+
fs.fema.get_nfip(search_items, argument.location, csv=True, limit=limit, extra_param=argument.extra_param)
101102

102103
elif argument.product == 'environmental.get_precipitation':
103-
fs.environmental.get_precipitation(search_items, csv=True, limit=limit)
104+
fs.environmental.get_precipitation(search_items, csv=True, limit=limit, extra_param=argument.extra_param)
104105

105106
else:
106107
logging.error("Product not found. Please check that the argument"

firststreet/api/adaptation.py

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class Adaptation(Api):
1919
get_summary: Retrieves a list of Adaptation Summary for the given list of IDs
2020
"""
2121

22-
def get_detail(self, search_item, csv=False, limit=100, output_dir=None):
22+
def get_detail(self, search_item, csv=False, limit=100, output_dir=None, extra_param=None):
2323
"""Retrieves adaptation detail product data from the First Street Foundation API given a list of search_items
2424
and returns a list of Adaptation Detail objects.
2525
@@ -29,11 +29,13 @@ def get_detail(self, search_item, csv=False, limit=100, output_dir=None):
2929
csv (bool): To output extracted data to a csv or not
3030
limit (int): max number of connections to make
3131
output_dir (str): The output directory to save the generated csvs
32+
extra_param (str): Extra parameter to be added to the url
33+
3234
Returns:
3335
A list of Adaptation Detail
3436
"""
3537
# Get data from api and create objects
36-
api_datas = self.call_api(search_item, "adaptation", "detail", None, limit=limit)
38+
api_datas = self.call_api(search_item, "adaptation", "detail", None, limit=limit, extra_param=extra_param)
3739
product = [AdaptationDetail(api_data) for api_data in api_datas]
3840

3941
if csv:
@@ -43,7 +45,8 @@ def get_detail(self, search_item, csv=False, limit=100, output_dir=None):
4345

4446
return product
4547

46-
def get_details_by_location(self, search_item, location_type, csv=False, limit=100, output_dir=None):
48+
def get_details_by_location(self, search_item, location_type, csv=False, limit=100, output_dir=None,
49+
extra_param=None):
4750
"""Retrieves adaptation detail product data from the First Street Foundation API given a list of location
4851
search_items and returns a list of Adaptation Detail objects.
4952
@@ -54,6 +57,8 @@ def get_details_by_location(self, search_item, location_type, csv=False, limit=1
5457
csv (bool): To output extracted data to a csv or not
5558
limit (int): max number of connections to make
5659
output_dir (str): The output directory to save the generated csvs
60+
extra_param (str): Extra parameter to be added to the url
61+
5762
Returns:
5863
A list of list of Adaptation Summary and Adaptation Detail
5964
Raises:
@@ -67,28 +72,31 @@ def get_details_by_location(self, search_item, location_type, csv=False, limit=1
6772
raise TypeError("location is not a string")
6873

6974
# Get data from api and create objects
70-
api_datas_summary = self.call_api(search_item, "adaptation", "summary", location_type, limit=limit)
75+
api_datas_summary = self.call_api(search_item, "adaptation", "summary", location_type, limit=limit,
76+
extra_param=extra_param)
7177
summary = [AdaptationSummary(api_data) for api_data in api_datas_summary]
7278

7379
search_items = list(set([adaptation for sum_adap in summary if sum_adap.adaptation for
74-
adaptation in sum_adap.adaptation]))
80+
adaptation in sum_adap.adaptation]))
7581

7682
if search_items:
77-
api_datas_detail = self.call_api(search_items, "adaptation", "detail", None, limit=limit)
83+
api_datas_detail = self.call_api(search_items, "adaptation", "detail", None, limit=limit,
84+
extra_param=extra_param)
7885

7986
else:
8087
api_datas_detail = [{"adaptationId": None}]
8188

8289
detail = [AdaptationDetail(api_data) for api_data in api_datas_detail]
8390

8491
if csv:
85-
csv_format.to_csv([summary, detail], "adaptation", "summary_detail", location_type, output_dir=output_dir)
92+
csv_format.to_csv([summary, detail], "adaptation", "summary_detail", location_type,
93+
output_dir=output_dir)
8694

8795
logging.info("Adaptation Summary Detail Data Ready.")
8896

8997
return [summary, detail]
9098

91-
def get_summary(self, search_item, location_type, csv=False, limit=100, output_dir=None):
99+
def get_summary(self, search_item, location_type, csv=False, limit=100, output_dir=None, extra_param=None):
92100
"""Retrieves adaptation summary product data from the First Street Foundation API given a list of
93101
search_items and returns a list of Adaptation Summary objects.
94102
@@ -99,6 +107,8 @@ def get_summary(self, search_item, location_type, csv=False, limit=100, output_d
99107
csv (bool): To output extracted data to a csv or not
100108
limit (int): max number of connections to make
101109
output_dir (str): The output directory to save the generated csvs
110+
extra_param (str): Extra parameter to be added to the url
111+
102112
Returns:
103113
A list of Adaptation Summary
104114
Raises:
@@ -112,7 +122,8 @@ def get_summary(self, search_item, location_type, csv=False, limit=100, output_d
112122
raise TypeError("location is not a string")
113123

114124
# Get data from api and create objects
115-
api_datas = self.call_api(search_item, "adaptation", "summary", location_type, limit=limit)
125+
api_datas = self.call_api(search_item, "adaptation", "summary", location_type, limit=limit,
126+
extra_param=extra_param)
116127
product = [AdaptationSummary(api_data) for api_data in api_datas]
117128

118129
if csv:

firststreet/api/api.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class Api:
2323
def __init__(self, http):
2424
self._http = http
2525

26-
def call_api(self, search_item, product, product_subtype, location, limit=100):
26+
def call_api(self, search_item, product, product_subtype, location, limit=100, extra_param=None):
2727
"""Receives an item, a product, a product subtype, and a location to create and call an endpoint to the First
2828
Street Foundation API.
2929
@@ -34,6 +34,7 @@ def call_api(self, search_item, product, product_subtype, location, limit=100):
3434
product_subtype (str): The product subtype (if suitable)
3535
location (str/None): The location type (if suitable)
3636
limit (int): max number of connections to make
37+
extra_param (str): Extra parameter to be added to the url
3738
Returns:
3839
A list of JSON responses
3940
"""
@@ -71,15 +72,15 @@ def call_api(self, search_item, product, product_subtype, location, limit=100):
7172

7273
# fsid
7374
if isinstance(item, int):
74-
endpoint = endpoint + "/{}".format(item)
75+
endpoint = endpoint + "/{}".format(item) + "?{}".format(extra_param)
7576

7677
# lat/lng
7778
elif isinstance(item, tuple):
78-
endpoint = endpoint + "?lat={}&lng={}".format(item[0], item[1])
79+
endpoint = endpoint + "?lat={}&lng={}&{}".format(item[0], item[1], extra_param)
7980

8081
# address
8182
elif isinstance(item, str):
82-
endpoint = endpoint + "?address={}".format(item)
83+
endpoint = endpoint + "?address={}&{}".format(item, extra_param)
8384

8485
endpoints.append((endpoint, item, product, product_subtype))
8586

firststreet/api/csv_format.py

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import datetime
66
import logging
77
import os
8+
import shapely.geometry
89

910
# External Imports
1011
import pandas as pd
@@ -146,6 +147,25 @@ def to_csv(data, product, product_subtype, location_type=None, output_dir=None):
146147
logging.info("CSV generated to '{}'.".format(output_dir + '/' + file_name))
147148

148149

150+
def get_geom_center(geom):
151+
152+
if hasattr(geom, "center"):
153+
if isinstance(geom.center, shapely.geometry.MultiPolygon):
154+
return {"latitude": geom.center.centroid.y, "longitude": geom.center.centroid.x}
155+
156+
elif isinstance(geom.center, shapely.geometry.Point):
157+
return {"latitude": geom.center.y, "longitude": geom.center.x}
158+
159+
else:
160+
raise NotImplementedError
161+
162+
elif hasattr(geom, "y") and hasattr(geom, "x"):
163+
return {"latitude": geom.y, "longitude": geom.x}
164+
165+
return {"latitude": None, "longitude": None}
166+
167+
168+
149169
def format_adaptation_detail(data):
150170
"""Reformat the list of data to Adaptation Detail format
151171
@@ -155,10 +175,12 @@ def format_adaptation_detail(data):
155175
A pandas formatted DataFrame
156176
"""
157177
df = pd.DataFrame([vars(o) for o in data]).explode('type').explode('scenario').reset_index(drop=True)
158-
df.drop(["serving", "geometry"], axis=1, inplace=True)
159178
df['adaptationId'] = df['adaptationId'].astype('Int64').apply(str)
160179
df['returnPeriod'] = df['returnPeriod'].astype('Int64').apply(str)
161-
return df[['adaptationId', 'name', 'type', 'scenario', 'conveyance', 'returnPeriod']]
180+
df['geometry'] = df['geometry'].apply(get_geom_center)
181+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
182+
183+
return df[['adaptationId', 'name', 'type', 'scenario', 'conveyance', 'returnPeriod', 'latitude', 'longitude']]
162184

163185

164186
def format_adaptation_summary(data):
@@ -410,7 +432,6 @@ def format_historic_event(data):
410432
A pandas formatted DataFrame
411433
"""
412434
df = pd.DataFrame([vars(o) for o in data])
413-
df.drop(["geometry"], axis=1, inplace=True)
414435
if not df['properties'].isna().values.all():
415436
df = pd.concat([df.drop(['properties'], axis=1), df['properties'].apply(pd.Series)], axis=1)
416437
df['eventId'] = df['eventId'].astype('Int64').apply(str)
@@ -425,8 +446,11 @@ def format_historic_event(data):
425446
df.drop(['properties'], axis=1, inplace=True)
426447
df['propertiesTotal'] = pd.NA
427448
df['propertiesAffected'] = pd.NA
449+
df['geometry'] = df['geometry'].apply(get_geom_center)
450+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
428451

429-
return df[['eventId', 'name', 'month', 'year', 'returnPeriod', 'type', 'propertiesTotal', 'propertiesAffected']]
452+
return df[['eventId', 'name', 'month', 'year', 'returnPeriod', 'type', 'propertiesTotal',
453+
'propertiesAffected', 'latitude', 'longitude']]
430454

431455

432456
def format_historic_summary_property(data):
@@ -567,9 +591,11 @@ def format_location_detail_property(data):
567591
df['state_fips'] = df['state_fips'].astype('Int64').apply(str).apply(lambda x: x.zfill(2))
568592
df['footprintId'] = df['footprintId'].astype('Int64').apply(str)
569593
df['elevation'] = df['city_fips'].apply(str)
594+
df['geometry'] = df['geometry'].apply(get_geom_center)
595+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
570596
return df[['fsid', 'streetNumber', 'route', 'city_fips', 'city_name', 'zipCode', 'neighborhood_fips',
571597
'neighborhood_name', 'tract_fips', 'county_fips', 'county_name', 'cd_fips',
572-
'cd_name', 'state_fips', 'state_name', 'footprintId', 'elevation', 'fema']]
598+
'cd_name', 'state_fips', 'state_name', 'footprintId', 'elevation', 'fema', 'latitude', 'longitude']]
573599

574600

575601
def format_location_detail_neighborhood(data):
@@ -612,8 +638,10 @@ def format_location_detail_neighborhood(data):
612638
df['city_fips'] = df['city_fips'].astype('Int64').apply(str)
613639
df['county_fips'] = df['county_fips'].astype('Int64').apply(str)
614640
df['state_fips'] = df['state_fips'].astype('Int64').apply(str).apply(lambda x: x.zfill(2))
641+
df['geometry'] = df['geometry'].apply(get_geom_center)
642+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
615643
return df[['fsid', 'name', 'city_fips', 'city_name', 'county_fips', 'county_name', 'subtype',
616-
'state_fips', 'state_name']]
644+
'state_fips', 'state_name', 'latitude', 'longitude']]
617645

618646

619647
def format_location_detail_city(data):
@@ -666,8 +694,10 @@ def format_location_detail_city(data):
666694
df['county_fips'] = df['county_fips'].astype('Int64').apply(str)
667695
df['neighborhood_fips'] = df['neighborhood_fips'].astype('Int64').apply(str)
668696
df['state_fips'] = df['state_fips'].astype('Int64').apply(str).apply(lambda x: x.zfill(2))
697+
df['geometry'] = df['geometry'].apply(get_geom_center)
698+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
669699
return df[['fsid', 'name', 'lsad', 'zipCode', 'neighborhood_fips', 'neighborhood_name',
670-
'county_fips', 'county_name', 'state_fips', 'state_name']]
700+
'county_fips', 'county_name', 'state_fips', 'state_name', 'latitude', 'longitude']]
671701

672702

673703
def format_location_detail_zcta(data):
@@ -710,7 +740,10 @@ def format_location_detail_zcta(data):
710740
df['city_fips'] = df['city_fips'].astype('Int64').apply(str)
711741
df['county_fips'] = df['county_fips'].astype('Int64').apply(str)
712742
df['state_fips'] = df['state_fips'].astype('Int64').apply(str).apply(lambda x: x.zfill(2))
713-
return df[['fsid', 'name', 'city_fips', 'city_name', 'county_fips', 'county_name', 'state_fips', 'state_name']]
743+
df['geometry'] = df['geometry'].apply(get_geom_center)
744+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
745+
return df[['fsid', 'name', 'city_fips', 'city_name', 'county_fips', 'county_name', 'state_fips',
746+
'state_name', 'latitude', 'longitude']]
714747

715748

716749
def format_location_detail_tract(data):
@@ -744,7 +777,9 @@ def format_location_detail_tract(data):
744777
df['fsid'] = df['fsid'].apply(str)
745778
df['county_fips'] = df['county_fips'].astype('Int64').apply(str)
746779
df['state_fips'] = df['state_fips'].astype('Int64').apply(str).apply(lambda x: x.zfill(2))
747-
return df[['fsid', 'fips', 'county_fips', 'county_name', 'state_fips', 'state_name']]
780+
df['geometry'] = df['geometry'].apply(get_geom_center)
781+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
782+
return df[['fsid', 'fips', 'county_fips', 'county_name', 'state_fips', 'state_name', 'latitude', 'longitude']]
748783

749784

750785
def format_location_detail_county(data):
@@ -797,8 +832,10 @@ def format_location_detail_county(data):
797832
df['zipCode'] = df['zipCode'].astype('Int64').apply(str)
798833
df['cd_fips'] = df['cd_fips'].astype('Int64').apply(str)
799834
df['state_fips'] = df['state_fips'].astype('Int64').apply(str).apply(lambda x: x.zfill(2))
835+
df['geometry'] = df['geometry'].apply(get_geom_center)
836+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
800837
return df[['fsid', 'city_fips', 'city_name', 'zipCode', 'fips', 'isCoastal', 'cd_fips',
801-
'cd_name', 'state_fips', 'state_name']]
838+
'cd_name', 'state_fips', 'state_name', 'latitude', 'longitude']]
802839

803840

804841
def format_location_detail_cd(data):
@@ -832,7 +869,9 @@ def format_location_detail_cd(data):
832869
df['fsid'] = df['fsid'].apply(str)
833870
df['county_fips'] = df['county_fips'].astype('Int64').apply(str)
834871
df['state_fips'] = df['state_fips'].astype('Int64').apply(str).apply(lambda x: x.zfill(2))
835-
return df[['fsid', 'district', 'county_fips', 'county_name', 'state_fips', 'state_name']]
872+
df['geometry'] = df['geometry'].apply(get_geom_center)
873+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
874+
return df[['fsid', 'district', 'county_fips', 'county_name', 'state_fips', 'state_name', 'latitude', 'longitude']]
836875

837876

838877
def format_location_detail_state(data):
@@ -845,7 +884,9 @@ def format_location_detail_state(data):
845884
"""
846885
df = pd.DataFrame([vars(o) for o in data])
847886
df['fsid'] = df['fsid'].apply(str)
848-
return df[['fsid', 'name', 'fips']]
887+
df['geometry'] = df['geometry'].apply(get_geom_center)
888+
df = pd.concat([df.drop(['geometry'], axis=1), df['geometry'].apply(pd.Series)], axis=1)
889+
return df[['fsid', 'name', 'fips', 'latitude', 'longitude']]
849890

850891

851892
def format_location_summary_property(data):

0 commit comments

Comments
 (0)