avtDataTree_p
avtTimeIteratorDataTreeIteratorExpression::ConstructOutput(avtDataTree_p t)
{
    if (*t == NULL)
    {
        return NULL;
    }

    int nc = t->GetNChildren();

    if (nc <= 0 && !t->HasData())
    {
        return NULL;
    }

    if (nc == 0)
    {
        //
        // there is only one dataset to process
        //
        vtkDataSet *in_ds = t->GetDataRepresentation().GetDataVTK();
        vtkDataSet *new_ds = in_ds->NewInstance();
        new_ds->ShallowCopy(in_ds);
        vtkDataArray *final_arr = 
                        ConvertIntermediateArrayToFinalArray(vars[arrayIndex]);
        vars[arrayIndex]->Delete();
        arrayIndex++;
        if (IsPointVariable())
            new_ds->GetPointData()->AddArray(final_arr);
        else
            new_ds->GetCellData()->AddArray(final_arr);
        final_arr->Delete();
        avtDataTree_p rv = new avtDataTree(new_ds,
                                   t->GetDataRepresentation().GetDomain(),
                                   t->GetDataRepresentation().GetLabel());
        new_ds->Delete();
        return rv;
    }
    else
    {
        // there is more than one input dataset to process
        // and we need an output datatree for each
        //
        avtDataTree_p *outDT = new avtDataTree_p[nc];
        for (int j = 0; j < nc; j++)
        {
            if (t->ChildIsPresent(j))
            {
                outDT[j] = ConstructOutput(t->GetChild(j));
            }
            else
            {
                outDT[j] = NULL;
            }
        }
        avtDataTree_p rv = new avtDataTree(nc, outDT);
        delete [] outDT;
        return (rv);
    }
}
void
avtTimeIteratorDataTreeIteratorExpression::InitializeOutput(void)
{
    avtDataTree_p topTree = GetInputDataTree();
    std::vector<avtDataTree_p> treesToProcess;
    treesToProcess.push_back(topTree);
    size_t curIndex = 0;
    vars.clear();
    while (curIndex < treesToProcess.size())
    {
        avtDataTree_p tree = treesToProcess[curIndex];
        curIndex++;
        if (*tree == NULL)
            continue;

        int nc = tree->GetNChildren();
        if (nc <= 0 && !tree->HasData())
            continue;

        if (nc == 0)
        {
            vtkDataSet *in_ds = tree->GetDataRepresentation().GetDataVTK();
            vtkDoubleArray *arr = vtkDoubleArray::New();
            arr->SetNumberOfComponents(GetIntermediateSize());
            if (IsPointVariable())
                arr->SetNumberOfTuples(in_ds->GetNumberOfPoints());
            else
                arr->SetNumberOfTuples(in_ds->GetNumberOfCells());
            arr->SetName(outputVariableName);
            vars.push_back(arr);
        }
        else
        {
            for (int j = 0; j < nc; j++)
                if (tree->ChildIsPresent(j))
                    treesToProcess.push_back(tree->GetChild(j));
        }
    }
    
    // Set up this counter variable that we use during "ProcessDataTree".
    arrayIndex = 0;
}
vtkDataArray *
avtUnaryMathExpression::DeriveVariable(vtkDataSet *in_ds, int currentDomainsIndex)
{
    int  i;

    vtkDataArray *cell_data = NULL;
    vtkDataArray *point_data = NULL;
    vtkDataArray *data = NULL;

    if (activeVariable == NULL)
    {
        //
        // This hack is getting more and more refined.  This situation comes up
        // when we don't know what the active variable is (mostly for the
        // constant creation filter).  We probably need more infrastructure
        // to handle this.
        // Iteration 1 of this hack said take any array.
        // Iteration 2 said take any array that isn't vtkGhostLevels, etc.
        // Iteration 3 says take the first scalar array if one is available,
        //             provided that array is not vtkGhostLevels, etc.
        //             This is because most constants we create are scalar.
        //
        // Note: this hack used to be quite important because we would use
        // the resulting array to determine the centering of the variable.
        // Now we use the IsPointVariable() method.  So this data array is
        // only used to get the type.
        //
        int ncellArray = in_ds->GetCellData()->GetNumberOfArrays();
        for (i = 0 ; i < ncellArray ; i++)
        {
            vtkDataArray *candidate = in_ds->GetCellData()->GetArray(i);
            if (strstr(candidate->GetName(), "vtk") != NULL)
                continue;
            if (strstr(candidate->GetName(), "avt") != NULL)
                continue;
            if (candidate->GetNumberOfComponents() == 1)
            {
                // Definite winner
                cell_data = candidate;
                break;
            }
            else
                // Potential winner -- keep looking
                cell_data = candidate;
        }
        int npointArray = in_ds->GetPointData()->GetNumberOfArrays();
        for (i = 0 ; i < npointArray ; i++)
        {
            vtkDataArray *candidate = in_ds->GetPointData()->GetArray(i);
            if (strstr(candidate->GetName(), "vtk") != NULL)
                continue;
            if (strstr(candidate->GetName(), "avt") != NULL)
                continue;
            if (candidate->GetNumberOfComponents() == 1)
            {
                // Definite winner
                point_data = candidate;
                break;
            }
            else
                // Potential winner -- keep looking
                point_data = candidate;
        }

        if (cell_data != NULL && cell_data->GetNumberOfComponents() == 1)
        {
            data = cell_data;
            centering = AVT_ZONECENT;
        }
        else if (point_data != NULL && point_data->GetNumberOfComponents()== 1)
        {
            data = point_data;
            centering = AVT_NODECENT;
        }
        else if (cell_data != NULL)
        {
            data = cell_data;
            centering = AVT_ZONECENT;
        }
        else
        {
            data = point_data;
            centering = AVT_NODECENT;
        }
    } 
    else
    {
        cell_data = in_ds->GetCellData()->GetArray(activeVariable);
        point_data = in_ds->GetPointData()->GetArray(activeVariable);

        if (cell_data != NULL)
        {
            data = cell_data;
            centering = AVT_ZONECENT;
        }
        else
        {
            data = point_data;
            centering = AVT_NODECENT;
        }
    }

    //
    // Set up a VTK variable reflecting the calculated variable
    //
    int ncomps = 0;
    int nvals = 0;
    if (FilterCreatesSingleton())
        nvals = 1;
    else if (activeVariable == NULL || data == NULL)
        nvals = (IsPointVariable() ? in_ds->GetNumberOfPoints() 
                                   : in_ds->GetNumberOfCells());
    else
        nvals = data->GetNumberOfTuples();

    vtkDataArray *dv = NULL;
    if (data == NULL)
    {
        //
        // We could not find a single array.  We must be doing something with
        // the mesh.
        //
        ncomps = 1;
        dv = CreateArrayFromMesh(in_ds);
    }
    else
    {
        ncomps = data->GetNumberOfComponents();
        dv = CreateArray(data);
    }

    if (data == NULL)
    {
        if (! NullInputIsExpected())
        {
            // One way to get here is to have vtkPolyData Curve plots.
            EXCEPTION2(ExpressionException, outputVariableName,
                 "An internal error occurred when "
                 "trying to calculate your expression.  Please contact a "
                 "VisIt developer.");
        }
    }

    int noutcomps = GetNumberOfComponentsInOutput(ncomps);
    dv->SetNumberOfComponents(noutcomps);
    dv->SetNumberOfTuples(nvals);

    //
    // Should we send in ncomps or noutcomps?  They are the same number 
    // unless the derived type re-defined GetNumberOfComponentsInOutput.
    // If it did, it probably doesn't matter.  If not, then it is the same
    // number.  So send in the input.  Really doesn't matter.
    //
    cur_mesh = in_ds;
    DoOperation(data, dv, ncomps, nvals);
    cur_mesh = NULL;

    return dv;
}