Chem-Structure-Parser

 view release on metacpan or  search on metacpan

README.md  view on Meta::CPAN


    h('structure_info');    # by name
    h(*res_type);           # by name, unquoted
    h(\&aa3to1);            # by reference
    h();                    # the list of documented functions

    perl -MChem::Structure::Parser -e 'h(*structure_info)'   # straight from the shell

Note that `h(res_type)`, with no quotes and no sigil, cannot be made to work:
every function here is exported, so Perl parses the bareword as a call to
`res_type()` before `h` is ever reached. Use one of the three forms above.

# Functions/Subroutines

## structure_info

    my $info = structure_info($file, %options);

Reads `$file` and returns a hash reference. The format is worked out from the
file name — `.pdb`, `.ent`, `.cif`, `.mmcif`, `.pdbx` — and from the first
records in the file when the name gives nothing away. `.gz` files are read as
they are, without unpacking to a temporary file.

### What comes back

Laid out the way `tree` lays out a directory, this is `1a22.ent.pdb` — a real
file, real values, the long lists cut short:

    $info
    ├── file            '1a22.ent.pdb'          the path it was read from
    ├── format          'pdb'                   or 'mmcif'
    ├── id              '1A22'                  from HEADER, or from the file name
    ├── title           'HUMAN GROWTH HORMONE BOUND TO SINGLE RECEPTOR'
    ├── header
    │   ├── classification  'COMPLEX (HORMONE/RECEPTOR)'
    │   ├── deposit_date    '15-JAN-98'
    │   └── id_code         '1A22'
    ├── experiment      [ 'X-RAY DIFFRACTION' ]
    ├── resolution      2.6                     REMARK 2
    ├── r_work          0.187                   REMARK 3
    ├── r_free          undef                   this entry does not report one
    ├── temperature     287                     REMARK 200
    ├── ph              6.5
    ├── keywords        [ 'COMPLEX (HORMONE-RECEPTOR)', 'PITUITARY HORMONE', ... ]
    ├── authors         [ 'A.M.DE VOS', 'M.ULTSCH' ]
    ├── journal
    │   ├── auth        [ 'T.CLACKSON', 'M.H.ULTSCH', 'J.A.WELLS', 'A.M.DE VOS' ]
    │   ├── titl        'STRUCTURAL AND FUNCTIONAL ANALYSIS OF THE 1:1 GROWTH...'
    │   ├── ref         'J.MOL.BIOL.                   V. 277  1111 1998'
    │   ├── refn        'ISSN 0022-2836'
    │   ├── pmid        '9571026'
    │   └── doi         '10.1006/JMBI.1998.1669'
    ├── compound                                COMPND, by MOL_ID
    │   ├── 1
    │   │   ├── mol_id      '1'
    │   │   ├── molecule    'GROWTH HORMONE'
    │   │   ├── chain       [ 'A' ]
    │   │   ├── engineered  'YES'
    │   │   └── mutation    'YES'
    │   └── 2           { molecule 'GROWTH HORMONE RECEPTOR', chain [ 'B' ],
    │                     fragment 'EXTRACELLULAR DOMAIN', engineered 'YES' }
    ├── source                                  SOURCE, by MOL_ID
    │   └── 1           { organism_scientific 'HOMO SAPIENS', organism_common
    │                     'HUMAN', organism_taxid '9606', mol_id '1',
    │                     expression_system 'ESCHERICHIA COLI',
    │                     expression_system_taxid '562' }
    ├── entity_of_chain                         COMPND and SOURCE, by chain
    │   ├── A           { mol_id '1', molecule 'GROWTH HORMONE', fragment undef,
    │   │                 ec undef, organism 'HOMO SAPIENS', taxid '9606',
    │   │                 expressed_in 'ESCHERICHIA COLI' }
    │   └── B           { ..., fragment 'EXTRACELLULAR DOMAIN' }
    ├── seqres                                  what SEQRES says was in the crystal
    │   ├── A
    │   │   ├── sequence    'FPTIPLSRLFDNAMLRAHRLHQLAFDTYQEFEEAYIPKEQKYSFLQ...'
    │   │   ├── residues    [ 'PHE', 'PRO', 'THR', 'ILE', ... ]        191 of them
    │   │   └── length      191
    │   └── B               { sequence, residues, length 238 }
    ├── dbref
    │   └── A           [ { database 'UNP', accession 'P01241',
    │                       db_id 'SOMA_HUMAN', seq_begin '1', seq_end '191',
    │                       db_begin '27', db_end '217', chain 'A' } ]
    ├── seqadv          [ { chain 'A', resseq '120', resname 'ARG',
    │                       db_res 'GLY', db_seq '146', comment 'ENGINEERED' } ]
    ├── modres          { }                     no MSE-style residues here
    ├── het
    │   └── HOH         { het_id 'HOH', formula '69(H2 O)', water 1 }
    ├── hetnam          { }
    ├── formul          { }
    ├── helix           [ { id '1', class '1', length '29',
    │                       init_chain 'A', init_resname 'SER', init_resseq '7',
    │                       end_chain 'A', end_resname 'TYR', end_resseq '35' },
    │                     ... ]                                     12 of them
    ├── sheet           [ ... ]                                     12
    ├── ssbond          [ { chain1 'A', resseq1 '53',
    │                       chain2 'A', resseq2 '165', length '2.02' }, ... ]  5
    ├── link            [ ]
    ├── cispep          [ ]
    ├── site            [ ]
    ├── cryst1          { a '67.7', b '67.7', c '228',
    │                     alpha '90', beta '90', gamma '90',
    │                     sgroup 'P 43 21 2', z '8' }
    ├── biological_assembly  [ 32 lines of REMARK 350, verbatim ]
    ├── revdat          [ { num '3', date '18-APR-18', id '1A22',
    │                       type '1', what 'REMARK' }, ... ]
    ├── remarks                                 every REMARK, by number
    │   ├── 2           [ '', 'RESOLUTION.    2.60 ANGSTROMS.' ]
    │   ├── 350         [ ... ]                                     32 lines
    │   └── ...         1, 3, 4, 100, 200, 280, 290, 300, 465, 470, 500
    ├── conect          [ [ 448, 1255 ], ... ]                      10
    ├── records                                 every record type, counted
    │   ├── REMARK      365
    │   ├── SEQRES      34
    │   ├── HELIX       12
    │   └── ...         AUTHOR, COMPND, CONECT, CRYST1, DBREF, SOURCE, SSBOND, ...
    ├── n_models        1                       how many MODEL records the file has
    ├── model           1                       which one the chains below are
    ├── models                                  there only with model => 'all'
    ├── stats
    │   ├── n_atoms         3113    atoms kept: this model, less what was filtered
    │   ├── total_atoms     3113    atoms the file has, every model, unfiltered
    │   ├── n_hetatm        69      of n_atoms, the ones written as HETATM
    │   ├── n_hydrogens     0
    │   ├── n_water_atoms   69
    │   ├── n_lines         3605
    │   ├── n_atom_records  3044    ATOM lines seen, whether kept or not
    │   ├── n_hetatm_records 69     HETATM lines, likewise
    │   ├── n_anisou        0
    │   ├── n_skipped       0       coordinate lines the options threw away
    │   ├── elements        { C 1946, O 643, N 507, S 17 }
    │   │                           every element in the file, keyed by its IUPAC
    │   │                           symbol; the counts add up to n_atoms
    │   ├── bfactor         { min '2.7', max '85.39', mean 30.83, n 3113 }
    │   ├── bbox            { xmin '12.142', xmax '80.34', ymin '2.011', ... }
    │   └── center          [ '46.241', '29.135', '134.559' ]
    ├── chain_order     [ 'A', 'B' ]            the order the file has them in
    └── chains
        ├── A
        │   ├── id              'A'
        │   ├── type            'protein'   protein dna rna water hetero unknown
        │   ├── sequence        'FPTIPLSRLFDNAMLRAHRLHQLAFDTYQEFEEAYIPKEQ...'
        │   │                               single-letter, what has coordinates
        │   ├── seqres          'FPTIPLSRLFDNAMLRAHRLHQLAFDTYQEFEEAYIPKEQ...'
        │   ├── seqres_length   191
        │   ├── n_residues      206
        │   ├── n_polymer       180
        │   ├── n_water         26
        │   ├── n_ligand        0
        │   ├── n_atoms         1492
        │   ├── n_hetatm        26
        │   ├── elements        { C 938, O 301, N 246, S 7 }
        │   │                               the same tally for this chain alone;
        │   │                               adds up to the chain's n_atoms
        │   ├── n_missing       11          SEQRES less what was modelled
        │   ├── gaps            [ { after 129, before 136, missing 6 },
        │   │                     { after 148, before 154, missing 5 } ]
        │   ├── n_gaps          2
        │   ├── missing_residues
        │   │                   [ 130, 131, 132, 133, 134, 135,
        │   │                     149, 150, 151, 152, 153 ]
        │   ├── first           1           the first and last polymer residue keys
        │   ├── last            191
        │   ├── residue_types   { amino_acid 180, water 26 }
        │   ├── molecule        'GROWTH HORMONE'            from COMPND
        │   ├── organism        'HOMO SAPIENS'              from SOURCE
        │   ├── mol_id          '1'
        │   ├── dbref           [ { ... } ]     as in the top-level dbref
        │   │                                   ec and fragment are here too, in a
        │   │                                   chain whose file gives them
        │   ├── residue_order   [ '1', '2', '3', ... '574' ]        file order, 206
        │   └── residues                    keyed number + insertion code
        │       ├── 54
        │       │   ├── resname     'PHE'
        │       │   ├── number      54
        │       │   ├── icode       ''
        │       │   ├── key         '54'
        │       │   ├── chain       'A'
        │       │   ├── one         'F'     '' when there is no letter for it
        │       │   ├── type        'amino_acid'
        │       │   │                       nucleotide water ligand ion
        │       │   ├── standard    1       one of the twenty, or a standard base
        │       │   ├── modified    0       1 for MSE, still an M in the sequence
        │       │   ├── hetero      0       1 when it was written as HETATM
        │       │   ├── free                not here; 1 for a free amino acid
        │       │   │                       bound in a site (see below)
        │       │   ├── n_atoms     11
        │       │   ├── b_mean      22.55
        │       │   ├── center      [ 65.311, 17.127, 140.515 ]
        │       │   ├── atom_order  [ 'N', 'CA', 'C', 'O', 'CB', ... ]
        │       │   └── atoms
        │       │       ├── CA
        │       │       │   ├── name       'CA'
        │       │       │   ├── serial     450
        │       │       │   ├── element    'C'
        │       │       │   ├── charge     ''
        │       │       │   ├── x          '66.446'
        │       │       │   ├── y          '18.25'
        │       │       │   ├── z          '141.982'
        │       │       │   ├── occupancy  '1'
        │       │       │   ├── bfactor    '24.53'
        │       │       │   ├── altloc     ''
        │       │       │   ├── hetero     0
        │       │       │   └── altlocs    [ { altloc, x, y, z, occupancy,
        │       │       │                      bfactor }, ... ]
        │       │       │                  present only when the atom has
        │       │       │                  alternate conformers; every conformer
        │       │       │                  is listed, the chosen one included,
        │       │       │                  and one of them having no letter at
        │       │       │                  all does not take it off the list
        │       │       └── ...    N, C, O, CB, CG, CD1, CD2, CE1, CE2, CZ
        │       └── ...            1 .. 191, then the waters at 512 .. 574
        └── B                      the same again: 235 residues, 1621 atoms

A record that is not in the file reads as `undef`, and a list that is not in
the file reads as an empty arrayref — `title` being `undef` means there was no
TITLE, which is a different thing from a TITLE that was blank.

Everything the module does not take apart is still in `remarks` and in the
raw record counts, so nothing in the file is lost.

### The two sequences

`sequence` and `seqres` are the two different questions people mean by "the
sequence": what was modelled, and what was in the crystal. They differ
wherever a terminus or a loop went unmodelled, which is what `gaps` counts and
`n_missing` totals — eleven residues of chain A above, in two stretches.
`missing_residues` is the same eleven one number at a time, in ascending
order, for asking whether a particular residue was modelled without walking



( run in 1.032 second using v1.01-cache-2.11-cpan-364913b4093 )