Task 353: .LDT File Format
Task 353: .LDT File Format
The .LDT file format is the EULUMDAT format, a text-based format for specifying photometric data, particularly intensity distributions from light sources such as lamps and luminaires. It is the European equivalent to the IESNA LM-63 format and is used in lighting design software like DIALux, Relux, and others.
- List of all the properties of this file format intrinsic to its file system:
The format is a plain text ASCII file where each property is on a specific line or set of lines, with fixed or maximum character lengths. The properties are as follows (based on the standard specification, with line numbers for reference):
Line 1: Company identification/databank/version/format identification (max 78 characters, ASCII string)
Line 2: Ityp - Type indicator (1 character, ASCII string: 0 = point source with no symmetry; 1 = symmetry about the vertical axis; 2 = linear luminaire; 3 = point source with any other symmetry)
Line 3: Isym - Symmetry indicator (1 character, ASCII string: 0 = no symmetry; 1 = symmetry about the vertical axis; 2 = symmetry to plane C0-C180; 3 = symmetry to plane C90-C270; 4 = symmetry to plane C0-C180 and to plane C90-C270)
Line 4: Mc - Number of C-planes between 0 and 360 degrees (2 characters, integer, typically 24 for interior or 36 for road lighting)
Line 5: Dc - Distance between C-planes (5 characters, number, Dc = 0 for non-equidistantly available C-planes)
Line 6: Ng - Number of luminous intensities in each C-plane (2 characters, integer, typically 19 or 37)
Line 7: Dg - Distance between luminous intensities per C-plane (5 characters, number, Dg = 0 for non-equidistantly available luminous intensities in C-planes)
Line 8: Measurement report number (max 78 characters, ASCII string)
Line 9: Luminaire name (max 78 characters, ASCII string)
Line 10: Luminaire number (max 78 characters, ASCII string)
Line 11: File name (8 characters, ASCII string)
Line 12: Date/user (max 78 characters, ASCII string)
Line 13: Length/diameter of luminaire (4 characters, mm, integer)
Line 14: b - Width of luminaire (4 characters, mm, integer, b = 0 for circular luminaire)
Line 15: Height of luminaire (4 characters, mm, integer)
Line 16: Length/diameter of luminous area (4 characters, mm, integer)
Line 17: b1 - Width of luminous area (4 characters, mm, integer, b1 = 0 for circular luminous area)
Line 18: Height of luminous area C0-plane (4 characters, mm, integer)
Line 19: Height of luminous area C90-plane (4 characters, mm, integer)
Line 20: Height of luminous area C180-plane (4 characters, mm, integer)
Line 21: Height of luminous area C270-plane (4 characters, mm, integer)
Line 22: DFF - Downward flux fraction (4 characters, %, number)
Line 23: LORL - Light output ratio luminaire (4 characters, %, number)
Line 24: Conversion factor for luminous intensities (6 characters, number)
Line 25: Tilt of luminaire during measurement (6 characters, number, for road lighting luminaires)
Line 26: n - Number of standard sets of lamps (4 characters, integer, optional; for absolute photometry, this is 1)
Line 26a: Number of lamps (n * 4 characters, integer; negative for absolute photometry)
Line 26b: Type of lamps (n * 24 characters, ASCII string)
Line 26c: Total luminous flux of lamps (n * 12 characters, lm, number; for absolute photometry, this is total luminous flux of luminaire)
Line 26d: Color appearance / color temperature of lamps (n * 16 characters, ASCII string)
Line 26e: Color rendering group / color rendering index (n * 6 characters, ASCII string)
Line 26f: Wattage including ballast (n * 8 characters, W, number)
Line 27: DR - Direct ratios for room indices k = 0.6 ... 5 (10 * 7 characters, numbers, for utilization factor method)
Line 28: Angles C (beginning with 0 degrees) (Mc * 6 characters, numbers)
Line 29: Angles G (beginning with 0 degrees) (Ng * 6 characters, numbers)
Line 30: Tilt angles during measurement (road lighting luminaires) (optional, numbers)
Line 31 and beyond: Luminous intensity distribution (cd / klm, numbers, arranged by C-planes and G-angles; the number of lines depends on Mc and Ng)
- Two direct download links for files of format .LDT:
https://paulbourke.net/dataformats/ldt/sample.ldt
https://www.ransensoftware.com/Photometric/sample.ldt (note: based on site references to sample files; verify accessibility as some sites may require navigation)
- Ghost blog embedded html javascript that allows a user to drag n drop a file of format .LDT and it will dump to screen all these properties.
Here is a self-contained HTML snippet with JavaScript that can be embedded in a Ghost blog post (or any HTML editor). It creates a drag-and-drop area, reads the .LDT file using FileReader, parses the lines according to the spec, and displays the properties in a readable format on the screen.
- Python class that can open any file of format .LDT and decode read and write and print to console all the properties from the above list.
Here is a Python class LDTFile
that opens, reads, parses, prints the properties to console, and can write a new .LDT file based on modified properties.
import os
class LDTFile:
def __init__(self, filepath):
self.filepath = filepath
self.properties = {}
self.data_lines = []
self.read()
def read(self):
with open(self.filepath, 'r') as f:
lines = [line.strip() for line in f.readlines()]
self.properties['company_identification'] = lines[0]
self.properties['type_indicator'] = lines[1]
self.properties['symmetry_indicator'] = lines[2]
self.properties['num_c_planes'] = lines[3]
self.properties['dist_c_planes'] = lines[4]
self.properties['num_luminous_intensities'] = lines[5]
self.properties['dist_luminous_intensities'] = lines[6]
self.properties['measurement_report_num'] = lines[7]
self.properties['luminaire_name'] = lines[8]
self.properties['luminaire_num'] = lines[9]
self.properties['file_name'] = lines[10]
self.properties['date_user'] = lines[11]
self.properties['luminaire_length_diameter'] = lines[12]
self.properties['luminaire_width'] = lines[13]
self.properties['luminaire_height'] = lines[14]
self.properties['luminous_area_length_diameter'] = lines[15]
self.properties['luminous_area_width'] = lines[16]
self.properties['luminous_area_height_c0'] = lines[17]
self.properties['luminous_area_height_c90'] = lines[18]
self.properties['luminous_area_height_c180'] = lines[19]
self.properties['luminous_area_height_c270'] = lines[20]
self.properties['downward_flux_fraction'] = lines[21]
self.properties['light_output_ratio'] = lines[22]
self.properties['conversion_factor'] = lines[23]
self.properties['tilt_during_measurement'] = lines[24]
self.properties['num_lamp_sets'] = lines[25]
# Assume n=1 for simplicity; extend for multiple
self.properties['num_lamps'] = lines[26]
self.properties['lamp_type'] = lines[27]
self.properties['luminous_flux'] = lines[28]
self.properties['color_appearance_temp'] = lines[29]
self.properties['color_rendering'] = lines[30]
self.properties['wattage'] = lines[31]
self.properties['direct_ratios'] = lines[32]
self.properties['angles_c'] = lines[33]
self.properties['angles_g'] = lines[34]
self.properties['tilt_angles'] = lines[35]
self.data_lines = lines[36:]
def print_properties(self):
for key, value in self.properties.items():
print(f"{key.capitalize().replace('_', ' ')}: {value}")
print("Luminous intensity distribution:")
print('\n'.join(self.data_lines))
def write(self, new_filepath=None):
if not new_filepath:
new_filepath = self.filepath + '.new'
with open(new_filepath, 'w') as f:
for value in self.properties.values():
f.write(f"{value}\n")
for line in self.data_lines:
f.write(f"{line}\n")
print(f"File written to {new_filepath}")
# Example usage:
# ldt = LDTFile('sample.ldt')
# ldt.print_properties()
# ldt.write('modified.ldt')
- Java class that can open any file of format .LDT and decode read and write and print to console all the properties from the above list.
Here is a Java class LDTFile
that opens, reads, parses, prints the properties to console, and can write a new .LDT file.
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
public class LDTFile {
private String filepath;
private Map<String, String> properties = new LinkedHashMap<>();
private List<String> dataLines = new ArrayList<>();
public LDTFile(String filepath) {
this.filepath = filepath;
read();
}
private void read() {
try (BufferedReader br = new BufferedReader(new FileReader(filepath))) {
List<String> lines = new ArrayList<>();
String line;
while (line = br.readLine() != null) {
lines.add(line.trim());
}
properties.put("company_identification", lines.get(0));
properties.put("type_indicator", lines.get(1));
properties.put("symmetry_indicator", lines.get(2));
properties.put("num_c_planes", lines.get(3));
properties.put("dist_c_planes", lines.get(4));
properties.put("num_luminous_intensities", lines.get(5));
properties.put("dist_luminous_intensities", lines.get(6));
properties.put("measurement_report_num", lines.get(7));
properties.put("luminaire_name", lines.get(8));
properties.put("luminaire_num", lines.get(9));
properties.put("file_name", lines.get(10));
properties.put("date_user", lines.get(11));
properties.put("luminaire_length_diameter", lines.get(12));
properties.put("luminaire_width", lines.get(13));
properties.put("luminaire_height", lines.get(14));
properties.put("luminous_area_length_diameter", lines.get(15));
properties.put("luminous_area_width", lines.get(16));
properties.put("luminous_area_height_c0", lines.get(17));
properties.put("luminous_area_height_c90", lines.get(18));
properties.put("luminous_area_height_c180", lines.get(19));
properties.put("luminous_area_height_c270", lines.get(20));
properties.put("downward_flux_fraction", lines.get(21));
properties.put("light_output_ratio", lines.get(22));
properties.put("conversion_factor", lines.get(23));
properties.put("tilt_during_measurement", lines.get(24));
properties.put("num_lamp_sets", lines.get(25));
// Assume n=1 for simplicity; extend for multiple
properties.put("num_lamps", lines.get(26));
properties.put("lamp_type", lines.get(27));
properties.put("luminous_flux", lines.get(28));
properties.put("color_appearance_temp", lines.get(29));
properties.put("color_rendering", lines.get(30));
properties.put("wattage", lines.get(31));
properties.put("direct_ratios", lines.get(32));
properties.put("angles_c", lines.get(33));
properties.put("angles_g", lines.get(34));
properties.put("tilt_angles", lines.get(35));
for (int i = 36; i < lines.size(); i++) {
dataLines.add(lines.get(i));
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void printProperties() {
for (Map.Entry<String, String> entry : properties.entrySet()) {
System.out.println(entry.getKey().replace('_', ' ').substring(0, 1).toUpperCase() + entry.getKey().replace('_', ' ').substring(1) + ": " + entry.getValue());
}
System.out.println("Luminous intensity distribution:");
for (String line : dataLines) {
System.out.println(line);
}
}
public void write(String newFilepath) {
if (newFilepath == null) {
newFilepath = filepath + ".new";
}
try (PrintWriter pw = new PrintWriter(newFilepath)) {
for (String value : properties.values()) {
pw.println(value);
}
for (String line : dataLines) {
pw.println(line);
}
System.out.println("File written to " + newFilepath);
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
LDTFile ldt = new LDTFile("sample.ldt");
ldt.printProperties();
ldt.write("modified.ldt");
}
}
- Javascript class that can open any file of format .LDT and decode read and write and print to console all the properties from the above list.
Here is a JavaScript class LDTFile
that can be used in a browser or Node.js (with fs for Node). It reads, parses, prints to console, and can write a new file (in browser, it prompts download; in Node, it writes to disk).
class LDTFile {
constructor(filepath) {
this.filepath = filepath;
this.properties = {};
this.dataLines = [];
// For browser, this would require FileReader; for Node, use fs
// Assuming Node for this example
const fs = require('fs');
this.read(fs.readFileSync(filepath, 'utf8'));
}
read(content) {
const lines = content.split('\n').map(line => line.trim());
this.properties.company_identification = lines[0];
this.properties.type_indicator = lines[1];
this.properties.symmetry_indicator = lines[2];
this.properties.num_c_planes = lines[3];
this.properties.dist_c_planes = lines[4];
this.properties.num_luminous_intensities = lines[5];
this.properties.dist_luminous_intensities = lines[6];
this.properties.measurement_report_num = lines[7];
this.properties.luminaire_name = lines[8];
this.properties.luminaire_num = lines[9];
this.properties.file_name = lines[10];
this.properties.date_user = lines[11];
this.properties.luminaire_length_diameter = lines[12];
this.properties.luminaire_width = lines[13];
this.properties.luminaire_height = lines[14];
this.properties.luminous_area_length_diameter = lines[15];
this.properties.luminous_area_width = lines[16];
this.properties.luminous_area_height_c0 = lines[17];
this.properties.luminous_area_height_c90 = lines[18];
this.properties.luminous_area_height_c180 = lines[19];
this.properties.luminous_area_height_c270 = lines[20];
this.properties.downward_flux_fraction = lines[21];
this.properties.light_output_ratio = lines[22];
this.properties.conversion_factor = lines[23];
this.properties.tilt_during_measurement = lines[24];
this.properties.num_lamp_sets = lines[25];
// Assume n=1 for simplicity; extend for multiple
this.properties.num_lamps = lines[26];
this.properties.lamp_type = lines[27];
this.properties.luminous_flux = lines[28];
this.properties.color_appearance_temp = lines[29];
this.properties.color_rendering = lines[30];
this.properties.wattage = lines[31];
this.properties.direct_ratios = lines[32];
this.properties.angles_c = lines[33];
this.properties.angles_g = lines[34];
this.properties.tilt_angles = lines[35];
this.dataLines = lines.slice(36);
}
printProperties() {
for (const [key, value] in Object.entries(this.properties)) {
console.log(`${key.replace(/_/g, ' ').replace(/\b\w/g, c => c.toUpperCase())}: ${value}`);
}
console.log('Luminous intensity distribution:');
this.dataLines.forEach(line => console.log(line));
}
write(newFilepath) {
const fs = require('fs');
if (!newFilepath) {
newFilepath = this.filepath + '.new';
}
const content = Object.values(this.properties).join('\n') + '\n' + this.dataLines.join('\n');
fs.writeSync(newFilepath, content, 'utf8');
console.log(`File written to ${newFilepath}`);
}
}
// Example usage in Node:
const ldt = new LDTFile('sample.ldt');
ldt.printProperties();
ldt.write('modified.ldt');
- C class that can open any file of format .LDT and decode read and write and print to console all the properties from the above list.
Since C does not have classes, here is a C++ class LDTFile
that opens, reads, parses, prints the properties to console, and can write a new .LDT file.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <map>
class LDTFile {
private:
std::string filepath;
std::map<std::string, std::string> properties;
std::vector<std::string> dataLines;
public:
LDTFile(const std::string& fp) : filepath(fp) {
read();
}
void read() {
std::ifstream file(filepath);
std::vector<std::string> lines;
std::string line;
while (std::getline(file, line)) {
// Trim
line.erase(0, line.find_first_not_of(" \t"));
line.erase(line.find_last_not_of(" \t") + 1);
lines.push_back(line);
}
file.close();
properties["company_identification"] = lines[0];
properties["type_indicator"] = lines[1];
properties["symmetry_indicator"] = lines[2];
properties["num_c_planes"] = lines[3];
properties["dist_c_planes"] = lines[4];
properties["num_luminous_intensities"] = lines[5];
properties["dist_luminous_intensities"] = lines[6];
properties["measurement_report_num"] = lines[7];
properties["luminaire_name"] = lines[8];
properties["luminaire_num"] = lines[9];
properties["file_name"] = lines[10];
properties["date_user"] = lines[11];
properties["luminaire_length_diameter"] = lines[12];
properties["luminaire_width"] = lines[13];
properties["luminaire_height"] = lines[14];
properties["luminous_area_length_diameter"] = lines[15];
properties["luminous_area_width"] = lines[16];
properties["luminous_area_height_c0"] = lines[17];
properties["luminous_area_height_c90"] = lines[18];
properties["luminous_area_height_c180"] = lines[19];
properties["luminous_area_height_c270"] = lines[20];
properties["downward_flux_fraction"] = lines[21];
properties["light_output_ratio"] = lines[22];
properties["conversion_factor"] = lines[23];
properties["tilt_during_measurement"] = lines[24];
properties["num_lamp_sets"] = lines[25];
// Assume n=1 for simplicity; extend for multiple
properties["num_lamps"] = lines[26];
properties["lamp_type"] = lines[27];
properties["luminous_flux"] = lines[28];
properties["color_appearance_temp"] = lines[29];
properties["color_rendering"] = lines[30];
properties["wattage"] = lines[31];
properties["direct_ratios"] = lines[32];
properties["angles_c"] = lines[33];
properties["angles_g"] = lines[34];
properties["tilt_angles"] = lines[35];
for (size_t i = 36; i < lines.size(); ++i) {
dataLines.push_back(lines[i]);
}
}
void printProperties() {
for (const auto& pair : properties) {
std::string key = pair.first;
for (size_t pos = 0; (pos = key.find('_', pos)) != std::string::npos; ++pos) {
key[pos] = ' ';
}
key[0] = toupper(key[0]);
std::cout << key << ": " << pair.second << std::endl;
}
std::cout << "Luminous intensity distribution:" << std::endl;
for (const auto& line : dataLines) {
std::cout << line << std::endl;
}
}
void write(const std::string& newFilepath = "") {
std::string outPath = newFilepath.empty() ? filepath + ".new" : newFilepath;
std::ofstream file(outPath);
for (const auto& pair : properties) {
file << pair.second << std::endl;
}
for (const auto& line : dataLines) {
file << line << std::endl;
}
file.close();
std::cout << "File written to " << outPath << std::endl;
}
};
int main() {
LDTFile ldt("sample.ldt");
ldt.printProperties();
ldt.write("modified.ldt");
return 0;
}