Save a tabarray to a separated-variable (CSV) file.

    **Parameters**

        **fname** :  string

            Path to a separated variable (CSV) text file.

        **X** :  tabarray

            The actual data in a :class:`tabular.tab.tabarray`.

        **comments** :  string, optional

            The character to be used to denote the start of a header (non-data) 
            line, e.g. '#'.  If not specified, it is determined according to the 
            following rule:  '#' if `metadata` argument is set, otherwise ''.

        **delimiter** :  string, optional

            The character to beused to separate values in each line of text, 
            e.g. ','.  If not specified, by default, this is inferred from 
            the file extension: if the file ends in `.csv`, the delimiter is 
            ',', otherwise it is '\\t.'

        **linebreak** :  string, optional

            The string separating lines of text.  By default, this is assumed to 
            be '\\n', and can also be set to be '\\r' or '\\r\\n'.

        **metadata** :  list of strings or Boolean, optional

            Allowed values are True, False, or any sublists of the list 
            `['names', 'formats', 'types', 'coloring', 'dialect']`.  These 
            keys indicate what special metadata is printed in the header.

            * If a sublist of 
             `['names', 'formats', 'types', 'coloring', 'dialect']`, then the 
             indicated types of metadata are written out.  

            * If `True`, this is the same as 
              `metadata = ['coloring', 'types', 'names','dialect']`, e.g. as 
               many types of metadata as this algorithm currently knows how to 
               write out. 

            * If 'False', no metadata is printed at all, e.g. just the data.
                    
            * If `metadata` is not specified, the default is `['names']`, that 
              is, just column names are written out.
                        
        **printmetadict** :  Boolean, optional

            Whether or not to print a string representation of the 
            `metadatadict` in the first line of the header.

            If `printmetadict` is not specified, then:

            * If `metadata` is specified and is not `False`, then
              `printmetadata` defaults to `True`.

            * Else if `metadata` is `False`, then `printmetadata` defaults 
              to `False`.

            * Else `metadata` is not specified, and `printmetadata` defaults 
              to `False`.

            See the :func:`tabular.io.loadSV` for more information about 
            `metadatadict`.
            
        **stringifier** : callable 
        
            Callable taking 1-d numpy array and returning Python list of strings 
            of same length, or dictionary or tuple of such callables.  
                    
            If specified, the callable will be applied to each column, and the 
            resulting list of strings will be written to the file.  If 
            specified as a list or dictionary of callables, the functions will 
            be applied to correponding columns.  The default used if 
            **stringifier** is not specified, is `tb.utils.DEFAULT_STRINGIFIER`, 
            which merely passes through string-type columns, and converts 
            numerical-type columns directly to corresponding strings with NaNs 
            replaced with blank values.  The main purpose of specifying a 
            non-default value is to encode numerical values in various string 
            encodings that might be used required for other applications like 
            databases.                    
                               
            NOTE:  In certain special circumstances (e.g. when the 
            lineterminator or delimiter character appears in a field of the 
            data), the Python CSV writer is used to write out data.  To allow 
            for control of the operation of the writer in these circumstances, 
            the following other parameters replicating the interface of the CSV 
            module are also valid, and values will be passed through:  
            **doublequote**, **escapechar**, **quoting**, **quotechar**, and 
            **skipinitialspace**.  (See Python CSV module documentation for more 
            information.)     

    **See Also:**

            :func:`tabular.io.loadSV`

def saveSV(fname, X, comments=None, metadata=None, printmetadict=None,
                   dialect=None, delimiter=None, doublequote=True, 
                   lineterminator='\n', escapechar = None, 
                   quoting=csv.QUOTE_MINIMAL, quotechar='"', 
                   skipinitialspace=False, stringifier=None,
                   verbosity=DEFAULT_VERBOSITY):
    """
    Save a tabarray to a separated-variable (CSV) file.

    **Parameters**

        **fname** :  string

            Path to a separated variable (CSV) text file.

        **X** :  tabarray

            The actual data in a :class:`tabular.tab.tabarray`.

        **comments** :  string, optional

            The character to be used to denote the start of a header (non-data) 
            line, e.g. '#'.  If not specified, it is determined according to the 
            following rule:  '#' if `metadata` argument is set, otherwise ''.

        **delimiter** :  string, optional

            The character to beused to separate values in each line of text, 
            e.g. ','.  If not specified, by default, this is inferred from 
            the file extension: if the file ends in `.csv`, the delimiter is 
            ',', otherwise it is '\\t.'

        **linebreak** :  string, optional

            The string separating lines of text.  By default, this is assumed to 
            be '\\n', and can also be set to be '\\r' or '\\r\\n'.

        **metadata** :  list of strings or Boolean, optional

            Allowed values are True, False, or any sublists of the list 
            `['names', 'formats', 'types', 'coloring', 'dialect']`.  These 
            keys indicate what special metadata is printed in the header.

            * If a sublist of 
             `['names', 'formats', 'types', 'coloring', 'dialect']`, then the 
             indicated types of metadata are written out.  

            * If `True`, this is the same as 
              `metadata = ['coloring', 'types', 'names','dialect']`, e.g. as 
               many types of metadata as this algorithm currently knows how to 
               write out. 

            * If 'False', no metadata is printed at all, e.g. just the data.
                    
            * If `metadata` is not specified, the default is `['names']`, that 
              is, just column names are written out.
                        
        **printmetadict** :  Boolean, optional

            Whether or not to print a string representation of the 
            `metadatadict` in the first line of the header.

            If `printmetadict` is not specified, then:

            * If `metadata` is specified and is not `False`, then
              `printmetadata` defaults to `True`.

            * Else if `metadata` is `False`, then `printmetadata` defaults 
              to `False`.

            * Else `metadata` is not specified, and `printmetadata` defaults 
              to `False`.

            See the :func:`tabular.io.loadSV` for more information about 
            `metadatadict`.
            
        **stringifier** : callable 
        
            Callable taking 1-d numpy array and returning Python list of strings 
            of same length, or dictionary or tuple of such callables.  
                    
            If specified, the callable will be applied to each column, and the 
            resulting list of strings will be written to the file.  If 
            specified as a list or dictionary of callables, the functions will 
            be applied to correponding columns.  The default used if 
            **stringifier** is not specified, is `tb.utils.DEFAULT_STRINGIFIER`, 
            which merely passes through string-type columns, and converts 
            numerical-type columns directly to corresponding strings with NaNs 
            replaced with blank values.  The main purpose of specifying a 
            non-default value is to encode numerical values in various string 
            encodings that might be used required for other applications like 
            databases.                    
                               
            NOTE:  In certain special circumstances (e.g. when the 
            lineterminator or delimiter character appears in a field of the 
            data), the Python CSV writer is used to write out data.  To allow 
            for control of the operation of the writer in these circumstances, 
            the following other parameters replicating the interface of the CSV 
            module are also valid, and values will be passed through:  
            **doublequote**, **escapechar**, **quoting**, **quotechar**, and 
            **skipinitialspace**.  (See Python CSV module documentation for more 
            information.)     

    **See Also:**

            :func:`tabular.io.loadSV`

    """    
    if metadata is None:
        metakeys = ['names']
        if printmetadict is None:
            printmetadict = False
            if verbosity > 8:
                print '''Defaulting to not printing out the metametadata 
                         dictionary line.'''
        if comments is None:
            comments = ''
            if verbosity > 8:
                print 'Defaulting empty comment string.'
        if verbosity > 7:
            print 'Defaulting to writing out names metadata.'
    elif metadata is True:
        
        metakeys = defaultmetadatakeys(X)
        
        if printmetadict is None:
            printmetadict = True
            if verbosity > 8:
                print '''Defaulting to printing out the metametadata dictionary 
                         line.'''
        if comments is None:
            comments = ''
            if verbosity > 8:
                print 'Defaulting empty comment string.'            
        if verbosity >= 5:
            print 'Writing out all present metadata keys ... '
    elif metadata is False:
        metakeys = []
        printmetadict = False
        comments = ''
        if verbosity >= 5:
            print 'Writing out no metadata at all.'
    else:
        metakeys = metadata
        if printmetadict is None:
            if metakeys == []:
                printmetadict = False
            else:
                printmetadict = True
        if comments is None:
            comments = ''
        if verbosity >= 5:
            print '''Using user-specified metadata keys to contol metadata 
                     writing.'''
            
    assert lineterminator in ['\r','\n','\r\n'], '''lineterminator must be one 
                                              of ''' + repr( ['\r','\n','\r\n'])
    dialect = getdialect(fname, dialect, delimiter, lineterminator, doublequote, 
                         escapechar, quoting, quotechar, skipinitialspace)
    delimiter = dialect.delimiter     
    
    if 6 > verbosity > 2:
        print 'Using delimiter ', repr(delimiter)
    elif verbosity >= 6:
        print 'Using dialect with values:', repr(printdialect(dialect))
            
    metadata = getstringmetadata(X,metakeys,dialect)
    
    metametadata = {}
    v = 1
    for k in metakeys:
        if k in metadata.keys():
            nl = len(metadata[k].split(lineterminator))
            metametadata[k] = v if nl == 1 else (v, v + nl)
            v = v + nl

    F = open(fname,'wb')

    if printmetadict is True:
        line = "metametadata=" + repr(metametadata)
        F.write(comments + line + lineterminator)

    for k in metakeys:
        if k in metadata.keys():
            for line in metadata[k].split(lineterminator):
                F.write(comments + line + lineterminator)
        
    Write(X, F, dialect, stringifier=stringifier)
    
    F.close()