Commit 82c73fe3 authored by David C. Lonie's avatar David C. Lonie
Browse files

Added vtkPeriodicTable and associated classes to Chemistry kit.

This patch introduces 3 new classes:

- vtkPeriodicTable: Convert between atomic number and symbol/name,
  lookup rgb values, lookup atomic radii, etc.
- vtkBODR: Container for arrays parsed from the Blue Obelisk Data
  Repository
- vtkBODRParser: Parser to read the XML files from the bodr.

It also contains bodr's elements.xml file and COPYING notice (MIT
license). These are installed to share/.

Change-Id: Ia7c928250e788695ad22a007dfdc9de4363c0474
parent 33c92265
......@@ -4,9 +4,21 @@ SET(UKIT CHEMISTRY)
SET(KIT_LIBS vtkRendering vtkFiltering)
SET(Kit_SRCS
vtkBlueObeliskData.cxx
vtkBlueObeliskDataParser.cxx
vtkPeriodicTable.cxx
)
#-----------------------------------------------------------------------------
# Include CMake code common to all kits.
INCLUDE(${VTK_CMAKE_DIR}/KitCommonBlock.cmake)
#-----------------------------------------------------------------------------
# Install Blue Obelisk Data Repository files
INSTALL(DIRECTORY vtkBODRData
DESTINATION ${VTK_INSTALL_SHARE_DIR_CM24}/vtkChemistry
)
# Generate configured header file
CONFIGURE_FILE(${VTK_SOURCE_DIR}/Chemistry/vtkChemistryConfigure.h.in
${VTK_BINARY_DIR}/Chemistry/vtkChemistryConfigure.h IMMEDIATE)
......@@ -3,7 +3,7 @@ IF (VTK_USE_RENDERING AND VTK_USE_CHEMISTRY)
SET(KIT Chemistry)
SET(MyTests
TestPeriodicTable.cxx
)
# Tests with data
......
/*=========================================================================
Program: Visualization Toolkit
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkNew.h"
#include "vtkPeriodicTable.h"
#define DIE(_fmt, ...) \
printf(_fmt "\n", __VA_ARGS__); \
return EXIT_FAILURE
int TestPeriodicTable(int argc, char *argv[])
{
vtkNew<vtkPeriodicTable> pTab;
// Test that numeric strings are parsed correctly
if (pTab->GetAtomicNumber("25") != 25)
{
DIE("vtkPeriodicTable::GetAtomicNumber cannot parse numeric "
"strings properly. Given \"25\", should get 25, got %hu.",
pTab->GetAtomicNumber("25"));
}
if (pTab->GetAtomicNumber("300") != 0 ||
pTab->GetAtomicNumber("-300") != 0)
{
DIE("vtkPeriodicTable does not return 0 for invalid numeric strings. "
"Given \"300\" and \"-300\", returned %hu and %hu respectively.",
pTab->GetAtomicNumber("300"), pTab->GetAtomicNumber("-300"));
}
// Check that invalid strings return zero
const char *nullString = {'\0'};
if (pTab->GetAtomicNumber("I'm not an element.") != 0 ||
pTab->GetAtomicNumber(0) != 0 ||
pTab->GetAtomicNumber(nullString) != 0)
{
DIE("vtkPeriodicTable did not return 0 for an invalid string: %hu, %hu, %hu",
pTab->GetAtomicNumber("I'm not an element."),
pTab->GetAtomicNumber(0),
pTab->GetAtomicNumber(nullString));
}
// Round-trip element names and symbols
const char *symbol, *name;
for (unsigned short i = 0; i <= pTab->GetNumberOfElements(); ++i)
{
name = pTab->GetElementName(i);
symbol = pTab->GetSymbol(i);
if (pTab->GetAtomicNumber(name) != i)
{
DIE("Element name failed roundtrip: Name: \"%s\" atomic number: "
"%hu vtkPeriodicTable::GetAtomicNumber(\"%s\") returns: %hu",
name, i, name, pTab->GetAtomicNumber(name));
}
if (pTab->GetAtomicNumber(symbol) != i)
{
DIE("Element symbol failed roundtrip: Symbol: \"%s\" atomic number: "
"%hu vtkPeriodicTable::GetAtomicNumber(\"%s\") returns: %hu",
symbol, i, symbol, pTab->GetAtomicNumber(symbol));
}
}
// Test alternate names/symbols:
// - Deuterium
if (pTab->GetAtomicNumber("D") != pTab->GetAtomicNumber("H"))
{
DIE("Failed to identify \"D\" as a hydrogen isotrope. "
"Atomic number for \"D\": %hu", pTab->GetAtomicNumber("D"));
}
if (pTab->GetAtomicNumber("Deuterium") != pTab->GetAtomicNumber("Hydrogen"))
{
DIE("Failed to identify \"Deuterium\" as a hydrogen isotrope. "
"Atomic number for \"Deuterium\": %hu",
pTab->GetAtomicNumber("Deuterium"));
}
// - Tritium
if (pTab->GetAtomicNumber("T") != pTab->GetAtomicNumber("H"))
{
DIE("Failed to identify \"T\" as a hydrogen isotrope. "
"Atomic number for \"T\": %hu", pTab->GetAtomicNumber("T"));
}
if (pTab->GetAtomicNumber("Tritium") != pTab->GetAtomicNumber("Hydrogen"))
{
DIE("Failed to identify \"Tritium\" as a hydrogen isotrope. "
"Atomic number for \"Tritium\": %hu",
pTab->GetAtomicNumber("Tritium"));
}
// - Aluminum, Aluminium
if (pTab->GetAtomicNumber("Aluminum") != pTab->GetAtomicNumber("Aluminium"))
{
DIE("\"Aluminum\" returns a different atomic number than \"Aluminium\", "
"(%hu and %hu respectively).",
pTab->GetAtomicNumber("Aluminum"),
pTab->GetAtomicNumber("Aluminium"));
}
return EXIT_SUCCESS;
}
Copyright (C) 2006-2008,2010 The Blue Obelisk Project (http://www.blueobelisk.org/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*=========================================================================
Program: Visualization Toolkit
Module: vtkBlueObeliskData.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkBlueObeliskData.h"
#include "vtkAbstractArray.h"
#include "vtkBlueObeliskDataParser.h"
#include "vtkFloatArray.h"
#include "vtkObjectFactory.h"
#include "vtkStringArray.h"
#include "vtkMutexLock.h"
#include "vtkUnsignedShortArray.h"
// Hidden STL reference: vtkstd::vector<vtkAbstractArray*>
class MyStdVectorOfVtkAbstractArrays :
public vtkstd::vector<vtkAbstractArray*> {};
vtkStandardNewMacro(vtkBlueObeliskData);
//----------------------------------------------------------------------------
vtkBlueObeliskData::vtkBlueObeliskData()
: WriteMutex(vtkSimpleMutexLock::New()),
Initialized(false), NumberOfElements(0),
Arrays(new MyStdVectorOfVtkAbstractArrays)
{
// Setup arrays and build Arrays
this->Arrays->reserve(19);
this->Symbols->SetNumberOfComponents(1);
this->Arrays->push_back(this->Symbols.GetPointer());
this->LowerSymbols->SetNumberOfComponents(1);
this->Arrays->push_back(this->LowerSymbols.GetPointer());
this->Names->SetNumberOfComponents(1);
this->Arrays->push_back(this->Names.GetPointer());
this->LowerNames->SetNumberOfComponents(1);
this->Arrays->push_back(this->LowerNames.GetPointer());
this->PeriodicTableBlocks->SetNumberOfComponents(1);
this->Arrays->push_back(this->PeriodicTableBlocks.GetPointer());
this->ElectronicConfigurations->SetNumberOfComponents(1);
this->Arrays->push_back(this->ElectronicConfigurations.GetPointer());
this->Families->SetNumberOfComponents(1);
this->Arrays->push_back(this->Families.GetPointer());
this->Masses->SetNumberOfComponents(1);
this->Arrays->push_back(this->Masses.GetPointer());
this->ExactMasses->SetNumberOfComponents(1);
this->Arrays->push_back(this->ExactMasses.GetPointer());
this->IonizationEnergies->SetNumberOfComponents(1);
this->Arrays->push_back(this->IonizationEnergies.GetPointer());
this->ElectronAffinities->SetNumberOfComponents(1);
this->Arrays->push_back(this->ElectronAffinities.GetPointer());
this->PaulingElectronegativities->SetNumberOfComponents(1);
this->Arrays->push_back(this->PaulingElectronegativities.GetPointer());
this->CovalentRadii->SetNumberOfComponents(1);
this->Arrays->push_back(this->CovalentRadii.GetPointer());
this->VDWRadii->SetNumberOfComponents(1);
this->Arrays->push_back(this->VDWRadii.GetPointer());
this->DefaultColors->SetNumberOfComponents(3);
this->Arrays->push_back(this->DefaultColors.GetPointer());
this->BoilingPoints->SetNumberOfComponents(1);
this->Arrays->push_back(this->BoilingPoints.GetPointer());
this->MeltingPoints->SetNumberOfComponents(1);
this->Arrays->push_back(this->MeltingPoints.GetPointer());
this->Periods->SetNumberOfComponents(1);
this->Arrays->push_back(this->Periods.GetPointer());
this->Groups->SetNumberOfComponents(1);
this->Arrays->push_back(this->Groups.GetPointer());
}
//----------------------------------------------------------------------------
vtkBlueObeliskData::~vtkBlueObeliskData()
{
delete Arrays;
this->WriteMutex->Delete();
}
//----------------------------------------------------------------------------
void vtkBlueObeliskData::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os,indent);
os << indent << "NumberOfElements: " << this->NumberOfElements << "\n";
this->PrintSelfIfExists("this->Symbols",
this->Symbols.GetPointer(), os, indent);
this->PrintSelfIfExists("this->LowerSymbols",
this->LowerSymbols.GetPointer(), os, indent);
this->PrintSelfIfExists("this->Names",
this->Names.GetPointer(), os, indent);
this->PrintSelfIfExists("this->LowerNames",
this->LowerNames.GetPointer(), os, indent);
this->PrintSelfIfExists("this->PeriodicTableBlocks",
this->PeriodicTableBlocks.GetPointer(), os, indent);
this->PrintSelfIfExists("this->ElectronicConfigurations",
this->ElectronicConfigurations.GetPointer(),
os, indent);
this->PrintSelfIfExists("this->Families",
this->Families.GetPointer(), os, indent);
this->PrintSelfIfExists("this->Masses",
this->Masses.GetPointer(), os, indent);
this->PrintSelfIfExists("this->ExactMasses",
this->ExactMasses.GetPointer(), os, indent);
this->PrintSelfIfExists("this->IonizationEnergies",
this->IonizationEnergies.GetPointer(), os, indent);
this->PrintSelfIfExists("this->ElectronAffinities",
this->ElectronAffinities.GetPointer(), os, indent);
this->PrintSelfIfExists("this->PaulingElectronegativities",
this->PaulingElectronegativities.GetPointer(),
os, indent);
this->PrintSelfIfExists("this->CovalentRadii",
this->CovalentRadii.GetPointer(), os, indent);
this->PrintSelfIfExists("this->VDWRadii",
this->VDWRadii.GetPointer(), os, indent);
this->PrintSelfIfExists("this->DefaultColors",
this->DefaultColors.GetPointer(), os, indent);
this->PrintSelfIfExists("this->BoilingPoints",
this->BoilingPoints.GetPointer(), os, indent);
this->PrintSelfIfExists("this->MeltingPoints",
this->MeltingPoints.GetPointer(), os, indent);
this->PrintSelfIfExists("this->Periods",
this->Periods.GetPointer(), os, indent);
this->PrintSelfIfExists("this->Groups",
this->Groups.GetPointer(), os, indent);
}
//----------------------------------------------------------------------------
void vtkBlueObeliskData::PrintSelfIfExists(const char * name, vtkObject *obj,
ostream& os, vtkIndent indent)
{
if (obj)
{
os << indent << name << ": @" << obj << "\n";
obj->PrintSelf(os, indent.GetNextIndent());
}
else
{
os << indent << name << " is null.\n";
}
}
//----------------------------------------------------------------------------
void vtkBlueObeliskData::Initialize()
{
if (IsInitialized())
{
vtkDebugMacro(<<"vtkBlueObeliskData @" << this
<< " already initialized.\n");
return;
}
vtkNew<vtkBlueObeliskDataParser> parser;
parser->SetTarget(this);
parser->Parse();
this->Initialized = true;
}
//----------------------------------------------------------------------------
int vtkBlueObeliskData::Allocate(vtkIdType sz, vtkIdType ext)
{
for (MyStdVectorOfVtkAbstractArrays::iterator it = this->Arrays->begin(),
it_end = this->Arrays->end(); it != it_end; ++it)
{
if ((*it)->Allocate(sz * (*it)->GetNumberOfComponents(), ext) == 0)
{
return 0;
}
}
return 1;
}
//----------------------------------------------------------------------------
void vtkBlueObeliskData::Squeeze()
{
for (MyStdVectorOfVtkAbstractArrays::iterator it = this->Arrays->begin(),
it_end = this->Arrays->end(); it != it_end; ++it)
{
(*it)->Squeeze();
}
}
//----------------------------------------------------------------------------
void vtkBlueObeliskData::Reset()
{
for (MyStdVectorOfVtkAbstractArrays::iterator it = this->Arrays->begin(),
it_end = this->Arrays->end(); it != it_end; ++it)
{
(*it)->Reset();
}
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkBlueObeliskData.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
// .NAME vtkBlueObeliskData - Contains chemical data from the Blue
// Obelisk Data Repository
//
// .SECTION Description
// The Blue Obelisk Data Repository is a free, open repository of
// chemical information. This class is a container for this
// information.
//
// \note This class contains only the raw arrays parsed from the
// BODR. For more convenient access to this data, use the
// vtkPeriodicTable class.
//
// \note If you must use this class directly, consider using the
// static vtkBlueObeliskData object accessible through
// vtkPeriodicTable::GetBlueObeliskData(). This object is
// automatically populated on the first instantiation of
// vtkPeriodicTable.
#ifndef __vtkBlueObeliskData_h
#define __vtkBlueObeliskData_h
#include "vtkObject.h"
#include "vtkNew.h" // For vtkNew
class vtkAbstractArray;
class vtkFloatArray;
class vtkStringArray;
class vtkSimpleMutexLock;
class vtkUnsignedShortArray;
// Hidden STL reference: vtkstd::vector<vtkAbstractArray*>
class MyStdVectorOfVtkAbstractArrays;
class VTK_CHEMISTRY_EXPORT vtkBlueObeliskData : public vtkObject
{
public:
vtkTypeMacro(vtkBlueObeliskData,vtkObject);
void PrintSelf(ostream& os, vtkIndent indent);
static vtkBlueObeliskData *New();
// Description:
// Fill this object using an internal vtkBlueObeliskDataParser
// instance. Check that the vtkSimpleMutexLock GetWriteMutex() is
// locked before calling this method on a static instance in a
// multithreaded environment.
void Initialize();
// Description:
// Check if this object has been initialized yet.
bool IsInitialized() { return this->Initialized;}
// Description:
// Access the mutex that protects the arrays during a call to
// Initialize()
vtkGetObjectMacro(WriteMutex, vtkSimpleMutexLock);
// Description:
// Return the number of elements for which this vtkBlueObeliskData
// instance contains information.
vtkGetMacro(NumberOfElements, unsigned short);
// Description:
// Access the raw arrays stored in this vtkBlueObeliskData.
vtkGetNewMacro(Symbols, vtkStringArray);
vtkGetNewMacro(LowerSymbols, vtkStringArray);
vtkGetNewMacro(Names, vtkStringArray);
vtkGetNewMacro(LowerNames, vtkStringArray);
vtkGetNewMacro(PeriodicTableBlocks, vtkStringArray);
vtkGetNewMacro(ElectronicConfigurations, vtkStringArray);
vtkGetNewMacro(Families, vtkStringArray);
vtkGetNewMacro(Masses, vtkFloatArray);
vtkGetNewMacro(ExactMasses, vtkFloatArray);
vtkGetNewMacro(IonizationEnergies, vtkFloatArray);
vtkGetNewMacro(ElectronAffinities, vtkFloatArray);
vtkGetNewMacro(PaulingElectronegativities, vtkFloatArray);
vtkGetNewMacro(CovalentRadii, vtkFloatArray);
vtkGetNewMacro(VDWRadii, vtkFloatArray);
vtkGetNewMacro(DefaultColors, vtkFloatArray);
vtkGetNewMacro(BoilingPoints, vtkFloatArray);
vtkGetNewMacro(MeltingPoints, vtkFloatArray);
vtkGetNewMacro(Periods, vtkUnsignedShortArray);
vtkGetNewMacro(Groups, vtkUnsignedShortArray);
protected:
friend class vtkBlueObeliskDataParser;
vtkBlueObeliskData();
~vtkBlueObeliskData();
vtkSimpleMutexLock *WriteMutex;
bool Initialized;
// Description:
// Allocate enough memory in each array for sz elements. ext is not
// used.
virtual int Allocate(vtkIdType sz, vtkIdType ext=1000);
// Description:
// Reset each array.
virtual void Reset();
// Description:
// Free any unused memory in the member arrays
virtual void Squeeze();
unsigned short NumberOfElements;
// Lists all arrays
MyStdVectorOfVtkAbstractArrays *Arrays;
// Atomic Symbols
vtkNew<vtkStringArray> Symbols;
vtkNew<vtkStringArray> LowerSymbols;
// Element Names
vtkNew<vtkStringArray> Names;
vtkNew<vtkStringArray> LowerNames;
// Misc Strings
vtkNew<vtkStringArray> PeriodicTableBlocks;
vtkNew<vtkStringArray> ElectronicConfigurations;
vtkNew<vtkStringArray> Families; // Non-Metal, Noblegas, Metalloids, etc
// Misc Data
vtkNew<vtkFloatArray> Masses; // amu
vtkNew<vtkFloatArray> ExactMasses; // amu
vtkNew<vtkFloatArray> IonizationEnergies; // eV
vtkNew<vtkFloatArray> ElectronAffinities; // eV
vtkNew<vtkFloatArray> PaulingElectronegativities; // eV
vtkNew<vtkFloatArray> CovalentRadii; // Angstrom
vtkNew<vtkFloatArray> VDWRadii; // Angstom
vtkNew<vtkFloatArray> DefaultColors; // rgb 3-tuples, [0.0,1.0]
vtkNew<vtkFloatArray> BoilingPoints; // K
vtkNew<vtkFloatArray> MeltingPoints; // K
vtkNew<vtkUnsignedShortArray> Periods; // Row of periodic table
vtkNew<vtkUnsignedShortArray> Groups; // Column of periodic table
void PrintSelfIfExists(const char *, vtkObject *, ostream&, vtkIndent);
private:
vtkBlueObeliskData(const vtkBlueObeliskData&); // Not implemented.
void operator=(const vtkBlueObeliskData&); // Not implemented.
};
#endif
/*=========================================================================
Program: Visualization Toolkit
Module: vtkBlueObeliskDataParser.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkBlueObeliskDataParser.h"
#include "vtkAbstractArray.h"
#include "vtkBlueObeliskData.h"
#include "vtkFloatArray.h"
#include "vtkObjectFactory.h"
#include "vtkStdString.h"
#include "vtkStringArray.h"
#include "vtkUnsignedShortArray.h"
// Defines VTK_BODR_DATA_PATH
#include "vtkChemistryConfigure.h"
#include <locale>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef MSC_VER
#define stat _stat
#endif
//----------------------------------------------------------------------------
vtkStandardNewMacro(vtkBlueObeliskDataParser);
//----------------------------------------------------------------------------
vtkBlueObeliskDataParser::vtkBlueObeliskDataParser()
: vtkXMLParser(),
Target(NULL),
IsProcessingAtom(false),
IsProcessingValue(false),
CurrentValueType(None),
CurrentSymbol(new vtkStdString),
CurrentName(new vtkStdString),
CurrentPeriodicTableBlock(new vtkStdString),
CurrentElectronicConfiguration(new vtkStdString),
CurrentFamily(new vtkStdString)
{
// Find elements.xml. Check the share directory first, then the source dir
// if running from the build directory before installing.
struct stat buf;
if (stat(VTK_BODR_DATA_PATH "/elements.xml", &buf) == 0)
{
this->SetFileName(VTK_BODR_DATA_PATH "/elements.xml");
}
else if (stat(VTK_BODR_DATA_PATH_BUILD "/elements.xml", &buf) == 0)
{
this->SetFileName(VTK_BODR_DATA_PATH_BUILD "/elements.xml");
}