Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ocean eddy map #1

Open
wants to merge 142 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
142 commits
Select commit Hold shift + click to select a range
f710260
added jQRangeSlider
Jun 13, 2016
b45ab45
revised jQRangeSlider
Jun 14, 2016
0111092
revised the JavaScript script
Jun 15, 2016
99b70ed
revised the flask script
Jun 15, 2016
1e2b52f
revised home page structure
Jun 16, 2016
0a181f2
added date inquery
Jun 16, 2016
a4596b7
made progress on eddy inquiry
Jun 17, 2016
3eda6b2
almost there
Jun 21, 2016
4c94f5e
revised scripts
Jun 21, 2016
5906083
revised html
Jun 21, 2016
f3aaa5b
before meeting
Jun 30, 2016
be89d46
revised scripts
Jul 22, 2016
ab80f31
revised scripts
Jul 22, 2016
a3ae29f
updated static
Jul 23, 2016
ce2f237
added leaflet images
Jul 23, 2016
2edc0a9
updated map style
Jul 23, 2016
cebc7f5
revised slider style
Jul 25, 2016
0da9328
fixed eddy layer remains
Jul 26, 2016
ad685f7
made progress on info control
Jul 26, 2016
e5486f5
added panel slider
Jul 26, 2016
5bd9c1a
adjust slide panel paddings
Jul 26, 2016
a615fc4
before meeting
Aug 23, 2016
fc01175
revised HTML
Aug 23, 2016
eb14ba8
revised information panel
Aug 23, 2016
c1af972
for sverdrup
Aug 24, 2016
d2b2c32
eddy id
Aug 25, 2016
bbbddad
interactive id does not work
Aug 25, 2016
0324e95
before meeting
Aug 26, 2016
bf80708
before meeting again
Aug 26, 2016
9056af7
before meeting
Aug 26, 2016
9565154
collection selection
Aug 26, 2016
0daed53
radio button
Aug 26, 2016
49039ee
bootstrap switch
Aug 29, 2016
c9f4138
bootstrap switch
Aug 29, 2016
8c363ce
events
Aug 29, 2016
a237eed
bootstrap switch works now
Aug 29, 2016
8714944
fixed a bug on eddy layer
Aug 29, 2016
90dafc0
fixed RCS
Aug 29, 2016
ab8802f
zindex
Aug 29, 2016
08dcd5e
z index
Aug 29, 2016
5e9727f
z index
Aug 29, 2016
12a265c
z index
Aug 29, 2016
023e230
z index
Aug 29, 2016
58265e3
z index
Aug 29, 2016
21493e5
before meeting
Aug 29, 2016
d66e2b4
info panel
Aug 31, 2016
b5742cb
info panel
Aug 31, 2016
8cdd0ea
info panel
Aug 31, 2016
ffe8830
info panel
Aug 31, 2016
3c571f8
info panel
Aug 31, 2016
1d816c3
info panel
Aug 31, 2016
b6b13b2
info panel
Aug 31, 2016
46857e0
info panel
Aug 31, 2016
e0af2fb
rcs points
Sep 1, 2016
8795f01
checkbox
Sep 2, 2016
fb3b47b
checkbox
Sep 2, 2016
23fa99c
checkbox
Sep 2, 2016
d8b59ce
checkbox
Sep 2, 2016
726e454
checkbox
Sep 2, 2016
65a3818
checkbox
Sep 2, 2016
2cbf267
color
Sep 2, 2016
73729bf
color
Sep 2, 2016
15a59f4
color
Sep 2, 2016
d7a53e2
color
Sep 2, 2016
b9f8fcd
color
Sep 2, 2016
382c314
color
Sep 2, 2016
5c30cef
color
Sep 2, 2016
39434e6
color
Sep 5, 2016
b903d2c
color
Sep 5, 2016
8212c63
color
Sep 5, 2016
8727142
before warning
Sep 6, 2016
7d6a9ca
before warning
Sep 6, 2016
af5eece
before warning
Sep 6, 2016
c6d3d73
before warning
Sep 6, 2016
0e99309
before warning
Sep 6, 2016
524c785
before warning
Sep 6, 2016
a284eaf
before warning
Sep 6, 2016
58b07f2
before warning
Sep 6, 2016
fb3d58c
before warning
Sep 6, 2016
fd4cc8e
before warning
Sep 6, 2016
945bf82
fullscreen
Sep 8, 2016
e8e01a6
fullscreen
Sep 8, 2016
7859454
space
Sep 9, 2016
903cc57
before results
Sep 11, 2016
58bbfa9
before results
Sep 11, 2016
8e45882
before meeting
Sep 12, 2016
9716b15
before meeting
Sep 12, 2016
d882026
flask
Sep 13, 2016
2dfc931
flask
Sep 13, 2016
72771c2
flask
Sep 13, 2016
9e20601
flask
Sep 13, 2016
6da168a
read json from a url
Sep 14, 2016
489c46a
alert
Sep 14, 2016
3f00bed
alert
Sep 14, 2016
ff2ae41
alert
Sep 14, 2016
603fe13
fullscreen
Sep 14, 2016
b07fe6d
adjust
Sep 15, 2016
c1e2703
z index
Sep 15, 2016
9a577d2
z index
Sep 15, 2016
d662736
before meeting
Sep 15, 2016
410f643
before meeting
Sep 15, 2016
17672c7
delete
Sep 15, 2016
029f024
fix file name issue
Sep 15, 2016
d57a814
fix file name issue
Sep 15, 2016
722ee32
fix power symbol issue
Sep 15, 2016
55a8b73
fix bootstrap file issue
Sep 15, 2016
36a6fb3
before meeting
Sep 16, 2016
efb9fa6
before group meeting
Sep 20, 2016
3761b35
change loading max to 5000
Sep 20, 2016
6c7f2eb
fix filtering bar length
Sep 20, 2016
548b3e6
cchdo
Sep 28, 2016
b34f1b6
cchdo
Sep 28, 2016
5d13a47
cchdo
Sep 28, 2016
c847275
cchdo
Sep 28, 2016
c486c48
cchdo
Sep 28, 2016
e626e2c
cchdo
Sep 28, 2016
1953103
cchdo
Sep 28, 2016
3a1e237
cchdo
Sep 28, 2016
64afcba
cchdo
Sep 28, 2016
ae2f4f0
cchdo
Sep 28, 2016
1cdeb62
cchdo
Sep 28, 2016
c51a878
cchdo
Sep 28, 2016
6b3a19c
cchdo
Sep 28, 2016
7a130d9
cchdo
Sep 28, 2016
412cc50
cchdo
Sep 28, 2016
5333814
cchdo
Sep 28, 2016
7c24d47
cchdo
Sep 28, 2016
f266a8f
cchdo
Sep 28, 2016
13cb644
cchdo
Sep 28, 2016
af3e5f9
cchdo
Sep 28, 2016
06d72d6
cchdo
Sep 28, 2016
f3e3997
cchdo
Sep 28, 2016
9e77f2f
cchdo
Sep 28, 2016
401ef10
cchdo
Sep 28, 2016
dd32888
cchdo
Sep 28, 2016
ea89c47
cchdo
Sep 28, 2016
13a55f3
cchdo
Sep 28, 2016
4f6b1f1
version 2016
Nov 4, 2016
b62fa3f
readme.md
Jan 4, 2017
08b407e
readme
Mar 31, 2017
196d647
new commit
Jul 27, 2018
19e15a5
new commit
Jul 27, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,10 @@
# eddy_map
# Ocean Eddy Map

### Introduction

Ocean Eddy Map is an interactive application in which the positions, sizes, and trajectories of ocean mesoscale and submesoscale eddies can be viewed and explored on a global map.

### Data

Sea Surface Height Anomaly (SSHA) eddies
Rotationally Coherent Lagrangian Vortex (RCLV) eddies
9 changes: 5 additions & 4 deletions environment.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
name: flask_eddy_map
dependencies:
- python=2.7
- flask=0.10
- pymongo=3.0.3

- python=2.7.15
- flask=1.0.2
- pymongo=3.7.0
- pip:
- Flask-PyMongo
- Flask-PyMongo=2.0.1
254 changes: 192 additions & 62 deletions flask_app/app.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,220 @@
# -------------------------------------------------------------------------------------- imports ----- #
#!/usr/bin/env python
from flask import Flask, jsonify, send_file, request, Response
from flask.ext.pymongo import PyMongo
import json
from bson import json_util
from datetime import datetime
from flask import Flask, jsonify, request, Response, send_file
from flask_pymongo import PyMongo
import json


# --------------------------------------------------------------------------------------- basics ----- #
app = Flask(__name__)
app.config['MONGO_DBNAME'] = 'eddies'
app.config['MONGO_URI'] = 'mongodb://localhost:27017/eddies'
mongo = PyMongo(app)
#COLLECTION = 'rcs_eddies'
COLLECTION = 'ssh_eddies'


# ----------------------------------------------------------------------------------------- data ----- #
COLLECTION_RCS = 'rcs_eddies'
COLLECTION_SSH = 'ssh_eddies'


# ----------------------------------------------------------------------------------------- home ----- #
@app.route('/')
def index():
return send_file('static/index.html')

@app.route('/eddy/<eddy_id>')
def get_eddy(eddy_id):
"""Full data for eddy."""
eddy = mongo.db[COLLECTION].find_one({'_id': int(eddy_id)})

# ------------------------------------------------------------------------------------------ rcs ----- #

# --------------------------------------------------------------------- eddy ----- #
@app.route('/rcs_eddy/<string:eddy_id>')
def get_rcs_eddy(eddy_id):
eddy = mongo.db[COLLECTION_RCS].find_one({'_id': eddy_id})
return jsonify(eddy)

# ------------------------------------------------------------------- eddies ----- #
@app.route('/rcs_eddies')
def get_rcs_eddies(full_data=False, mean_trajectory=False,
dat_min=datetime.strptime('0001-01-01-12', '%Y-%m-%d-%H'),
dat_max=datetime.strptime('9999-12-31-12', '%Y-%m-%d-%H'),
dur_min=0, dur_max=10**10, lat_min=-90, lat_max=90, lon_min=0, lon_max=360):

# ------------------------------------------------- date ----- #
if request.args.get('dat_min'):
dat_min = datetime.strptime(str(request.args.get('dat_min'))+'-12', '%Y-%m-%d-%H')
if request.args.get('dat_max'):
dat_max = datetime.strptime(str(request.args.get('dat_max'))+'-12', '%Y-%m-%d-%H')

# --------------------------------------------- duration ----- #
if request.args.get('dur_min'):
dur_min = int(request.args.get('dur_min'))*7
if request.args.get('dur_max'):
dur_max = int(request.args.get('dur_max'))*7

# --------------------------------------------- latitude ----- #
if request.args.get('lat_min'):
lat_min = float(request.args.get('lat_min'))
if request.args.get('lat_max'):
lat_max = float(request.args.get('lat_max'))

# -------------------------------------------- longitude ----- #
if request.args.get('lon_min'):
lon_min = float(request.args.get('lon_min'))
if request.args.get('lon_max'):
lon_max = float(request.args.get('lon_max'))

# ----------------------------------------------- filter ----- #
filter = {'date_start': {'$gt': dat_min, '$lt': dat_max},
'duration': {'$gt': dur_min, '$lt': dur_max},
'loc_start': {'$within': {'$box': [[lon_min, lat_min], [lon_max, lat_max]]}}}

# ------------------------------------------------ slice ----- #
if full_data:
projection = None
else:
projection = {'features': {'$slice': 1}}

# ------------------------------------------------ alert ----- #
loading_max = 1000;
result_count = mongo.db[COLLECTION_RCS].find(filter, projection).count()
if result_count > loading_max:
alert = "Warning! Showing " + str(loading_max) + "/" + str(result_count) + " result(s)."
else:
alert = "Success! Showing all " + str(result_count) + " result(s)."

# ----------------------------------------------- inject ----- #
data = []
for eddy in mongo.db[COLLECTION_RCS].find(filter, projection).limit(loading_max):
try:
eddy['features'][0]['properties']['eddy_id'] = eddy['_id']
eddy['features'][0]['properties']['start_date'] = eddy['date_start']
eddy['features'][0]['properties']['end_date'] = eddy['date_end']
eddy['features'][0]['properties']['duration'] = eddy['duration']
eddy['features'][0]['properties']['mean_area'] = eddy['area']
if mean_trajectory:
start_pt = eddy['features'][0]['geometry']['coordinates']
end_pt = eddy['features'][1]['geometry']['coordinates']
eddy['features'].append({
'type': 'Feature',
'properties': {'name': 'trajectory'},
'geometry': {
'type': 'LineString',
'coordinates': [start_pt, end_pt]
}
})
data.append(eddy)
except KeyError:
app.logger.warning('problem parsing eddy ' + eddy['_id'])

# ------------------------------------------------- wrap ----- #
fc = {'type': 'FeatureCollection', 'features': data, 'properties': {'alert': alert}}
return jsonify(fc)


# ------------------------------------------------------------------------------------------ ssh ----- #

# --------------------------------------------------------------------- eddy ----- #
@app.route('/ssh_eddy/<int:eddy_id>')
def get_ssh_eddy(eddy_id):
eddy = mongo.db[COLLECTION_SSH].find_one({'_id': eddy_id})
return jsonify(eddy)

# ------------------------------------------------------------------- eddies ----- #
@app.route('/ssh_eddies')
def get_ssh_eddies(full_data=False, mean_trajectory=False,
dat_min=datetime.strptime('0001-01-01-12', '%Y-%m-%d-%H'),
dat_max=datetime.strptime('9999-12-31-12', '%Y-%m-%d-%H'),
dur_min=0, dur_max=10**10, lat_min=-90, lat_max=90, lon_min=0, lon_max=360):

# ------------------------------------------------- date ----- #
if request.args.get('dat_min'):
dat_min = datetime.strptime(str(request.args.get('dat_min'))+'-12', '%Y-%m-%d-%H')
if request.args.get('dat_max'):
dat_max = datetime.strptime(str(request.args.get('dat_max'))+'-12', '%Y-%m-%d-%H')

# --------------------------------------------- duration ----- #
if request.args.get('dur_min'):
dur_min = int(request.args.get('dur_min'))*7
if request.args.get('dur_max'):
dur_max = int(request.args.get('dur_max'))*7

# --------------------------------------------- latitude ----- #
if request.args.get('lat_min'):
lat_min = float(request.args.get('lat_min'))
if request.args.get('lat_max'):
lat_max = float(request.args.get('lat_max'))

# -------------------------------------------- longitude ----- #
if request.args.get('lon_min'):
lon_min = float(request.args.get('lon_min'))
if request.args.get('lon_max'):
lon_max = float(request.args.get('lon_max'))

# ----------------------------------------------- filter ----- #
filter = {'date_start': {'$gt': dat_min, '$lt': dat_max},
'duration': {'$gt': dur_min, '$lt': dur_max},
'loc_start': {'$within': {'$box': [[lon_min, lat_min], [lon_max, lat_max]]}}}

# ------------------------------------------------ slice ----- #
if full_data:
projection = None
else:
projection = {'features': {'$slice': 1}}

# ------------------------------------------------ alert ----- #
loading_max = 1000;
result_count = mongo.db[COLLECTION_SSH].find(filter, projection).count()
if result_count > loading_max:
alert = "Warning! Showing " + str(loading_max) + "/" + str(result_count) + " result(s)."
else:
alert = "Success! Showing all " + str(result_count) + " result(s)."

# ----------------------------------------------- inject ----- #
data = []
for eddy in mongo.db[COLLECTION_SSH].find(filter, projection).limit(loading_max):
try:
eddy['features'][0]['properties']['eddy_id'] = eddy['_id']
eddy['features'][0]['properties']['start_date'] = eddy['date_start']
eddy['features'][0]['properties']['end_date'] = eddy['date_end']
eddy['features'][0]['properties']['duration'] = eddy['duration']
eddy['features'][0]['properties']['mean_area'] = eddy['area']
if mean_trajectory:
start_pt = eddy['features'][0]['geometry']['coordinates']
end_pt = eddy['features'][1]['geometry']['coordinates']
eddy['features'].append({
'type': 'Feature',
'properties': {'name': 'trajectory'},
'geometry': {
'type': 'LineString',
'coordinates': [start_pt, end_pt]
}
})
data.append(eddy)
except KeyError:
app.logger.warning('problem parsing eddy ' + eddy['_id'])

# ------------------------------------------------- wrap ----- #
fc = {'type': 'FeatureCollection', 'features': data, 'properties': {'alert': alert}}
return jsonify(fc)


# ----------------------------------------------------------------------------------------- test ----- #
@app.route('/eddy_stream')
def stream_eddies(full_data=False, duration=30, add_mean_trajectory=False):
"""Query mongodb for all eddies in the database."""

# maybe overwrite duration from query string
if request.args.get('duration'):
duration = int(request.args.get('duration'))

# get everything
filter = {'duration': duration}

filter = {'duration': duration}
if full_data:
# get all fields, overloads the browser
projection = None
else:
# just get the first two features
# (initial center, final center)
projection = {'features': {'$slice': 1}}

query = mongo.db[COLLECTION].find(filter, projection)

# https://blog.al4.co.nz/2016/01/streaming-json-with-flask/
def generate():
"""
Expand All @@ -50,7 +223,6 @@ def generate():
thus we use a lagging generator, similar to http://stackoverflow.com/questions/1630320/
"""
releases = query.__iter__()

json_prefix = '{"type": "FeatureCollection", "features": ['
json_suffix = ']}'
try:
Expand All @@ -67,57 +239,15 @@ def generate():
prev_release = release
# Now yield the last iteration without comma but with the closing brackets
yield json.dumps(prev_release, default=json_util.default) + json_suffix

return Response(generate(), content_type='application/json')


@app.route('/eddies')
def get_eddies(full_data=False, duration=30, add_mean_trajectory=False):
"""Query mongodb for all eddies in the database."""

# maybe overwrite duration from query string
if request.args.get('duration'):
duration = int(request.args.get('duration'))

# get everything
#filter = {'duration': duration}
filter = {}

if full_data:
# get all fields, overloads the browser
projection = None
else:
# just get the first two features
# (initial center, final center)
projection = {'features': {'$slice': 1}}

data = []
for eddy in mongo.db[COLLECTION].find(filter, projection):
# inject id into properties of start point
try:
eddy['features'][0]['properties']['eddy_id'] = eddy['_id']
if add_mean_trajectory:
start_pt = eddy['features'][0]['geometry']['coordinates']
end_pt = eddy['features'][1]['geometry']['coordinates']
eddy['features'].append({
'type': 'Feature',
'properties': {'name': 'trajectory'},
'geometry': {
'type': 'LineString',
'coordinates': [start_pt, end_pt]
}
})
data.append(eddy)
except KeyError:
app.logger.warning('problem parsing eddy ' + eddy['_id'])

# wrap data into a larger FeatureCollection
fs = {'type': 'FeatureCollection', 'features': data}
return jsonify(fs)

# ----------------------------------------------------------------------------------------- path ----- #
@app.route('/static/<path:path>')
def send_js(path):
return send_from_directory('static', path)


# ------------------------------------------------------------------------------------------ end ----- #
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
Binary file added flask_app/static/.my_switch.js.swp
Binary file not shown.
Loading