/// <summary>
        /// A given sequence is turned into a CSV file with a single column. The sequence can be one of int's, doubles,
        /// tuples made up of int's or double, or a custom object that contains int's or doubles. In the latter case
        /// the column names are pulled from the field names. Otherwise you should specify them in the column headers.
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="outputFile"></param>
        /// <param name="columnHeader"></param>
        /// <returns></returns>
        public static IFutureValue <FileInfo[]> FutureAsCSV <T>(this IQueryable <T> source, FileInfo outputFile, params string[] columnHeader)
        {
            var q = FutureResultOperators.CheckSource <T>(source);

            // Build up the AsCSV expression.

            var asCSVMethodGeneric = typeof(FileHelperQueryExtensions).GetMethods().Where(m => m.Name == "AsCSV").First();
            var asCSVMethod        = asCSVMethodGeneric.MakeGenericMethod(typeof(T));
            var expr = Expression.Call(null, asCSVMethod, q.Expression, Expression.Constant(outputFile), Expression.Constant(columnHeader));

            return(FutureResultOperators.FutureExecuteScalarHelper <T, FileInfo[]>(q, expr));
        }
        /// <summary>
        /// A given sequence is turned into a TTree in a ROOT file. The sequence can be one of int's, doubles,
        /// tuples made up of int's or double, or a custom object that contains int's or doubles. In the latter case
        /// the column names are pulled from the field names. Otherwise you should specify them in the column headers.
        /// </summary>
        /// <typeparam name="T">Sequence type. Can be int, double, Tuple (of int or double), or POCO (of int or double)</typeparam>
        /// <param name="source"></param>
        /// <param name="outputFile"></param>
        /// <param name="columnHeader"></param>
        /// <returns>A Future<FileInfo> that points to the resulting ROOT file.</FileInfo></returns>
        /// Because TTree's can get large, we don't hold this in memory. Rather the TTree is attached to the
        /// specified ROOT file. The file is also not cached. Be careful about modifying it - if it is modified,
        /// the framework will almost certainly detect it, and cause it to be regenerated.
        public static IFutureValue <FileInfo[]> FutureAsTTree <T>(this IQueryable <T> source, string treeName = "DataTree", string treeTitle = "Tree data saved via AsTTree output", FileInfo outputFile = null, params string[] columnHeader)
        {
            var q = FutureResultOperators.CheckSource <T>(source);

            // Build up the AsCSV expression.

            var countMethodGeneric = typeof(FileHelperQueryExtensions).GetMethods().Where(m => m.Name == "AsTTree").First();
            var countMethod        = countMethodGeneric.MakeGenericMethod(typeof(T));
            var expr = Expression.Call(null, countMethod, q.Expression, Expression.Constant(treeName), Expression.Constant(treeTitle), Expression.Constant(outputFile, typeof(FileInfo)), Expression.Constant(columnHeader));

            return(FutureResultOperators.FutureExecuteScalarHelper <T, FileInfo[]>(q, expr));
        }