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

Added OpenQube support to vtkChemistry.

This patch add a concrete subclass of vtkAbstractElectronicData
(vtkOpenQubeElectronicData) and a molecule source
(vtkOpenQubeMoleculeSource). These are compiled optionally only if
OpenQube is installed.

Eigen is needed to include OpenQube's headers.

Change-Id: I2b30d0d53ec9659b43adb7fd4dbe351de9d1d4b9
parent 49344cbd
# - Try to find Eigen2 lib
# Once done this will define
#
# EIGEN2_FOUND - system has eigen lib
# EIGEN2_INCLUDE_DIR - the eigen include directory
# Copyright (c) 2006, 2007 Montel Laurent, <montel@kde.org>
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
if (EIGEN2_INCLUDE_DIR)
# in cache already
set(EIGEN2_FOUND TRUE)
else (EIGEN2_INCLUDE_DIR)
find_path(EIGEN2_INCLUDE_DIR NAMES Eigen/Core
PATHS
${INCLUDE_INSTALL_DIR}
${KDE4_INCLUDE_DIR}
PATH_SUFFIXES eigen2
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Eigen2 DEFAULT_MSG EIGEN2_INCLUDE_DIR )
mark_as_advanced(EIGEN2_INCLUDE_DIR)
endif(EIGEN2_INCLUDE_DIR)
INCLUDE(vtkDependentOption)
SET(KIT Chemistry)
SET(UKIT CHEMISTRY)
SET(KIT_LIBS vtkRendering vtkFiltering)
SET(KIT_LIBS vtkRendering vtkFiltering vtkVolumeRendering)
SET(Kit_SRCS
vtkAbstractElectronicData.cxx
......@@ -21,6 +23,24 @@ SET_SOURCE_FILES_PROPERTIES(
ABSTRACT
)
# OpenQube setup
FIND_PACKAGE(OpenQube QUIET)
IF(OpenQube_FOUND)
FIND_PACKAGE(Eigen2 QUIET)
ENDIF(OpenQube_FOUND)
VTK_DEPENDENT_OPTION(VTK_USE_OPENQUBE
"Compile OpenQube support into vtkChemistry."
ON "OpenQube_FOUND;EIGEN2_FOUND" OFF)
IF(VTK_USE_OPENQUBE)
INCLUDE_DIRECTORIES(${OpenQube_INCLUDE_DIRS} ${EIGEN2_INCLUDE_DIR})
SET(KIT_LIBS ${KIT_LIBS} OpenQube)
SET(Kit_SRCS
${Kit_SRCS}
vtkOpenQubeElectronicData.cxx
vtkOpenQubeMoleculeSource.cxx
)
ENDIF(VTK_USE_OPENQUBE)
#-----------------------------------------------------------------------------
# Include CMake code common to all kits.
INCLUDE(${VTK_CMAKE_DIR}/KitCommonBlock.cmake)
......
......@@ -4,18 +4,18 @@ IF (VTK_USE_RENDERING AND VTK_USE_CHEMISTRY)
SET(MyTests
TestBallAndStick.cxx
TestPeriodicTable.cxx
TestBondColorModeDiscreteByAtom.cxx
TestBondColorModeSingleColor.cxx
TestBondColorModeSmoothByAtom.cxx
TestCompositeRender.cxx
TestFastRender.cxx
TestLiqouriceSticks.cxx
TestMolecule.cxx
TestMoleculeSelection.cxx
TestMultiCylinderOn.cxx
TestMultiCylinderOff.cxx
TestCompositeRender.cxx
TestPeriodicTable.cxx
TestVDWSpheres.cxx
TestLiqouriceSticks.cxx
TestFastRender.cxx
)
# Tests with data
......@@ -24,6 +24,16 @@ IF (VTK_USE_RENDERING AND VTK_USE_CHEMISTRY)
${MyTests}
TestCMLMoleculeReader.cxx
)
IF(VTK_USE_OPENQUBE)
# Add Eigen to the include path for the OpenQube headers
INCLUDE_DIRECTORIES(${EIGEN2_INCLUDE_DIR})
SET(MyTests
${MyTests}
TestOpenQubeElectronicData.cxx
TestOpenQubeMOPACDensity.cxx
TestOpenQubeMOPACOrbital.cxx
)
ENDIF(VTK_USE_OPENQUBE)
ENDIF(VTK_DATA_ROOT)
# Use the testing object factory, to reduce boilerplate code in tests.
......
/*=========================================================================
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 "vtkAbstractElectronicData.h"
#include "vtkDataSetCollection.h"
#include "vtkImageData.h"
#include "vtkMolecule.h"
#include "vtkNew.h"
#include "vtkOpenQubeElectronicData.h"
#include "vtkOpenQubeMoleculeSource.h"
#include "vtkTestUtilities.h"
#include "vtkWeakPointer.h"
#include <openqube/basissetloader.h>
int TestOpenQubeElectronicData(int argc, char *argv[])
{
char* fname = vtkTestUtilities::ExpandDataFileName(
argc, argv, "Data/2h2o.out");
vtkNew<vtkOpenQubeMoleculeSource> oq;
oq->SetFileName(fname);
oq->Update();
vtkWeakPointer<vtkOpenQubeElectronicData> oqed;
oqed = vtkOpenQubeElectronicData::SafeDownCast(
oq->GetOutput()->GetElectronicData());
if (!oqed)
{
cerr << "Molecule's electronic data is not from OpenQube.\n";
return EXIT_FAILURE;
}
// Set parameters to generate fast, low-res cubes
const float lowResSpacing1 = 1.0;
const float lowResSpacing2 = 1.5;
const float lowResPadding1 = 1.0;
const float lowResPadding2 = 1.5;
vtkIdType expectedNumberOfImages = 0;
// Calculate 4 cubes using all combinations of the above parameters.
// Test that the number of cached images increases accordingly, and that
// when a cached image is returned, it is the correct one.
oqed->SetSpacing(lowResSpacing1);
oqed->SetPadding(lowResPadding1);
vtkImageData *testImage11 = oqed->GetHOMO();
++expectedNumberOfImages;
if (oqed->GetImages()->GetNumberOfItems() != expectedNumberOfImages)
{
cerr << "Number of cached images ("
<< oqed->GetImages()->GetNumberOfItems() << ") not equal to the "
"number of expected images (" << expectedNumberOfImages << ")\n";
return EXIT_FAILURE;
}
if (oqed->GetHOMO() != testImage11)
{
cerr << "(Test11) New orbital calculated when cached image is "
"available\n";
return EXIT_FAILURE;
}
oqed->SetSpacing(lowResSpacing1);
oqed->SetPadding(lowResPadding2);
vtkImageData *testImage12 = oqed->GetHOMO();
++expectedNumberOfImages;
if (oqed->GetImages()->GetNumberOfItems() != expectedNumberOfImages)
{
cerr << "Number of cached images ("
<< oqed->GetImages()->GetNumberOfItems() << ") not equal to the "
"number of expected images (" << expectedNumberOfImages << ")\n";
return EXIT_FAILURE;
}
if (oqed->GetHOMO() != testImage12)
{
cerr << "(Test12) New orbital calculated when cached image is "
"available\n";
return EXIT_FAILURE;
}
oqed->SetSpacing(lowResSpacing2);
oqed->SetPadding(lowResPadding1);
vtkImageData *testImage21 = oqed->GetHOMO();
++expectedNumberOfImages;
if (oqed->GetImages()->GetNumberOfItems() != expectedNumberOfImages)
{
cerr << "Number of cached images ("
<< oqed->GetImages()->GetNumberOfItems() << ") not equal to the "
"number of expected images (" << expectedNumberOfImages << ")\n";
return EXIT_FAILURE;
}
if (oqed->GetHOMO() != testImage21)
{
cerr << "(Test21) New orbital calculated when cached image is "
"available\n";
return EXIT_FAILURE;
}
oqed->SetSpacing(lowResSpacing2);
oqed->SetPadding(lowResPadding2);
vtkImageData *testImage22 = oqed->GetHOMO();
++expectedNumberOfImages;
if (oqed->GetImages()->GetNumberOfItems() != expectedNumberOfImages)
{
cerr << "Number of cached images ("
<< oqed->GetImages()->GetNumberOfItems() << ") not equal to the "
"number of expected images (" << expectedNumberOfImages << ")\n";
return EXIT_FAILURE;
}
if (oqed->GetHOMO() != testImage22)
{
cerr << "(Test22) New orbital calculated when cached image is "
"available\n";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/*=========================================================================
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 "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkAbstractElectronicData.h"
#include "vtkActor.h"
#include "vtkCamera.h"
#include "vtkColorTransferFunction.h"
#include "vtkImageData.h"
#include "vtkImageShiftScale.h"
#include "vtkMolecule.h"
#include "vtkMoleculeMapper.h"
#include "vtkNew.h"
#include "vtkOpenQubeMoleculeSource.h"
#include "vtkPiecewiseFunction.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
#include "vtkSmartVolumeMapper.h"
#include "vtkVolume.h"
#include "vtkVolumeProperty.h"
#include <openqube/basissetloader.h>
#include <openqube/basisset.h>
int TestOpenQubeMOPACDensity(int argc, char *argv[])
{
char* fname = vtkTestUtilities::ExpandDataFileName(
argc, argv, "Data/2h2o.out");
vtkNew<vtkOpenQubeMoleculeSource> oq;
oq->SetFileName(fname);
oq->Update();
delete [] fname;
vtkSmartPointer<vtkMolecule> mol = vtkSmartPointer<vtkMolecule>::New();
mol = oq->GetOutput();
vtkNew<vtkMoleculeMapper> molMapper;
molMapper->SetInput(mol);
molMapper->UseLiqouriceStickSettings();
molMapper->SetBondRadius(0.1);
molMapper->SetAtomicRadiusScaleFactor(0.1);
vtkNew<vtkActor> molActor;
molActor->SetMapper(molMapper.GetPointer());
vtkAbstractElectronicData *edata = oq->GetOutput()->GetElectronicData();
if (!edata)
{
cout << "NULL vtkAbstractElectronicData returned from "
"vtkOpenQubeElectronicData.\n";
return EXIT_FAILURE;
}
cout << "Num electrons: " << edata->GetNumberOfElectrons() << "\n";
vtkSmartPointer<vtkImageData> data = vtkSmartPointer<vtkImageData>::New();
data = edata->GetElectronDensity();
if (!data)
{
cout << "NULL vtkImageData returned from vtkOpenQubeElectronicData.\n";
return EXIT_FAILURE;
}
double range[2];
data->Update();
data->GetScalarRange(range);
cout << "ImageData range: " << range[0] <<" "<< range[1] << "\n";
vtkNew<vtkImageShiftScale> t;
t->SetInput(data.GetPointer());
t->SetShift(0.0);
double magnitude = range[1];
if(fabs(magnitude) < 1e-10)
magnitude = 1.0;
t->SetScale(255.0/magnitude);
t->SetOutputScalarTypeToDouble();
cout << "magnitude: " << magnitude << "\n";
t->Update();
t->GetOutput()->GetScalarRange(range);
cout << "Shifted min/max: " << range[0] << " " << range[1] << "\n";
vtkNew<vtkPiecewiseFunction> compositeOpacity;
compositeOpacity->AddPoint( 0.000, 0.00);
compositeOpacity->AddPoint( 0.001, 0.00);
compositeOpacity->AddPoint( 5.000, 0.45);
// compositeOpacity->AddPoint( 10.000, 0.45);
compositeOpacity->AddPoint(255.000, 0.90);
vtkNew<vtkColorTransferFunction> color;
color->AddRGBPoint( 0.000, 0.0, 0.0, 0.00);
color->AddRGBPoint( 0.001, 0.0, 0.0, 0.20);
color->AddRGBPoint( 5.000, 0.0, 0.0, 0.50);
color->AddRGBPoint(255.000, 0.0, 0.0, 1.00);
vtkNew<vtkSmartVolumeMapper> volumeMapper;
volumeMapper->SetInputConnection(t->GetOutputPort());
volumeMapper->SetBlendModeToComposite();
volumeMapper->SetInterpolationModeToLinear();
vtkNew<vtkVolumeProperty> volumeProperty;
volumeProperty->ShadeOff();
volumeProperty->SetInterpolationTypeToLinear();
volumeProperty->SetScalarOpacity(compositeOpacity.GetPointer());
volumeProperty->SetColor(color.GetPointer());
vtkNew<vtkVolume> volume;
volume->SetMapper(volumeMapper.GetPointer());
volume->SetProperty(volumeProperty.GetPointer());
vtkNew<vtkRenderer> ren;
vtkNew<vtkRenderWindow> win;
win->AddRenderer(ren.GetPointer());
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(win.GetPointer());
ren->AddActor(volume.GetPointer());
ren->AddActor(molActor.GetPointer());
ren->SetBackground(0.0, 0.0, 0.0);
win->SetSize(450,450);
win->Render();
ren->GetActiveCamera()->Zoom(2.4);
win->Render();
int retVal = vtkRegressionTestImage(win.GetPointer());
if ( retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Start();
}
cout << volumeMapper->GetLastUsedRenderMode() << "\n";
return retVal;
}
/*=========================================================================
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 "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkAbstractElectronicData.h"
#include "vtkActor.h"
#include "vtkCamera.h"
#include "vtkColorTransferFunction.h"
#include "vtkImageData.h"
#include "vtkImageShiftScale.h"
#include "vtkMolecule.h"
#include "vtkMoleculeMapper.h"
#include "vtkNew.h"
#include "vtkOpenQubeMoleculeSource.h"
#include "vtkPiecewiseFunction.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkRenderWindow.h"
#include "vtkRenderer.h"
#include "vtkSmartPointer.h"
#include "vtkSmartVolumeMapper.h"
#include "vtkVolume.h"
#include "vtkVolumeProperty.h"
#include <openqube/basissetloader.h>
#include <openqube/basisset.h>
int TestOpenQubeMOPACOrbital(int argc, char *argv[])
{
char* fname = vtkTestUtilities::ExpandDataFileName(
argc, argv, "Data/2h2o.out");
vtkNew<vtkOpenQubeMoleculeSource> oq;
oq->SetFileName(fname);
oq->Update();
delete [] fname;
vtkSmartPointer<vtkMolecule> mol = vtkSmartPointer<vtkMolecule>::New();
mol = oq->GetOutput();
vtkNew<vtkMoleculeMapper> molMapper;
molMapper->SetInput(mol);
molMapper->UseLiqouriceStickSettings();
molMapper->SetBondRadius(0.1);
molMapper->SetAtomicRadiusScaleFactor(0.1);
vtkNew<vtkActor> molActor;
molActor->SetMapper(molMapper.GetPointer());
vtkAbstractElectronicData *edata = oq->GetOutput()->GetElectronicData();
if (!edata)
{
cout << "NULL vtkAbstractElectronicData returned from "
"vtkOpenQubeElectronicData.\n";
return EXIT_FAILURE;
}
cout << "Num electrons: " << edata->GetNumberOfElectrons() << "\n";
vtkSmartPointer<vtkImageData> data = vtkSmartPointer<vtkImageData>::New();
data = edata->GetMO(4);
if (!data)
{
cout << "NULL vtkImageData returned from vtkOpenQubeElectronicData.\n";
return EXIT_FAILURE;
}
double range[2];
data->Update();
data->GetScalarRange(range);
cout << "ImageData range: " << range[0] <<" "<< range[1] << "\n";
double maxAbsVal = (fabs(range[0]) > fabs(range[1])) ? fabs(range[0])
: fabs(range[1]);
vtkNew<vtkImageShiftScale> t;
t->SetInput(data.GetPointer());
t->SetShift(maxAbsVal);
double magnitude = maxAbsVal + maxAbsVal;
if(fabs(magnitude) < 1e-10)
magnitude = 1.0;
t->SetScale(255.0/magnitude);
t->SetOutputScalarTypeToDouble();
cout << "magnitude: " << magnitude << "\n";
t->Update();
t->GetOutput()->GetScalarRange(range);
cout << "Shifted min/max: " << range[0] << " " << range[1] << "\n";
vtkNew<vtkPiecewiseFunction> compositeOpacity;
compositeOpacity->AddPoint( 0.00, 1.0);
compositeOpacity->AddPoint( 63.75, 0.8);
compositeOpacity->AddPoint(127.50, 0.0);
compositeOpacity->AddPoint(191.25, 0.8);
compositeOpacity->AddPoint(255.00, 1.0);
vtkNew<vtkColorTransferFunction> color;
color->AddRGBSegment( 0.00, 1.0, 0.0, 0.0, 127.0, 1.0, 0.0, 0.0);
color->AddRGBSegment(128.0, 0.0, 0.0, 1.0, 255.0, 0.0, 0.0, 1.0);
vtkNew<vtkSmartVolumeMapper> volumeMapper;
volumeMapper->SetInputConnection(t->GetOutputPort());
volumeMapper->SetBlendModeToComposite();
vtkNew<vtkVolumeProperty> volumeProperty;
volumeProperty->ShadeOff();
volumeProperty->SetInterpolationTypeToLinear();
volumeProperty->SetScalarOpacity(compositeOpacity.GetPointer());
volumeProperty->SetColor(color.GetPointer());
vtkNew<vtkVolume> volume;
volume->SetMapper(volumeMapper.GetPointer());
volume->SetProperty(volumeProperty.GetPointer());
vtkNew<vtkRenderer> ren;
vtkNew<vtkRenderWindow> win;
win->AddRenderer(ren.GetPointer());
vtkNew<vtkRenderWindowInteractor> iren;
iren->SetRenderWindow(win.GetPointer());
ren->AddActor(volume.GetPointer());
ren->AddActor(molActor.GetPointer());
ren->SetBackground(0.0, 0.0, 0.0);
win->SetSize(450,450);
win->Render();
ren->GetActiveCamera()->Zoom(2.4);
win->Render();
int retVal = vtkRegressionTestImage(win.GetPointer());
if ( retVal == vtkRegressionTester::DO_INTERACTOR)
{
iren->Start();
}
return retVal;
}
......@@ -20,4 +20,7 @@
#define VTK_BODR_DATA_PATH "@CMAKE_INSTALL_PREFIX@/@VTK_INSTALL_SHARE_DIR_CM24@/vtkChemistry/vtkBODRData"
#define VTK_BODR_DATA_PATH_BUILD "@VTK_SOURCE_DIR@/Chemistry/vtkBODRData"
/* Whether OpenQube is enabled */
#cmakedefine VTK_USE_OPENQUBE
#endif
/*=========================================================================
Program: Visualization Toolkit
Module: vtkOpenQubeElectronicData.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 "vtkOpenQubeElectronicData.h"
#include "vtkDataSetCollection.h"
#include "vtkImageData.h"
#include "vtkNew.h"
#include "vtkObjectFactory.h"
#include <openqube/basisset.h>
#include <openqube/cube.h>
// Internal class to store queue/qube information along with the image
class OQEDImageData : public vtkImageData
{
public:
vtkTypeMacro(OQEDImageData, vtkImageData);
static OQEDImageData * New();
vtkSetMacro(OrbitalNumber, vtkIdType);
vtkGetMacro(OrbitalNumber, vtkIdType);