def trainMali( mali, options ):
    """train a grammar on a multiple alignment."""

    ## remove empty columns and masked columns
    if options.clean_mali:
        mali.mGapChars = mali.mGapChars + ("n", "N")
        mali.removeGaps( minimum_gaps = 1, frame=1 )
    
    length = mali.getNumColumns()

    input_model = prepareGrammar( options )

    for id in mali.getIdentifiers():
        if options.separator in id:
            species = id.split(options.separator)[0]
            mali.rename( id, species )

    map_new2old = mali.mapIdentifiers()
    map_old2new = IOTools.getInvertedDictionary( map_new2old, make_unique = True )
    
    ids = mali.getIdentifiers()

    if options.input_filename_tree:
        nexus = TreeTools.Newick2Nexus( open(options.input_filename_tree,"r") )
        tree = nexus.trees[0]
        try:
            tree.relabel( map_old2new, warn = True )
        except __HOLE__, msg:
            raise KeyError( "names in mali and tree are not congruent: %s" % msg )
    else:
        tree = None

    filename_mali = prepareMali( mali, tree, map_old2new, options )
    
    result = trainOnMali( input_model, filename_mali, options )

    options.stdout.write( "%f\t%i" % (result.getLogLikelihood(), result.getNumIterations() ) )
    outputRates( result, options )
    outputAnnotations( result, options )
    
    options.stdout.write("\n")

    return result

##-----------------------------------------------------------------------------------
dataset/ETHPy150Open CGATOxford/cgat/obsolete/xrate_blocks.py/trainMali