Task 852: .XYZ File Format

Task 852: .XYZ File Format

  1. The .XYZ file format is a simple, text-based format commonly used in computational chemistry to represent molecular structures. It specifies atomic positions in Cartesian coordinates. The properties intrinsic to this file format include:
  • Atom count: An integer indicating the total number of atoms in the molecule.
  • Title: A string providing a comment or description of the molecule.
  • Atom details: For each atom, the following are specified:
  • Element identifier: A string representing the chemical element symbol (e.g., "C" for carbon) or, alternatively, an integer for the atomic number.
  • X coordinate: A floating-point number representing the position along the X-axis, typically in angstroms.
  • Y coordinate: A floating-point number representing the position along the Y-axis, typically in angstroms.
  • Z coordinate: A floating-point number representing the position along the Z-axis, typically in angstroms.

These properties are structured sequentially in the file: the atom count on the first line, the title on the second line, and each subsequent line detailing one atom's element identifier and coordinates.

Two direct download links for .XYZ files are as follows:

Below is the HTML code with embedded JavaScript that can be embedded in a Ghost blog post. It enables users to drag and drop a .XYZ file, parses the file, and displays the properties (atom count, title, and atom details) on the screen.

XYZ File Parser
Drag and drop a .XYZ file here
  1. Below is a Python class that can open, read, decode, write, and print the properties of a .XYZ file to the console.
import sys

class XYZFileHandler:
    def __init__(self, filepath):
        self.filepath = filepath
        self.atom_count = 0
        self.title = ''
        self.atoms = []  # List of tuples: (element, x, y, z)

    def read(self):
        try:
            with open(self.filepath, 'r') as file:
                lines = file.readlines()
                if len(lines) < 2:
                    raise ValueError("Invalid .XYZ file format.")
                self.atom_count = int(lines[0].strip())
                self.title = lines[1].strip()
                self.atoms = []
                for line in lines[2:]:
                    parts = line.strip().split()
                    if len(parts) >= 4:
                        element = parts[0]
                        x, y, z = float(parts[1]), float(parts[2]), float(parts[3])
                        self.atoms.append((element, x, y, z))
                if len(self.atoms) != self.atom_count:
                    raise ValueError("Atom count mismatch in .XYZ file.")
        except Exception as e:
            print(f"Error reading file: {e}", file=sys.stderr)

    def write(self, new_filepath=None):
        if not new_filepath:
            new_filepath = self.filepath
        try:
            with open(new_filepath, 'w') as file:
                file.write(f"{self.atom_count}\n")
                file.write(f"{self.title}\n")
                for atom in self.atoms:
                    file.write(f"{atom[0]} {atom[1]:.6f} {atom[2]:.6f} {atom[3]:.6f}\n")
        except Exception as e:
            print(f"Error writing file: {e}", file=sys.stderr)

    def print_properties(self):
        print(f"Atom Count: {self.atom_count}")
        print(f"Title: {self.title}")
        print("Atoms:")
        for i, atom in enumerate(self.atoms, start=1):
            print(f"Atom {i}: Element: {atom[0]}, X: {atom[1]}, Y: {atom[2]}, Z: {atom[3]}")

# Example usage:
# handler = XYZFileHandler('example.xyz')
# handler.read()
# handler.print_properties()
# handler.write('new_example.xyz')
  1. Below is a Java class that can open, read, decode, write, and print the properties of a .XYZ file to the console.
import java.io.*;
import java.util.ArrayList;
import java.util.List;

public class XYZFileHandler {
    private String filepath;
    private int atomCount;
    private String title;
    private List<Atom> atoms;  // Inner class for atom details

    public XYZFileHandler(String filepath) {
        this.filepath = filepath;
        this.atoms = new ArrayList<>();
    }

    public void read() throws IOException {
        try (BufferedReader reader = new BufferedReader(new FileReader(filepath))) {
            String line = reader.readLine();
            if (line == null) {
                throw new IOException("Invalid .XYZ file format.");
            }
            atomCount = Integer.parseInt(line.trim());
            line = reader.readLine();
            if (line == null) {
                throw new IOException("Invalid .XYZ file format.");
            }
            title = line.trim();
            atoms.clear();
            while ((line = reader.readLine()) != null) {
                String[] parts = line.trim().split("\\s+");
                if (parts.length >= 4) {
                    String element = parts[0];
                    double x = Double.parseDouble(parts[1]);
                    double y = Double.parseDouble(parts[2]);
                    double z = Double.parseDouble(parts[3]);
                    atoms.add(new Atom(element, x, y, z));
                }
            }
            if (atoms.size() != atomCount) {
                throw new IOException("Atom count mismatch in .XYZ file.");
            }
        }
    }

    public void write(String newFilepath) throws IOException {
        if (newFilepath == null) {
            newFilepath = filepath;
        }
        try (BufferedWriter writer = new BufferedWriter(new FileWriter(newFilepath))) {
            writer.write(atomCount + "\n");
            writer.write(title + "\n");
            for (Atom atom : atoms) {
                writer.write(String.format("%s %.6f %.6f %.6f\n", atom.element, atom.x, atom.y, atom.z));
            }
        }
    }

    public void printProperties() {
        System.out.println("Atom Count: " + atomCount);
        System.out.println("Title: " + title);
        System.out.println("Atoms:");
        for (int i = 0; i < atoms.size(); i++) {
            Atom atom = atoms.get(i);
            System.out.printf("Atom %d: Element: %s, X: %.6f, Y: %.6f, Z: %.6f\n", i + 1, atom.element, atom.x, atom.y, atom.z);
        }
    }

    private static class Atom {
        String element;
        double x, y, z;

        Atom(String element, double x, double y, double z) {
            this.element = element;
            this.x = x;
            this.y = y;
            this.z = z;
        }
    }

    // Example usage:
    // public static void main(String[] args) throws IOException {
    //     XYZFileHandler handler = new XYZFileHandler("example.xyz");
    //     handler.read();
    //     handler.printProperties();
    //     handler.write("new_example.xyz");
    // }
}
  1. Below is a JavaScript class (assuming a Node.js environment for file operations) that can open, read, decode, write, and print the properties of a .XYZ file to the console.
const fs = require('fs');

class XYZFileHandler {
    constructor(filepath) {
        this.filepath = filepath;
        this.atomCount = 0;
        this.title = '';
        this.atoms = [];  // Array of objects: {element, x, y, z}
    }

    read() {
        try {
            const content = fs.readFileSync(this.filepath, 'utf8');
            const lines = content.trim().split('\n');
            if (lines.length < 2) {
                throw new Error('Invalid .XYZ file format.');
            }
            this.atomCount = parseInt(lines[0].trim(), 10);
            this.title = lines[1].trim();
            this.atoms = [];
            for (let i = 2; i < lines.length; i++) {
                const parts = lines[i].trim().split(/\s+/);
                if (parts.length >= 4) {
                    const element = parts[0];
                    const x = parseFloat(parts[1]);
                    const y = parseFloat(parts[2]);
                    const z = parseFloat(parts[3]);
                    this.atoms.push({ element, x, y, z });
                }
            }
            if (this.atoms.length !== this.atomCount) {
                throw new Error('Atom count mismatch in .XYZ file.');
            }
        } catch (error) {
            console.error(`Error reading file: ${error.message}`);
        }
    }

    write(newFilepath = this.filepath) {
        try {
            let output = `${this.atomCount}\n${this.title}\n`;
            for (const atom of this.atoms) {
                output += `${atom.element} ${atom.x.toFixed(6)} ${atom.y.toFixed(6)} ${atom.z.toFixed(6)}\n`;
            }
            fs.writeFileSync(newFilepath, output);
        } catch (error) {
            console.error(`Error writing file: ${error.message}`);
        }
    }

    printProperties() {
        console.log(`Atom Count: ${this.atomCount}`);
        console.log(`Title: ${this.title}`);
        console.log('Atoms:');
        this.atoms.forEach((atom, index) => {
            console.log(`Atom ${index + 1}: Element: ${atom.element}, X: ${atom.x}, Y: ${atom.y}, Z: ${atom.z}`);
        });
    }
}

// Example usage:
// const handler = new XYZFileHandler('example.xyz');
// handler.read();
// handler.printProperties();
// handler.write('new_example.xyz');
  1. Below is C code using a struct and associated functions (as C does not support classes in the same way as object-oriented languages) that can open, read, decode, write, and print the properties of a .XYZ file to the console.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    char *element;
    double x, y, z;
} Atom;

typedef struct {
    char *filepath;
    int atom_count;
    char *title;
    Atom *atoms;
} XYZFileHandler;

XYZFileHandler* xyz_create(const char *filepath) {
    XYZFileHandler *handler = (XYZFileHandler*)malloc(sizeof(XYZFileHandler));
    handler->filepath = strdup(filepath);
    handler->atom_count = 0;
    handler->title = NULL;
    handler->atoms = NULL;
    return handler;
}

void xyz_read(XYZFileHandler *handler) {
    FILE *file = fopen(handler->filepath, "r");
    if (!file) {
        fprintf(stderr, "Error opening file.\n");
        return;
    }
    char line[256];
    if (!fgets(line, sizeof(line), file)) {
        fprintf(stderr, "Invalid .XYZ file format.\n");
        fclose(file);
        return;
    }
    handler->atom_count = atoi(line);
    if (!fgets(line, sizeof(line), file)) {
        fprintf(stderr, "Invalid .XYZ file format.\n");
        fclose(file);
        return;
    }
    handler->title = strdup(strtok(line, "\n"));
    handler->atoms = (Atom*)malloc(handler->atom_count * sizeof(Atom));
    int index = 0;
    while (fgets(line, sizeof(line), file)) {
        char *token = strtok(line, " \t\n");
        if (token && index < handler->atom_count) {
            handler->atoms[index].element = strdup(token);
            token = strtok(NULL, " \t\n");
            handler->atoms[index].x = atof(token);
            token = strtok(NULL, " \t\n");
            handler->atoms[index].y = atof(token);
            token = strtok(NULL, " \t\n");
            handler->atoms[index].z = atof(token);
            index++;
        }
    }
    if (index != handler->atom_count) {
        fprintf(stderr, "Atom count mismatch in .XYZ file.\n");
    }
    fclose(file);
}

void xyz_write(XYZFileHandler *handler, const char *new_filepath) {
    const char *path = new_filepath ? new_filepath : handler->filepath;
    FILE *file = fopen(path, "w");
    if (!file) {
        fprintf(stderr, "Error opening file for writing.\n");
        return;
    }
    fprintf(file, "%d\n", handler->atom_count);
    fprintf(file, "%s\n", handler->title);
    for (int i = 0; i < handler->atom_count; i++) {
        fprintf(file, "%s %.6f %.6f %.6f\n", handler->atoms[i].element, handler->atoms[i].x, handler->atoms[i].y, handler->atoms[i].z);
    }
    fclose(file);
}

void xyz_print_properties(XYZFileHandler *handler) {
    printf("Atom Count: %d\n", handler->atom_count);
    printf("Title: %s\n", handler->title);
    printf("Atoms:\n");
    for (int i = 0; i < handler->atom_count; i++) {
        printf("Atom %d: Element: %s, X: %.6f, Y: %.6f, Z: %.6f\n", i + 1, handler->atoms[i].element, handler->atoms[i].x, handler->atoms[i].y, handler->atoms[i].z);
    }
}

void xyz_destroy(XYZFileHandler *handler) {
    free(handler->filepath);
    free(handler->title);
    for (int i = 0; i < handler->atom_count; i++) {
        free(handler->atoms[i].element);
    }
    free(handler->atoms);
    free(handler);
}

// Example usage:
// int main() {
//     XYZFileHandler *handler = xyz_create("example.xyz");
//     xyz_read(handler);
//     xyz_print_properties(handler);
//     xyz_write(handler, "new_example.xyz");
//     xyz_destroy(handler);
//     return 0;
// }