<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:

def read_tree(input, schema):
    '''Read a tree from a string or file

    Args:
        ``input`` (``str``): Either a tree string, a path to a tree file (plain-text or gzipped), or a DendroPy Tree object

        ``schema`` (``str``): The schema of ``input`` (DendroPy, Newick, NeXML, or Nexus)

    Returns:
        * If the input is Newick, either a ``Tree`` object if ``input`` contains a single tree, or a ``list`` of ``Tree`` objects if ``input`` contains multiple trees (one per line)

        * If the input is NeXML or Nexus, a ``dict`` of trees represented by ``input``, where keys are tree names (``str``) and values are ``Tree`` objects
    '''
    schema_to_function = {
        'dendropy': read_tree_dendropy,
        'newick': read_tree_newick,
        'nexml': read_tree_nexml,
        'nexus': read_tree_nexus
    }
    if schema.lower() not in schema_to_function:
        raise ValueError("Invalid schema: %s (valid options: %s)" % (schema, ', '.join(sorted(schema_to_function.keys()))))
    return schema_to_function[schema.lower()](input)