File size: 1,860 Bytes
96272bc
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#!/usr/bin/env python3

'''Small helpers shared by analyze_flex_ddG.py and extract_structures.py.

Standard library only, so that extract_structures.py keeps running without numpy or pandas.
'''

import re
import sqlite3

# Rosetta records the full option list it was invoked with in the "protocols" table of every
# features database it writes, so the stride a run actually used can be read back out of the
# output instead of being remembered and re-typed by hand.
_stride_re = re.compile( r'backrub_trajectory_stride[= ]+(\d+)' )

def trajectory_stride_from_db3( db3_file ):
    '''The backrub_trajectory_stride the run in db3_file was launched with.

    Returns None if it cannot be determined, which happens for databases written by Rosetta
    versions that predate the protocols table, or if the stride was left at the XML default
    instead of being passed on the command line. Callers should fall back to a default and say
    so, because the stride does not affect any energy -- it only labels the checkpoints, so a
    wrong value silently mislabels every row (and misnames every extracted PDB) rather than
    causing a visible failure.
    '''
    try:
        conn = sqlite3.connect( 'file:%s?mode=ro' % db3_file, uri = True )
    except sqlite3.Error:
        return None

    try:
        try:
            rows = conn.execute( 'SELECT specified_options, command_line FROM protocols' ).fetchall()
        except sqlite3.Error:
            return None

        strides = set()
        for row in rows:
            for field in row:
                if field:
                    strides.update( int(m) for m in _stride_re.findall( field ) )
    finally:
        conn.close()

    # More than one distinct value means the database mixes runs; we cannot label it correctly.
    if len( strides ) == 1:
        return strides.pop()
    return None