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.

  1. 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)

  1. 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)

  1. 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.

Drag and drop .LDT file here
  1. 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')
  1. 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");
    }
}
  1. 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');
  1. 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;
}