// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

#include <PickVarInfo.h>
#include <DataNode.h>
#include <stdio.h>
#include <cstring>

//
// Enum conversion methods for PickVarInfo::Centering
//

static const char *Centering_strings[] = {
"Nodal", "Zonal", "None"
};

std::string
PickVarInfo::Centering_ToString(PickVarInfo::Centering t)
{
    int index = int(t);
    if(index < 0 || index >= 3) index = 0;
    return Centering_strings[index];
}

std::string
PickVarInfo::Centering_ToString(int t)
{
    int index = (t < 0 || t >= 3) ? 0 : t;
    return Centering_strings[index];
}

bool
PickVarInfo::Centering_FromString(const std::string &s, PickVarInfo::Centering &val)
{
    val = PickVarInfo::Nodal;
    for(int i = 0; i < 3; ++i)
    {
        if(s == Centering_strings[i])
        {
            val = (Centering)i;
            return true;
        }
    }
    return false;
}

// ****************************************************************************
// Method: PickVarInfo::PickVarInfo
//
// Purpose:
//   Init utility for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void PickVarInfo::Init()
{
    mixVar = false;
    centering = None;
    treatAsASCII = false;
    floatFormat = "%g";

    PickVarInfo::SelectAll();
}

// ****************************************************************************
// Method: PickVarInfo::PickVarInfo
//
// Purpose:
//   Copy utility for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void PickVarInfo::Copy(const PickVarInfo &obj)
{
    variableName = obj.variableName;
    variableType = obj.variableType;
    names = obj.names;
    values = obj.values;
    mixNames = obj.mixNames;
    mixValues = obj.mixValues;
    mixVar = obj.mixVar;
    centering = obj.centering;
    miscMessage = obj.miscMessage;
    numMatsPerZone = obj.numMatsPerZone;
    matNames = obj.matNames;
    numSpecsPerMat = obj.numSpecsPerMat;
    treatAsASCII = obj.treatAsASCII;
    floatFormat = obj.floatFormat;

    PickVarInfo::SelectAll();
}

// Type map format string
const char *PickVarInfo::TypeMapFormatString = PICKVARINFO_TMFS;
const AttributeGroup::private_tmfs_t PickVarInfo::TmfsStruct = {PICKVARINFO_TMFS};


// ****************************************************************************
// Method: PickVarInfo::PickVarInfo
//
// Purpose:
//   Default constructor for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

PickVarInfo::PickVarInfo() :
    AttributeSubject(PickVarInfo::TypeMapFormatString)
{
    PickVarInfo::Init();
}

// ****************************************************************************
// Method: PickVarInfo::PickVarInfo
//
// Purpose:
//   Constructor for the derived classes of PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

PickVarInfo::PickVarInfo(private_tmfs_t tmfs) :
    AttributeSubject(tmfs.tmfs)
{
    PickVarInfo::Init();
}

// ****************************************************************************
// Method: PickVarInfo::PickVarInfo
//
// Purpose:
//   Copy constructor for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

PickVarInfo::PickVarInfo(const PickVarInfo &obj) :
    AttributeSubject(PickVarInfo::TypeMapFormatString)
{
    PickVarInfo::Copy(obj);
}

// ****************************************************************************
// Method: PickVarInfo::PickVarInfo
//
// Purpose:
//   Copy constructor for derived classes of the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

PickVarInfo::PickVarInfo(const PickVarInfo &obj, private_tmfs_t tmfs) :
    AttributeSubject(tmfs.tmfs)
{
    PickVarInfo::Copy(obj);
}

// ****************************************************************************
// Method: PickVarInfo::~PickVarInfo
//
// Purpose:
//   Destructor for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

PickVarInfo::~PickVarInfo()
{
    // nothing here
}

// ****************************************************************************
// Method: PickVarInfo::operator =
//
// Purpose:
//   Assignment operator for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

PickVarInfo&
PickVarInfo::operator = (const PickVarInfo &obj)
{
    if (this == &obj) return *this;

    PickVarInfo::Copy(obj);

    return *this;
}

// ****************************************************************************
// Method: PickVarInfo::operator ==
//
// Purpose:
//   Comparison operator == for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
PickVarInfo::operator == (const PickVarInfo &obj) const
{
    // Create the return value
    return ((variableName == obj.variableName) &&
            (variableType == obj.variableType) &&
            (names == obj.names) &&
            (values == obj.values) &&
            (mixNames == obj.mixNames) &&
            (mixValues == obj.mixValues) &&
            (mixVar == obj.mixVar) &&
            (centering == obj.centering) &&
            (miscMessage == obj.miscMessage) &&
            (numMatsPerZone == obj.numMatsPerZone) &&
            (matNames == obj.matNames) &&
            (numSpecsPerMat == obj.numSpecsPerMat) &&
            (treatAsASCII == obj.treatAsASCII) &&
            (floatFormat == obj.floatFormat));
}

// ****************************************************************************
// Method: PickVarInfo::operator !=
//
// Purpose:
//   Comparison operator != for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
PickVarInfo::operator != (const PickVarInfo &obj) const
{
    return !(this->operator == (obj));
}

// ****************************************************************************
// Method: PickVarInfo::TypeName
//
// Purpose:
//   Type name method for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const std::string
PickVarInfo::TypeName() const
{
    return "PickVarInfo";
}

// ****************************************************************************
// Method: PickVarInfo::CopyAttributes
//
// Purpose:
//   CopyAttributes method for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
PickVarInfo::CopyAttributes(const AttributeGroup *atts)
{
    if(TypeName() != atts->TypeName())
        return false;

    // Call assignment operator.
    const PickVarInfo *tmp = (const PickVarInfo *)atts;
    *this = *tmp;

    return true;
}

// ****************************************************************************
// Method: PickVarInfo::CreateCompatible
//
// Purpose:
//   CreateCompatible method for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeSubject *
PickVarInfo::CreateCompatible(const std::string &tname) const
{
    AttributeSubject *retval = 0;
    if(TypeName() == tname)
        retval = new PickVarInfo(*this);
    // Other cases could go here too.

    return retval;
}

// ****************************************************************************
// Method: PickVarInfo::NewInstance
//
// Purpose:
//   NewInstance method for the PickVarInfo class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeSubject *
PickVarInfo::NewInstance(bool copy) const
{
    AttributeSubject *retval = 0;
    if(copy)
        retval = new PickVarInfo(*this);
    else
        retval = new PickVarInfo;

    return retval;
}

// ****************************************************************************
// Method: PickVarInfo::SelectAll
//
// Purpose:
//   Selects all attributes.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
PickVarInfo::SelectAll()
{
    Select(ID_variableName,   (void *)&variableName);
    Select(ID_variableType,   (void *)&variableType);
    Select(ID_names,          (void *)&names);
    Select(ID_values,         (void *)&values);
    Select(ID_mixNames,       (void *)&mixNames);
    Select(ID_mixValues,      (void *)&mixValues);
    Select(ID_mixVar,         (void *)&mixVar);
    Select(ID_centering,      (void *)&centering);
    Select(ID_miscMessage,    (void *)&miscMessage);
    Select(ID_numMatsPerZone, (void *)&numMatsPerZone);
    Select(ID_matNames,       (void *)&matNames);
    Select(ID_numSpecsPerMat, (void *)&numSpecsPerMat);
    Select(ID_treatAsASCII,   (void *)&treatAsASCII);
    Select(ID_floatFormat,    (void *)&floatFormat);
}

///////////////////////////////////////////////////////////////////////////////
// Set property methods
///////////////////////////////////////////////////////////////////////////////

void
PickVarInfo::SetVariableName(const std::string &variableName_)
{
    variableName = variableName_;
    Select(ID_variableName, (void *)&variableName);
}

void
PickVarInfo::SetVariableType(const std::string &variableType_)
{
    variableType = variableType_;
    Select(ID_variableType, (void *)&variableType);
}

void
PickVarInfo::SetNames(const stringVector &names_)
{
    names = names_;
    Select(ID_names, (void *)&names);
}

void
PickVarInfo::SetValues(const doubleVector &values_)
{
    values = values_;
    Select(ID_values, (void *)&values);
}

void
PickVarInfo::SetMixNames(const stringVector &mixNames_)
{
    mixNames = mixNames_;
    Select(ID_mixNames, (void *)&mixNames);
}

void
PickVarInfo::SetMixValues(const doubleVector &mixValues_)
{
    mixValues = mixValues_;
    Select(ID_mixValues, (void *)&mixValues);
}

void
PickVarInfo::SetMixVar(bool mixVar_)
{
    mixVar = mixVar_;
    Select(ID_mixVar, (void *)&mixVar);
}

void
PickVarInfo::SetCentering(PickVarInfo::Centering centering_)
{
    centering = centering_;
    Select(ID_centering, (void *)&centering);
}

void
PickVarInfo::SetMiscMessage(const std::string &miscMessage_)
{
    miscMessage = miscMessage_;
    Select(ID_miscMessage, (void *)&miscMessage);
}

void
PickVarInfo::SetNumMatsPerZone(const intVector &numMatsPerZone_)
{
    numMatsPerZone = numMatsPerZone_;
    Select(ID_numMatsPerZone, (void *)&numMatsPerZone);
}

void
PickVarInfo::SetMatNames(const stringVector &matNames_)
{
    matNames = matNames_;
    Select(ID_matNames, (void *)&matNames);
}

void
PickVarInfo::SetNumSpecsPerMat(const intVector &numSpecsPerMat_)
{
    numSpecsPerMat = numSpecsPerMat_;
    Select(ID_numSpecsPerMat, (void *)&numSpecsPerMat);
}

void
PickVarInfo::SetTreatAsASCII(bool treatAsASCII_)
{
    treatAsASCII = treatAsASCII_;
    Select(ID_treatAsASCII, (void *)&treatAsASCII);
}

void
PickVarInfo::SetFloatFormat(const std::string &floatFormat_)
{
    floatFormat = floatFormat_;
    Select(ID_floatFormat, (void *)&floatFormat);
}

///////////////////////////////////////////////////////////////////////////////
// Get property methods
///////////////////////////////////////////////////////////////////////////////

const std::string &
PickVarInfo::GetVariableName() const
{
    return variableName;
}

std::string &
PickVarInfo::GetVariableName()
{
    return variableName;
}

const std::string &
PickVarInfo::GetVariableType() const
{
    return variableType;
}

std::string &
PickVarInfo::GetVariableType()
{
    return variableType;
}

const stringVector &
PickVarInfo::GetNames() const
{
    return names;
}

stringVector &
PickVarInfo::GetNames()
{
    return names;
}

const doubleVector &
PickVarInfo::GetValues() const
{
    return values;
}

doubleVector &
PickVarInfo::GetValues()
{
    return values;
}

const stringVector &
PickVarInfo::GetMixNames() const
{
    return mixNames;
}

stringVector &
PickVarInfo::GetMixNames()
{
    return mixNames;
}

const doubleVector &
PickVarInfo::GetMixValues() const
{
    return mixValues;
}

doubleVector &
PickVarInfo::GetMixValues()
{
    return mixValues;
}

bool
PickVarInfo::GetMixVar() const
{
    return mixVar;
}

PickVarInfo::Centering
PickVarInfo::GetCentering() const
{
    return Centering(centering);
}

const std::string &
PickVarInfo::GetMiscMessage() const
{
    return miscMessage;
}

std::string &
PickVarInfo::GetMiscMessage()
{
    return miscMessage;
}

const intVector &
PickVarInfo::GetNumMatsPerZone() const
{
    return numMatsPerZone;
}

intVector &
PickVarInfo::GetNumMatsPerZone()
{
    return numMatsPerZone;
}

const stringVector &
PickVarInfo::GetMatNames() const
{
    return matNames;
}

stringVector &
PickVarInfo::GetMatNames()
{
    return matNames;
}

const intVector &
PickVarInfo::GetNumSpecsPerMat() const
{
    return numSpecsPerMat;
}

intVector &
PickVarInfo::GetNumSpecsPerMat()
{
    return numSpecsPerMat;
}

bool
PickVarInfo::GetTreatAsASCII() const
{
    return treatAsASCII;
}

const std::string &
PickVarInfo::GetFloatFormat() const
{
    return floatFormat;
}

std::string &
PickVarInfo::GetFloatFormat()
{
    return floatFormat;
}

///////////////////////////////////////////////////////////////////////////////
// Select property methods
///////////////////////////////////////////////////////////////////////////////

void
PickVarInfo::SelectVariableName()
{
    Select(ID_variableName, (void *)&variableName);
}

void
PickVarInfo::SelectVariableType()
{
    Select(ID_variableType, (void *)&variableType);
}

void
PickVarInfo::SelectNames()
{
    Select(ID_names, (void *)&names);
}

void
PickVarInfo::SelectValues()
{
    Select(ID_values, (void *)&values);
}

void
PickVarInfo::SelectMixNames()
{
    Select(ID_mixNames, (void *)&mixNames);
}

void
PickVarInfo::SelectMixValues()
{
    Select(ID_mixValues, (void *)&mixValues);
}

void
PickVarInfo::SelectMiscMessage()
{
    Select(ID_miscMessage, (void *)&miscMessage);
}

void
PickVarInfo::SelectNumMatsPerZone()
{
    Select(ID_numMatsPerZone, (void *)&numMatsPerZone);
}

void
PickVarInfo::SelectMatNames()
{
    Select(ID_matNames, (void *)&matNames);
}

void
PickVarInfo::SelectNumSpecsPerMat()
{
    Select(ID_numSpecsPerMat, (void *)&numSpecsPerMat);
}

void
PickVarInfo::SelectFloatFormat()
{
    Select(ID_floatFormat, (void *)&floatFormat);
}

///////////////////////////////////////////////////////////////////////////////
// Keyframing methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: PickVarInfo::GetFieldName
//
// Purpose:
//   This method returns the name of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

std::string
PickVarInfo::GetFieldName(int index) const
{
    switch (index)
    {
    case ID_variableName:   return "variableName";
    case ID_variableType:   return "variableType";
    case ID_names:          return "names";
    case ID_values:         return "values";
    case ID_mixNames:       return "mixNames";
    case ID_mixValues:      return "mixValues";
    case ID_mixVar:         return "mixVar";
    case ID_centering:      return "centering";
    case ID_miscMessage:    return "miscMessage";
    case ID_numMatsPerZone: return "numMatsPerZone";
    case ID_matNames:       return "matNames";
    case ID_numSpecsPerMat: return "numSpecsPerMat";
    case ID_treatAsASCII:   return "treatAsASCII";
    case ID_floatFormat:    return "floatFormat";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: PickVarInfo::GetFieldType
//
// Purpose:
//   This method returns the type of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeGroup::FieldType
PickVarInfo::GetFieldType(int index) const
{
    switch (index)
    {
    case ID_variableName:   return FieldType_string;
    case ID_variableType:   return FieldType_string;
    case ID_names:          return FieldType_stringVector;
    case ID_values:         return FieldType_doubleVector;
    case ID_mixNames:       return FieldType_stringVector;
    case ID_mixValues:      return FieldType_doubleVector;
    case ID_mixVar:         return FieldType_bool;
    case ID_centering:      return FieldType_enum;
    case ID_miscMessage:    return FieldType_string;
    case ID_numMatsPerZone: return FieldType_intVector;
    case ID_matNames:       return FieldType_stringVector;
    case ID_numSpecsPerMat: return FieldType_intVector;
    case ID_treatAsASCII:   return FieldType_bool;
    case ID_floatFormat:    return FieldType_string;
    default:  return FieldType_unknown;
    }
}

// ****************************************************************************
// Method: PickVarInfo::GetFieldTypeName
//
// Purpose:
//   This method returns the name of a field type given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

std::string
PickVarInfo::GetFieldTypeName(int index) const
{
    switch (index)
    {
    case ID_variableName:   return "string";
    case ID_variableType:   return "string";
    case ID_names:          return "stringVector";
    case ID_values:         return "doubleVector";
    case ID_mixNames:       return "stringVector";
    case ID_mixValues:      return "doubleVector";
    case ID_mixVar:         return "bool";
    case ID_centering:      return "enum";
    case ID_miscMessage:    return "string";
    case ID_numMatsPerZone: return "intVector";
    case ID_matNames:       return "stringVector";
    case ID_numSpecsPerMat: return "intVector";
    case ID_treatAsASCII:   return "bool";
    case ID_floatFormat:    return "string";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: PickVarInfo::FieldsEqual
//
// Purpose:
//   This method compares two fields and return true if they are equal.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
PickVarInfo::FieldsEqual(int index_, const AttributeGroup *rhs) const
{
    const PickVarInfo &obj = *((const PickVarInfo*)rhs);
    bool retval = false;
    switch (index_)
    {
    case ID_variableName:
        {  // new scope
        retval = (variableName == obj.variableName);
        }
        break;
    case ID_variableType:
        {  // new scope
        retval = (variableType == obj.variableType);
        }
        break;
    case ID_names:
        {  // new scope
        retval = (names == obj.names);
        }
        break;
    case ID_values:
        {  // new scope
        retval = (values == obj.values);
        }
        break;
    case ID_mixNames:
        {  // new scope
        retval = (mixNames == obj.mixNames);
        }
        break;
    case ID_mixValues:
        {  // new scope
        retval = (mixValues == obj.mixValues);
        }
        break;
    case ID_mixVar:
        {  // new scope
        retval = (mixVar == obj.mixVar);
        }
        break;
    case ID_centering:
        {  // new scope
        retval = (centering == obj.centering);
        }
        break;
    case ID_miscMessage:
        {  // new scope
        retval = (miscMessage == obj.miscMessage);
        }
        break;
    case ID_numMatsPerZone:
        {  // new scope
        retval = (numMatsPerZone == obj.numMatsPerZone);
        }
        break;
    case ID_matNames:
        {  // new scope
        retval = (matNames == obj.matNames);
        }
        break;
    case ID_numSpecsPerMat:
        {  // new scope
        retval = (numSpecsPerMat == obj.numSpecsPerMat);
        }
        break;
    case ID_treatAsASCII:
        {  // new scope
        retval = (treatAsASCII == obj.treatAsASCII);
        }
        break;
    case ID_floatFormat:
        {  // new scope
        retval = (floatFormat == obj.floatFormat);
        }
        break;
    default: retval = false;
    }

    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// User-defined methods.
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: PickVarInfo::PrintSelf
//
// Purpose:
//   Prints the contents of this class to the passed stream.
//
// Modifications:
//   Kathleen Bonnell, Thu Jun 26 09:31:56 PDT 2003
//   Logic changed in order to support node picking. Info from material var's
//   now handled differently.
//
//   Kathleen Bonnell, Thu Nov 20 10:18:54 PST 2003
//   Support species variableType.
//
// ****************************************************************************

void
PickVarInfo::PrintSelf(ostream &os)
{
    int j, k, nMats, matOffset, mixOffset;
    os << variableName.c_str() << ":  ";
    switch (centering)
    {
        case Nodal:  os << "nodal "; break;
        case Zonal:  os << "zonal "; break;
        case None : break;
    }
    if (!(names.empty() && mixNames.empty()))
    {
        if (variableType == "material")
        {
            mixOffset = 0;
            for (size_t i = 0; i < numMatsPerZone.size(); i++)
            {
                if (names.size() > 0)
                    os << "    " << names[i].c_str() << "\n";
                nMats = numMatsPerZone[i];
                for (j = 0; j < nMats; j++)
                {
                    if (names.size() > 0)
                        os << "    ";
                    os << "    " << mixNames[j+mixOffset].c_str();
                    if (mixValues[j+mixOffset] < 1.)
                        os << " = " << mixValues[j+mixOffset];
                    os << "\n";
                }
                mixOffset += nMats;
            }
        }
        else if (variableType == "species")
        {
            matOffset = 0;
            mixOffset = 0;
            for (size_t i = 0; i < numMatsPerZone.size(); i++)
            {
                if (names.size() > 0)
                {
                    os << "    " << names[i].c_str();
                    if (values.size() > 0)
                        os << " = " << values[i] << "\n";
                }
                nMats = numMatsPerZone[i];
                for (j = 0; j < nMats; j++)
                {
                    os << "    " << matNames[j+matOffset].c_str() << "\n";
                    int nSpecs = numSpecsPerMat[j+matOffset];
                    for (k = 0; k < nSpecs; k++)
                    {
                        os << "        " << mixNames[k+mixOffset].c_str();
                        os << " =  " << mixValues[k+mixOffset] << "\n";
                    }
                    mixOffset += nSpecs;
                }
                matOffset += nMats;
            }
        }
        else
        {
            mixOffset = 0;
            for (size_t i = 0; i < names.size(); i++)
            {
                os << "    " << names[i].c_str() << " = ";
                if (values.size() > names.size())
                {
                    int stride = values.size() / names.size();
                    os << "(";
                    for (j = 0; j < stride; j++)
                    {
                        os << values[i*stride + j] << ", ";
                    }
                    os << ")\n";
                }
                else if (values.size() == names.size())
                {
                    os << values[i] << "\n";
                }
                if (mixVar)
                {
                    nMats = numMatsPerZone[i];
                    for (j = 0; j < nMats; j++)
                    {
                        os << "        " << mixNames[j+mixOffset].c_str();
                        os << " = " <<  mixValues[j+mixOffset] << "\n";
                    }
                    mixOffset += nMats;
                }
            }
        }
    }
    else if (!miscMessage.empty())
    {
        os << "    " << miscMessage.c_str() << "\n";
    }
    else
    {
        os << "    No Information Found\n";
    }
}


// ****************************************************************************
// Method: PickVarInfo::CreateOutputString
//
// Purpose:
//   Creates a single output string containing all the information gathered
//   from a pick.
//
// Modifications:
//   Kathleen Bonnell, Thu Jun 26 09:31:56 PDT 2003
//   Logic changed in order to support node picking. Info from material vars
//   now handled differently.
//
//   Hank Childs, Mon Sep 22 11:19:22 PDT 2003
//   Extend for tensors.
//
//   Kathleen Bonnell, Thu Nov 20 10:18:54 PST 2003
//   Support species variableType.
//
//   Kathleen Bonnell, Wed Dec 17 15:19:46 PST 2003
//   Added arg 'type' indicating the type of pick that generated this info.
//
//   Kathleen Bonnell, Tue Jun  1 16:42:46 PDT 2004
//   Added DomainNode and DomainZone as pick types.
//
//   Kathleen Bonnell, Thu Jun 10 17:31:37 PDT 2004
//   Reduce whitespace for material vars.
//
//   Kathleen Bonnell, Thu Jul 22 12:06:53 PDT 2004
//   Cast values to char if treatAsASCII is true.
//
//   Brad Whitlock, Mon Apr 4 12:12:19 PDT 2005
//   Added support for printing label variables.
//
//   Kathleen Bonnell, Tue Aug 30 09:35:44 PDT 2005
//   Change how ncomps is computed for tensor vars.
//
//   Hank Childs, Thu May 25 08:35:12 PDT 2006
//   Add support for arrays.
//
//   Mark C. Miller, Mon Jan  8 20:48:30 PST 2007
//   Initialized buff at top to avoid possible creation of code blocks where
//   buff is uninitialized (as for tensor/array variables)
//
//   Cyrus Harrison, Mon Sep 17 08:57:13 PDT 2007
//   Added support for user settable floating point format string
//
//   Kathleen Biagas, Wed Oct 19 20:53:18 MST 2011
//   Modify how Tensors/Arrays are printed for consistency and a cleaner look.
//
// ****************************************************************************
void
PickVarInfo::CreateOutputString(std::string &os, const std::string &type)
{
    int j, k;
    int matOffset = 0, mixOffset = 0;
    int nMats;
    char buff[256];
    buff[0] = '\0';
    os = variableName;
    os +=  ":  ";
    bool centeringsMatch = false;
    std::string format="";
    switch (centering)
    {
        case Nodal:  os += "<nodal> ";
                     if (type == "Node" || type == "DomainNode")
                         centeringsMatch = true;
                     break;
        case Zonal:  os += "<zonal> ";
                     if (type == "Zone" || type == "DomainZone")
                         centeringsMatch = true;
                     break;
        case None :  if (variableType == "material" &&
                         numMatsPerZone.size() == 1 && numMatsPerZone[0] == 1)
                         ;
                     else
                         os += "\n";
                     break;
    }
    if (!(names.empty() && mixNames.empty()))
    {
        if (variableType == "material")
        {
            mixOffset  = 0;
            std::string spacing;
            if (numMatsPerZone.size() == 1 && numMatsPerZone[0] == 1)
            {
                if (names.size() > 0)
                {
                    snprintf(buff, 256, "%s ", names[0].c_str());
                    os += buff;
                }
                snprintf(buff, 256, "%s ", mixNames[mixOffset].c_str());
                os += buff;
                if (mixValues[mixOffset] < 1.)
                {
                    format = "= " + floatFormat;
                    snprintf(buff, 256, format.c_str(), mixValues[mixOffset]);
                    os += buff;
                }
                os += "\n";
            }
            else
            {
                for (size_t i = 0; i < numMatsPerZone.size(); i++)
                {
                    nMats = numMatsPerZone[i];
                    if (names.size() > 0)
                    {
                        snprintf(buff, 256, "    %s", names[i].c_str());
                        os += buff;
                        if (nMats == 1)
                            spacing = "  ";
                        else
                        {
                            os += "\n";
                            spacing = "        ";
                        }
                    }
                    else
                        spacing = "    ";
                    for (j = 0; j < nMats; j++)
                    {
                        snprintf(buff, 256, "%s%s ", spacing.c_str(),
                                 mixNames[j+mixOffset].c_str());
                        os += buff;
                        if (mixValues[j+mixOffset] < 1.)
                        {
                            format = "= " + floatFormat;
                            snprintf(buff, 256, format.c_str(), mixValues[j+mixOffset]);
                            os += buff;
                        }
                        os += "\n";
                    }
                    mixOffset += nMats;
                }
            }
        }
        else if (variableType == "species")
        {
            os += "\n";
            matOffset  = 0;
            mixOffset  = 0;
            std::string spacing1;
            std::string spacing2;
            for (size_t i = 0; i < numMatsPerZone.size(); i++)
            {
                if (names.size() > 0)
                {
                    if (values.size() > 0)
                    {
                        format = "    %s = " + floatFormat + "\n";
                        snprintf(buff, 256, format.c_str(), names[i].c_str(),
                                 values[i]);
                    }
                    else
                    {
                        snprintf(buff, 256, "    %s\n", names[i].c_str());
                    }
                    os += buff;
                    spacing1 = "        ";
                    spacing2 = "            ";
                }
                else
                {
                    spacing1 = "    ";
                    spacing2 = "        ";
                }
                nMats = numMatsPerZone[i];
                for (j = 0; j < nMats; j++)
                {
                    snprintf(buff, 256, "%s%s\n", spacing1.c_str(),
                             matNames[j+matOffset].c_str());
                    os += buff;
                    int nSpecs = numSpecsPerMat[j+matOffset];
                    for (k = 0; k < nSpecs; k++)
                    {
                        snprintf(buff, 256, "%s%s  ", spacing2.c_str(),
                                 mixNames[k+mixOffset].c_str());
                        os += buff;
                        format = "= " + floatFormat + "\n";
                        snprintf(buff, 256, format.c_str(), mixValues[k+mixOffset]);
                        os += buff;
                    }
                    os += "\n";
                    mixOffset += nSpecs;
                }
                matOffset += nMats;
            }
        }
        else
        {
            if (!centeringsMatch)
               os += "\n";
            mixOffset  = 0;
            for (size_t i = 0; i < names.size(); i++)
            {
                if (!centeringsMatch)
                {
                    snprintf(buff, 256, "    %s ", names[i].c_str());
                    os += buff;
                }
                os += "= ";
                if (variableType == "vector")
                {
                    int stride = values.size() / names.size();
                    format = "(" + floatFormat;
                    snprintf(buff, 256, format.c_str(), values[i*stride]);
                    os += buff;
                    for (j = 1; j < stride-1; j++)
                    {
                        format = "," + floatFormat;
                        snprintf(buff, 256, format.c_str(), values[i*stride+j]);
                        os += buff;
                    }
                    format = ") mag = " + floatFormat + "\n";
                    snprintf(buff, 256, format.c_str(), values[i*stride+stride-1]);
                    os += buff;
                }
                else if (variableType == "scalar")
                {
                    if (!treatAsASCII)
                    {
                        format = floatFormat + "\n";
                        snprintf(buff, 256, format.c_str(), values[i]);
                    }
                    else
                    {
                        snprintf(buff, 256, "%c\n", (char) values[i]);
                    }
                    os += buff;
                }
                else if (variableType == "tensor")
                {
                    os += "\n";
                    int buf_len = strlen(buff);
                    if (buf_len == 0)
                        buf_len = 4;
                    int ncomps = (values.size()-names.size()) / names.size();
                    PrintTensor(os, values, i, ncomps, buf_len);
                }
                else if (variableType == "symm_tensor")
                {
                    os += "\n";
                    int buf_len = strlen(buff);
                    if (buf_len == 0)
                        buf_len = 4;
                    int ncomps = (values.size()-names.size()) / names.size();
                    PrintSymmetricTensor(os, values, i, ncomps, buf_len);
                }
                else if (variableType == "array")
                {
                    int ncomps = (values.size()-names.size()) / names.size();
                    int buf_len = strlen(buff);
                    if (buf_len == 0)
                        buf_len = 4;
                    if (ncomps > 5)
                        os += "\n";
                    PrintArray(os, values, i, ncomps, buf_len);
                }
                else if (variableType == "label")
                {
                    int labelSize = values.size() / names.size();
                    for (size_t j = labelSize*i; j < labelSize * (i+1); j++)
                    {
                        char c[2] = {(char)values[j], 0};
                        os += c;
                    }
                    os += "\n";
                }
                else
                {
                    os += "\n";
                }
                if (mixVar)
                {
                    nMats = numMatsPerZone[i];
                    for (j = 0; j < nMats; j++)
                    {
                        snprintf(buff, 256, "        material %s = ",
                                 mixNames[j+mixOffset].c_str());
                        os += buff;
                        format = floatFormat + "\n";
                        snprintf(buff, 256, format.c_str(), mixValues[j+mixOffset]);
                        os += buff;
                    }
                    mixOffset += nMats;
                }
            }
        }
    }
    else if (!miscMessage.empty())
    {
        snprintf(buff, 256, "    %s\n", miscMessage.c_str());
        os += buff;
    }
    else
    {
        snprintf(buff, 256, "    No Information Found\n");
        os += buff;
    }
}


// ****************************************************************************
// Method: PickVarInfo::PrintTensor
//
// Purpose:
//     Prints the information out for a tensor.
//
// Programmer: Hank Childs
// Creation:   September 22, 2003
//
// Modifications:
//   Kathleen Bonnell, Tue Aug 30 09:35:44 PDT 2005
//   Print major eigenvalue.  Change how offset is computed.
//
//   Kathleen Bonnell, Tue Aug 30 09:35:44 PDT 2005
//   Print major eigenvalue.  Change how offset is computed.
//
//   Cyrus Harrison, Mon Sep 17 08:57:13 PDT 2007
//   Added support for user settable floating point format string
//
//   Kathleen Biagas, Wed Oct 19 20:54:54 MST 2011
//   Use "format" string, not "floatFormat" when printing Major Eigenvalue.
//
// ****************************************************************************

void
PickVarInfo::PrintTensor(std::string &os, const std::vector<double> &values,
                         int tuple, int ncomps, int buff_len)
{
    int  j;
    std::string format="";

    int offset = tuple*(ncomps+1);
    if (ncomps == 2)  // 2D tensor
    {
        char line[256];
        for (j = 0; j < buff_len; j++)
            os += " ";
        format = "(" + floatFormat + ", "  + floatFormat + ")\n";
        sprintf(line, format.c_str(), values[offset], values[offset+1]);

        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        sprintf(line, format.c_str(), values[offset+2], values[offset+3]);

        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        format = "Major Eigenvalue: " + floatFormat + "\n";
        sprintf(line, format.c_str(), values[offset+4]);
        os += line;
    }
    else if (ncomps == 9) // 3D tensor
    {
        char line[256];
        for (j = 0; j < buff_len; j++)
            os += " ";

        format = "(" + floatFormat + ", "
                     + floatFormat + ", "
                     + floatFormat + ")\n";
        sprintf(line, format.c_str(), values[offset], values[offset+1],
                                        values[offset+2]);
        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        sprintf(line, format.c_str(), values[offset+3], values[offset+4],
                                        values[offset+5]);
        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        sprintf(line, format.c_str(), values[offset+6], values[offset+7],
                                        values[offset+8]);
        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        format = "Major Eigenvalue: " + floatFormat + "\n";
        sprintf(line, format.c_str(), values[offset+9]);
        os += line;
    }
}


// ****************************************************************************
// Method: PickVarInfo::PrintSymmetricTensor
//
// Purpose:
//     Prints the information out for a tensor.
//
// Programmer: Hank Childs
// Creation:   September 22, 2003
//
// Modifications:
//   Kathleen Bonnell, Tue Aug 30 09:35:44 PDT 2005
//   Print major eigenvalue.  Change how offset is computed.
//
//   Cyrus Harrison, Mon Sep 17 08:57:13 PDT 2007
//   Added support for user settable floating point format string
//
// ****************************************************************************

void
PickVarInfo::PrintSymmetricTensor(std::string &os,
         const std::vector<double> &values, int tuple, int ncomps, int buff_len)
{
    int  j;
    std::string format="";
    int offset = tuple*ncomps;
    if (ncomps == 2)  // 2D tensor
    {
        char line[256];
        for (j = 0; j < buff_len; j++)
            os += " ";

        format = "(" + floatFormat + ", "  + floatFormat + ")\n";
        sprintf(line, format.c_str(), values[offset], values[offset+1]);

        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        sprintf(line, format.c_str(), values[offset+2], values[offset+3]);

        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        format = "Major Eigenvalue: " + floatFormat + "\n";
        sprintf(line, format.c_str(), values[offset+4]);
        os += line;
    }
    else if (ncomps == 9) // 3D tensor
    {
        char line[256];
        for (j = 0; j < buff_len; j++)
            os += " ";

        format = "(" + floatFormat + ", "
                     + floatFormat + ", "
                     + floatFormat + ")\n";
        sprintf(line, format.c_str(), values[offset], values[offset+1],
                                        values[offset+2]);
        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        sprintf(line, format.c_str(), values[offset+3], values[offset+4],
                                        values[offset+5]);
        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        sprintf(line, format.c_str(), values[offset+6], values[offset+7],
                                        values[offset+8]);
        os += line;
        for (j = 0; j < buff_len; j++)
            os += " ";

        format = "Major Eigenvalue: " + floatFormat + "\n";
        sprintf(line, format.c_str(), values[offset+9]);
        os += line;
    }
}


// ****************************************************************************
// Method: PickVarInfo::HasInfo
//
// Purpose:
//    Returns true if the info has been filled in, false otherwise.
//
// Programmer: Kathleen Bonnell
// Creation:   March 2, 2004
// ****************************************************************************

bool
PickVarInfo::HasInfo()
{
    return (!(names.empty() && mixNames.empty()));
}

// ****************************************************************************
// Method: PickVarInfo::PrintArray
//
// Purpose:
//     Prints the information out for an array
//
// Programmer: Hank Childs
// Creation:   May 24, 2006
//
// Modifications:
//
//   Hank Childs, Tue Sep  5 17:05:32 PDT 2006
//   Fix indexing bug.
//
//   Cyrus Harrison, Mon Sep 17 08:57:13 PDT 2007
//   Added support for user settable floating point format string
//
//   Kathleen Biagas, Wed Oct 19 20:55:47 MST 2011
//   Reformat for a cleaner output.
//
// ****************************************************************************

void
PickVarInfo::PrintArray(std::string &os,
         const std::vector<double> &values, int tuple, int ncomps, int buff_len)
{
    int j;
    std::string format="";
    int offset = tuple*(ncomps+1);
    char line[256];
    line[0] = '\0';
    if (ncomps > 5)
    {
        for (j = 0; j < buff_len; j++)
            os += " ";
    }
    os += "(";
    format = floatFormat + ", ";
    for (j = 0 ; j < ncomps ; j++)
    {
        if (j == ncomps-1)
            format = floatFormat + ")\n";
        snprintf(line, 256, format.c_str(), values[offset+j]);
        os += line;
    }
}


// ****************************************************************************
// Method: PickVarInfo::CreateOutputMapNode
//
// Purpose:
//   Creates a MapNode object containing all the information gathered
//   from a pick.
//
// Programmer: Kathleen Biagas
// Creation:   October 24, 2011
//
// Modifications:
//    Alister Maguire, Fri Aug 23 13:53:07 PDT 2019
//    Avoid adding null terminating characters to label strings.
//
//    Kathleen Biagas, Thu Dec 12 12:08:58 PST 2019
//    Fix logic for tensor, which was printing out too much info. Separate the
//    'values' and the 'major_eigenvalue' into separate entries for the var.
//
// ****************************************************************************

void
PickVarInfo::CreateOutputMapNode(const std::string &type, MapNode &m)
{
    bool centeringsMatch = false;
    switch (centering)
    {
        case Nodal:  if (type == "Node" || type == "DomainNode")
                         centeringsMatch = true;
                     break;
        case Zonal:  if (type == "Zone" || type == "DomainZone")
                         centeringsMatch = true;
                     break;
        case None: break;
    }
    if (!(names.empty() && mixNames.empty()))
    {
        if (variableType == "material")
        {
            int mixOffset = 0;
            if (numMatsPerZone.size() == 1 && numMatsPerZone[0] == 1)
            {
                std::string subname;
                if (names.size() > 0)
                    subname = names[0] + " ";
                subname += mixNames[mixOffset];
                if (mixValues[mixOffset] < 1.)
                {
                    MapNode n;
                    n[subname] = mixValues[mixOffset];
                    m[variableName] = n;
                }
                else
                {
                    m[variableName] = subname;
                }
            }
            else
            {
                MapNode n;
                MapNode o;
                for (size_t i = 0; i < numMatsPerZone.size(); ++i)
                {
                    int nMats = numMatsPerZone[i];
                    std::string base;
                    if (names.size() > 0)
                        base = names[i].substr(1, names[i].size()-2);
                    for (int j = 0; j < nMats; ++j)
                    {
                        if (mixValues[j+mixOffset] < 1.)
                        {

                           // n[base + mixNames[j+mixOffset]] = mixValues[j+mixOffset];
                           if (!base.empty())
                               o[mixNames[j+mixOffset]] = mixValues[j+mixOffset];
                           else
                               n[mixNames[j+mixOffset]] = mixValues[j+mixOffset];
                        }
                        else
                        {
                           if (!base.empty())
                               n[base] = mixNames[j+mixOffset];
#if 0
                           else
                               n[mixNames[j+mixOffset]] = std::string("type2b");
#endif
                        }
                    }
                    if (!base.empty() && o.GetNumEntries() > 0)
                        n[base] = o;
                    mixOffset += nMats;
                }
                m[variableName] = n;
            }
        }
        else if (variableType == "species")
        {
            int matOffset = 0;
            int mixOffset = 0;
            MapNode n;
            MapNode o;
            MapNode p;
            for (size_t i = 0; i < numMatsPerZone.size(); ++i)
            {
                std::string base;
                if (names.size() > 1)
                {
                    base = names[i].substr(1, names[i].size() -2);
                }
                int nMats = numMatsPerZone[i];
                for (int j = 0; j < numMatsPerZone[i]; ++j)
                {
                    int nSpecs = numSpecsPerMat[j+matOffset];
                    for (int k = 0; k < nSpecs; k++)
                    {
                        p[mixNames[k+mixOffset]] =  mixValues[k+mixOffset];
                    }
                    o[matNames[j+matOffset]] = p;
                    mixOffset += nSpecs;
                }
                if (!base.empty() && o.GetNumEntries() > 0)
                    n[base] = o;
                matOffset += nMats;
            }
            if (n.GetNumEntries() > 0)
                m[variableName] = n;
            else
                m[variableName] = o;
        }
        else
        {
            MapNode n;
            for (size_t i = 0; i < names.size(); ++i)
            {
                std::string stripName = names[i].substr(1, names[i].size() -2);
                if (variableType == "scalar")
                {
                    if (centeringsMatch)
                    {
                        if (!treatAsASCII)
                            m[variableName] = values[i];
                        else
                            m[variableName] = (char) values[i];
                    }
                    else
                    {
                        if (!treatAsASCII)
                            n[stripName] = values[i];
                        else
                            n[stripName] = (char) values[i];
                    }
                }
                else if (variableType == "vector")
                {
                    doubleVector v;
                    size_t stride = values.size() / names.size();
                    for (size_t j = 0; j < stride -1; j++)
                        v.push_back(values[i*stride+j]);
                    if (centeringsMatch)
                        m[variableName] = v;
                    else
                        n[stripName] = v;
                }
                else if (variableType == "tensor")
                {
                    size_t ncomps = (values.size()-names.size())/names.size();
                    size_t offset = i*(ncomps+1);
                    doubleVector v;
                    for (size_t j = 0; j < ncomps; j++)
                    {
                        v.push_back(values[offset+j]);
                    }
                    if (centeringsMatch)
                    {
                        m[variableName]["values"] = v;
                        m[variableName]["major_eigenvalue"] = values[offset+ncomps];
                    }
                    else
                    {
                        n[stripName]["values"] = v;
                        n[stripName]["major_eigenvalue"] = values[offset+ncomps];
                    }
                }
                else if (variableType == "symm_tensor")
                {
                    if (centeringsMatch)
                        m[variableName] = std::string("some symm_tensor info here");
                    else
                        n[stripName] = std::string("some symm_tensor info here");
                }
                else if (variableType == "array")
                {
                    size_t ncomps = (values.size()-names.size())/names.size();
                    size_t offset = i*(ncomps+1);
                    doubleVector v;
                    for (size_t j = 0; j < ncomps; j++)
                        v.push_back(values[offset+j]);
                    if (centeringsMatch)
                        m[variableName] = v;
                    else
                        n[stripName] = v;
                }
                else if (variableType == "label")
                {
                    size_t labelSize = values.size() / names.size();
                    std::string l;
                    for (size_t j = labelSize*i; j < labelSize *(i+1); ++j)
                    {
                        //
                        // We don't want to add the null terminators; doing
                        // so causes strange behaviors.
                        //
                        if ((char)values[j] == '\0')
                            break;
                        l += (char)values[j];
                    }
                    if (centeringsMatch)
                        m[variableName] = l;
                    else
                        n[stripName] = l;
                }
            }
            if (!centeringsMatch && n.GetNumEntries() != 0)
                m[variableName] = n;

#if 0
            int mixOffset = 0;
            if (mixVar)
            {
                int nMats = numMatsPerZone[i];
                std::string matname;
                for (int j = 0; j < nMats; ++j)
                {
                    matname = "material " + mixNames[j+mixOffset];
                    m[matname] = mixValues[j+mixOffset];
                }
                mixOffset += nMats;
            }
#endif
        }
    }
}

