Skip to content

Commit c14bd04

Browse files
authored
Merge pull request #50 from Imageomics/bug-fix/lat-lon
Bug fix for lat/lon out of range
2 parents c47c550 + 12305d7 commit c14bd04

File tree

6 files changed

+68
-11
lines changed

6 files changed

+68
-11
lines changed

README.md

+4-3
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ For full dashboard functionality, upload a CSV or XLS file with the following co
1111
- `View`: View of the sample (eg., 'ventral' or 'dorsal' for butterflies).
1212
- `Sex`: Sex of each sample.
1313
- `hybrid_stat`: Hybrid status of each sample (eg., 'valid_subspecies', 'subspecies_synonym', or 'unknown').
14-
- `lat`*: Latitude at which image was taken or specimen was collected.
15-
- `lon`*: Longitude at which image was taken or specimen was collected.
14+
- `lat`*: Latitude at which image was taken or specimen was collected: number in [-90,90].
15+
- `lon`*: Longitude at which image was taken or specimen was collected: number in [-180,180].
1616
- `file_url`*: URL to access file.
1717

1818
***Note:**
19-
- `lat` and `lon` columns are not required to utilize the dashboard, but there will be no map view if they are not included.
19+
- `lat` and `lon` columns are not required to utilize the dashboard, but there will be no map view if they are not included. Blank (or null) entries are recorded as `unknown`, and thus excluded from map view.
2020
- `Image_filename` and `file_url` are not required, but there will be no sample images option if either one is not included.
21+
- `locality` may be provided, otherwise it will take on the value `lat|lon` or `unknown` if these are not provided.
2122

2223
## Running Dashboard
2324

components/divs.py

+16-8
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@
2222
{'label': 'Locality', 'value': 'locality'}
2323
]
2424
DOCS_URL = "https://github.com/Imageomics/dashboard-prototype#how-it-works"
25+
DOCS_LINK = html.A("documentation",
26+
href=DOCS_URL,
27+
target='_blank',
28+
style = ERROR_STYLE)
2529

2630
def get_hist_div(mapping):
2731
'''
@@ -306,20 +310,24 @@ def get_error_div(error_dict):
306310
html.H3("Source data does not have '" + feature + "' column. ",
307311
style = ERROR_STYLE),
308312
html.H4(["Please see the ",
309-
html.A("documentation",
310-
href=DOCS_URL,
311-
target='_blank',
312-
style = ERROR_STYLE),
313+
DOCS_LINK,
313314
" for list of required columns."],
314315
style = ERROR_STYLE)
315316
])
317+
elif 'mapping' in error_dict.keys():
318+
error_msg = error_dict['mapping']
319+
error_div = html.Div([
320+
html.H4("Latitude or longitude columns have non-numeric values: " + error_msg + ".",
321+
style = ERROR_STYLE),
322+
html.H4(["Please see the ",
323+
DOCS_LINK,
324+
"."],
325+
style = ERROR_STYLE)
326+
])
316327
elif 'type' in error_dict.keys():
317328
error_div = html.Div([
318329
html.H4(["The source file is not a valid CSV format, please see the ",
319-
html.A("documentation",
320-
href=DOCS_URL,
321-
target='_blank',
322-
style = ERROR_STYLE),
330+
DOCS_LINK,
323331
"."],
324332
style = ERROR_STYLE)
325333
])

dashboard.py

+13
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import pandas as pd
2+
import numpy as np
23
import base64
34
import io
45
import json
@@ -97,6 +98,18 @@ def parse_contents(contents, filename):
9798
else:
9899
included_features.append(feature)
99100

101+
# Check for lat/lon bounds & type if columns exist
102+
if mapping:
103+
try:
104+
# Check lat and lon within appropriate ranges (lat: [-90, 90], lon: [-180, 180])
105+
valid_lat = df['lat'].astype(float).between(-90, 90)
106+
df.loc[~valid_lat, 'lat'] = 'unknown'
107+
valid_lon = df['lon'].astype(float).between(-180, 180)
108+
df.loc[~valid_lon, 'lon'] = 'unknown'
109+
except ValueError as e:
110+
print(e)
111+
return json.dumps({'error': {'mapping': str(e)}})
112+
100113
# get dataset-determined static data:
101114
# the dataframe and categorical features - processed for map view if mapping is True
102115
# all possible species, subspecies

test_data/HCGSD_test_latLonOOB.csv

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
NHM_Specimen,Image_filename,View,Species,Subspecies,Sex,addit_taxa_info,type_stat,hybrid_stat,in_reduced,locality,lat,lon,speciesdesig,file_url
2+
10429021,10429021_V_lowres.png,,erato,notabilis,,f._notabilis,,subspecies synonym,1,,-1.583333333,-77.75,e. notabilis,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
3+
10428972,10428972_V_lowres.png,ventral,erato,petiverana,male,petiverana,,valid subspecies,1,Songolica (= Zongolica) MEX VC,18.66666667,-96.98333333,e. petiverana,
4+
10429172,,ventral,,petiverana,male,petiverana,,valid subspecies,1,San Ramon NIC ZE,92,-84.68333333,e. petiverana,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
5+
10428595,10428595_D_lowres.png,dorsal,erato,phyllis,male,f._phyllis,,subspecies synonym,1,Resistencia ARG CH,-27.45,-58.98333333,e. phyllis,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/dorsal_images/
6+
10428140,10428140_V_lowres.png,ventral,,plesseni,male,plesseni,,valid subspecies,1,Banos ECD TU,-1.4,-740,m. plesseni,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
7+
10428250,10428250_V_lowres.png,ventral,melpomene,,male,ab._rubra,,subspecies synonym,1,Caradoc (Hda) PER CU,-13.36666667,-70.95,m. schunkei,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
8+
10427979,,dorsal,melpomene,rosina_S,male,rosina_S,,valid subspecies,1,Turrialba CRI CA,9.883333333,-83.63333333,m. rosina,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/dorsal_images/
9+
10428803,10428803_D_lowres.png,dorsal,erato,guarica,female,guarica,,valid subspecies,1,Fusagasuga COL CN,4.35,-74.36666667,e. guarica,
10+
10428169,10428169_V_lowres.png,ventral,melpomene,plesseni,male,f._pura,ST,subspecies synonym,1,Canelos ECD PA,-1.583333333,730,m. plesseni,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
11+
10428321,10428321_D_lowres.png,,melpomene,nanna,male,nanna,ST,valid subspecies,1,Espirito Santo BRA ES,-20.33333333,-40.28333333,m. nanna,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/dorsal_images/

test_data/HCGSD_test_nonnumeric.csv

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
NHM_Specimen,Image_filename,View,Species,Subspecies,Sex,addit_taxa_info,type_stat,hybrid_stat,in_reduced,locality,lat,lon,speciesdesig,file_url
2+
10429021,10429021_V_lowres.png,,erato,notabilis,,f._notabilis,,subspecies synonym,1,,-1.583333333,-77.75,e. notabilis,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
3+
10428972,10428972_V_lowres.png,ventral,erato,petiverana,male,petiverana,,valid subspecies,1,Songolica (= Zongolica) MEX VC,18.66666667,,e. petiverana,
4+
10429172,,ventral,,petiverana,male,petiverana,,valid subspecies,1,San Ramon NIC ZE,92,-84.68333333,e. petiverana,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
5+
10428595,10428595_D_lowres.png,dorsal,erato,phyllis,male,f._phyllis,,subspecies synonym,1,Resistencia ARG CH,-27.45,-58.98333333,e. phyllis,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/dorsal_images/
6+
10428140,10428140_V_lowres.png,ventral,,plesseni,male,plesseni,,valid subspecies,1,Banos ECD TU,,Non numeric,m. plesseni,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
7+
10428250,10428250_V_lowres.png,ventral,melpomene,,male,ab._rubra,,subspecies synonym,1,Caradoc (Hda) PER CU,-13.36666667,-70.95,m. schunkei,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
8+
10427979,,dorsal,melpomene,rosina_S,male,rosina_S,,valid subspecies,1,Turrialba CRI CA,Non numeric,-83.63333333,m. rosina,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/dorsal_images/
9+
10428803,10428803_D_lowres.png,dorsal,erato,guarica,female,guarica,,valid subspecies,1,Fusagasuga COL CN,4.35,-74.36666667,e. guarica,
10+
10428169,10428169_V_lowres.png,ventral,melpomene,plesseni,male,f._pura,ST,subspecies synonym,1,Canelos ECD PA,-1.583333333,,m. plesseni,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/ventral_images/
11+
10428321,10428321_D_lowres.png,,melpomene,nanna,male,nanna,ST,valid subspecies,1,Espirito Santo BRA ES,-20.33333333,-40.28333333,m. nanna,https://github.com/Imageomics/dashboard-prototype/raw/main/test_data/images/dorsal_images/

tests/test_filters.py

+13
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,15 @@ def generate_mock_upload(filepath):
5757
"expected_mapping": False,
5858
"expected_images": True
5959
},
60+
{ # Check with full columns expected, but lat/lon out of bounds (1 lat and 2 lon)
61+
"filepath": "test_data/HCGSD_test_latLonOOB.csv",
62+
"filename": "HCGSD_test_latLonOOB.csv",
63+
"expected_columns": ['Species', 'Subspecies', 'View', 'Sex', 'hybrid_stat', 'lat', 'lon',
64+
'file_url', 'Image_filename', 'locality', 'lat-lon',
65+
'Samples_at_locality', 'Species_at_locality', 'Subspecies_at_locality'],
66+
"expected_mapping": True,
67+
"expected_images": True
68+
},
6069
]
6170

6271
def test_parse_contents():
@@ -70,3 +79,7 @@ def test_parse_contents():
7079
assert list(dff.columns) == case['expected_columns']
7180
assert output['mapping'] == case['expected_mapping']
7281
assert output['images'] == case['expected_images']
82+
83+
if case['filename'] == "HCGSD_test_latLonOOB.csv":
84+
assert len(dff.loc[dff.lat == 'unknown']) == 1
85+
assert len(dff.loc[dff.lon == 'unknown']) == 2

0 commit comments

Comments
 (0)