Heatmap API

×

Warning message

You can't delete this newsletter because it has not been sent to all its subscribers.

''' Snap4city Computing HEATMAP.
   Copyright (C) 2024 DISIT Lab http://www.disit.org - University of Florence
   
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU Affero General Public License as
   published by the Free Software Foundation, either version 3 of the
   License, or (at your option) any later version.
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU Affero General Public License for more details.
   You should have received a copy of the GNU Affero General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
'''

from datetime import datetime

from flask import Flask, request, jsonify, make_response

from heatmap import heatmapIDW
from helper import parse_from_date, is_date

app = Flask(__name__)

@app.route('/')
def hello_word():
    return 'hello_word'

@app.route('/heatmap', methods=['POST'])
def heat_map():
    data = request.json
    date_format = '%Y-%m-%dT%H:%M:%S'

    required_fields = {
        'city': str,
        'long_min': float,
        'long_max': float,
        'lat_min': float,
        'lat_max': float,
        'epsg_projection': int,
        'value_types': list,
        'subnature': str,
        'scenario': str,
        'color_map': str,
        'from_date_time': str,
        'to_date_time': str,
        'token': str,
        'heat_map_model_name': str, 
    }

    missing_fields = [field for field in required_fields if field not in data]
    if missing_fields:
        return make_response(jsonify({
            "response": "error",
            "error": f"Missing fields: {', '.join(missing_fields)}"
        }), 400)

    for field, field_type in required_fields.items():
        if not isinstance(data.get(field), field_type):
            return make_response(jsonify({
                "response": "error",
                "message": f"Invalid data type for {field}. Expected {field_type.__name__}."
            }), 400)

    city = data.get('city')
    long_min = float(data.get('long_min'))
    long_max = float(data.get('long_max'))
    lat_min = float(data.get('lat_min'))
    lat_max = float(data.get('lat_max'))
    epsg_projection = int(data.get('epsg_projection'))
    value_types = data.get('value_types')
    # TODO handle value unit
    value_types = [value.split('-')[0] for value in value_types]
    subnature = data.get('subnature')
    scenario = data.get('scenario')
    color_map = data.get('color_map')
    from_date_time = data.get('from_date_time')
    to_date_time = data.get('to_date_time')
    token = data.get('token')
    heat_map_model_name = data.get('heat_map_model_name')
    model = data.get('model')
    clustered = int(data.get('clustered', 0))
    file = int(data.get('file', 1))
    broker = data.get('broker')

    if not (-180 <= long_min <= 180 and -180 <= long_max <= 180):
        return make_response(jsonify({
            "response": "error",
            "message": "Longitude values (long_min, long_max) must be between -180 and 180."
        }), 400)

    if not (-90 <= lat_min <= 90 and -90 <= lat_max <= 90):
        return make_response(jsonify({
            "response": "error",
            "message": "Latitude values (lat_min, lat_max) must be between -90 and 90."
        }), 400)

    if long_max <= long_min:
        return make_response(jsonify({
            "response": "error",
            "message": "Please insert 'long_max' and 'long_min' parameters correctly. 'long_max' must be greater than 'long_min'."
        }), 400)

    if lat_max <= lat_min:
        return make_response(jsonify({
            "response": "error",
            "message": "Please insert 'lat_max' and 'lat_min' parameters correctly. 'lat_max' must be greater than 'lat_min'."
        }), 400)

    parsed_from_date = parse_from_date(from_date_time, to_date_time)

    if parsed_from_date == None and is_date(from_date_time) == False:
        return make_response(jsonify({
            "response": "error",
            "error": "Please insert 'fromDateTime' parameter correctly and inject the node again. "
                     "The parameter has to be in a string format (n-hour or n-day) or in a date and time format (yyyy-mm-ddThh:mm:ss)"
        }), 400)

    if parsed_from_date == None:
        parsed_from_date = datetime.strptime(from_date_time, "%Y-%m-%dT%H:%M:%S")

    if is_date(to_date_time) == False:
        return make_response(jsonify({
            "response": "error",
            "error": "Please insert 'to_date_time' parameter correctly and inject the node again. The parameter has to be in a date and time format (yyyy-mm-ddThh:mm:ss)"
        }), 400)

    parsed_to_date = datetime.strptime(to_date_time, date_format)

    if parsed_to_date <= parsed_from_date:
        return make_response(jsonify({
            "response": "error",
            "message": "Please insert 'from_date_time' and 'to_date_time' parameters correctly. 'to_date_time' must be later than 'from_date_time'."
        }), 400)

    if model not in ['IDW']:
        return make_response(jsonify({
            "response": "error",
            "message": "Invalid AI model. Choose either 'IDW'."
        }), 400)

    if model == 'IDW':
        response = heatmapIDW(
            city=city,
            long_min=long_min,
            long_max=long_max,
            lat_min=lat_min,
            lat_max=lat_max,
            epsg_projection=epsg_projection,
            value_types=value_types,
            subnature=subnature,
            scenario=scenario,
            color_map=color_map,
            from_date_time=from_date_time,
            to_date_time=to_date_time,
            token=token,
            heat_map_model_name=heat_map_model_name,
            clustered=clustered,
            file=file,
            broker=broker
        )

        return response

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8085)

-------------------------

from https://github.com/disit/snap4city/blob/master/Computing/predictions/heatmap_service.py