Esempio n. 1
0
    def generate_streamed_json_response():

        cartogram_gen_output = b''
        current_loading_point = "null"

        # We have to format our JSON manually, since we're not sending a complete object.
        # On the client side, Oboe.js is intelligent enough to parse this and get the loading information and cartogram output
        yield '{"loading_progress_points":['

        for source, line in cartwrap.generate_cartogram(
                cartogram_handler.gen_area_data(values),
                cartogram_handler.get_gen_file(), settings.CARTOGRAM_EXE):

            if source == "stdout":
                cartogram_gen_output += line
            else:
                s = re.search(r'max\. abs\. area error: (.+)', line.decode())

                if s != None:
                    current_loading_point = s.groups(1)[0]

                # We always include the loading progress, even if it hasn't changed.
                # This makes life easier on the client side
                yield '{{"loading_point": {}, "stderr_line": "{}"}},'.format(
                    current_loading_point, line.decode())

        # We create a fake last entry because you can't have dangling commas in JSON
        yield '{"loading_point":0, "stderr_line": ""}],"cartogram_data":'

        if cartogram_handler.expect_geojson_output():
            # Just confirm that we've been given valid JSON. Calculate the extrema if necessary
            cartogram_json = json.loads(cartogram_gen_output.decode())

            if "bbox" not in cartogram_json:
                cartogram_json[
                    "bbox"] = geojson_extrema.get_extrema_from_geojson(
                        cartogram_json)
        else:
            cartogram_json = gen2dict.translate(
                io.StringIO(cartogram_gen_output.decode()),
                settings.CARTOGRAM_COLOR, cartogram_handler.remove_holes())

        cartogram_json['unique_sharing_key'] = unique_sharing_key

        cartogram_json = json.dumps(cartogram_json)

        if settings.USE_DATABASE:
            cartogram_entry = CartogramEntry.query.filter_by(
                string_key=unique_sharing_key).first()

            if cartogram_entry != None:
                cartogram_entry.cartogram_data = cartogram_json
                db.session.commit()

        yield cartogram_json

        yield "}"
Esempio n. 2
0
def cartogram():
    if 'handler' not in request.form:
        return Response('{"error":"badrequest"}',
                        status=400,
                        content_type="application/json")

    if request.form['handler'] not in cartogram_handlers:
        return Response('{"error":"badhandler"}',
                        status=404,
                        content_type="application/json")

    handler = request.form['handler']
    cartogram_handler = cartogram_handlers[handler]

    if 'values' not in request.form:
        return Response('{"error":"badrequest"}',
                        status=400,
                        content_type="application/json")

    values = request.form['values'].split(";")
    # The existing verificaiton code expects all floats. To avoid modifying it, we replace the string "NA" with the
    # number 0.0 for verification purposes only.
    values_to_verify = []

    try:
        for i in range(len(values)):
            if values[i] == "NA":
                values_to_verify.append(0.0)
            else:
                values[i] = float(values[i])
                values_to_verify.append(values[i])
    except ValueError:
        return Response('{"error":"badvalues"}',
                        status=400,
                        content_type="application/json")

    if cartogram_handler.validate_values(values_to_verify) != True:
        return Response('{"error":"badvalues"}',
                        status=400,
                        content_type="application/json")

    unique_sharing_key = ""

    if 'unique_sharing_key' in request.form:
        unique_sharing_key = request.form['unique_sharing_key']

    lambda_result = awslambda.generate_cartogram(
        cartogram_handler.gen_area_data(values),
        cartogram_handler.get_gen_file(), settings.CARTOGRAM_LAMBDA_URL,
        settings.CARTOGRAM_LAMDA_API_KEY, unique_sharing_key)

    cartogram_gen_output = lambda_result['stdout']

    if cartogram_handler.expect_geojson_output():
        # Just confirm that we've been given valid JSON. Calculate the extrema if necessary
        cartogram_json = json.loads(cartogram_gen_output)

        if "bbox" not in cartogram_json:
            cartogram_json["bbox"] = geojson_extrema.get_extrema_from_geojson(
                cartogram_json)
    else:
        cartogram_json = gen2dict.translate(io.StringIO(cartogram_gen_output),
                                            settings.CARTOGRAM_COLOR,
                                            cartogram_handler.remove_holes())

    cartogram_json['unique_sharing_key'] = unique_sharing_key

    if settings.USE_DATABASE:
        cartogram_entry = CartogramEntry.query.filter_by(
            string_key=unique_sharing_key).first()

        if cartogram_entry != None:
            cartogram_entry.cartogram_data = json.dumps(cartogram_json)
            db.session.commit()

    return Response(json.dumps({'cartogram_data': cartogram_json}),
                    content_type='application/json',
                    status=200)
Esempio n. 3
0
    cartogram_output = ""

    for source, line in cartwrap.generate_cartogram(area_data,
                                                    handler.get_gen_file(),
                                                    settings.CARTOGRAM_EXE):

        if source == "stderr":
            print("Generating {}: {}".format(sysname, line.decode()))
        else:
            cartogram_output += line.decode()

    if handler.expect_geojson_output():

        cartogram_json = json.loads(cartogram_output)

        if "bbox" not in cartogram_json:
            cartogram_json["bbox"] = geojson_extrema.get_extrema_from_geojson(
                cartogram_json)

    else:

        cartogram_json = gen2dict.translate(io.StringIO(cartogram_output),
                                            settings.CARTOGRAM_COLOR,
                                            handler.remove_holes())

    cartogram_json['tooltip'] = tooltip

    with open("static/cartdata/{}/population.json".format(sysname),
              'w') as population_json_file:

        json.dump(cartogram_json, population_json_file)
Esempio n. 4
0
def generate_cartogram_set(maps, cartogram_executable, default_color):

    maximum_progress = 95.0
    current_progress = 0.0
    main_average_density = 0.0

    map_number = 1

    for cart_map in maps:

        cartogram_gen = ""
        cartogram_json = {}

        cartogram_area = 0.0
        cartogram_average_density = 0.0

        initial_area_error = None
        one_region_cartogram = False

        yield "loading", {
            'loading_point': current_progress,
            'stderr_line':
            'Computing Map {} of {}'.format(map_number, len(maps))
        }

        for source, line in generate_cartogram(cart_map['area_data'],
                                               cart_map['gen_file'],
                                               cartogram_executable):

            if source == "stdout":
                map_gen += line
            else:
                s = re.search(r'max\. abs\. area error: (.+)', line.decode())

                if s != None:

                    if initial_area_error == None:
                        initial_area_error = float(s.groups(1)[0])
                        current_progress = (
                            0 if map_number == 1 else maximum_progress /
                            map_number) + (maximum_progress / len(maps)) * 0.2
                    else:
                        current_progress = (
                            0 if map_number == 1 else maximum_progress /
                            map_number) + (
                                ((initial_area_error - float(s.groups(1)[0])) /
                                 ((initial_area_error - 0.01))) *
                                ((maximum_progress / len(maps))))

                area_search = re.search(r'total cartogram area: (.+)',
                                        line.decode())

                if area_search != None:
                    cartogram_area = float(area_search.groups(1)[0])

                one_region_search = re.search(
                    r'WARNING: There is only one region. The output cartogram will',
                    line.decode())

                if one_region_search != None:
                    one_region_cartogram = True

                yield "loading", {
                    'loading_point': current_progress,
                    'stderr_line': line.decode()
                }

        # Now we want to calculate the average density
        cartogram_average_density = sum([
            float(entry.split(' ')[1])
            for entry in cart_map['area_data'].split('\n')
        ]) / cartogram_area

        if map_number == 1:
            main_average_density = cartogram_average_density

        cartogram_json = gen2dict.translate(
            io.StringIO(cartogram_gen.decode()), default_color)

        # If we're not dealing with the main map (i.e., the first one) and we
        # only one region, then we need to do the scaling here.

        if map_number != 1 and one_region_cartogram:

            # In this case, cartogram_average_density is the same as the user-
            # supplied area for the one region in this map.

            scaling_factor = math.sqrt(cartogram_average_density /
                                       main_average_density)

            for feature in cartogram_json['features']:

                for pair in feature['coordinates']:

                    pair[0] *= scaling_factor
                    pair[1] *= scaling_factor

        yield "output", cartogram_json

        map_number += 1
Esempio n. 5
0
import gen2dict
import sys

with open(sys.argv[1]) as map_gen_file:
    gen_json = gen2dict.translate(map_gen_file, "#aaaaaa", True)

with open(sys.argv[2], "w") as svg_file:

    max_x = gen_json["extrema"]["max_x"]
    min_x = gen_json["extrema"]["min_x"]
    max_y = gen_json["extrema"]["max_y"]
    min_y = gen_json["extrema"]["min_y"]

    width = max_x - min_x
    height = max_y - min_y

    scale = 750.0 / width

    width *= scale
    height *= scale

    def x_transform(x):

        return (x - min_x) * scale

    def y_transform(y):

        return ((max_y - min_y) - (y - min_y)) * scale

    svg_file.write("""<svg version="1.1"
baseProfile="full"