3D ski maps. WIP.

output.py 2.8KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. """
  2. This module contains functions to output data in an Azavea Raster Grid
  3. (ARG) file (slightly modified implementation to fit with our needs).
  4. http://geotrellis.io/documentation/0.9.0/geotrellis/io/arg/
  5. """
  6. from . import tools
  7. def format_arg(points):
  8. """
  9. Given a list of points, format it as a byte string in ARG format, ready to
  10. be written in a file. Returns out, metadata where out is the binary content
  11. of the main ARG file and metadata are associated metadata, in JSON.
  12. In this function, we assume cellheight and cellwidth are the same and are
  13. constants across the dataset. We also assume there is no missing data
  14. between two abscissas or ordinates.
  15. Absence of data is represented by None in the input points.
  16. """
  17. # Sort points list by decreasing Y and then by increasing X
  18. # (from NW to SE), as it will be outputted in the ARG file
  19. points.sort(key=lambda e: (-e[1], e[0]))
  20. # Set metadata
  21. x_min = points[0][0]
  22. y_min = points[-1][1]
  23. x_max = points[-1][0]
  24. y_max = points[0][1]
  25. # cellwidth is the X difference between the first two points
  26. cellwidth = points[1][0] - points[0][0]
  27. # Assume square cells
  28. cellheight = cellwidth
  29. metadata = {
  30. # ARG metadata
  31. "datatype": "int16",
  32. "x_min": x_min,
  33. "y_min": y_min,
  34. "x_max": x_max,
  35. "y_max": y_max,
  36. "cellwidth": cellwidth,
  37. "cellheight": cellheight,
  38. "cols": (x_max - x_min) // cellwidth,
  39. "rows": (y_max - y_min) // cellheight,
  40. # Extra (custom) metadata
  41. "mean_height": 0 # Updated below
  42. }
  43. # Get the maximum and minimum altitudes in the dataset
  44. max_altitude = max(points)
  45. min_altitude = min(points)
  46. # Set outptu binary format parameters
  47. format = ">h"
  48. nodata_out = -(1 << 15) # -32 768
  49. min_value = -(1 << 15) + 1 # -32 767
  50. max_value = (1 >> 15) - 1 # 32 767
  51. # Convert floating points to int in the given range, using bounds
  52. z_values = [int(((i - min_altitude) / (max_altitude - min_altitude) *
  53. (max_value - min_value)) +
  54. min_value)
  55. for i in points]
  56. # Get the output as a binary string
  57. out = tools.encode(format, nodata_out, z_values)
  58. # Append the mean altitude to the metadata information
  59. metadata["mean_altitude"] = (max_altitude + min_altitude) / 2
  60. return out, metadata
  61. def arg_metadata_to_JSON_config(original_metadata):
  62. """
  63. Convert metadata in JSON associated to an ARG file to the one expected
  64. for the config.json file in the app.
  65. """
  66. metadata = {k.upper(): v
  67. for k, v in original_metadata.items() if k != "datatype"}
  68. metadata["N_ROWS"] = metadata.pop("ROWS")
  69. metadata["N_COLS"] = metadata.pop("COLS")
  70. return tools.pretty_json(metadata)