Skip to content

mmCIF writer emits no entry identifier: getPdbId() is lost on a write-then-read round trip #1143

Description

@aalhossary

Summary

AbstractCifFileSupplier writes the PDB identifier only as the name of the data_ block. It emits neither _entry.id nor _struct.entry_id, so the identifier is lost for every consumer that reads it as a data item rather than from the block header.

Two independent consumers are affected:

consumer reads result today
BioJava's own CifStructureConsumerImpl.consumeStruct _struct.entry_id Structure.getPdbId() is null after a write-then-read round trip
Jmol's mmCIF reader _entry.id _M.pdbID is empty for a structure passed via openStringInline(structure.toMMCIF())

Steps to reproduce

Structure s = CifStructureConverter.fromInputStream(
        new GZIPInputStream(...open 4hhb.cif.gz...));
System.out.println(s.getPdbId());                 // 4HHB

String cif = CifStructureConverter.toText(s);
System.out.println(cif.contains("_entry.id"));        // false
System.out.println(cif.contains("_struct.entry_id")); // false

Structure back = CifStructureConverter.fromInputStream(
        new ByteArrayInputStream(cif.getBytes()));
System.out.println(back.getPdbId());              // null   <-- expected 4HHB

Actual output of the block header and identifier items as written today:

data_4HHB
(no _entry.id, no _struct.entry_id)

Expected

Structure.getPdbId() should survive a toText() / fromInputStream() round trip, and the written file should carry the identifier where mmCIF consumers look for it.

Why both items matter

_entry.id is the canonical place for the identifier and is what Jmol reads. BioJava's own reader (CifStructureConsumerImpl.consumeStruct) only looks at _struct.entry_id. Writing just one of the two leaves the other consumer broken, so both should be written.

Measured with Jmol, loading the identical structure inline with one item added at a time:

as written today (block header only)  ->  _M.pdbID = []
plus  _entry.id         3ALB          ->  _M.pdbID = [3ALB]
plus  _struct.entry_id  3ALB          ->  _M.pdbID = []
plus  both                            ->  _M.pdbID = [3ALB]

A practical consequence downstream: Jmol's isosurface ... eds fetches an electron-density box around the selection, but it needs an entry to ask about. With load =3alb it renders; with the same structure pushed inline via toMMCIF() it renders nothing, purely because the identifier was lost.

Location

biojava-structure/src/main/java/org/biojava/nbio/structure/io/cif/AbstractCifFileSupplier.java, in getInternal(...) — the identifier appears only in the enterBlock(...) call.

Version

Reproduced on master (5b29945). The behaviour is long-standing, not a recent regression.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions