Beispiel #1
0
def AtomStyle2ColNames(atom_style_string):

    atom_style_string = atom_style_string.strip()
    if len(atom_style_string) == 0:
        raise InputError('Error: Invalid atom_style\n'
                         '       (The atom_style command was followed by an empty string.)\n')
    atom_style_args = atom_style_string.split()
    atom_style = atom_style_args[0]

    hybrid_args = atom_style_args[1:]
    if (atom_style not in g_style_map):
        if (len(atom_style_args) >= 2):
            # If the atom_style_string includes at least 2 words, then we
            # interpret this as a list of the individual column names
            return atom_style_args
        else:
            raise InputError(
                'Error: Unrecognized atom_style: \"' + atom_style + '\"\n')

    if (atom_style != 'hybrid'):
        return g_style_map[atom_style]
    else:
        column_names = ['atom-ID', 'atom-type', 'x', 'y', 'z']
        if (len(hybrid_args) == 0):
            raise InputError(
                'Error: atom_style hybrid must be followed by a sub_style.\n')
        for sub_style in hybrid_args:
            if (sub_style not in g_style_map):
                raise InputError(
                    'Error: Unrecognized atom_style: \"' + sub_style + '\"\n')
            for cname in g_style_map[sub_style]:
                if cname not in column_names:
                    column_names.append(cname)

        return column_names
Beispiel #2
0
def ColNames2Vects(column_names):
    """ Which of the columns correspond to coordinates
        which must be transformed using rotations?
        Some coordinates like dipole moments and
        ellipsoid orientations should only be rotated
        (not translated).
        This function outputs a list of lists of triplets of integers.

    """
    vects = []
    i_mux = None
    i_muy = None
    i_muz = None
    if 'mux' in column_names:
        i_mux = column_names.index('mux')
    if 'muy' in column_names:
        i_muy = column_names.index('muy')
    if 'muz' in column_names:
        i_muz = column_names.index('muz')
    if (((i_mux != None) != (i_muy != None)) or
            ((i_muy != None) != (i_muz != None)) or
            ((i_muz != None) != (i_mux != None))):
        raise InputError(
            'Error: custom atom_style list must define mux, muy, and muz or none.\n')
    if i_mux != None:
        vects.append([i_mux, i_muy, i_muz])
    return vects
Beispiel #3
0
def ColNames2Coords(column_names):
    """ Which of the columns correspond to coordinates
        which must be transformed using rigid-body
        (affine: rotation + translation) transformations?
        This function outputs a list of lists of triplets of integers.

    """
    i_x = None
    i_y = None
    i_z = None
    if 'x' in column_names:
        i_x = column_names.index('x')
    if 'y' in column_names:
        i_y = column_names.index('y')
    if 'z' in column_names:
        i_z = column_names.index('z')
    if (((i_x != None) != (i_y != None)) or ((i_y != None) != (i_z != None))
            or ((i_z != None) != (i_x != None))):
        raise InputError(
            'Error: custom atom_style list must define x, y, and z.\n')
    return [[i_x, i_y, i_z]]
def main():
    try:
        if (len(sys.argv) < 2):
            raise InputError(
                'Error running  \"' + g_program_name + '\"\n'
                ' Typical usage:\n'
                ' ttree_render.py ttree_assignments.txt < file.template > file.rendered\n'
                '\n'
                '   Missing argument.\n'
                '   Expected the name of a 2-column file containing\n'
                '   variable names and their bindings (values).\n'
                '   (This is likely a programmer error.\n'
                '    This script was not intended to be run by end users.)\n')

        bindings_filename = sys.argv[1]
        ftemplate = sys.stdin
        ftemplate_name = '__standard_input_for_ttree_render__'
        if len(sys.argv) >= 3:
            ftemplate_name = sys.argv[2]
            ftemplate = open(ftemplate_name, 'r')

        fbindings = open(bindings_filename)
        assignments = {}

        #BasicUIReadBindingsStream(assignments, f, bindings_filename)

        # The line above is robust but it uses far too much memory.
        # This for loop below works for most cases.
        for line in fbindings:
            #tokens = lines.strip().split()
            # like split but handles quotes
            tokens = SplitQuotedString(line.strip())
            if len(tokens) < 2:
                continue
            assignments[tokens[0]] = tokens[1]

        fbindings.close()
        gc.collect()

        lex = TemplateLexer(ftemplate, ftemplate_name)
        lex.var_delim = '$@'

        text_block_list = lex.ReadTemplate(simplify_output=True)

        output = []

        for entry in text_block_list:
            assert (isinstance(entry, str))

            if ((len(entry) > 1) and (entry[0] in lex.var_delim)):

                var_prefix = ''
                var_suffix = ''
                var_format = ''
                if ((len(entry) >= 3) and (entry[1] == '{')
                        and (entry[-1] == '}')):
                    var_prefix = '{'
                    var_suffix = '}'
                    entry = entry[0] + entry[2:-1]

                if '.' in entry:
                    ic = entry.find('.')
                    var_name = entry[:ic]
                    var_format = entry[ic:]
                    if not var_format[0:7] in ('.ljust(', '.rjust('):
                        var_name = entry
                        var_format = ''
                else:
                    var_name = entry
                    var_format = ''

                if var_name not in assignments:
                    #COMMENTING OUT:
                    #raise(InputError('Error(' + g_program_name + ')'
                    #                 #' at '+ErrorLeader(var_ref.src_loc.infile,
                    #                 #                   var_ref.src_loc.lineno)+
                    #                 ' unknown variable:\n'
                    #                 '         \"' + var_name + '\"\n'))
                    # ...actually don't raise an error message:
                    # Actually there are some legitimate reaons this could occur.
                    # Some users want to put LAMMPS-style variables in the
                    # write_once() {...} text blocks in their moltemplate files.
                    # Variables in both LAMMPS and moltemplate contain $ characters,
                    # and this script gets confused.  Better to just ignore it
                    # when this happens instead of printing an error message.
                    # Just leave the text alone and print the variable name.
                    #
                    # Do this by substituting the variable's name as it's value:

                    var_value = entry[0] + var_prefix + var_name[
                        1:] + var_suffix

                else:
                    var_value = assignments[var_name]

                format_fname, args = ExtractFormattingCommands(var_format)
                if format_fname == 'ljust':
                    if len(args) == 1:
                        var_value = var_value.ljust(int(args[0]))
                    else:
                        var_value = var_value.ljust(int(args[0]), args[1])
                elif format_fname == 'rjust':
                    if len(args) == 1:
                        var_value = var_value.rjust(int(args[0]))
                    else:
                        var_value = var_value.rjust(int(args[0]), args[1])
                output.append(var_value)
            else:
                output += entry

        sys.stdout.write(''.join(output))

        # If we are not reading the file from sys.stdin, then close the file:
        if ftemplate_name == '__standard_input_for_ttree_render__':
            assert (ftemplate == sys.stdin)
        else:
            ftemplate.close()

    except (ValueError, InputError) as err:
        sys.stderr.write('\n' + str(err) + '\n')
        sys.exit(-1)

    return
Beispiel #5
0
def ColNames2AidAtypeMolid(column_names):
    # Because of the diversity of ways that these
    # numbers are referred to in the LAMMPS documentation,
    # we have to be flexible and allow the user to refer
    # to these quantities in a variety of ways.
    # Hopefully this covers everything:

    if 'atom-ID' in column_names:
        i_atomid = column_names.index('atom-ID')
    elif 'atom−ID' in column_names:  # (− is the character used in the manual)
        i_atomid = column_names.index('atom−ID')
    elif 'atomID' in column_names:
        i_atomid = column_names.index('atomID')
    elif 'atomid' in column_names:
        i_atomid = column_names.index('atomid')
    elif 'id' in column_names:
        i_atomid = column_names.index('id')
    elif 'atom' in column_names:
        i_atomid = column_names.index('atom')
    elif '$atom' in column_names:
        i_atomid = column_names.index('$atom')
    else:
        raise InputError('Error: List of column names lacks an \"atom-ID\"\n')

    if 'atom-type' in column_names:
        i_atomtype = column_names.index('atom-type')
    elif 'atom−type' in column_names:  # (− hyphen character used in manual)
        i_atomtype = column_names.index('atom−type')
    elif 'atomtype' in column_names:
        i_atomtype = column_names.index('atomtype')
    elif 'type' in column_names:
        i_atomtype = column_names.index('type')
    elif '@atom' in column_names:
        i_atomtype = column_names.index('@atom')
    else:
        raise InputError(
            'Error: List of column names lacks an \"atom-type\"\n')

    i_molid = None
    if 'molecule-ID' in column_names:
        i_molid = column_names.index('molecule-ID')
    elif 'molecule−ID' in column_names:  # (− hyphen character used in manual)
        i_molid = column_names.index('molecule−ID')
    elif 'moleculeID' in column_names:
        i_molid = column_names.index('moleculeID')
    elif 'moleculeid' in column_names:
        i_molid = column_names.index('moleculeid')
    elif 'molecule' in column_names:
        i_molid = column_names.index('molecule')
    elif 'molID' in column_names:
        i_molid = column_names.index('molID')
    elif 'molid' in column_names:
        i_molid = column_names.index('molid')
    elif 'mol' in column_names:
        i_molid = column_names.index('mol')
    elif '$mol' in column_names:
        i_molid = column_names.index('$mol')
    else:
        pass  # some atom_types do not have a valid molecule-ID

    return i_atomid, i_atomtype, i_molid
def GenInteractions_int(
        G_system,
        g_bond_pattern,
        typepattern_to_coefftypes,
        canonical_order,  # function to sort atoms and bonds
        atomtypes_int2str,
        bondtypes_int2str,
        report_progress=False,  # print messages to sys.stderr?
        check_undefined_atomids_str=None):
    """
    GenInteractions() automatically determines a list of interactions
    present in a system of bonded atoms (argument "G_system"),
    which satisfy the bond topology present in "g_bond_pattern", and
    satisfy the atom and bond type requirements in "typepattern_to_coefftypes".

    Whenever a set of atoms in "G_system" are bonded together in a way which
    matches "g_bond_pattern", and when the atom and bond types is consistent
    with one of the entries in "typepattern_to_coefftypes", the corresponding
    list of atoms from G_system is appended to the list of results.

    These results (the list of lists of atoms participating in an interaction)
    are organized according their corresponding "coefftype", a string
    which identifies the type of interaction they obey as explained above.
    results are returned as a dictionary using "coefftype" as the lookup key.

    Arguments:

     -- typepattern_to_coefftypes is a list of 2-tuples --
    The first element of the 2-tuple is the "typepattern".
    It contains a string describing a list of atom types and bond types.
    The typepattern is associated with a "coefftype",
    which is the second element of the 2-tuple.  This is a string
    which identifies the type of interaction between the atoms.
    Later on, this string can be used to lookup the force field
    parameters for this interaction elsewhere.)

     -- Arguments: G_system, g_bond_pattern, atomtypes_int2str, bondtypes_int2str --

    G_system stores a list of atoms and bonds, and their attributes in
    "Ugraph" format.  In this format:
    Atom ID numbers are represented by indices into the G_system.verts[] list.
    Bond ID numbers are represented by indices into the G_system.edges[] list.
    Atom types are represented as integers in the G_system.verts[i].attr list.
    Bond types are represented as integers in the G_system.edges[i].attr list.
    They are converted into strings using
    atomtypes_int2str, and bondtypes_int2str.

    g_bond_pattern is a graph which specifies the type of bonding between
    the atoms required for a match. It is in Ugraph format (however the
    atom and bond types are left blank.)

    Atom and bond types are supplied by the user in string format. (These
    strings typically encode integers, but could be any string in principle.)
    The string-version of the ith atom type is stored in
       atomtypes_int2str[ G_system.verts[i].attr ]
    The string-version of the ith bond type is stored in
       bondtypes_int2str[ G_system.edges[i].attr ]

     -- The "canonical_order" argument: --

    The search for atoms with a given bond pattern often yields
    redundant matches.  There is no difference for example
    between the angle formed between three consecutively
    bonded atoms (named, 1, 2, 3, for example), and the
    angle between the same atoms in reverse order (3, 2, 1).
    However both triplets of atoms will be returned by the subgraph-
    matching algorithm when searching for ALL 3-body interactions.)

    To eliminate this redundancy, the caller must supply a "canonical_order"
    argument.  This is a function which sorts the atoms and bonds in a way
    which is consistent with the type of N-body interaction being considered.
    The atoms (and bonds) in a candidate match are rearranged by the
    canonical_order().  Then the re-ordered list of atom and bond ids is
    tested against the list of atom/bond ids in the matches-found-so-far,
    before it is added.

    """

    if report_progress:
        startatomid = 0
        sys.stderr.write('  searching for matching bond patterns:\n')
        sys.stderr.write('    0%')

    # Figure out which atoms from "G_system" bond together in a way which
    # matches the "g_bond_pattern" argument.  Organize these matches by
    # atom and bond types and store all of the non-redundant ones in
    # the "interactions_by_type" variable.

    gm = GraphMatcher(G_system, g_bond_pattern)

    interactions_by_type = defaultdict(list)

    for atombondids in gm.Matches():
        # "atombondids" is a tuple.
        #  atombondids[0] has atomIDs from G_system corresponding to g_bond_pattern
        #     (These atomID numbers are indices into the G_system.verts[] list.)
        #  atombondids[1] has bondIDs from G_system corresponding to g_bond_pattern
        #     (These bondID numbers are indices into the G_system.edges[] list.)

        # It's convenient to organize the list of interactions-between-
        # atoms in a dictionary indexed by atomtypes and bondtypes.
        # (Because many atoms and bonds typically share the same type,
        #  organizing the results this way makes it faster to check
        #  whether a given interaction matches a "typepattern" defined
        #  by the user.  We only have to check once for the whole group.)

        atombondtypes = \
            (tuple([G_system.GetVert(Iv).attr for Iv in atombondids[0]]),
             tuple([G_system.GetEdge(Ie).attr for Ie in atombondids[1]]))

        interactions_by_type[atombondtypes].append(atombondids)

        if report_progress:
            # GraphMatcher.Matches() searches for matches in an order
            # that selects a different atomid number from G_system,
            # starting at 0, and continuing up to the number of atoms (-1)
            # in the system (G_system.nv-1), and using this as the first
            # atom in the match (ie match[0][0]). This number can be used
            # to guess much progress has been made so far.
            oldatomid = startatomid
            startatomid = atombondids[0][0]
            percent_complete = (100 * startatomid) // G_system.GetNumVerts()
            # report less often as more progress made
            if percent_complete <= 4:
                old_pc = (100 * oldatomid) // G_system.GetNumVerts()
                if percent_complete > old_pc:
                    sys.stderr.write('  ' + str(percent_complete) + '%')
            elif percent_complete <= 8:
                pc_d2 = (100 * startatomid) // (2 * G_system.GetNumVerts())
                oldpc_d2 = (100 * oldatomid) // (2 * G_system.GetNumVerts())
                if pc_d2 > oldpc_d2:
                    sys.stderr.write('  ' + str(percent_complete) + '%')
            elif percent_complete <= 20:
                pc_d4 = (100 * startatomid) // (4 * G_system.GetNumVerts())
                oldpc_d4 = (100 * oldatomid) // (4 * G_system.GetNumVerts())
                if pc_d4 > oldpc_d4:
                    sys.stderr.write('  ' + str(percent_complete) + '%')
            else:
                pc_d10 = (100 * startatomid) // (10 * G_system.GetNumVerts())
                oldpc_d10 = (100 * oldatomid) // (10 * G_system.GetNumVerts())
                if pc_d10 > oldpc_d10:
                    sys.stderr.write('  ' + str(percent_complete) + '%')

    if report_progress:
        sys.stderr.write('  100%\n')
        #sys.stderr.write('    ...done\n')
        #sys.stderr.write('    Looking up available atom and bond types...')

    #coefftype_to_atomids = defaultdict(list)
    #abids_to_coefftypes = defaultdict(list)
    coefftype_to_atomids = OrderedDict()
    abids_to_coefftypes = OrderedDict()

    # -------------------- reporting progress -----------------------
    if report_progress:
        # The next interval of code is not technically necessary, but it makes
        # the printed output easier to read by excluding irrelevant interactions
        # Now, test each match to see if the atoms and bonds involved match
        # any of the type-patterns in the "typepattern_to_coefftypes" argument.

        types_atoms_all_str = set([])
        types_bonds_all_str = set([])
        for typepattern, coefftype in typepattern_to_coefftypes:
            for atombondtypes, abidslist in interactions_by_type.items():
                for Iv in atombondtypes[0]:
                    types_atoms_all_str.add(atomtypes_int2str[Iv])
                for Ie in atombondtypes[1]:
                    types_bonds_all_str.add(bondtypes_int2str[Ie])
    # ------------------ reporting progress (end) -------------------

    # ------------------ check to make sure all interactions are defined ------
    if check_undefined_atomids_str:
        # Checking for missing interactions is a headache.
        # Please excuse the messy code below.
        atomids_matched = OrderedDict()
        # Then loop through all the interactions (tuples of atoms) found by
        # GraphMatcher, sort the atoms and store them in dictionary
        # (atomids_matched) which keeps track of which interactions have
        # been defined (ie have force-field parameters assigned to them).
        # Initialize them to False, and update as interactions are found.
        for atombondtypes, abidslist in interactions_by_type.items():
            for abids in abidslist:
                abids = canonical_order(abids)
                atomids_int = tuple(abids[0])

                # NOTE TO SELF:
                # If in the future, different interactions (type_patterns) have
                # different symmetries, and canonical_order() varies from
                # interaction to interaction, then DONT loop over type_pattern:
                # for type_pattern, coefftype in typepattern_to_coefftypes)
                #     abids = canonical_order(abids, type_pattern)
                # Why:  When checking for undefined interactions,
                # we just want to make sure that SOME kind of interaction
                # involving these atoms exists.  The gruesome details of
                # force-field symmetry should not enter into this.
                # (We certainly don't want to require that different
                # interactions are simultaneously present for the same set of
                # atoms for ALL the possible different atom orderings for the
                # different possible symmetries in the force field you are using
                # Perhaps, in the future I should just use something like this:
                # atomids_int = abids[0]
                # atomids_int.sort()
                # atomids_int = tuple(atomids_int)
                # This would work for most molecules.
                # I suppose that in some some bizarre molecules containing
                # triangular or square cycles, for example, this would not
                # distinguish all 3 angles in the triangle, for example.
                # mistakenly thinking there was only one interaction there.
                # But these cases are rare.)

                if not atomids_int in atomids_matched:
                    atomids_matched[atomids_int] = False
                    # (Later on, we'll set some of these to True)

    # ------------------ check to make sure all interactions are defined (end)

    count = 0

    for typepattern, coefftype in typepattern_to_coefftypes:

        # ------------------ reporting progress -----------------------
        # The next interval of code is not technically necessary, but it makes
        # the printed output easier to read by excluding irrelevant
        # interactions

        if report_progress:

            # Check to see if the atoms or bonds referred to in typepattern
            # are (potentially) satisfied by any of the atoms present in the system.
            # If any of the required atoms for this typepattern are not present
            # in this system, then skip to the next typepattern.
            atoms_available_Iv = [
                False for Iv in range(0, g_bond_pattern.GetNumVerts())
            ]
            for Iv in range(0, g_bond_pattern.GetNumVerts()):
                for type_atom_str in types_atoms_all_str:
                    if MatchesPattern(type_atom_str, typepattern[Iv]):
                        atoms_available_Iv[Iv] = True
            atoms_available = True
            for Iv in range(0, g_bond_pattern.GetNumVerts()):
                if not atoms_available_Iv[Iv]:
                    atoms_available = False

            bonds_available_Ie = [
                False for Ie in range(0, g_bond_pattern.GetNumEdges())
            ]
            for Ie in range(0, g_bond_pattern.GetNumEdges()):
                for type_bond_str in types_bonds_all_str:
                    if MatchesPattern(
                            type_bond_str,
                            typepattern[g_bond_pattern.GetNumVerts() + Ie]):
                        bonds_available_Ie[Ie] = True
            bonds_available = True
            for Ie in range(0, g_bond_pattern.GetNumEdges()):
                if not bonds_available_Ie[Ie]:
                    bonds_available = False

            if atoms_available and bonds_available:

                # Explanation:
                # (Again) only if ALL of the atoms and bond requirements for
                # this type pattern are satisfied by at least SOME of the atoms
                # present in the this system, ...THEN print a status message.
                # (Because for complex all-atom force-fields, the number of
                # possible atom types, and typepatterns far exceeds the number
                # of atom types typically present in the system.  Otherwise
                # hundreds of kB of irrelevant information can be printed.)

                sys.stderr.write('    checking ' + coefftype +
                                 ' type requirements:'
                                 #' (atom-types,bond-types) '
                                 '\n     ' + str(typepattern) + '\n')

        # ------------------ reporting progress (end) -------------------

        for atombondtypes, abidslist in interactions_by_type.items():
            # express atom & bond types in a tuple of the original string
            # format
            types_atoms = [atomtypes_int2str[Iv] for Iv in atombondtypes[0]]
            types_bonds = [bondtypes_int2str[Ie] for Ie in atombondtypes[1]]
            type_strings = types_atoms + types_bonds

            # use string comparisons to check for a match with typepattern
            if MatchesAll(type_strings, typepattern):  # <-see "ttree_lex.py"
                for abids in abidslist:
                    # Re-order the atoms (and bonds) in a "canonical" way.
                    # Only add new interactions to the list after re-ordering
                    # them and checking that they have not been added earlier.
                    # (...well not when using the same coefftype at least.
                    #  This prevents the same triplet of atoms from
                    #  being used to calculate the bond-angle twice:
                    #  once for 1-2-3 and 3-2-1, for example.)
                    abids = canonical_order(abids)
                    redundant = False
                    if abids in abids_to_coefftypes:
                        coefftypes = abids_to_coefftypes[abids]
                        if coefftype in coefftypes:
                            redundant = True

                    if check_undefined_atomids_str:
                        atomids_int = tuple(abids[0])
                        atomids_matched[atomids_int] = True

                    if not redundant:

                        # (It's too bad python does not
                        #  have an Ordered defaultdict)
                        if coefftype in coefftype_to_atomids:
                            coefftype_to_atomids[coefftype].append(abids[0])
                        else:
                            coefftype_to_atomids[coefftype] = [abids[0]]
                        if abids in abids_to_coefftypes:
                            abids_to_coefftypes[abids].append(coefftype)
                        else:
                            abids_to_coefftypes[abids] = [coefftype]
                        count += 1

    if report_progress:
        sys.stderr.write('  (found ' + str(count) +
                         ' non-redundant matches)\n')

    if check_undefined_atomids_str:
        for atomids_int, found_match in atomids_matched.items():
            if not found_match:
                atomids_str = [
                    check_undefined_atomids_str[Iv] for Iv in atomids_int
                ]
                raise InputError(
                    'Error: A bonded interaction should exist between atoms:\n'
                    + '       ' + (',\n       '.join(atomids_str)) + '\n' +
                    '       ...however no interaction between these types of atoms has been defined\n'
                    +
                    '       This usually means that at least one of your atom TYPES is incorrect.\n'
                    +
                    '       If this is not the case, then you can override this error message by\n'
                    +
                    '       invoking moltemplate.sh without the \"-checkff\" argument.\n'
                )

    return coefftype_to_atomids
def GenInteractions_str(
        bond_pairs,
        g_bond_pattern,
        typepattern_to_coefftypes,
        canonical_order,  # function to sort atoms and bonds
        atomids_str,
        atomtypes_str,
        bondids_str,
        bondtypes_str,
        report_progress=False,  # print messages to sys.stderr?
        check_undefined=False):

    assert (len(atomids_str) == len(atomtypes_str))
    assert (len(bondids_str) == len(bondtypes_str))
    # The atomids and atomtypes and bondtypes are strings.
    # First we assign a unique integer id to each string.

    atomids_str2int = {}
    atomtypes_str2int = {}
    atomtypes_int2str = []
    atomtype_int = 0
    for i in range(0, len(atomids_str)):
        if atomids_str[i] in atomids_str2int:
            raise InputError('Error: multiple atoms have the same id (' +
                             str(atomids_str[i]) + ')')
        atomids_str2int[atomids_str[i]] = i
        #atomtypes_int = len(atomtypes_int)+1
        if (not (atomtypes_str[i] in atomtypes_str2int)):
            atomtypes_str2int[atomtypes_str[i]] = atomtype_int
            atomtypes_int2str.append(atomtypes_str[i])
            atomtype_int += 1
        # atomtypes_int.append(atomtype_int)

    bondids_str2int = {}
    bondtypes_str2int = {}
    bondtypes_int2str = []
    bondtype_int = 0
    for i in range(0, len(bondids_str)):
        if bondids_str[i] in bondids_str2int:
            raise InputError('Error: multiple bonds have the same id (' +
                             str(bondids_str[i]) + ')')
        bondids_str2int[bondids_str[i]] = i
        #bondtype_int = len(bondtypes_int)+1
        if (not (bondtypes_str[i] in bondtypes_str2int)):
            bondtypes_str2int[bondtypes_str[i]] = bondtype_int
            bondtypes_int2str.append(bondtypes_str[i])
            bondtype_int += 1

    # Now convert "bond_pairs" into the UGraph format
    G_system = Ugraph()
    for iv in range(0, len(atomtypes_str)):
        G_system.AddVertex(iv, atomtypes_str2int[atomtypes_str[iv]])

    for ie in range(0, len(bond_pairs)):
        atomid1_str = bond_pairs[ie][0]
        atomid2_str = bond_pairs[ie][1]
        if (atomid1_str not in atomids_str2int):
            raise InputError('Error in Bonds Section:\n'
                             '  ' + atomid1_str +
                             ' is not defined in Atoms section\n')
        if (atomid2_str not in atomids_str2int):
            raise InputError('Error in Bonds Section:\n'
                             '  ' + atomid2_str +
                             ' is not defined in Atoms section\n')
        G_system.AddEdge(atomids_str2int[atomid1_str],
                         atomids_str2int[atomid2_str],
                         bondtypes_str2int[bondtypes_str[ie]])

    coefftype_to_atomids_int = GenInteractions_int(
        G_system, g_bond_pattern, typepattern_to_coefftypes, canonical_order,
        atomtypes_int2str, bondtypes_int2str, report_progress,
        (atomids_str if check_undefined else None))

    coefftype_to_atomids_str = OrderedDict()
    for coefftype, atomidss_int in coefftype_to_atomids_int.items():
        if report_progress:
            sys.stderr.write('    processing coefftype: ' + str(coefftype) +
                             '\n')
        for atomids_int in atomidss_int:
            if coefftype in coefftype_to_atomids_str:
                coefftype_to_atomids_str[coefftype].append(
                    [atomids_str[iv] for iv in atomids_int])
            else:
                coefftype_to_atomids_str[coefftype] = \
                    [[atomids_str[iv] for iv in atomids_int]]
        # gc.collect()

    return coefftype_to_atomids_str
    def CommandsToMatrix(text,  # text containing affine transformation commands
                         src_loc=OSrcLoc(),   # for debugging
                         xcm=None):  # position of center of object
        Mdest = [[1.0, 0.0, 0.0, 0.0], [
            0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0]]
        M = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0]]
        Mtmp = [[1.0, 0.0, 0.0, 0.0], [
            0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0]]

        transform_commands = text.split(').')
        for transform_str in transform_commands:
            if transform_str.find('move(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[5:i_paren_close].split(',')
                if (len(args) != 3):
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires 3 numerical arguments.')
                M = [[1.0, 0.0, 0.0, float(args[0])],
                     [0.0, 1.0, 0.0, float(args[1])],
                     [0.0, 0.0, 1.0, float(args[2])]]
                AffineCompose(Mtmp, M, Mdest)
                CopyMat(Mdest, Mtmp)

            # if transform_str.find('movecm(') == 0:
            # #     assert(xcm != None)
            #    i_paren_close = transform_str.find(')')
            #    if i_paren_close == -1:
            #        i_paren_close = len(transform_str)
            #    args = transform_str[8:i_paren_close].split(',')
            #    if (len(args) != 3):
            #        raise InputError('Error near '+ErrorLeader(src_loc.infile, src_loc.lineno)+':\n'
            #                         '       Invalid command: \"'+transform_str+'\"\n'
            #                         '       This command requires 3 numerical arguments.')
            #    M = [[1.0, 0.0, 0.0, float(args[0])-(xcm[0])],
            #         [0.0, 1.0, 0.0, float(args[1])-(xcm[1])],
            #         [0.0, 0.0, 1.0, float(args[2])-(xcm[2])]]
            #    AffineCompose(Mtmp, M, Mdest)
            #    CopyMat(Mdest, Mtmp)

            elif transform_str.find('move_rand(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[10:i_paren_close].split(',')

                seed = 1
                if len(args) in (2,4,7):
                    seed = int(args[0])
                random.seed(seed)
                if len(args) == 1:
                    sigma = float(args[1])
                    x = random.gauss(0.0, sigma)
                    y = random.gauss(0.0, sigma)
                    z = random.gauss(0.0, sigma)
                elif len(args) == 2:
                    # seed = int(args[0])  this was already handled above
                    sigma = float(args[1])
                    x = random.gauss(0.0, sigma)
                    y = random.gauss(0.0, sigma)
                    z = random.gauss(0.0, sigma)
                elif len(args) == 3:
                    x = random.gauss(0.0, float(args[0]))
                    y = random.gauss(0.0, float(args[1]))
                    z = random.gauss(0.0, float(args[2]))
                elif len(args) == 4:
                    # seed = int(args[0])   this was already handled above
                    x = random.gauss(0.0, float(args[1]))
                    y = random.gauss(0.0, float(args[2]))
                    z = random.gauss(0.0, float(args[3]))
                elif len(args) == 6:
                    x_min = float(args[0])
                    x_max = float(args[1])
                    y_min = float(args[2])
                    y_max = float(args[3])
                    z_min = float(args[4])
                    z_max = float(args[5])
                    x = x_min + (x_max - x_min)*(random.random()-0.5)
                    y = y_min + (y_max - y_min)*(random.random()-0.5)
                    z = z_min + (z_max - z_min)*(random.random()-0.5)
                        
                elif len(args) == 7:
                    # seed = int(args[0])  this was already handled above
                    x_min = float(args[1])
                    x_max = float(args[2])
                    y_min = float(args[3])
                    y_max = float(args[4])
                    z_min = float(args[5])
                    z_max = float(args[6])
                    x = x_min + (x_max - x_min)*(random.random()-0.5)
                    y = y_min + (y_max - y_min)*(random.random()-0.5)
                    z = z_min + (z_max - z_min)*(random.random()-0.5)
                else:
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires either 1, 2, 3, 4, 6 or 7 numerical arguments.  Either:\n'
                                     '           move_rand(gauss_sigma) or\n'
                                     '           move_rand(seed, gauss_sigma) or\n'
                                     '           move_rand(gauss_sigma_x, gauss_sigma_y, gauss_sigma_z) or\n'
                                     '           move_rand(seed, gauss_sigma_x, gauss_sigma_y, gauss_sigma_z) or\n'
                                     '           move_rand(x_min, x_max, y_min, y_max, z_min, z_max) or\n'
                                     '           move_rand(seed, x_min, x_max, y_min, y_max, z_min, z_max)\n')

                M = [[1.0, 0.0, 0.0, x],
                     [0.0, 1.0, 0.0, y],
                     [0.0, 0.0, 1.0, z]]
                AffineCompose(Mtmp, M, Mdest)
                CopyMat(Mdest, Mtmp)

            elif transform_str.find('rot(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[4:i_paren_close].split(',')
                center_v = None
                if (len(args) == 7):
                    center_v = [float(args[4]), float(args[5]), float(args[6])]
                elif (len(args) != 4):
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires either 4 or 7 numerical arguments.  Either:\n'
                                     '           rot(angle, axisX, axisY, axiZ)  or \n'
                                     '           rot(angle, axisX, axisY, axiZ, centerX, centerY, centerZ)')
                M[0][3] = 0.0  # RotMatAXYZ() only modifies 3x3 submatrix of M
                M[1][3] = 0.0  # The remaining final column must be zeroed by hand
                M[2][3] = 0.0
                RotMatAXYZ(M,
                           float(args[0]) * math.pi / 180.0,
                           float(args[1]),
                           float(args[2]),
                           float(args[3]))
                if (center_v == None):
                    AffineCompose(Mtmp, M, Mdest)
                    CopyMat(Mdest, Mtmp)
                else:
                    # Move "center_v" to the origin
                    moveCentToOrig = [[1.0, 0.0, 0.0, -center_v[0]],
                                      [0.0, 1.0, 0.0, -center_v[1]],
                                      [0.0, 0.0, 1.0, -center_v[2]]]
                    AffineCompose(Mtmp, moveCentToOrig, Mdest)
                    CopyMat(Mdest, Mtmp)
                    # Rotate the coordinates (relative to the origin)
                    AffineCompose(Mtmp, M, Mdest)  # M is the rotation matrix
                    CopyMat(Mdest, Mtmp)
                    # Move the origin back to center_v
                    moveCentBack = [[1.0, 0.0, 0.0, center_v[0]],
                                    [0.0, 1.0, 0.0, center_v[1]],
                                    [0.0, 0.0, 1.0, center_v[2]]]
                    AffineCompose(Mtmp, moveCentBack, Mdest)
                    CopyMat(Mdest, Mtmp)

            # # elif transform_str.find('rotcm(') == 0:
            # #     assert(xcm != None)
            # #     i_paren_close = transform_str.find(')')
            # #     if i_paren_close == -1:
            # #         i_paren_close = len(transform_str)
            # #     args = transform_str[6:i_paren_close].split(',')
            # #     if (len(args) != 4):
            # #         raise InputError('Error near '+ErrorLeader(src_loc.infile, src_loc.lineno)+':\n'
            # #                          '       Invalid command: \"'+transform_str+'\"\n'
            # #                          '       This command requires 4 numerical arguments.')
            # #
            # #     moveCMtoOrig = [[1.0, 0.0, 0.0, -xcm[0]],
            # #                     [0.0, 1.0, 0.0, -xcm[1]],
            # #                     [0.0, 0.0, 1.0, -xcm[2]]]
            # #     AffineCompose(Mtmp, moveCMtoOrig, Mdest)
            # #     CopyMat(Mdest, Mtmp)
            # #     M[0][3] = 0.0#RotMatAXYZ() only modifies 3x3 submatrix of M
            # #     M[1][3] = 0.0#The remaining final column must be zeroed by hand
            # #     M[2][3] = 0.0
            # #     RotMatAXYZ(M,
            # #                float(args[0])*math.pi/180.0,
            # #                float(args[1]),
            # #                float(args[2]),
            # #                float(args[3]))
            # #     AffineCompose(Mtmp, M, Mdest)
            # #     CopyMat(Mdest, Mtmp)
            # #     moveCmBack = [[1.0, 0.0, 0.0, xcm[0]],
            # #                   [0.0, 1.0, 0.0, xcm[1]],
            # #                   [0.0, 0.0, 1.0, xcm[2]]]
            # #     AffineCompose(Mtmp, moveCmBack, Mdest)
            # #     CopyMat(Mdest, Mtmp)

            elif transform_str.find('rot_rand(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[9:i_paren_close].split(',')

                seed = 1
                if len(args) in (2,6):
                    seed = int(args[0])
                random.seed(seed)
                raxis = [0.0, 0.0, 0.0]
                if len(args) < 5:
                    # choose a random rotation axis
                    raxis_len = 0.0
                    while (not ((0.01<raxis_len) and (raxis_len <= 1.0))):
                        raxis = [-1+2.0*(random.random()-0.5) for d in range(0,3)]
                        raxis_len = math.sqrt(raxis[0]**2 + raxis[1]**2 + raxis[2]**2)
                    for d in range(0,3):
                        raxis[d] /= raxis_len
                if len(args) == 0:
                    angle_min = angle_max = 2*math.pi
                elif len(args) == 1:
                    angle_min = 0.0
                    angle_max = float(args[0]) * math.pi / 180.0,
                elif len(args) == 5:
                    angle_min = float(args[0])
                    angle_max = float(args[1])
                    raxis[0]  = float(args[2])
                    raxis[1]  = float(args[3])
                    raxis[2]  = float(args[4])
                elif len(args) == 6:
                    seed      = int(args[0])
                    angle_min = float(args[1])
                    angle_max = float(args[2])
                    raxis[0]  = float(args[3])
                    raxis[1]  = float(args[4])
                    raxis[2]  = float(args[5])
                else:
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires either 0, 1, 2, 5 or 6 numerical arguments. Either:\n'
                                     '           rot_rand()  or \n'
                                     '           rot_rand(delta_angle)  or \n'
                                     '           rot_rand(seed, delta_angle)  or \n'
                                     '           rot_rand(angle_min, angle_max, axisX, axisY, axiZ) or\n'
                                     '           rot_rand(seed, angle_min, angle_max, axisX, axisY, axiZ)')

                angle = angle_min + (angle_max - angle_min)*(random.random() - 0.5)

                M[0][3] = 0.0  # RotMatAXYZ() only modifies 3x3 submatrix of M
                M[1][3] = 0.0  # The remaining final column must be zeroed by hand
                M[2][3] = 0.0
                RotMatAXYZ(M,
                           angle,
                           raxis[0], raxis[1], raxis[2])
                AffineCompose(Mtmp, M, Mdest)
                CopyMat(Mdest, Mtmp)


            elif transform_str.find('rotvv(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[6:i_paren_close].split(',')
                center_v = None
                if (len(args) == 9):
                    center_v = [float(args[6]), float(args[7]), float(args[8])]
                elif (len(args) != 6):
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires either 6 or 9 numerical arguments.  Either:\n'
                                     '           rotvv(Xold,Yold,Zold,Xnew,Ynew,Znew)  or \n'
                                     '           rotvv(Xold,Yold,Zold,Xnew,Ynew,Znew,centerX,centerY,centerZ)')
                M[0][3] = 0.0  # RotMatXYZXYZ() only modifies 3x3 submatrix of M
                M[1][3] = 0.0  # The remaining final column must be zeroed by hand
                M[2][3] = 0.0
                RotMatXYZXYZ(M,
                             float(args[0]),
                             float(args[1]),
                             float(args[2]),
                             float(args[3]),
                             float(args[4]),
                             float(args[5]))
                if (center_v == None):
                    AffineCompose(Mtmp, M, Mdest)
                    CopyMat(Mdest, Mtmp)
                else:
                    # Move "center_v" to the origin
                    moveCentToOrig = [[1.0, 0.0, 0.0, -center_v[0]],
                                      [0.0, 1.0, 0.0, -center_v[1]],
                                      [0.0, 0.0, 1.0, -center_v[2]]]
                    AffineCompose(Mtmp, moveCentToOrig, Mdest)
                    CopyMat(Mdest, Mtmp)
                    # Rotate the coordinates (relative to the origin)
                    AffineCompose(Mtmp, M, Mdest)  # M is the rotation matrix
                    CopyMat(Mdest, Mtmp)
                    # Move the origin back to center_v
                    moveCentBack = [[1.0, 0.0, 0.0, center_v[0]],
                                    [0.0, 1.0, 0.0, center_v[1]],
                                    [0.0, 0.0, 1.0, center_v[2]]]
                    AffineCompose(Mtmp, moveCentBack, Mdest)
                    CopyMat(Mdest, Mtmp)

            elif transform_str.find('scale(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[6:i_paren_close].split(',')

                if (len(args) == 1):
                    scale_v = [float(args[0]), float(args[0]), float(args[0])]
                    center_v = [0.0, 0.0, 0.0]
                elif (len(args) == 3):
                    scale_v = [float(args[0]), float(args[1]), float(args[2])]
                    center_v = [0.0, 0.0, 0.0]
                elif (len(args) == 4):
                    scale_v = [float(args[0]), float(args[0]), float(args[0])]
                    center_v = [float(args[1]), float(args[2]), float(args[3])]
                elif (len(args) == 6):
                    scale_v = [float(args[0]), float(args[1]), float(args[2])]
                    center_v = [float(args[3]), float(args[4]), float(args[5])]
                else:
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires either 1, 3, 4, or 6 numerical arguments. Either:\n'
                                     '           scale(ratio), or \n'
                                     '           scale(ratioX, ratioY, ratioZ),\n'
                                     '           scale(ratio, centerX, centerY, centerZ), or\n'
                                     '           scale(ratioX, ratioY, ratioZ, centerX, centerY, centerZ)')

                ScaleMat(M, scale_v)

                # Now worry about translation:
                for d in range(0, 3):
                    M[d][3] = center_v[d] * (1.0 - scale_v[d])

                AffineCompose(Mtmp, M, Mdest)
                CopyMat(Mdest, Mtmp)

            # # elif transform_str.find('scalecm(') == 0:
            # #     assert(xcm != None)
            # #     i_paren_close = transform_str.find(')')
            # #     if i_paren_close == -1:
            # #         i_paren_close = len(transform_str)
            # #     args = transform_str[8:i_paren_close].split(',')
            # #
            # #     moveCMtoOrig = [[1.0, 0.0, 0.0, -xcm[0]],
            # #                     [0.0, 1.0, 0.0, -xcm[1]],
            # #                     [0.0, 0.0, 1.0, -xcm[2]]]
            # #     AffineCompose(Mtmp, moveCMtoOrig, Mdest)
            # #     CopyMat(Mdest, Mtmp)
            # #
            # #     M[0][3] = 0.0 #ScaleMat() only modifies 3x3 submatrix of M
            # #     M[1][3] = 0.0 #The remaining final column must be zeroed by hand
            # #     M[2][3] = 0.0
            # #     if (len(args) == 1):
            # #         ScaleMat(M, args[0])
            # #     elif (len(args) == 3):
            # #         ScaleMat(M, args)
            # #     else:
            # #         raise InputError('Error near '+ErrorLeader(src_loc.infile, src_loc.lineno)+':\n'
            # #                          '       Invalid command: \"'+transform_str+'\"\n'
            # #                          '       This command requires either 1 or 3 numerical arguments.')
            # #
            # #     AffineCompose(Mtmp, M, Mdest)
            # #     CopyMat(Mdest, Mtmp)
            # #     moveCmBack = [[1.0, 0.0, 0.0, xcm[0]],
            # #                   [0.0, 1.0, 0.0, xcm[1]],
            # #                   [0.0, 0.0, 1.0, xcm[2]]]
            # #     AffineCompose(Mtmp, moveCmBack, Mdest)
            # #     CopyMat(Mdest, Mtmp)

            else:
                raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                 '       Unknown transformation command: \"' + transform_str + '\"\n')

        return Mdest
Beispiel #9
0
    def CommandsToMatrix(text,  # text containing affine transformation commands
                         src_loc=OSrcLoc(),   # for debugging
                         xcm=None):  # position of center of object
        Mdest = [[1.0, 0.0, 0.0, 0.0], [
            0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0]]
        M = [[1.0, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0]]
        Mtmp = [[1.0, 0.0, 0.0, 0.0], [
            0.0, 1.0, 0.0, 0.0], [0.0, 0.0, 1.0, 0.0]]

        transform_commands = text.split(').')
        for transform_str in transform_commands:
            if transform_str.find('move(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[5:i_paren_close].split(',')
                if (len(args) != 3):
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires 3 numerical arguments.')
                M = [[1.0, 0.0, 0.0, float(args[0])],
                     [0.0, 1.0, 0.0, float(args[1])],
                     [0.0, 0.0, 1.0, float(args[2])]]
                AffineCompose(Mtmp, M, Mdest)
                CopyMat(Mdest, Mtmp)

            # if transform_str.find('movecm(') == 0:
            # #     assert(xcm != None)
            #    i_paren_close = transform_str.find(')')
            #    if i_paren_close == -1:
            #        i_paren_close = len(transform_str)
            #    args = transform_str[8:i_paren_close].split(',')
            #    if (len(args) != 3):
            #        raise InputError('Error near '+ErrorLeader(src_loc.infile, src_loc.lineno)+':\n'
            #                         '       Invalid command: \"'+transform_str+'\"\n'
            #                         '       This command requires 3 numerical arguments.')
            #    M = [[1.0, 0.0, 0.0, float(args[0])-(xcm[0])],
            #         [0.0, 1.0, 0.0, float(args[1])-(xcm[1])],
            #         [0.0, 0.0, 1.0, float(args[2])-(xcm[2])]]
            #    AffineCompose(Mtmp, M, Mdest)
            #    CopyMat(Mdest, Mtmp)

            elif transform_str.find('rot(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[4:i_paren_close].split(',')
                center_v = None
                if (len(args) == 7):
                    center_v = [float(args[4]), float(args[5]), float(args[6])]
                elif (len(args) != 4):
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires either 4 or 7 numerical arguments.  Either:\n'
                                     '           rot(angle, axisX, axisY, axiZ)  or \n'
                                     '           rot(angle, axisX, axisY, axiZ, centerX, centerY, centerZ)')
                M[0][3] = 0.0  # RotMatAXYZ() only modifies 3x3 submatrix of M
                M[1][3] = 0.0  # The remaining final column must be zeroed by hand
                M[2][3] = 0.0
                RotMatAXYZ(M,
                           float(args[0]) * math.pi / 180.0,
                           float(args[1]),
                           float(args[2]),
                           float(args[3]))
                if (center_v == None):
                    AffineCompose(Mtmp, M, Mdest)
                    CopyMat(Mdest, Mtmp)
                else:
                    # Move "center_v" to the origin
                    moveCentToOrig = [[1.0, 0.0, 0.0, -center_v[0]],
                                      [0.0, 1.0, 0.0, -center_v[1]],
                                      [0.0, 0.0, 1.0, -center_v[2]]]
                    AffineCompose(Mtmp, moveCentToOrig, Mdest)
                    CopyMat(Mdest, Mtmp)
                    # Rotate the coordinates (relative to the origin)
                    AffineCompose(Mtmp, M, Mdest)  # M is the rotation matrix
                    CopyMat(Mdest, Mtmp)
                    # Move the origin back to center_v
                    moveCentBack = [[1.0, 0.0, 0.0, center_v[0]],
                                    [0.0, 1.0, 0.0, center_v[1]],
                                    [0.0, 0.0, 1.0, center_v[2]]]
                    AffineCompose(Mtmp, moveCentBack, Mdest)
                    CopyMat(Mdest, Mtmp)

            # # elif transform_str.find('rotcm(') == 0:
            # #     assert(xcm != None)
            # #     i_paren_close = transform_str.find(')')
            # #     if i_paren_close == -1:
            # #         i_paren_close = len(transform_str)
            # #     args = transform_str[6:i_paren_close].split(',')
            # #     if (len(args) != 4):
            # #         raise InputError('Error near '+ErrorLeader(src_loc.infile, src_loc.lineno)+':\n'
            # #                          '       Invalid command: \"'+transform_str+'\"\n'
            # #                          '       This command requires 4 numerical arguments.')
            # #
            # #     moveCMtoOrig = [[1.0, 0.0, 0.0, -xcm[0]],
            # #                     [0.0, 1.0, 0.0, -xcm[1]],
            # #                     [0.0, 0.0, 1.0, -xcm[2]]]
            # #     AffineCompose(Mtmp, moveCMtoOrig, Mdest)
            # #     CopyMat(Mdest, Mtmp)
            # #     M[0][3] = 0.0#RotMatAXYZ() only modifies 3x3 submatrix of M
            # #     M[1][3] = 0.0#The remaining final column must be zeroed by hand
            # #     M[2][3] = 0.0
            # #     RotMatAXYZ(M,
            # #                float(args[0])*math.pi/180.0,
            # #                float(args[1]),
            # #                float(args[2]),
            # #                float(args[3]))
            # #     AffineCompose(Mtmp, M, Mdest)
            # #     CopyMat(Mdest, Mtmp)
            # #     moveCmBack = [[1.0, 0.0, 0.0, xcm[0]],
            # #                   [0.0, 1.0, 0.0, xcm[1]],
            # #                   [0.0, 0.0, 1.0, xcm[2]]]
            # #     AffineCompose(Mtmp, moveCmBack, Mdest)
            # #     CopyMat(Mdest, Mtmp)

            elif transform_str.find('rotvv(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[6:i_paren_close].split(',')
                center_v = None
                if (len(args) == 9):
                    center_v = [float(args[6]), float(args[7]), float(args[8])]
                elif (len(args) != 6):
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires either 6 or 9 numerical arguments.  Either:\n'
                                     '           rotvv(Xold,Yold,Zold,Xnew,Ynew,Znew)  or \n'
                                     '           rotvv(Xold,Yold,Zold,Xnew,Ynew,Znew,centerX,centerY,centerZ)')
                M[0][3] = 0.0  # RotMatXYZXYZ() only modifies 3x3 submatrix of M
                M[1][3] = 0.0  # The remaining final column must be zeroed by hand
                M[2][3] = 0.0
                RotMatXYZXYZ(M,
                             float(args[0]),
                             float(args[1]),
                             float(args[2]),
                             float(args[3]),
                             float(args[4]),
                             float(args[5]))
                if (center_v == None):
                    AffineCompose(Mtmp, M, Mdest)
                    CopyMat(Mdest, Mtmp)
                else:
                    # Move "center_v" to the origin
                    moveCentToOrig = [[1.0, 0.0, 0.0, -center_v[0]],
                                      [0.0, 1.0, 0.0, -center_v[1]],
                                      [0.0, 0.0, 1.0, -center_v[2]]]
                    AffineCompose(Mtmp, moveCentToOrig, Mdest)
                    CopyMat(Mdest, Mtmp)
                    # Rotate the coordinates (relative to the origin)
                    AffineCompose(Mtmp, M, Mdest)  # M is the rotation matrix
                    CopyMat(Mdest, Mtmp)
                    # Move the origin back to center_v
                    moveCentBack = [[1.0, 0.0, 0.0, center_v[0]],
                                    [0.0, 1.0, 0.0, center_v[1]],
                                    [0.0, 0.0, 1.0, center_v[2]]]
                    AffineCompose(Mtmp, moveCentBack, Mdest)
                    CopyMat(Mdest, Mtmp)

            elif transform_str.find('scale(') == 0:
                i_paren_close = transform_str.find(')')
                if i_paren_close == -1:
                    i_paren_close = len(transform_str)
                args = transform_str[6:i_paren_close].split(',')

                if (len(args) == 1):
                    scale_v = [float(args[0]), float(args[0]), float(args[0])]
                    center_v = [0.0, 0.0, 0.0]
                elif (len(args) == 3):
                    scale_v = [float(args[0]), float(args[1]), float(args[2])]
                    center_v = [0.0, 0.0, 0.0]
                elif (len(args) == 4):
                    scale_v = [float(args[0]), float(args[0]), float(args[0])]
                    center_v = [float(args[1]), float(args[2]), float(args[3])]
                elif (len(args) == 6):
                    scale_v = [float(args[0]), float(args[1]), float(args[2])]
                    center_v = [float(args[3]), float(args[4]), float(args[5])]
                else:
                    raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                     '       Invalid command: \"' + transform_str + '\"\n'
                                     '       This command requires either 1, 3, 4, or 6 numerical arguments. Either:\n'
                                     '           scale(ratio), or \n'
                                     '           scale(ratioX, ratioY, ratioZ),\n'
                                     '           scale(ratio, centerX, centerY, centerZ), or\n'
                                     '           scale(ratioX, ratioY, ratioZ, centerX, centerY, centerZ)')

                ScaleMat(M, scale_v)

                # Now worry about translation:
                for d in range(0, 3):
                    M[d][3] = center_v[d] * (1.0 - scale_v[d])

                AffineCompose(Mtmp, M, Mdest)
                CopyMat(Mdest, Mtmp)

            # # elif transform_str.find('scalecm(') == 0:
            # #     assert(xcm != None)
            # #     i_paren_close = transform_str.find(')')
            # #     if i_paren_close == -1:
            # #         i_paren_close = len(transform_str)
            # #     args = transform_str[8:i_paren_close].split(',')
            # #
            # #     moveCMtoOrig = [[1.0, 0.0, 0.0, -xcm[0]],
            # #                     [0.0, 1.0, 0.0, -xcm[1]],
            # #                     [0.0, 0.0, 1.0, -xcm[2]]]
            # #     AffineCompose(Mtmp, moveCMtoOrig, Mdest)
            # #     CopyMat(Mdest, Mtmp)
            # #
            # #     M[0][3] = 0.0 #ScaleMat() only modifies 3x3 submatrix of M
            # #     M[1][3] = 0.0 #The remaining final column must be zeroed by hand
            # #     M[2][3] = 0.0
            # #     if (len(args) == 1):
            # #         ScaleMat(M, args[0])
            # #     elif (len(args) == 3):
            # #         ScaleMat(M, args)
            # #     else:
            # #         raise InputError('Error near '+ErrorLeader(src_loc.infile, src_loc.lineno)+':\n'
            # #                          '       Invalid command: \"'+transform_str+'\"\n'
            # #                          '       This command requires either 1 or 3 numerical arguments.')
            # #
            # #     AffineCompose(Mtmp, M, Mdest)
            # #     CopyMat(Mdest, Mtmp)
            # #     moveCmBack = [[1.0, 0.0, 0.0, xcm[0]],
            # #                   [0.0, 1.0, 0.0, xcm[1]],
            # #                   [0.0, 0.0, 1.0, xcm[2]]]
            # #     AffineCompose(Mtmp, moveCmBack, Mdest)
            # #     CopyMat(Mdest, Mtmp)

            else:
                raise InputError('Error near ' + ErrorLeader(src_loc.infile, src_loc.lineno) + ':\n'
                                 '       Unknown transformation command: \"' + transform_str + '\"\n')

        return Mdest
Beispiel #10
0
def main():
    try:
        if (len(sys.argv) != 2):
            raise InputError(
                'Error running  \"' + g_program_name + '\"\n'
                ' Typical usage:\n'
                ' ttree_render.py ttree_assignments.txt < file.template > file.rendered\n'
                '\n'
                '   Missing argument.\n'
                '   Expected the name of a 2-column file containing\n'
                '   variable names and their bindings (values).\n'
                '   (This is likely a programmer error.\n'
                '    This script was not intended to be run by end users.)\n')

        bindings_filename = sys.argv[1]
        f = open(bindings_filename)
        assignments = {}

        #BasicUIReadBindingsStream(assignments, f, bindings_filename)

        # The line above is robust but it uses far too much memory.
        # This for loop below works for most cases.
        for line in f:
            #tokens = lines.strip().split()
            # like split but handles quotes
            tokens = SplitQuotedString(line.strip())
            if len(tokens) < 2:
                continue
            assignments[tokens[0]] = tokens[1]

        f.close()
        gc.collect()

        lex = TemplateLexer(sys.stdin, '__standard_input_for_ttree_render__')
        lex.var_delim = '$@'

        text_block_list = lex.ReadTemplate(simplify_output=True)

        output = []

        for entry in text_block_list:
            assert (isinstance(entry, str))

            if ((len(entry) > 1) and (entry[0] in lex.var_delim)):
                if '.' in entry:
                    ic = entry.find('.')
                    var_name = entry[:ic]
                    var_suffix = entry[ic:]
                else:
                    var_name = entry
                    var_suffix = ''

                var_name = entry
                if var_name not in assignments:
                    raise (InputError(
                        'Error(' + g_program_name + ')'
                        #' at '+ErrorLeader(var_ref.src_loc.infile,
                        #                  var_ref.src_loc.lineno)+
                        ' unknown variable:\n'
                        '         \"' + var_name + '\"\n'))
                else:
                    var_value = assignments[var_name]

                format_fname, args = ExtractFormattingCommands(var_suffix)
                if format_fname == 'ljust':
                    if len(args) == 1:
                        var_value = var_value.ljust(int(args[0]))
                    else:
                        var_value = var_value.ljust(int(args[0]), args[1])
                elif format_fname == 'rjust':
                    if len(args) == 1:
                        var_value = var_value.rjust(int(args[0]))
                    else:
                        var_value = var_value.rjust(int(args[0]), args[1])
                output.append(var_value)
            else:
                output += entry

        sys.stdout.write(''.join(output))

    except (ValueError, InputError) as err:
        sys.stderr.write('\n' + str(err) + '\n')
        sys.exit(-1)

    return
                              else {if (found) {passed=1}} 
                              if (passed) print $0}' \
          < ttree_assignments.txt >> ttree_assignments_new.txt

I wrote this python script (instead of using awk) just to handle quoted stings
(and strings with other fancy characters and escape sequences).

"""

import sys
from ttree_lex import SplitQuotedString, EscCharStrToChar, SafelyEncodeString, InputError

try:
    if (len(sys.argv) != 3):
        raise InputError('Error running  \"'+__file__+'\"\n'
                         '   Wrong number of arguments.\n'
                         '   (This is likely a programmer error.\n'
                         '    This script was not intended to be run by end users.)\n')

    cat_name = sys.argv[1] 
    f = open(sys.argv[2])
    lines_generated = f.readlines()
    f.close()

    # Selections are simply lists of 2-tuples (pairs) 
    #f = open('ttree_assignments.txt','r')
    #lines_bindings = f.readlines()
    #f.close()
    lines_bindings = sys.stdin.readlines()

    # Figure out which lines in the 'ttree_assignments.txt' file
    # contain the variables of the type you are looking for.