Task 032: .ANN File Format
Task 032: .ANN File Format
The .ANN file format refers to the annotation file used in UAVSAR (Uninhabited Aerial Vehicle Synthetic Aperture Radar) data products from NASA. It is an ASCII text file containing keyword-value pairs that provide metadata for radar imagery, such as dimensions, spacing, coordinates, and processing details. The format supports comments starting with ';' and blank lines, with keywords potentially including units in parentheses. Keywords and their order may vary between files.
- List of all the properties of this file format intrinsic to its file system:
- Number of Looks in Range (looks)
- Number of Looks in Azimuth (looks)
- Slant Range Data Azimuth Lines (lines)
- Slant Range Data Range Samples (samples)
- Slant Range Data Azimuth Spacing (meters)
- Slant Range Data Range Spacing (meters)
- Slant Range Data at Near Range (meters)
- Slant Range Data Starting Azimuth (meters)
- Peg position and heading
- Ground Range Data Latitude Lines (lines)
- Ground Range Data Latitude Samples (samples)
- Ground Range Data Latitude Spacing (degrees)
- Ground Range Data Longitude Spacing (degrees)
- Ground Range Data Starting Latitude (degrees)
- Ground Range Data Starting Longitude (degrees)
- DEM Datum
- DEM source
- Two direct download links for files of format .ANN:
- https://uavsar.jpl.nasa.gov/science/documents/example_rpi.ann.txt
- https://uavsar.jpl.nasa.gov/Release2l/cscade_26901_10066-005_11057-002_0362d_s01_L090_00//cscade_26901_10066-005_11057-002_0362d_s01_L090HH_00.ann
- Ghost blog embedded HTML JavaScript for drag-and-drop .ANN file dump:
Drag and drop a .ANN file here
- Python class:
class AnnFile:
def __init__(self, filename=None):
self.properties = {}
if filename:
self.load(filename)
def load(self, filename):
with open(filename, 'r') as f:
for line in f:
line = line.strip()
if line.startswith(';') or not line:
continue
if '=' in line:
key, value = line.split('=', 1)
key = key.strip()
value = value.strip()
self.properties[key] = value
def print_properties(self):
for key, value in self.properties.items():
print(f"{key}: {value}")
def write(self, filename):
with open(filename, 'w') as f:
for key, value in self.properties.items():
f.write(f"{key} = {value}\n")
- Java class:
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class AnnFile {
private Map<String, String> properties = new HashMap<>();
public AnnFile(String filename) throws IOException {
if (filename != null) {
load(filename);
}
}
public void load(String filename) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filename))) {
String line;
while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.startsWith(";") || line.isEmpty()) {
continue;
}
if (line.contains("=")) {
String[] parts = line.split("=", 2);
String key = parts[0].trim();
String value = parts[1].trim();
properties.put(key, value);
}
}
}
}
public void printProperties() {
for (Map.Entry<String, String> entry : properties.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
public void write(String filename) throws IOException {
try (BufferedWriter writer = new BufferedWriter(new FileWriter(filename))) {
for (Map.Entry<String, String> entry : properties.entrySet()) {
writer.write(entry.getKey() + " = " + entry.getValue() + "\n");
}
}
}
}
- JavaScript class:
class AnnFile {
constructor(filename = null) {
this.properties = {};
if (filename) {
this.load(filename);
}
}
async load(filename) {
try {
const response = await fetch(filename);
const content = await response.text();
content.split('\n').forEach(line => {
line = line.trim();
if (line.startsWith(';') || !line) return;
if (line.includes('=')) {
const [key, value] = line.split('=', 2).map(s => s.trim());
this.properties[key] = value;
}
});
} catch (error) {
console.error('Error loading file:', error);
}
}
printProperties() {
for (const [key, value] of Object.entries(this.properties)) {
console.log(`${key}: ${value}`);
}
}
write(filename) {
let content = '';
for (const [key, value] of Object.entries(this.properties)) {
content += `${key} = ${value}\n`;
}
// For browser, use Blob to download
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
URL.revokeObjectURL(url);
}
}
- C class (implemented as C++ class for object-oriented support):
#include <iostream>
#include <fstream>
#include <string>
#include <map>
#include <algorithm>
class AnnFile {
private:
std::map<std::string, std::string> properties;
public:
AnnFile(const std::string& filename = "") {
if (!filename.empty()) {
load(filename);
}
}
void load(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
std::cerr << "Error opening file: " << filename << std::endl;
return;
}
std::string line;
while (std::getline(file, line)) {
line.erase(std::remove_if(line.begin(), line.end(), isspace), line.end()); // Trim whitespace
if (line.empty() || line[0] == ';') {
continue;
}
size_t pos = line.find('=');
if (pos != std::string::npos) {
std::string key = line.substr(0, pos);
std::string value = line.substr(pos + 1);
// Additional trim if needed
key.erase(std::remove_if(key.begin(), key.end(), isspace), key.end());
value.erase(std::remove_if(value.begin(), value.end(), isspace), value.end());
properties[key] = value;
}
}
file.close();
}
void printProperties() const {
for (const auto& pair : properties) {
std::cout << pair.first << ": " << pair.second << std::endl;
}
}
void write(const std::string& filename) const {
std::ofstream file(filename);
if (!file.is_open()) {
std::cerr << "Error opening file for writing: " << filename << std::endl;
return;
}
for (const auto& pair : properties) {
file << pair.first << " = " << pair.second << "\n";
}
file.close();
}
};