def build_field_time_series(local_time_indices,
                            file_names,
                            mesh_file,
                            out_dir,
                            blocking,
                            all_dim_vals,
                            blockDimName,
                            variable_list,
                            vertices,
                            connectivity,
                            offsets,
                            valid_mask,
                            output_32bit,
                            combine_output,
                            append,
                            xtimeName,
                            topo_dim=None,
                            topo_cell_indices=None,
                            cell_to_point_map=None,
                            boundary_mask=None):  # {{{

    if len(variable_list) == 0:
        return

    if output_32bit:
        outType = 'float32'
    else:
        outType = 'float64'

    # Get dimension info to allocate the size of Colors
    time_series_file = viz.open_netcdf(file_names[0])

    if mesh_file is not None:
        # blockDim may not exist in time series file
        blockDim = len(mesh_file.dimensions[blockDimName])
    else:
        blockDim = len(time_series_file.dimensions[blockDimName])

    if boundary_mask is not None:
        variable_list.append('boundaryMask')
        all_dim_vals['boundaryMask'] = None
        pointData = True
        cellData = False
    else:
        pointData = False
        cellData = True

    # Pre-compute the number of blocks
    nBlocks = int(np.ceil(blockDim / blocking))

    nPolygons = len(offsets)
    nPoints = len(vertices[0])
    nTimes = len(local_time_indices)
    nVars = len(variable_list)

    var_has_time_dim = np.zeros(nVars, bool)
    nHyperSlabs = 0
    for iVar in range(nVars):
        var_name = variable_list[iVar]
        if boundary_mask is not None and var_name == 'boundaryMask':
            var_has_time_dim[iVar] = False
        elif xtimeName is not None:
            if var_name in time_series_file.variables:
                var_has_time_dim[iVar] = \
                    'Time' in time_series_file.variables[var_name].dimensions
            else:
                # we can't support time dependence in the mesh file
                assert ('Time' not in mesh_file.variables[var_name].dimensions)
                var_has_time_dim[iVar] = False

        extra_dim_vals = all_dim_vals[var_name]
        if (extra_dim_vals is None) or (len(extra_dim_vals) == 0):
            nHyperSlabs += 1
        else:
            nHyperSlabs += len(extra_dim_vals)

    any_var_has_time_dim = np.any(var_has_time_dim)

    if topo_dim is not None:
        if (mesh_file is not None) and (topo_dim in mesh_file.dimensions):
            nTopoLevels = len(mesh_file.dimensions[topo_dim])
        else:
            nTopoLevels = len(time_series_file.dimensions[topo_dim])
    else:
        nTopoLevels = None

    time_series_file.close()

    try:
        os.makedirs(out_dir)
    except OSError:
        pass

    if any_var_has_time_dim:
        try:
            os.makedirs('{}/time_series'.format(out_dir))
        except OSError:
            pass
    else:
        # there is no point in combining output if no fields have Time dim
        combine_output = False
        nTimes = 1

    # Output time series
    if use_progress_bar:
        widgets = [
            'Writing time series: ',
            Percentage(), ' ',
            Bar(), ' ',
            ETA()
        ]
        field_bar = ProgressBar(widgets=widgets,
                                maxval=nTimes * nHyperSlabs).start()
    else:
        print("Writing time series....")

    suffix = blockDimName[1:]
    if any_var_has_time_dim:
        if combine_output or np.all(var_has_time_dim):
            out_prefix = "fieldsOn{}".format(suffix)
        else:
            out_prefix = "timeDependentFieldsOn{}".format(suffix)
        # start the pvd file
        pvd_file = viz.write_pvd_header(out_dir, out_prefix)
        pvd_file.write('<Collection>\n')

    if not combine_output and not np.all(var_has_time_dim):
        static_prefix = "staticFieldsOn{}".format(suffix)
        varIndices = np.arange(nVars)[np.logical_not(var_has_time_dim)]
        timeIndependentFile = viz.write_vtp_header(out_dir,
                                                   static_prefix,
                                                   varIndices[0],
                                                   varIndices,
                                                   variable_list,
                                                   all_dim_vals,
                                                   vertices,
                                                   connectivity,
                                                   offsets,
                                                   nPoints,
                                                   nPolygons,
                                                   outType,
                                                   cellData=cellData,
                                                   pointData=pointData,
                                                   xtime=None)

    prev_file = ""
    for time_index in range(nTimes):

        if prev_file != file_names[time_index]:
            if prev_file != "":
                time_series_file.close()
            time_series_file = viz.open_netcdf(file_names[time_index])
            prev_file = file_names[time_index]

        if any_var_has_time_dim:
            if xtimeName is None:
                xtime = None
                years = float(time_index)
            else:
                if xtimeName == 'none':
                    xtime = '{}'.format(time_index)
                    years = float(time_index)
                else:
                    if xtimeName not in time_series_file.variables:
                        raise ValueError("xtime variable name {} not found in "
                                         "{}".format(xtimeName,
                                                     time_series_file))
                    var = time_series_file.variables[xtimeName]
                    if len(var.shape) == 2:
                        xtime = var[
                            local_time_indices[time_index], :].tostring(
                            ).decode('utf-8').strip()
                        date = datetime(int(xtime[0:4]), int(xtime[5:7]),
                                        int(xtime[8:10]), int(xtime[11:13]),
                                        int(xtime[14:16]), int(xtime[17:19]))
                        years = date2num(date,
                                         units='days since 0000-01-01',
                                         calendar='noleap') / 365.
                    else:
                        xtime = var[local_time_indices[time_index]]
                        years = xtime / 365.
                        xtime = str(xtime)

            # write the header for the vtp file
            vtp_file_prefix = "time_series/{}.{:d}".format(
                out_prefix, time_index)
            file_name = '{}/{}.vtp'.format(out_dir, vtp_file_prefix)
            if append and os.path.exists(file_name):
                pvd_file.write('<DataSet timestep="{:.16f}" group="" '
                               'part="0"\n'.format(years))
                pvd_file.write('\tfile="{}.vtp"/>\n'.format(vtp_file_prefix))
                continue

            if combine_output:
                varIndices = np.arange(nVars)
            else:
                varIndices = np.arange(nVars)[var_has_time_dim]
            timeDependentFile = viz.write_vtp_header(out_dir,
                                                     vtp_file_prefix,
                                                     varIndices[0],
                                                     varIndices,
                                                     variable_list,
                                                     all_dim_vals,
                                                     vertices,
                                                     connectivity,
                                                     offsets,
                                                     nPoints,
                                                     nPolygons,
                                                     outType,
                                                     cellData=cellData,
                                                     pointData=pointData,
                                                     xtime=xtime)

            # add time step to pdv file
            pvd_file.write('<DataSet timestep="{:.16f}" group="" '
                           'part="0"\n'.format(years))
            pvd_file.write('\tfile="{}.vtp"/>\n'.format(vtp_file_prefix))

        if time_index == 0 or combine_output:
            varIndices = np.arange(nVars)
        else:
            # only the time-dependent variables
            varIndices = np.arange(nVars)[var_has_time_dim]

        iHyperSlabProgress = 0
        for iVar in varIndices:
            has_time = var_has_time_dim[iVar]

            var_name = variable_list[iVar]
            (out_var_names, dim_list) = \
                viz.get_hyperslab_name_and_dims(var_name,
                                                all_dim_vals[var_name])
            if has_time or combine_output:
                vtkFile = timeDependentFile
            else:
                vtkFile = timeIndependentFile
            for iHyperSlab in range(len(out_var_names)):
                if dim_list is not None:
                    dim_vals = dim_list[iHyperSlab]
                else:
                    dim_vals = None

                if boundary_mask is not None and var_name == 'boundaryMask':
                    field = np.array(boundary_mask, dtype=outType)
                else:
                    field = np.zeros(blockDim, dtype=outType)

                    for iBlock in np.arange(0, nBlocks):
                        blockStart = iBlock * blocking
                        blockEnd = min((iBlock + 1) * blocking, blockDim)
                        block_indices = np.arange(blockStart, blockEnd)
                        if topo_cell_indices is None:
                            block_topo_cell_indices = None
                        else:
                            block_topo_cell_indices = \
                                topo_cell_indices[block_indices]
                        field_block = viz.read_field(
                            var_name,
                            mesh_file,
                            time_series_file,
                            dim_vals,
                            local_time_indices[time_index],
                            block_indices,
                            outType,
                            topo_dim=topo_dim,
                            topo_cell_indices=block_topo_cell_indices,
                            nTopoLevels=nTopoLevels)

                        field[blockStart:blockEnd] = field_block

                    field = field[valid_mask]

                    if cell_to_point_map is not None:
                        # map field from cells to points
                        field = field[cell_to_point_map]

                vtkFile.appendData(field)

                if use_progress_bar:
                    field_bar.update(time_index * nHyperSlabs +
                                     iHyperSlabProgress)
                    iHyperSlabProgress += 1

                del field

        if any_var_has_time_dim:
            timeDependentFile.save()
            del timeDependentFile

        if time_index == 0 and not combine_output and not \
                np.all(var_has_time_dim):
            timeIndependentFile.save()
            del timeIndependentFile

    time_series_file.close()
    if use_progress_bar:
        field_bar.finish()

    if any_var_has_time_dim:
        # finish the pdv file
        pvd_file.write('</Collection>\n')
        pvd_file.write('</VTKFile>\n')
        pvd_file.close()  # }}}
    (time_indices,
     time_file_names) = viz.setup_time_indices(args.filename_pattern,
                                               args.xtime)

    if args.time:
        time_indices, time_file_names = \
            viz.parse_time_indices(args.time, time_indices, time_file_names)

    separate_mesh_file = True
    if not args.mesh_filename:
        args.mesh_filename = time_file_names[0]
        separate_mesh_file = False

    # Setting dimension values:
    time_series_file = viz.open_netcdf(time_file_names[0])
    if separate_mesh_file:
        mesh_file = viz.open_netcdf(args.mesh_filename)
    else:
        mesh_file = None
    extra_dims, topo_cell_indices = \
        viz.parse_extra_dims(args.dimension_list, time_series_file,
                             mesh_file, topo_dim=args.topo_dim,
                             topo_cell_index_name=args.topo_cell_index)
    basic_dims = ['nCells', 'nEdges', 'nVertices', 'Time']
    include_dims = ['nCells', 'nEdges', 'nVertices']
    if args.topo_dim is not None:
        basic_dims.append(args.topo_dim)
        include_dims = ['nCells']

    (all_dim_vals, cellVars, vertexVars, edgeVars) = \