Analysis Results Overall
Results Structure
Currently all our analyses return results on the pedestrian level. They are arranged in a JSON onject that contains a field called results
and it's value is an encoded string. Once this string is decoded and parsed (see Results Decoding), they are a 512x512 matrix.
Each value of the matrix coresponds to the result on the respective analysis area grid point. Null values are located under the buildings.
The results matrix is arranged as follows:
- Starts from the bottom-left grid cell of the analysis area (centre of that grid cell would be (0.5,0.5,0))
- Filling each row from letf to right in 1m steps (allong x-axis).
- Filling rows from bottom to top (along y-axis)
See the diagram below:
You can download some dummy results after they have been decoded for testing purposes.
Results Decoding
The analysis results returned from the run-analysis API are in JSON format and structured as {"results":<encoded string>}
.
The encoded string is a compressed zip file, encoded in base64. So in order to get to the numerical values the encoded string needs to first be decoded to bytes and then decompressed.
Infrared.city will migrate from zip to gzip, so in order to avoid breaking changes in your code you should handle both zip and gzip as the code sample below.
The following code sample will decode and decompress the encoded string to a human readable JSON string. As a next step the json string needs to be parsed.
- Python
- C#
import gzip, zipfile, base64
import io
def decompress_base64(compressed_base64):
"""
Decompress a base64 encoded string that might be compressed with ZIP or GZIP.
Args:
compressed_base64 (str): Base64 encoded compressed data
Returns:
bytes: Decompressed data
"""
# Decode base64 to bytes
compressed_bytes = base64.b64decode(compressed_base64)
# Try ZIP first
try:
with io.BytesIO(compressed_bytes) as compressed_io:
with zipfile.ZipFile(compressed_io, 'r') as zf:
# Get the first file in the archive
if zf.namelist():
file_name = zf.namelist()[0]
with zf.open(file_name) as file:
return file.read().decode('utf-8')
except zipfile.BadZipFile:
# If not a ZIP file, try GZIP
try:
with io.BytesIO(compressed_bytes) as compressed_io:
with gzip.GzipFile(fileobj=compressed_io, mode='rb') as gz:
return gz.read().decode('utf-8')
except gzip.BadGzipFile:
# If neither ZIP nor GZIP works, raise an error
raise ValueError("Could not decompress the base64 string. Unknown compression format.")
using System;
using System.IO;
using System.IO.Compression;
using System.Text;
public class DecompressionUtil
{
/// <summary>
/// Decompress a base64 encoded string that might be compressed with ZIP or GZIP.
/// </summary>
/// <param name="compressedBase64">Base64 encoded compressed data</param>
/// <returns>Decompressed string</returns>
/// <exception cref="ArgumentException">Thrown when decompression fails</exception>
public static string DecompressBase64(string compressedBase64)
{
// Decode base64 to bytes
byte[] compressedBytes = Convert.FromBase64String(compressedBase64);
// Try ZIP first
try
{
using (var compressedStream = new MemoryStream(compressedBytes))
using (var archive = new ZipArchive(compressedStream, ZipArchiveMode.Read))
{
// Get the first file in the archive
if (archive.Entries.Count > 0)
{
var firstEntry = archive.Entries[0];
using (var reader = new StreamReader(firstEntry.Open()))
{
return reader.ReadToEnd();
}
}
}
}
catch (InvalidDataException)
{
// If not a ZIP file, try GZIP
try
{
using (var compressedStream = new MemoryStream(compressedBytes))
using (var gzipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var reader = new StreamReader(gzipStream, Encoding.UTF8))
{
return reader.ReadToEnd();
}
}
catch (InvalidDataException)
{
// If neither ZIP nor GZIP works, throw an error
throw new ArgumentException("Could not decompress the base64 string. Unknown compression format.");
}
}
throw new ArgumentException("No files found in the ZIP archive.");
}
}