"""Module for writing cross-platform, Excel/JavaTreeView/Cluster3
compatible CDT files."""

import re

def writerow(out, row):
    """Write the elements of row in a conservative tab-delimited format."""
    out.write(
        # Use tab delimiters
        "\t".join(
        # Normalize all whitespace (including \t, \r, and \n) and "
        #   to "normal" spaces.
        [re.sub(r'[\s"]'," ",str(i)) for i in row])
        # Use UNIX-style newlines
        +"\n")

def writecdt(filename, matrix,
             row_names = None,
             row_annotations = None,
             columns = None):
    """Write the data in matrix in tab delimited, \n terminated
    format to a file named filename.  Elements are not quoted,
    and quotes and whitespace within elements are converted to
    generic spaces to avoid ambiguity.  If given, row_names,
    row_annotations, and columns are used for the UNIQID column,
    the NAME column, and the column headers respectively; otherwise,
    these are filled with default values.  Note that these optional
    lists should have the same dimensions as the rows or columns
    of matrix (e.g., columns should not include the "UNIQID" and "NAME"
    headers)."""

    # Check inputs

    if((len(matrix) < 1) or len(matrix[0]) < 1):
        raise ValueError, "No data in matrix!"

    # Use default values for missing labels
    if(row_names is None):
        row_names = ["Gene%05d" % i for i in xrange(len(matrix))]
    if(row_annotations is None):
        row_annotations = row_names
    if(columns is None):
        columns = ["Array%05d" % i for i in xrange(len(matrix[0]))]

    if(len(row_names) != len(matrix)):
        raise ValueError, "row_names doesn't match matrix (%d != %d)" % (
            (len(row_names), len(matrix)))

    if(len(row_annotations) != len(matrix)):
        raise ValueError, "row_annotations doesn't match matrix (%d != %d)" % (
            (len(row_annotations), len(matrix)))

    if(len(columns) != len(matrix[0])):
        raise ValueError, "columns doesn't match matrix (%d != %d)" % (
            (len(columns), len(matrix)))

    # Open file for writing
    out = open(filename,"w")

    # Write header
    writerow(out, ["UNIQID","NAME"]+columns)

    # Write body
    for (uniqid,name,row) in zip(row_names,row_annotations,matrix):
        writerow(out, [uniqid,name]+row)

    # Flush file to disk
    out.close()
